IDM和XDM 对比 分析 与 实验

我以前用过IDM,觉得这个东西是真心强大,下载速度又快,还能直接下载视频。
IDM:

  • https://www.internetdownloadmanager.com/

  • https://github.com/J2TEAM/idm-trial-reset (重置试用时间)
    今天遇到一个叫XDM的软件,也能下载视频,下载速度也还快。
    XDM:

  • http://xdman.sourceforge.net/ (这个页面不容易打开)

  • https://github.com/subhra74

  • https://sourceforge.net/projects/xdman/

  • https://subhra74.github.io/xdm/ (这个页面比较好打开)
    sourceforge上XDM的代码是残缺的,缺一大堆东西
    IDM和XDM 对比 分析 与 实验_第1张图片
    最后一次commit是2017年,现在明明有2018版
    GitHub上的代码也是差缺的,没有dll
    IDM和XDM 对比 分析 与 实验_第2张图片
    IDM和XDM 对比 分析 与 实验_第3张图片
    用这两个软件各自试着下载视频

  • YouTube
    https://www.youtube.com/watch?v=8X7vCbJvLFs
    IDM很快下完了,XDM下载不动,应该是梯子没用好

  • b站
    https://www.bilibili.com/video/av15819806?from=search&seid=1752343386019300591
    这个视频两个软件都很快下载完成,但是都是残缺的,明明几十分钟的视频,下载下来只能几分钟
    我拿到下载链接,两个都是一样的
    https://upos-hz-mirrorkodou.acgvideo.com/upgcxcode/41/67/25796741/25796741-1-64.flv?e=ig8euxZM2rNcNbUghbUVhoMBhbNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNC8xNEVE9EKE9IMvXBvE2ENvNCImNEVEK9GVqJIwqa80WXIekXRE9IMvXBvEuENvNCImNEVEua6m2jIxux0CkF6s2JZv5x0DQJZY2F8SkXKE9IB5QK&deadline=1546181549&gen=playurl&nbs=1&oi=1911980101&os=kodou&platform=pc&trid=7fc015af4cfa493cbee6ae1c7ef4320a&uipk=5&upsig=5684b9130c0f3906f729f7f58fbf143f
    IDM和XDM 对比 分析 与 实验_第4张图片
    然后我看b站的源码发现

window.__playinfo__={"code":0,"message":"0","ttl":1,"data":{"from":"local","result":"suee","message":"","quality":64,"format":"flv720","timelength":2969843,"accept_format":"flv720,flv480,flv360","accept_description":["高清 720P","清晰 480P","流畅 360P"],"accept_quality":[64,32,16],"video_codecid":7,"seek_param":"start","seek_type":"offset","durl":[{"order":1,"length":367991,"size":77159085,"ahead":"","vhead":"","url":"http://upos-hz-mirrorkodou.acgvideo.com/upgcxcode/41/67/25796741/25796741-1-64.flv?e=ig8euxZM2rNcNbUghbUVhoMBhbNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNC8xNEVE9EKE9IMvXBvE2ENvNCImNEVEK9GVqJIwqa80WXIekXRE9IMvXBvEuENvNCImNEVEua6m2jIxux0CkF6s2JZv5x0DQJZY2F8SkXKE9IB5QK==&deadline=1546181549&gen=playurl&nbs=1&oi=1911980101&os=kodou&platform=pc&trid=7fc015af4cfa493cbee6ae1c7ef4320a&uipk=5&upsig=5684b9130c0f3906f729f7f58fbf143f","backup_url":["http://upos-hz-mirrorcos.acgvideo.com/upgcxcode/41/67/25796741/25796741-1-64.flv?um_deadline=1546181549&platform=pc&rate=522500&oi=1911980101&um_sign=dbff5839d0eacadd3ccff3cc4f24f051&gen=playurl&os=cos&trid=7fc015af4cfa493cbee6ae1c7ef4320a"]},{"order":2,"length":351990,"size":73797189,"ahead":"","vhead":"","url":"http://upos-hz-mirrorcos.acgvideo.com/upgcxcode/41/67/25796741/25796741-2-64.flv?um_deadline=1546181549&platform=pc&rate=522500&oi=1911980101&um_sign=d5e3a533d06cae5db13ee45b7b26d38b&gen=playurl&os=cos&trid=7fc015af4cfa493cbee6ae1c7ef4320a","backup_url":null},{"order":3,"length":351990,"size":73767443,"ahead":"","vhead":"","url":"http://upos-hz-mirrorkodou.acgvideo.com/upgcxcode/41/67/25796741/25796741-3-64.flv?e=ig8euxZM2rNcNbUghbUVhoMBhbNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNC8xNEVE9EKE9IMvXBvE2ENvNCImNEVEK9GVqJIwqa80WXIekXRE9IMvXBvEuENvNCImNEVEua6m2jIxux0CkF6s2JZv5x0DQJZY2F8SkXKE9IB5QK==&deadline=1546181549&gen=playurl&nbs=1&oi=1911980101&os=kodou&platform=pc&trid=7fc015af4cfa493cbee6ae1c7ef4320a&uipk=5&upsig=fbc189d76e5a99f2d3e70b2b7176a773","backup_url":["http://upos-hz-mirrorcos.acgvideo.com/upgcxcode/41/67/25796741/25796741-3-64.flv?um_deadline=1546181549&platform=pc&rate=522500&oi=1911980101&um_sign=dab72b7b7e3ce382328f4c46a9ae3ce8&gen=playurl&os=cos&trid=7fc015af4cfa493cbee6ae1c7ef4320a"]},{"order":4,"length":359990,"size":75456447,"ahead":"","vhead":"","url":"http://upos-hz-mirrorcos.acgvideo.com/upgcxcode/41/67/25796741/25796741-4-64.flv?um_deadline=1546181549&platform=pc&rate=522500&oi=1911980101&um_sign=eaa5d9591e53700087a99a9feb4b3a27&gen=playurl&os=cos&trid=7fc015af4cfa493cbee6ae1c7ef4320a","backup_url":null},{"order":5,"length":375991,"size":78837544,"ahead":"","vhead":"","url":"http://upos-hz-mirrorkodo.acgvideo.com/upgcxcode/41/67/25796741/25796741-5-64.flv?e=ig8euxZM2rNcNbUghbUVhoMBhbNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNC8xNEVE9EKE9IMvXBvE2ENvNCImNEVEK9GVqJIwqa80WXIekXRE9IMvXBvEuENvNCImNEVEua6m2jIxux0CkF6s2JZv5x0DQJZY2F8SkXKE9IB5QK==&deadline=1546181549&dynamic=1&gen=playurl&oi=1911980101&os=kodo&platform=pc&rate=522500&trid=7fc015af4cfa493cbee6ae1c7ef4320a&uipk=5&uipv=5&um_deadline=1546181549&um_sign=a505132188420760a13fb1eb1765117a&upsig=355994beee838edfdf68659c7d084df8","backup_url":["http://upos-hz-mirrorcos.acgvideo.com/upgcxcode/41/67/25796741/25796741-5-64.flv?um_deadline=1546181549&platform=pc&rate=522500&oi=1911980101&um_sign=a505132188420760a13fb1eb1765117a&gen=playurl&os=cos&trid=7fc015af4cfa493cbee6ae1c7ef4320a"]},{"order":6,"length":359990,"size":75470114,"ahead":"","vhead":"","url":"http://upos-hz-mirrorwcsu.acgvideo.com/upgcxcode/41/67/25796741/25796741-6-64.flv?e=ig8euxZM2rNcNbUghbUVhoMBhbNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNC8xNEVE9EKE9IMvXBvE2ENvNCImNEVEK9GVqJIwqa80WXIekXRE9IMvXBvEuENvNCImNEVEua6m2jIxux0CkF6s2JZv5x0DQJZY2F8SkXKE9IB5QK==&deadline=1546181549&gen=playurl&nbs=1&oi=1911980101&os=wcsu&platform=pc&trid=7fc015af4cfa493cbee6ae1c7ef4320a&uipk=5&upsig=af88018f23c054e49b16974ec233035a","backup_url":["http://upos-hz-mirrorcos.acgvideo.com/upgcxcode/41/67/25796741/25796741-6-64.flv?um_deadline=1546181549&platform=pc&rate=522500&oi=1911980101&um_sign=24a18d588f38e6578bcdd25d951efdde&gen=playurl&os=cos&trid=7fc015af4cfa493cbee6ae1c7ef4320a"]},{"order":7,"length":351990,"size":73789206,"ahead":"","vhead":"","url":"http://upos-hz-mirrorks3u.acgvideo.com/upgcxcode/41/67/25796741/25796741-7-64.flv?e=ig8euxZM2rNcNbUghbUVhoMBhbNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNC8xNEVE9EKE9IMvXBvE2ENvNCImNEVEK9GVqJIwqa80WXIekXRE9IMvXBvEuENvNCImNEVEua6m2jIxux0CkF6s2JZv5x0DQJZY2F8SkXKE9IB5QK==&deadline=1546181549&gen=playurl&nbs=1&oi=1911980101&os=ks3u&platform=pc&trid=7fc015af4cfa493cbee6ae1c7ef4320a&uipk=5&upsig=3a85dba17bccdfa935e4c6cadc4601d1","backup_url":["http://upos-hz-mirrorcos.acgvideo.com/upgcxcode/41/67/25796741/25796741-7-64.flv?um_deadline=1546181549&platform=pc&rate=522500&oi=1911980101&um_sign=8b21244d7e8e881b5f24fa8eebc609f5&gen=playurl&os=cos&trid=7fc015af4cfa493cbee6ae1c7ef4320a"]},{"order":8,"length":449911,"size":94297092,"ahead":"","vhead":"","url":"http://upos-hz-mirrorks3u.acgvideo.com/upgcxcode/41/67/25796741/25796741-8-64.flv?e=ig8euxZM2rNcNbUghbUVhoMBhbNBhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNC8xNEVE9EKE9IMvXBvE2ENvNCImNEVEK9GVqJIwqa80WXIekXRE9IMvXBvEuENvNCImNEVEua6m2jIxux0CkF6s2JZv5x0DQJZY2F8SkXKE9IB5QK==&deadline=1546181549&gen=playurl&nbs=1&oi=1911980101&os=ks3u&platform=pc&trid=7fc015af4cfa493cbee6ae1c7ef4320a&uipk=5&upsig=ad3860f95d1696ccfff3d9a1921f2bac","backup_url":["http://upos-hz-mirrorcos.acgvideo.com/upgcxcode/41/67/25796741/25796741-8-64.flv?um_deadline=1546181549&platform=pc&rate=522500&oi=1911980101&um_sign=5172a19d7ee71a23d44fe3ccce35cde8&gen=playurl&os=cos&trid=7fc015af4cfa493cbee6ae1c7ef4320a"]}]},"session":"75cf2557bfb30fd057193de685adc360","videoFrame":{}}

