Commit 6ac77aad authored by Devlin Cronin's avatar Devlin Cronin Committed by Commit Bot

[Extensions] Update debugger API checks to use committed URL

We should be using last committed URL for security checks, not visible
URL. This requires updating a number of the extension API tests in
order to wait for the tab to commit before attaching the debugger; also
take this as an opportunity to update a few with some async helpers
(like await, etc).

Bug: 237908
Change-Id: Ic9fcb010e4d029204d5d2e0b8e6bbbe76738bc1f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2327462Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Reviewed-by: default avatarNasko Oskov <nasko@chromium.org>
Commit-Queue: Devlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#794853}
parent 0e43f403
......@@ -416,12 +416,9 @@ bool DebuggerFunction::InitAgentHost(std::string* error) {
*debuggee_.tab_id, browser_context(), include_incognito_information(),
&web_contents);
if (result && web_contents) {
// TODO(rdevlin.cronin) This should definitely be GetLastCommittedURL().
GURL url = web_contents->GetVisibleURL();
if (!ExtensionCanAttachToURL(
*extension(), url, Profile::FromBrowserContext(browser_context()),
error)) {
*extension(), web_contents->GetLastCommittedURL(),
Profile::FromBrowserContext(browser_context()), error)) {
return false;
}
......
......@@ -2,49 +2,49 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
function createTestFunction(expected_message) {
return function(tab) {
function onDebuggerEvent(debuggee, method, params) {
if (debuggee.tabId == tab.id && method == 'Runtime.exceptionThrown') {
var exception = params.exceptionDetails.exception;
if (exception.value.indexOf(expected_message) > -1) {
chrome.debugger.onEvent.removeListener(onDebuggerEvent);
chrome.test.succeed();
}
function verifyException(expectedMessage, tabId) {
function onDebuggerEvent(debuggee, method, params) {
if (debuggee.tabId == tabId && method == 'Runtime.exceptionThrown') {
var exception = params.exceptionDetails.exception;
if (exception.value.indexOf(expectedMessage) > -1) {
chrome.debugger.onEvent.removeListener(onDebuggerEvent);
chrome.test.succeed();
}
};
chrome.debugger.onEvent.addListener(onDebuggerEvent);
chrome.debugger.attach({ tabId: tab.id }, "1.1", function() {
// Enabling console provides both stored and new messages via the
// Console.messageAdded event.
chrome.debugger.sendCommand({ tabId: tab.id }, "Runtime.enable");
});
}
}
};
chrome.debugger.onEvent.addListener(onDebuggerEvent);
chrome.debugger.attach({ tabId: tabId }, "1.1", function() {
// Enabling console provides both stored and new messages via the
// Console.messageAdded event.
chrome.debugger.sendCommand({ tabId: tabId }, "Runtime.enable");
});
}
let openTab;
chrome.test.runTests([
function testExceptionInExtensionPage() {
chrome.tabs.create(
{url: chrome.runtime.getURL('extension_page.html')},
createTestFunction('Exception thrown in extension page.'));
async function testExceptionInExtensionPage() {
({openTab} = await import('/_test_resources/test_util/tabs_util.js'));
const tab = await openTab(chrome.runtime.getURL('extension_page.html'));
verifyException('Exception thrown in extension page.', tab.id);
},
function testExceptionInInjectedScript() {
async function testExceptionInInjectedScript() {
function injectScriptAndSendMessage(tab) {
chrome.tabs.executeScript(
tab.id,
{ file: 'content_script.js' },
function() {
createTestFunction('Exception thrown in injected script.')(tab);
verifyException('Exception thrown in injected script.', tab.id);
});
}
chrome.test.getConfig(function(config) {
var test_url =
'http://localhost:PORT/extensions/test_file.html'
.replace(/PORT/, config.testServer.port);
chrome.tabs.create({ url: test_url }, injectScriptAndSendMessage);
chrome.test.getConfig(async function(config) {
const testUrl =
`http://localhost:${config.testServer.port}/` +
'extensions/test_file.html';
const tab = await openTab(testUrl);
injectScriptAndSendMessage(tab);
});
}
]);
......@@ -16,6 +16,8 @@ var SILENT_FLAG_REQUIRED = "Cannot attach to this target unless " +
"'silent-debugger-extension-api' flag is enabled.";
var DETACHED_WHILE_HANDLING = "Detached while handling command.";
let openTab;
chrome.test.getConfig(config => chrome.test.runTests([
function attachMalformedVersion() {
......@@ -92,86 +94,83 @@ chrome.test.getConfig(config => chrome.test.runTests([
fail("Debugger is not attached to the tab with id: " + tabId + "."));
},
function closeTab() {
chrome.tabs.create({url:"inspected.html"}, function(tab) {
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();
}
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();
}
var debuggee2 = {tabId: tab.id};
chrome.debugger.attach(debuggee2, protocolVersion, function() {
chrome.debugger.onDetach.addListener(onDetach);
chrome.tabs.remove(tab.id);
});
const debuggee2 = {tabId: tab.id};
chrome.debugger.attach(debuggee2, protocolVersion, function() {
chrome.debugger.onDetach.addListener(onDetach);
chrome.tabs.remove(tab.id);
});
},
function attachToWebUI() {
chrome.tabs.create({url:"chrome://version"}, function(tab) {
var debuggee = {tabId: tab.id};
chrome.debugger.attach(debuggee, protocolVersion,
fail("Cannot access a chrome:// URL"));
chrome.tabs.remove(tab.id);
});
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);
},
function navigateToWebUI() {
chrome.tabs.create({url:"inspected.html"}, function(tab) {
var debuggee = {tabId: tab.id};
chrome.debugger.attach(debuggee, protocolVersion, function() {
var responded = false;
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 onResponse() {
chrome.test.assertLastError(DETACHED_WHILE_HANDLING);
responded = true;
}
function onDetach(from, reason) {
chrome.debugger.onDetach.removeListener(onDetach);
chrome.test.assertTrue(responded);
chrome.test.assertEq(debuggee.tabId, from.tabId);
chrome.test.assertEq("target_closed", reason);
chrome.tabs.remove(tab.id, function() {
chrome.test.assertNoLastError();
chrome.test.succeed();
});
}
function onDetach(from, reason) {
chrome.debugger.onDetach.removeListener(onDetach);
chrome.test.assertTrue(responded);
chrome.test.assertEq(debuggee.tabId, from.tabId);
chrome.test.assertEq("target_closed", reason);
chrome.tabs.remove(tab.id, function() {
chrome.test.assertNoLastError();
chrome.test.succeed();
});
}
chrome.test.assertNoLastError();
chrome.debugger.onDetach.addListener(onDetach);
chrome.debugger.sendCommand(
debuggee, "Page.navigate", {url: "chrome://version"}, onResponse);
});
chrome.test.assertNoLastError();
chrome.debugger.onDetach.addListener(onDetach);
chrome.debugger.sendCommand(
debuggee, "Page.navigate", {url: "chrome://version"}, onResponse);
});
},
function detachDuringCommand() {
chrome.tabs.create({url:"inspected.html"}, function(tab) {
var debuggee = {tabId: tab.id};
chrome.debugger.attach(debuggee, protocolVersion, function() {
var responded = false;
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 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();
});
}
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);
});
chrome.test.assertNoLastError();
chrome.debugger.sendCommand(debuggee, "command", null, onResponse);
chrome.debugger.detach(debuggee, onDetach);
});
},
......@@ -205,28 +204,22 @@ chrome.test.getConfig(config => chrome.test.runTests([
chrome.debugger.detach(debuggee, pass());
},
function createAndDiscoverTab() {
function onUpdated(tabId, changeInfo) {
if (changeInfo.status == 'loading')
return;
chrome.tabs.onUpdated.removeListener(onUpdated);
chrome.debugger.getTargets(function(targets) {
var page = targets.filter(
function(t) {
return t.type == 'page' &&
t.tabId == tabId &&
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");
}
});
}
chrome.tabs.onUpdated.addListener(onUpdated);
chrome.tabs.create({url: "inspected.html"});
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() {
......@@ -250,56 +243,54 @@ chrome.test.getConfig(config => chrome.test.runTests([
chrome.debugger.detach(debuggee, pass());
},
function sendCommandDuringNavigation() {
chrome.tabs.create({url:"inspected.html"}, function(tab) {
var debuggee = {tabId: tab.id};
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 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 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);
}
function onAttach() {
chrome.debugger.sendCommand(debuggee, "Page.enable");
chrome.debugger.sendCommand(
debuggee, "Page.navigate", {url:"about:blank"}, onNavigateDone);
}
chrome.debugger.attach(debuggee, protocolVersion, onAttach);
});
chrome.debugger.attach(debuggee, protocolVersion, onAttach);
},
function sendCommandToDataUri() {
chrome.tabs.create({url:"data:text/html,<h1>hi</h1>"}, function(tab) {
var debuggee = {tabId: tab.id};
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 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);
}
function onAttach() {
chrome.debugger.sendCommand(debuggee, "Page.enable", null, checkError);
}
chrome.debugger.attach(debuggee, protocolVersion, onAttach);
});
chrome.debugger.attach(debuggee, protocolVersion, onAttach);
},
// http://crbug.com/824174
function getResponseBodyInvalidChar() {
async function getResponseBodyInvalidChar() {
let requestId;
function onEvent(debuggeeId, message, params) {
......@@ -319,105 +310,103 @@ chrome.test.getConfig(config => chrome.test.runTests([
}
chrome.debugger.onEvent.addListener(onEvent);
chrome.tabs.create({url: 'inspected.html'}, function(tab) {
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'});
});
});
});
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'});
});
});
});
},
function offlineErrorPage() {
async function offlineErrorPage() {
const url = 'http://127.0.0.1//extensions/api_test/debugger/inspected.html';
chrome.tabs.create({url: url}, function(tab) {
var 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;
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 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 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 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 onDetach() {
failure = 'Detached before navigated to error page';
finish(false);
}
function onEvent(_, method, params) {
if (!expectingFrameNavigated || method !== 'Page.frameNavigated')
return;
function onEvent(_, method, params) {
if (!expectingFrameNavigated || method !== 'Page.frameNavigated')
return;
if (finishIfError())
return;
if (finishIfError())
return;
expectingFrameNavigated = false;
chrome.debugger.sendCommand(
debuggee, 'Page.navigate', {url: 'about:blank'}, onNavigateDone);
}
expectingFrameNavigated = false;
chrome.debugger.sendCommand(
debuggee, 'Page.navigate', {url: 'about:blank'}, onNavigateDone);
}
function onNavigateDone() {
if (finishIfError())
return;
finish(true);
}
function onNavigateDone() {
if (finishIfError())
return;
finish(true);
}
chrome.debugger.onDetach.addListener(onDetach);
chrome.debugger.onEvent.addListener(onEvent);
chrome.debugger.attach(debuggee, protocolVersion, onAttach);
});
chrome.debugger.onDetach.addListener(onDetach);
chrome.debugger.onEvent.addListener(onEvent);
chrome.debugger.attach(debuggee, protocolVersion, onAttach);
},
function autoAttachToOOPIF() {
......
......@@ -10,13 +10,13 @@ var protocolVersion = "1.3";
chrome.test.runTests([
function attachToWebUI() {
chrome.tabs.create({url:"chrome://version"}, function(tab) {
var debuggee = {tabId: tab.id};
chrome.debugger.attach(debuggee, protocolVersion,
fail("Cannot attach to this target."));
chrome.tabs.remove(tab.id);
});
async function attachToWebUI() {
const {openTab} = await import('/_test_resources/test_util/tabs_util.js');
const tab = await openTab('chrome://version');
const debuggee = {tabId: tab.id};
chrome.debugger.attach(debuggee, protocolVersion,
fail("Cannot attach to this target."));
chrome.tabs.remove(tab.id);
},
function attach() {
......
......@@ -10,29 +10,30 @@ function checkUrlsEqual(expected, actual) {
new URL(actual).href);
}
function runNotAllowedTest(method, params, expectAllowed) {
let openTab;
async function runNotAllowedTest(method, params, expectAllowed) {
const NOT_ALLOWED = "Not allowed";
chrome.tabs.create({url: 'dummy.html'}, function(tab) {
var debuggee = {tabId: tab.id};
chrome.debugger.attach(debuggee, '1.2', function() {
chrome.test.assertNoLastError();
chrome.debugger.sendCommand(debuggee, method, params, onResponse);
const tab = await openTab(chrome.runtime.getURL('dummy.html'));
const debuggee = {tabId: tab.id};
chrome.debugger.attach(debuggee, '1.2', function() {
chrome.test.assertNoLastError();
chrome.debugger.sendCommand(debuggee, method, params, onResponse);
function onResponse() {
var message;
try {
message = JSON.parse(chrome.runtime.lastError.message).message;
} catch (e) {
}
chrome.debugger.detach(debuggee, () => {
const allowed = message !== NOT_ALLOWED;
if (allowed === expectAllowed)
chrome.test.succeed();
else
chrome.test.fail('' + message);
});
function onResponse() {
var message;
try {
message = JSON.parse(chrome.runtime.lastError.message).message;
} catch (e) {
}
});
chrome.debugger.detach(debuggee, () => {
const allowed = message !== NOT_ALLOWED;
if (allowed === expectAllowed)
chrome.test.succeed();
else
chrome.test.fail('' + message);
});
}
});
}
......@@ -42,7 +43,8 @@ function runNotAllowedTest(method, params, expectAllowed) {
});
const fileUrl = config.testDataDirectory + '/../body1.html';
const expectFileAccess = !!config.customArg;
const { openTab } = await import('/_test_resources/test_util/tabs_util.js');
({ openTab } = await import('/_test_resources/test_util/tabs_util.js'));
console.log(fileUrl);
......
......@@ -6,8 +6,8 @@ const protocolVersion = '1.3';
chrome.test.getConfig(config => chrome.test.runTests([
async function testInspectWorkerForbidden() {
const tab = await new Promise(resolve =>
chrome.tabs.create({url: config.customArg}, resolve));
const {openTab} = await import('/_test_resources/test_util/tabs_util.js');
const tab = await openTab(config.customArg);
const debuggee = {tabId: tab.id};
await new Promise(resolve =>
chrome.debugger.attach(debuggee, protocolVersion, resolve));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment