| // Copyright 2011 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| var pass = chrome.test.callbackPass; |
| var fail = chrome.test.callbackFail; |
| |
| var tabId; |
| var debuggee; |
| var protocolVersion = "1.3"; |
| var protocolPreviousVersion = "1.2"; |
| var unsupportedMinorProtocolVersion = "1.5"; |
| var unsupportedMajorProtocolVersion = "100.0"; |
| |
| var DETACHED_WHILE_HANDLING = "Detached while handling command."; |
| |
| let openTab; |
| |
| chrome.test.getConfig(config => chrome.test.runTests([ |
| |
| function attachMalformedVersion() { |
| chrome.tabs.query({active: true}, function(tabs) { |
| chrome.debugger.attach({tabId: tabs[0].id}, "malformed-version", fail( |
| "Requested protocol version is not supported: malformed-version.")); |
| }); |
| }, |
| |
| function attachUnsupportedMinorVersion() { |
| chrome.tabs.query({active: true}, function(tabs) { |
| chrome.debugger.attach({tabId: tabs[0].id}, |
| unsupportedMinorProtocolVersion, |
| fail("Requested protocol version is not supported: " + |
| unsupportedMinorProtocolVersion + ".")); |
| }); |
| }, |
| |
| function attachUnsupportedVersion() { |
| chrome.tabs.query({active: true}, function(tabs) { |
| chrome.debugger.attach({tabId: tabs[0].id}, |
| unsupportedMajorProtocolVersion, |
| fail("Requested protocol version is not supported: " + |
| unsupportedMajorProtocolVersion + ".")); |
| }); |
| }, |
| |
| function attachPreviousVersion() { |
| chrome.tabs.query({active: true}, function(tabs) { |
| debuggee = {tabId: tabs[0].id}; |
| chrome.debugger.attach(debuggee, protocolPreviousVersion, function() { |
| chrome.debugger.detach(debuggee, pass()); |
| }); |
| }); |
| }, |
| |
| function attachLatestVersion() { |
| chrome.tabs.query({active: true}, function(tabs) { |
| tabId = tabs[0].id; |
| debuggee = {tabId: tabId}; |
| chrome.debugger.attach(debuggee, protocolVersion, pass()); |
| }); |
| }, |
| |
| function attachAgain() { |
| chrome.debugger.attach(debuggee, protocolVersion, |
| fail("Another debugger is already attached to the tab with id: " + |
| tabId + ".")); |
| }, |
| |
| function sendCommand() { |
| function onResponse() { |
| if (chrome.runtime.lastError && |
| chrome.runtime.lastError.message.indexOf("invalidMethod") != -1) |
| chrome.test.succeed(); |
| else |
| chrome.test.fail(); |
| } |
| chrome.debugger.sendCommand(debuggee, |
| "DOM.invalidMethod", |
| null, |
| onResponse); |
| }, |
| |
| function detach() { |
| chrome.debugger.detach(debuggee, pass()); |
| }, |
| |
| function sendCommandAfterDetach() { |
| chrome.debugger.sendCommand(debuggee, "Foo", null, |
| fail("Debugger is not attached to the tab with id: " + tabId + ".")); |
| }, |
| |
| function detachAgain() { |
| chrome.debugger.detach(debuggee, |
| fail("Debugger is not attached to the tab with id: " + tabId + ".")); |
| }, |
| |
| async function closeTab() { |
| ({openTab} = await import('/_test_resources/test_util/tabs_util.js')); |
| const tab = await openTab(chrome.runtime.getURL('inspected.html')); |
| function onDetach(debuggee, reason) { |
| chrome.test.assertEq(tab.id, debuggee.tabId); |
| chrome.test.assertEq("target_closed", reason); |
| chrome.debugger.onDetach.removeListener(onDetach); |
| chrome.test.succeed(); |
| } |
| |
| const debuggee2 = {tabId: tab.id}; |
| chrome.debugger.attach(debuggee2, protocolVersion, function() { |
| chrome.debugger.onDetach.addListener(onDetach); |
| chrome.tabs.remove(tab.id); |
| }); |
| }, |
| |
| async function closeTarget() { |
| const tab = await openTab(chrome.runtime.getURL('inspected.html')); |
| |
| let onDetachReceived = false; |
| let tabRemovedReceived = false; |
| |
| function checkFinish() { |
| if (onDetachReceived && tabRemovedReceived) |
| chrome.test.succeed(); |
| } |
| |
| function onDetach(debuggee, reason) { |
| chrome.test.assertEq(tab.id, debuggee.tabId); |
| chrome.test.assertEq("target_closed", reason); |
| chrome.debugger.onDetach.removeListener(onDetach); |
| onDetachReceived = true; |
| checkFinish(); |
| } |
| |
| function onTabRemoved(closedTabId) { |
| chrome.test.assertEq(tab.id, closedTabId); |
| chrome.tabs.onRemoved.removeListener(onTabRemoved); |
| tabRemovedReceived = true; |
| checkFinish(); |
| } |
| |
| const debuggee = {tabId: tab.id}; |
| chrome.debugger.attach(debuggee, protocolVersion, function() { |
| chrome.debugger.getTargets(function(targets) { |
| const target = targets.find(t => t.tabId === tab.id); |
| chrome.test.assertTrue(!!target); |
| chrome.debugger.onDetach.addListener(onDetach); |
| chrome.tabs.onRemoved.addListener(onTabRemoved); |
| chrome.debugger.sendCommand(debuggee, "Target.closeTarget", |
| { targetId: target.id }, () => chrome.test.assertNoLastError()); |
| }); |
| }); |
| }, |
| |
| async function attachToWebUI() { |
| const tab = await openTab('chrome://version'); |
| const debuggee = {tabId: tab.id}; |
| chrome.debugger.attach(debuggee, protocolVersion, |
| fail("Cannot access a chrome:// URL")); |
| chrome.tabs.remove(tab.id); |
| }, |
| |
| async function navigateToWebUI() { |
| const tab = await openTab(chrome.runtime.getURL('inspected.html')); |
| const debuggee = {tabId: tab.id}; |
| chrome.debugger.attach(debuggee, protocolVersion, function() { |
| var responded = false; |
| |
| function onResponse() { |
| chrome.test.assertLastError(DETACHED_WHILE_HANDLING); |
| responded = true; |
| } |
| |
| function onDetach(from, reason) { |
| chrome.debugger.onDetach.removeListener(onDetach); |
| chrome.debugger.attach( |
| debuggee, protocolVersion, fail('Cannot access a chrome:// URL')); |
| chrome.test.assertTrue(responded); |
| chrome.test.assertEq(debuggee.tabId, from.tabId); |
| chrome.test.assertEq("target_closed", reason); |
| chrome.tabs.remove(tab.id, pass()) |
| } |
| |
| chrome.test.assertNoLastError(); |
| chrome.debugger.onDetach.addListener(onDetach); |
| chrome.debugger.sendCommand( |
| debuggee, "Page.navigate", {url: "chrome://version"}, onResponse); |
| }); |
| }, |
| |
| async function detachDuringCommand() { |
| const tab = await openTab(chrome.runtime.getURL('inspected.html')); |
| const debuggee = {tabId: tab.id}; |
| chrome.debugger.attach(debuggee, protocolVersion, function() { |
| var responded = false; |
| |
| function onResponse() { |
| chrome.test.assertLastError(DETACHED_WHILE_HANDLING); |
| responded = true; |
| } |
| |
| function onDetach() { |
| chrome.debugger.onDetach.removeListener(onDetach); |
| chrome.test.assertTrue(responded); |
| chrome.tabs.remove(tab.id, function() { |
| chrome.test.assertNoLastError(); |
| chrome.test.succeed(); |
| }); |
| } |
| |
| chrome.test.assertNoLastError(); |
| chrome.debugger.sendCommand(debuggee, "command", null, onResponse); |
| chrome.debugger.detach(debuggee, onDetach); |
| }); |
| }, |
| |
| function attachToMissing() { |
| var missingDebuggee = {tabId: -1}; |
| chrome.debugger.attach(missingDebuggee, protocolVersion, |
| fail("No tab with given id " + missingDebuggee.tabId + ".")); |
| }, |
| |
| function attachToOwnBackgroundPageWithNoSilentFlag() { |
| var ownExtensionId = chrome.runtime.getURL('').split('/')[2]; |
| debuggee = {extensionId: ownExtensionId}; |
| chrome.debugger.attach(debuggee, protocolVersion, pass()); |
| }, |
| |
| function discoverOwnBackgroundPageWithNoSilentFlag() { |
| chrome.debugger.getTargets(function(targets) { |
| var target = targets.filter( |
| function(target) { return target.type == 'background_page'})[0]; |
| if (target) { |
| chrome.debugger.attach({targetId: target.id}, protocolVersion, fail( |
| "Another debugger is already attached to the target with id: " + |
| target.id + ".")); |
| } else { |
| chrome.test.succeed(); |
| } |
| }); |
| }, |
| |
| function detachFromOwnBackgroundPage() { |
| chrome.debugger.detach(debuggee, pass()); |
| }, |
| |
| async function createAndDiscoverTab() { |
| const tab = await openTab(chrome.runtime.getURL('inspected.html')); |
| chrome.debugger.getTargets(function(targets) { |
| var page = targets.filter( |
| function(t) { |
| return t.type == 'page' && |
| t.tabId == tab.id && |
| t.title == 'Test page'; |
| })[0]; |
| if (page) { |
| chrome.debugger.attach( |
| {targetId: page.id}, protocolVersion, pass()); |
| } else { |
| chrome.test.fail("Cannot discover a newly created tab"); |
| } |
| }); |
| }, |
| |
| function discoverWorker() { |
| var workerPort = new SharedWorker("worker.js").port; |
| workerPort.onmessage = function() { |
| chrome.debugger.getTargets(function(targets) { |
| var page = targets.filter( |
| function(t) { return t.type == 'worker' })[0]; |
| if (page) { |
| debuggee = {targetId: page.id}; |
| chrome.debugger.attach(debuggee, protocolVersion, pass()); |
| } else { |
| chrome.test.fail("Cannot discover a newly created worker"); |
| } |
| }); |
| }; |
| workerPort.start(); |
| }, |
| |
| function detachFromWorker() { |
| chrome.debugger.detach(debuggee, pass()); |
| }, |
| |
| async function sendCommandDuringNavigation() { |
| const tab = await openTab(chrome.runtime.getURL('inspected.html')); |
| const debuggee = {tabId: tab.id}; |
| |
| function checkError() { |
| if (chrome.runtime.lastError) { |
| chrome.test.fail(chrome.runtime.lastError.message); |
| } else { |
| chrome.tabs.remove(tab.id); |
| chrome.test.succeed(); |
| } |
| } |
| |
| function onNavigateDone() { |
| chrome.debugger.sendCommand(debuggee, "Page.disable", null, checkError); |
| } |
| |
| function onAttach() { |
| chrome.debugger.sendCommand(debuggee, "Page.enable"); |
| chrome.debugger.sendCommand( |
| debuggee, "Page.navigate", {url:"about:blank"}, onNavigateDone); |
| } |
| |
| chrome.debugger.attach(debuggee, protocolVersion, onAttach); |
| }, |
| |
| async function sendCommandToDataUri() { |
| const tab = await openTab('data:text/html,<h1>hi</h1>'); |
| const debuggee = {tabId: tab.id}; |
| |
| function checkError() { |
| if (chrome.runtime.lastError) { |
| chrome.test.fail(chrome.runtime.lastError.message); |
| } else { |
| chrome.tabs.remove(tab.id); |
| chrome.test.succeed(); |
| } |
| } |
| |
| function onAttach() { |
| chrome.debugger.sendCommand(debuggee, "Page.enable", null, checkError); |
| } |
| |
| chrome.debugger.attach(debuggee, protocolVersion, onAttach); |
| }, |
| |
| // http://crbug.com/824174 |
| async function getResponseBodyInvalidChar() { |
| let requestId; |
| |
| function onEvent(debuggeeId, message, params) { |
| if (message === 'Network.responseReceived' && |
| params.response.url.endsWith('invalid_char.html')) { |
| requestId = params.requestId; |
| } else if (message === 'Network.loadingFinished' && |
| params.requestId === requestId) { |
| chrome.debugger.sendCommand( |
| debuggeeId, 'Network.getResponseBody', |
| {requestId: params.requestId}, function(responseBody) { |
| chrome.debugger.onEvent.removeListener(onEvent); |
| chrome.debugger.detach(debuggeeId); |
| chrome.test.succeed(); |
| }); |
| } |
| } |
| |
| chrome.debugger.onEvent.addListener(onEvent); |
| const tab = await openTab(chrome.runtime.getURL('inspected.html')); |
| const debuggee = {tabId: tab.id}; |
| chrome.debugger.attach(debuggee, protocolVersion, function() { |
| chrome.debugger.sendCommand( |
| debuggee, 'Network.enable', null, function() { |
| chrome.debugger.sendCommand( |
| debuggee, 'Page.enable', null, function() { |
| // Navigate to a new page after attaching so we don't miss |
| // any protocol events that we might have missed while |
| // attaching to the first page. |
| chrome.debugger.sendCommand( |
| debuggee, 'Page.navigate', |
| {url: window.location.origin + '/fetch.html'}); |
| }); |
| }); |
| }); |
| }, |
| |
| /* TODO(crbug.com/40904113): This test is flaky. |
| async function offlineErrorPage() { |
| const url = 'http://127.0.0.1//extensions/api_test/debugger/inspected.html'; |
| const tab = await openTab(url); |
| const debuggee = {tabId: tab.id}; |
| var finished = false; |
| var failure = ''; |
| var expectingFrameNavigated = false; |
| |
| function finishIfError() { |
| if (chrome.runtime.lastError) { |
| failure = chrome.runtime.lastError.message; |
| finish(true); |
| return true; |
| } |
| return false; |
| } |
| |
| function onAttach() { |
| chrome.debugger.sendCommand(debuggee, 'Network.enable', null, |
| finishIfError); |
| chrome.debugger.sendCommand(debuggee, 'Page.enable', null, |
| finishIfError); |
| var offlineParams = { offline: true, latency: 0, |
| downloadThroughput: 0, uploadThroughput: 0 }; |
| chrome.debugger.sendCommand(debuggee, |
| 'Network.emulateNetworkConditions', |
| offlineParams, onOffline); |
| } |
| |
| function onOffline() { |
| if (finishIfError()) |
| return; |
| expectingFrameNavigated = true; |
| chrome.debugger.sendCommand(debuggee, 'Page.reload', null, |
| finishIfError); |
| } |
| |
| function finish(detach) { |
| if (finished) |
| return; |
| finished = true; |
| chrome.debugger.onDetach.removeListener(onDetach); |
| chrome.debugger.onEvent.removeListener(onEvent); |
| if (detach) |
| chrome.debugger.detach(debuggee); |
| chrome.tabs.remove(tab.id, () => { |
| if (failure) |
| chrome.test.fail(failure); |
| else |
| chrome.test.succeed(); |
| }); |
| } |
| |
| function onDetach() { |
| failure = 'Detached before navigated to error page'; |
| finish(false); |
| } |
| |
| function onEvent(_, method, params) { |
| if (!expectingFrameNavigated || method !== 'Page.frameNavigated') |
| return; |
| |
| if (finishIfError()) |
| return; |
| |
| expectingFrameNavigated = false; |
| chrome.debugger.sendCommand( |
| debuggee, 'Page.navigate', {url: 'about:blank'}, onNavigateDone); |
| } |
| |
| function onNavigateDone() { |
| if (finishIfError()) |
| return; |
| finish(true); |
| } |
| |
| chrome.debugger.onDetach.addListener(onDetach); |
| chrome.debugger.onEvent.addListener(onEvent); |
| chrome.debugger.attach(debuggee, protocolVersion, onAttach); |
| }, |
| */ |
| |
| function autoAttachToOOPIF() { |
| if (!config.customArg) { |
| chrome.test.succeed(); |
| return; |
| } |
| |
| var urls = config.customArg.split(";"); |
| var mainFrameUrl = urls[0]; |
| var oopFrameUrl = urls[1]; |
| |
| chrome.tabs.query({url: "http://*/*" + mainFrameUrl}, function(tabs) { |
| chrome.test.assertNoLastError(); |
| var debuggee = {tabId: tabs[0].id}; |
| var gotTarget = false; |
| |
| function onEvent(_, method, params) { |
| if (method === "Target.attachedToTarget") { |
| chrome.test.assertTrue( |
| params.targetInfo.url.indexOf(oopFrameUrl) !== -1); |
| gotTarget = true; |
| } |
| } |
| |
| function finish() { |
| chrome.test.assertNoLastError(); |
| chrome.test.assertTrue(gotTarget); |
| chrome.debugger.onEvent.removeListener(onEvent); |
| chrome.debugger.detach(debuggee, pass()); |
| } |
| |
| chrome.debugger.attach(debuggee, protocolVersion, () => { |
| chrome.test.assertNoLastError(); |
| chrome.debugger.onEvent.addListener(onEvent); |
| chrome.debugger.sendCommand(debuggee, "Target.setAutoAttach", |
| {autoAttach: true, waitForDebuggerOnStart: false}, finish); |
| }); |
| }); |
| }, |
| |
| async function detachFromOOPIFAllowed() { |
| if (!config.customArg) { |
| chrome.test.succeed(); |
| return; |
| } |
| |
| const urls = config.customArg.split(";"); |
| const mainFrameUrl = urls[0]; |
| const oopFrameUrl = urls[1]; |
| |
| chrome.tabs.query({url: "http://*/*" + mainFrameUrl}, function(tabs) { |
| chrome.test.assertNoLastError(); |
| const debuggee = {tabId: tabs[0].id}; |
| |
| function onEvent(_, method, params) { |
| if (method === "Target.attachedToTarget") { |
| chrome.test.assertTrue( |
| params.targetInfo.url.indexOf(oopFrameUrl) !== -1); |
| |
| chrome.debugger.sendCommand( |
| debuggee, |
| "Target.detachFromTarget", { sessionId: params.sessionId}, |
| function(response) { |
| // Extension should be allowed to detach from |
| // auto-attached targets. |
| chrome.test.assertNoLastError(); |
| chrome.test.assertEq({}, response); |
| finish(); |
| }); |
| } |
| } |
| |
| function finish() { |
| chrome.test.assertNoLastError(); |
| chrome.debugger.onEvent.removeListener(onEvent); |
| chrome.debugger.detach(debuggee, pass()); |
| } |
| |
| chrome.debugger.attach(debuggee, protocolVersion, () => { |
| chrome.test.assertNoLastError(); |
| chrome.debugger.onEvent.addListener(onEvent); |
| chrome.debugger.sendCommand(debuggee, "Target.setAutoAttach", |
| {autoAttach: true, waitForDebuggerOnStart: false}); |
| }); |
| }); |
| } |
| |
| ])); |