然后这个json串是
IDM和XDM 对比 分析 与 实验_第5张图片
每个durl是
IDM和XDM 对比 分析 与 实验_第6张图片
可以看到是分段存储,或者说是分段下载视频,怪不得我下载的时间这么短。
既然这样,那么对IDM和XDM这种软件就可以分为两部分,一部分负责拿到这个url,一部分负责根据url下载视频等。
看了XDM的chrome脚本源码真没看出什么东西,可能需要细读吧,我只扫了一下

(function () {
    var requests = [];
    var blockedHosts = [];
    var videoUrls = [];
    var fileExts = [];
    var vidExts = [];
    var isXDMUp = true;
    var monitoring = true;
    var debug = false;
    var xdmHost = "http://127.0.0.1:9614";
    var disabled = false;
    var lastIcon;
    var lastPopup;
    var videoList = [];
    var mimeList = [];

    var log = function (msg) {
        if (debug) {
            try {
                log(msg);
            } catch (e) {
                log(e + "");
            }
        }
    }

    var processRequest = function (request, response) {
        if (shouldInterceptFile(request, response)) {
            var file = getAttachedFile(response);
            if (!file) {
                file = getFileFromUrl(response.url);
            }
            sendToXDM(request, response, file, false);
            return { redirectUrl: "http://127.0.0.1:9614/204" };
        } else {
            checkForVideo(request, response);
        }
    };

    var sendToXDM = function (request, response, file, video) {
        log("sending to xdm: " + response.url);
        var data = "url=" + response.url + "\r\n";
        if (file) {
            data += "file=" + file + "\r\n";
        }
        for (var i = 0; i < request.requestHeaders.length; i++) {
            data += "req=" + request.requestHeaders[i].name + ":" + request.requestHeaders[i].value + "\r\n";
        }
        for (var i = 0; i < response.responseHeaders.length; i++) {
            data += "res=" + response.responseHeaders[i].name + ":" + response.responseHeaders[i].value + "\r\n";
        }
        data += "res=tabId:" + request.tabId + "\r\n";
        data += "res=realUA:" + navigator.userAgent + "\r\n";
        chrome.cookies.getAll({ "url": response.url }, function (cookies) {
            for (var i = 0; i < cookies.length; i++) {
                var cookie = cookies[i];
                data += "cookie=" + cookie.name + ":" + cookie.value + "\r\n";
            }
            log(data);

            var xhr = new XMLHttpRequest();
            xhr.open('POST', xdmHost + (video ? "/video" : "/download"), true);
            xhr.send(data);
        });
    };

    var sendRecUrl = function (urls, index, data) {
        if (index == urls.length - 1) {
            log(data);
            var xhr = new XMLHttpRequest();
            xhr.open('POST', xdmHost + "/links", true);
            xhr.send(data);
            return;
        }
        var url = urls[index];
        data += "url=" + url + "\r\n";
        data += "res=realUA:" + navigator.userAgent + "\r\n";
        chrome.cookies.getAll({ "url": url }, function (cookies) {
            for (var i = 0; i < cookies.length; i++) {
                var cookie = cookies[i];
                data += "cookie=" + cookie.name + ":" + cookie.value + "\r\n";
            }
            data += "\r\n\r\n";
            sendRecUrl(urls, index + 1, data);
        });
    };

    var sendUrlsToXDM = function (urls) {
        sendRecUrl(urls, 0, "");
    };

    var sendUrlToXDM = function (url) {
        log("sending to xdm: " + url);
        var data = "url=" + url + "\r\n";
        data += "res=realUA:" + navigator.userAgent + "\r\n";
        chrome.cookies.getAll({ "url": url }, function (cookies) {
            for (var i = 0; i < cookies.length; i++) {
                var cookie = cookies[i];
                data += "cookie=" + cookie.name + ":" + cookie.value + "\r\n";
            }
            log(data);

            var xhr = new XMLHttpRequest();
            xhr.open('POST', xdmHost + "/download", true);
            xhr.send(data);
        });
    };

    var sendImageToXDM = function (info, tab) {
        if (info.mediaType) {
            if ("image" == info.mediaType) {
                if (info.srcUrl) {
                    url = info.srcUrl;
                }
            }
        }

        if (!url) {
            url = info.linkUrl;
        }
        if (!url) {
            url = info.pageUrl;
        }
        if (!url) {
            return;
        }
        sendUrlToXDM(url);
    };

    var sendLinkToXDM = function (info, tab) {
        var url = info.linkUrl;
        if (!url) {
            if (info.mediaType) {
                if ("video" == info.mediaType || "audio" == info.mediaType) {
                    if (info.srcUrl) {
                        url = info.srcUrl;
                    }
                }
            }
        }
        if (!url) {
            url = info.pageUrl;
        }
        if (!url) {
            return;
        }
        sendUrlToXDM(url);
    };

    var runContentScript = function (info, tab) {
        log("running content script");
        chrome.tabs.executeScript({
            file: 'contentscript.js'
        });
    };

    var isVideoMime = function (mimeText) {
        if(!mimeList){
            return false;
        }
        var mime = mimeText.toLowerCase();
        for (var i = 0; i < mimeList.length; i++) {
            if (mime.indexOf(mimeList[i]) != -1) {
                return true;
            }
        }
        return false;
    }

    var checkForVideo = function (request, response) {
        
        var mime = "";
        var video = false;
        var url = response.url;

        for (var i = 0; i < response.responseHeaders.length; i++) {
            if (response.responseHeaders[i].name.toLowerCase() == "content-type") {
                mime = response.responseHeaders[i].value.toLocaleLowerCase();
                break;
            }
        }

        

        if (mime.startsWith("audio/") || mime.startsWith("video/") ||
            mime.indexOf("mpegurl") > 0 || mime.indexOf("f4m") > 0 || isVideoMime(mime)) {
                log("Checking video mime: "+mime+" "+JSON.stringify(mimeList));
            video = true;
        }

        if (!video) {
            if (videoUrls) {
                for (var i = 0; i < videoUrls.length; i++) {
                    var arr = videoUrls[i].split("|");
                    var matched = true;
                    for (var j = 0; j < arr.length; j++) {
                        //console.log(arr[j]);
                        if (url.indexOf(arr[j]) < 0) {
                            matched = false;
                            break;
                        }
                    }
                    if (matched) {
                        video = true;
                        log(url)
                        break;
                    }
                }
            }
        }


        if (!video) {
            if (vidExts) {
                var file = getFileFromUrl(url);
                var ext = getFileExtension(file);
                if (ext) {
                    ext = ext.toUpperCase();
                }
                for (var i = 0; i < vidExts.length; i++) {
                    if (vidExts[i] == ext) {
                        video = true;
                        break;
                    }
                }
            }
        }

        if (video) {
            if (request.tabId != -1) {
                chrome.tabs.get
                    (
                    request.tabId,
                    function (tab) {
                        sendToXDM(request, response, tab.title, true);
                    }
                    );
            } else {
                sendToXDM(request, response, null, true);
            }
        }
    };

    var getAttachedFile = function (response) {
        for (var i = 0; i < response.responseHeaders.length; i++) {
            if (response.responseHeaders[i].name.toLowerCase() == 'content-disposition') {
                return getFileFromContentDisposition(response.responseHeaders[i].value);
            }
        }
    };

    var isHtml = function (response) {
        for (var i = 0; i < response.responseHeaders.length; i++) {
            if (response.responseHeaders[i].name.toLowerCase() == 'content-type') {
                return (response.responseHeaders[i].value.indexOf("text/html") != -1);
            }
        }
    };

    var shouldInterceptFile = function (request, response) {
        var url = response.url;
        var isAttachment = false;
        if (isBlocked(url)) {
            return false;
        }

        if (isHtml(response)) {
            return false;
        }
        var file = getAttachedFile(response);
        if (!file) {
            file = getFileFromUrl(url);
        } else {
            isAttachment = true;
        }
        var ext = getFileExtension(file);
        if (ext) {
            if (!isAttachment) {
                for (var i = 0; i < vidExts.length; i++) {
                    if (vidExts[i] == ext.toUpperCase()) {
                        return false;
                    }
                }
            }
            for (var i = 0; i < fileExts.length; i++) {
                if (fileExts[i] == ext.toUpperCase()) {
                    return true;
                }
            }
        }
    };

    var isBlocked = function (url) {
        for (var i = 0; i < blockedHosts.length; i++) {
            var hostName = parseUrl(url).hostname;
            if (blockedHosts[i] == hostName) {
                return true;
            }
        }
        return false;
    };

    var syncXDM = function () {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (xhr.readyState == XMLHttpRequest.DONE) {
                if (xhr.status == 200) {
                    var data = JSON.parse(xhr.responseText);
                    monitoring = data.enabled;
                    blockedHosts = data.blockedHosts;
                    videoUrls = data.videoUrls;
                    fileExts = data.fileExts;
                    vidExts = data.vidExts;
                    isXDMUp = true;
                    videoList = data.vidList;
                    if (data.mimeList) {
                        mimeList = data.mimeList;
                    }
                    updateBrowserAction();
                }
                else {
                    isXDMUp = false;
                    monitoring = false;
                    updateBrowserAction();
                }
            }
        };

        xhr.open('GET', xdmHost + "/sync", true);
        xhr.send(null);
    };

    var getFileFromUrl = function (str) {
        return ustr = parseUrl(str).pathname;
    };

    var getFileFromContentDisposition = function (str) {
        var arr = str.split(";");
        for (var i = 0; i < arr.length; i++) {
            var ln = arr[i].trim();
            if (ln.indexOf("filename=") != -1) {
                log("matching line: " + ln);
                var arr2 = ln.split("=");
                log("name: " + arr2[1]);
                return arr2[1].replace(/"/g, '').trim();
            }
        }
    };

    var getFileExtension = function (file) {
        var index = file.lastIndexOf(".");
        if (index > 0) {
            return file.substr(index + 1);
        }
    };

    var parseUrl = function (str) {
        var match = str.match(/^(https?\:)\/\/(([^:\/?#]*)(?:\:([0-9]+))?)([\/]{0,1}[^?#]*)(\?[^#]*|)(#.*|)$/);
        return match && {
            href: str,
            protocol: match[1],
            host: match[2],
            hostname: match[3],
            port: match[4],
            pathname: match[5],
            search: match[6],
            hash: match[7]
        }
    };

    var removeRequest = function (requestId) {
        for (var i = 0; i < requests.length; i++) {
            if (requests[i].requestId == requestId) {
                return requests.splice(i, 1);
            }
        }
    };

    var updateBrowserAction = function () {
        if (!isXDMUp) {
            setBrowserActionPopUp("fatal.html");
            setBrowserActionIcon("icon_blocked.png");
            return;
        }
        if (monitoring) {
            if (disabled) {
                setBrowserActionIcon("icon_disabled.png");
            } else {
                setBrowserActionIcon("icon.png");
            }
            setBrowserActionPopUp("status.html");
        } else {
            setBrowserActionIcon("icon_disabled.png");
            setBrowserActionPopUp("disabled.html");
        }

        if (videoList && videoList.length > 0) {
            chrome.browserAction.setBadgeText({ text: videoList.length + "" });
        } else {
            chrome.browserAction.setBadgeText({ text: "" });
        }
    };

    var setBrowserActionIcon = function (icon) {
        if (lastIcon == icon) {
            return;
        }
        chrome.browserAction.setIcon({ path: icon });
        lastIcon = icon;
    };

    var setBrowserActionPopUp = function (pop) {
        if (lastPopup == pop) {
            return;
        }
        chrome.browserAction.setPopup({ popup: pop });
        lastPopup = pop;
    };



    var initSelf = function () {
        //This will add the request to request array for later use, 
        //the object is removed from array when request completes or fails
        chrome.webRequest.onSendHeaders.addListener
            (
            function (info) { requests.push(info); },
            { urls: ["http://*/*", "https://*/*"] },
            ["requestHeaders"]
            );
        chrome.webRequest.onCompleted.addListener
            (
            function (info) {
                removeRequest(info.requestId);
            },
            { urls: ["http://*/*", "https://*/*"] }
            );

        chrome.webRequest.onErrorOccurred.addListener
            (
            function (info) {
                removeRequest(info.requestId);
            },
            { urls: ["http://*/*", "https://*/*"] }
            );

        //This will monitor and intercept files download if 
        //criteria matches and XDM is running
        //Use request array to get request headers
        chrome.webRequest.onHeadersReceived.addListener
            (
            function (response) {
                var requests = removeRequest(response.requestId);
                if (!isXDMUp) {
                    return;
                }

                if (!monitoring) {
                    return;
                }

                if (disabled) {
                    return;
                }

                if (!(response.statusLine.indexOf("200") > 0
                    || response.statusLine.indexOf("206") > 0)) {
                    return;
                }

                if (requests) {
                    if (requests.length == 1) {
                        if (!(response.url + "").startsWith(xdmHost)) {
                            //console.log("processing request " + response.url);
                            return processRequest(requests[0], response);
                        }
                    }
                }
            },
            { urls: ["http://*/*", "https://*/*"] },
            ["blocking", "responseHeaders"]
            );

        //check XDM if is running and enable monitoring
        setInterval(function () { syncXDM(); }, 1000);

        chrome.runtime.onMessage.addListener(
            function (request, sender, sendResponse) {
                if (request.type === "links") {
                    var arr = [];
                    arr = request.links;
                    /* for (var i = 0; i < arr.length; i++) {
                        console.log("link " + arr[i]);
                    } */
                    sendUrlsToXDM(arr);
                    sendResponse({ done: "done" });
                }
                else if (request.type === "stat") {
                    var resp = { isDisabled: disabled };
                    resp.list = videoList;
                    sendResponse(resp);
                }
                else if (request.type === "cmd") {
                    disabled = request.disable;
                    log("disabled " + disabled);
                }
                else if (request.type === "vid") {
                    var xhr = new XMLHttpRequest();
                    xhr.open('POST', xdmHost + "/item", true);
                    xhr.send(request.itemId);
                }
                else if (request.type === "clear") {
                    var xhr = new XMLHttpRequest();
                    xhr.open('GET', xdmHost + "/clear", true);
                    xhr.send();
                }
            }
        );

        chrome.commands.onCommand.addListener(function (command) {
            if (isXDMUp && monitoring) {
                log("called")
                disabled = !disabled;
            }
        });

        chrome.contextMenus.create({
            title: "Download with XDM",
            contexts: ["link", "video", "audio"],
            onclick: sendLinkToXDM,
        });

        chrome.contextMenus.create({
            title: "Download Image with XDM",
            contexts: ["image"],
            onclick: sendImageToXDM,
        });

        chrome.contextMenus.create({
            title: "Download all links",
            contexts: ["all"],
            onclick: runContentScript,
        });
    };

    initSelf();
    log("loaded");
})();

原网址:
https://github.com/subhra74/xdm-browser-monitor/tree/master/xdm-browser-monitor/chrome

后面下载部分
IDM和XDM 对比 分析 与 实验_第7张图片
具体也没细看,这个代码在我本地跑起来缺N多个东西,尤其缺一个dll,我觉得非常奇怪,不知道从哪个地方编译出来的。

java.io.FileNotFoundException: fonts\NotoSansUI-Regular.ttf (系统找不到指定的路径。)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.(FileInputStream.java:138)
	at java.io.FileInputStream.(FileInputStream.java:93)
	at xdman.ui.res.FontResource.loadNoto(FontResource.java:14)
	at xdman.ui.res.FontResource.loadNotoRegular(FontResource.java:28)
	at xdman.ui.res.FontResource.getNormalFont(FontResource.java:52)
	at xdman.ui.laf.XDMTheme.(XDMTheme.java:22)
	at xdman.ui.laf.XDMLookAndFeel.(XDMLookAndFeel.java:21)
	at xdman.Main.main(Main.java:25)
[ main ] Noto regular font could not be loaded
[ main ] starting monitoring...
[ Thread-1 ] instance starting...
java.io.FileNotFoundException: lang\en.txt (系统找不到指定的路径。)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.(FileInputStream.java:138)
	at java.io.FileInputStream.(FileInputStream.java:93)
	at xdman.ui.res.StringResource.loadDefaultLanguage(StringResource.java:47)
	at xdman.ui.res.StringResource.get(StringResource.java:32)
	at xdman.QueueManager.loadQueues(QueueManager.java:65)
	at xdman.QueueManager.(QueueManager.java:28)
	at xdman.QueueManager.getInstance(QueueManager.java:33)
	at xdman.XDMApp.(XDMApp.java:154)
	at xdman.XDMApp.getInstance(XDMApp.java:279)
	at xdman.XDMApp.instanceStarted(XDMApp.java:82)
	at xdman.monitoring.BrowserMonitor.run(BrowserMonitor.java:31)
	at java.lang.Thread.run(Thread.java:748)
[ Thread-1 ] Context initialized
current component version: null
Stat: -1
[ Thread-2 ] Context initialized
[ Thread-1 ] Launch CMD: "D:\Program Files\Java\jdk1.8.0_171\jre\bin\javaw.exe" -jar "D:\src\xdman-code\out\production\classes" -m
[ Thread-1 ] java.lang.UnsatisfiedLinkError: Can't load library: D:\src\xdman-code\out\production\xdm_native.dll
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1827)
	at java.lang.Runtime.load0(Runtime.java:809)
	at java.lang.System.load(System.java:1086)
[ AWT-EventQueue-0 ] showing main window.
	at xdman.win32.NativeMethods.(NativeMethods.java:21)
	at xdman.win32.NativeMethods.getInstance(NativeMethods.java:13)
	at xdman.util.WinUtils.isAlreadyAutoStart(WinUtils.java:62)
	at xdman.util.XDMUtils.isAlreadyAutoStart(XDMUtils.java:311)
	at xdman.XDMApp.instanceStarted(XDMApp.java:98)
	at xdman.monitoring.BrowserMonitor.run(BrowserMonitor.java:31)
	at java.lang.Thread.run(Thread.java:748)
[ Thread-1 ] Launch CMD: "D:\Program Files\Java\jdk1.8.0_171\jre\bin\javaw.exe" -jar "D:\src\xdman-code\out\production\classes" -m
[ Thread-1 ] java.lang.UnsatisfiedLinkError: Can't load library: D:\src\xdman-code\out\production\xdm_native.dll
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1827)
	at java.lang.Runtime.load0(Runtime.java:809)
	at java.lang.System.load(System.java:1086)
	at xdman.win32.NativeMethods.(NativeMethods.java:21)
	at xdman.win32.NativeMethods.getInstance(NativeMethods.java:13)
	at xdman.util.WinUtils.addToStartup(WinUtils.java:55)
	at xdman.util.XDMUtils.addToStartup(XDMUtils.java:328)
	at xdman.XDMApp.instanceStarted(XDMApp.java:99)
	at xdman.monitoring.BrowserMonitor.run(BrowserMonitor.java:31)
	at java.lang.Thread.run(Thread.java:748)
[ Thread-1 ] instance started.
New session
New session
java.io.FileNotFoundException: fonts\NotoSansUI-Bold.ttf (系统找不到指定的路径。)
	at java.io.FileInputStream.open0(Native Method)
	at java.io.FileInputStream.open(FileInputStream.java:195)
	at java.io.FileInputStream.(FileInputStream.java:138)
	at java.io.FileInputStream.(FileInputStream.java:93)
	at xdman.ui.res.FontResource.loadNoto(FontResource.java:14)
	at xdman.ui.res.FontResource.loadNotoBold(FontResource.java:39)
	at xdman.ui.res.FontResource.getBigBoldFont(FontResource.java:73)
	at xdman.ui.components.MainWindow.createTabs(MainWindow.java:630)
	at xdman.ui.components.MainWindow.initWindow(MainWindow.java:682)
	at xdman.ui.components.MainWindow.(MainWindow.java:93)
	at xdman.XDMApp.showMainWindow(XDMApp.java:140)
	at xdman.XDMApp$1.run(XDMApp.java:88)
	at java.awt.event.InvocationEvent.dispatch$$$capture(InvocationEvent.java:311)
	at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
	at java.awt.EventQueue.access$500(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:709)
	at java.awt.EventQueue$3.run(EventQueue.java:703)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:80)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:205)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
[ AWT-EventQueue-0 ] Noto regular font could not be loaded
[ AWT-EventQueue-0 ] List changed
current component version: null
Stat: -1
[ Thread-5 ] java.io.IOException: Unexpected EOF while reading header line
	at xdman.util.NetUtils.readLine(NetUtils.java:18)
	at xdman.monitoring.Request.read(Request.java:16)
	at xdman.monitoring.MonitoringSession.serviceRequest(MonitoringSession.java:231)
	at xdman.monitoring.MonitoringSession.run(MonitoringSession.java:260)
	at java.lang.Thread.run(Thread.java:748)

大致就是这个样子
IDM看不到源码毕竟是卖钱的,所以就只能瞎猜了。
IDM功能还是很强的,就是界面丑了点,唉

你可能感兴趣的:(小结)