| Index: chrome/test/data/extensions/api_test/executescript/frame_id/test.js
|
| diff --git a/chrome/test/data/extensions/api_test/executescript/frame_id/test.js b/chrome/test/data/extensions/api_test/executescript/frame_id/test.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..cfd38c71bbfab4ae8d8b8e24e27cd8800440bef8
|
| --- /dev/null
|
| +++ b/chrome/test/data/extensions/api_test/executescript/frame_id/test.js
|
| @@ -0,0 +1,383 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// 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 assertEq = chrome.test.assertEq;
|
| +var assertTrue = chrome.test.assertTrue;
|
| +var relativePath = '/extensions/api_test/executescript/frame_id/frames.html';
|
| +var testOrigin = 'http://a.com:PORT';
|
| +var testUrl = 'http://a.com:PORT' + relativePath;
|
| +
|
| +var tabId;
|
| +
|
| +// Frame ID of every frame in this test, and the patterns of the frame URLs.
|
| +// Frame IDs are lazily initialized (and constant thereafter).
|
| +// All patterns are mutually exclusive.
|
| +
|
| +// Main frame.
|
| +var ID_FRAME_TOP = 0;
|
| +var R_FRAME_TOP = /frames\.html/;
|
| +// Frame with (same-origin) about:srcdoc.
|
| +var ID_FRAME_SRCDOC;
|
| +var R_FRAME_SRCDOC = /about:srcdoc/;
|
| +// Frame with (unique-origin) sandboxed about:blank.
|
| +var ID_FRAME_UNREACHABLE;
|
| +var R_FRAME_UNREACHABLE = /about:blank/;
|
| +// Frame with same-origin page.
|
| +var ID_FRAME_SECOND;
|
| +var R_FRAME_SECOND = /frame\.html/;
|
| +// Same-origin child frame of |frame_second|.
|
| +var ID_FRAME_THIRD;
|
| +var R_FRAME_THIRD = /nested\.html/;
|
| +// Frame for which the extension does not have the right permissions.
|
| +var ID_FRAME_NOPERMISSION;
|
| +var R_FRAME_NOPERMISSION = /empty\.html/;
|
| +
|
| +function matchesAny(urls, regex) {
|
| + return urls.some(function(url) { return regex.test(url); });
|
| +}
|
| +
|
| +var gCssCounter = 0;
|
| +
|
| +// Calls chrome.tabs.insertCSS and invokes the callback with a list of affected
|
| +// URLs. This function assumes that the tab identified by |tabId| exists, and
|
| +// that |injectDetails| is a valid argument for insertCSS.
|
| +function insertCSS(tabId, injectDetails, callback) {
|
| + var marker = (++gCssCounter) + 'px';
|
| + injectDetails.code = 'body { min-width: ' + marker + ';}';
|
| + chrome.tabs.insertCSS(tabId, injectDetails, function() {
|
| + chrome.test.assertNoLastError();
|
| + chrome.tabs.executeScript(
|
| + tabId, {
|
| + code: '[getComputedStyle(document.body).minWidth, document.URL];',
|
| + allFrames: true,
|
| + matchAboutBlank: true
|
| + },
|
| + function(results) {
|
| + chrome.test.assertNoLastError();
|
| + results = getAffectedUrls(results);
|
| + callback(results);
|
| + });
|
| + });
|
| +
|
| + // Selects the results from the frames whose CSS was changed by the insertCSS
|
| + // call, and returns the URLs of these frames.
|
| + function getAffectedUrls(results) {
|
| + return results.filter(function(result) {
|
| + return result && result[0] === marker;
|
| + }).map(function(result) {
|
| + return result[1]; // "document.URL"
|
| + });
|
| + }
|
| +}
|
| +
|
| +chrome.test.getConfig(function(config) {
|
| + testOrigin = testOrigin.replace(/PORT/, config.testServer.port);
|
| + testUrl = testUrl.replace(/PORT/, config.testServer.port);
|
| + chrome.tabs.onUpdated.addListener(function(_, changeInfo, tab) {
|
| + if (changeInfo.status != 'complete' || tab.id !== tabId) {
|
| + return;
|
| + }
|
| +
|
| + chrome.webNavigation.getAllFrames({tabId: tabId}, function(frames) {
|
| + function getFrameId(urlRegex) {
|
| + var filtered =
|
| + frames.filter(function(frame) { return urlRegex.test(frame.url); });
|
| + // Sanity check.
|
| + chrome.test.assertEq(1, filtered.length);
|
| + chrome.test.assertTrue(filtered[0].frameId > 0);
|
| + return filtered[0].frameId;
|
| + }
|
| +
|
| + ID_FRAME_SRCDOC = getFrameId(R_FRAME_SRCDOC);
|
| + ID_FRAME_UNREACHABLE = getFrameId(R_FRAME_UNREACHABLE);
|
| + ID_FRAME_SECOND = getFrameId(R_FRAME_SECOND);
|
| + ID_FRAME_THIRD = getFrameId(R_FRAME_THIRD);
|
| + ID_FRAME_NOPERMISSION = getFrameId(R_FRAME_NOPERMISSION);
|
| +
|
| + runTests(config);
|
| + });
|
| + });
|
| +
|
| + chrome.tabs.create({url: testUrl}, function(tab) { tabId = tab.id; });
|
| +});
|
| +
|
| +function runTests(config) {
|
| + // All of the following tests set the frameId parameter in the injection
|
| + // details.
|
| + chrome.test.runTests([
|
| + function executeScriptInTopFrame() {
|
| + chrome.tabs.executeScript(
|
| + tabId, {frameId: 0, code: 'document.URL'}, pass(function(results) {
|
| + assertEq(1, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_TOP));
|
| + }));
|
| + },
|
| +
|
| + function executeScriptInTopFrameIncludingAllFrames() {
|
| + chrome.tabs.executeScript(
|
| + tabId, {
|
| + frameId: 0,
|
| + matchAboutBlank: true,
|
| + allFrames: true,
|
| + code: 'document.URL'
|
| + },
|
| + pass(function(results) {
|
| + assertEq(4, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_TOP));
|
| + assertTrue(matchesAny(results, R_FRAME_SRCDOC));
|
| + assertTrue(matchesAny(results, R_FRAME_SECOND));
|
| + assertTrue(matchesAny(results, R_FRAME_THIRD));
|
| + }));
|
| + },
|
| +
|
| + function executeScriptInSrcdocFrame() {
|
| + chrome.tabs.executeScript(
|
| + tabId, {
|
| + frameId: ID_FRAME_SRCDOC,
|
| + matchAboutBlank: true,
|
| + code: 'document.URL'
|
| + },
|
| + pass(function(results) {
|
| + assertEq(1, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_SRCDOC));
|
| + }));
|
| + },
|
| +
|
| + function executeScriptInSrcdocFrameWithoutMatchAboutBlank() {
|
| + // TODO(robwu): Why is the origin serialized as "about:blank" instead of
|
| + // "about:srcdoc"?
|
| + chrome.tabs.executeScript(
|
| + tabId, {frameId: ID_FRAME_SRCDOC, code: 'document.URL'},
|
| + fail(
|
| + 'Cannot access "about:blank" at origin "' + testOrigin + '". ' +
|
| + 'Extension must have permission to access the frame\'s origin, ' +
|
| + 'and matchAboutBlank must be true.'));
|
| + },
|
| +
|
| + function executeScriptInSrcdocFrameIncludingAllFrames() {
|
| + chrome.tabs.executeScript(
|
| + tabId, {
|
| + frameId: ID_FRAME_SRCDOC,
|
| + matchAboutBlank: true,
|
| + allFrames: true,
|
| + code: 'document.URL'
|
| + },
|
| + pass(function(results) {
|
| + assertEq(1, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_SRCDOC));
|
| + }));
|
| + },
|
| +
|
| + function executeScriptInSandboxedFrame() {
|
| + chrome.tabs.executeScript(
|
| + tabId, {
|
| + frameId: ID_FRAME_UNREACHABLE,
|
| + matchAboutBlank: true,
|
| + code: 'document.URL'
|
| + },
|
| + fail(
|
| + 'Cannot access "about:blank" at origin "null". Extension must ' +
|
| + 'have permission to access the frame\'s origin, and ' +
|
| + 'matchAboutBlank must be true.'));
|
| + },
|
| +
|
| + function executeScriptInSubFrame() {
|
| + chrome.tabs.executeScript(
|
| + tabId, {frameId: ID_FRAME_SECOND, code: 'document.URL'},
|
| + pass(function(results) {
|
| + assertEq(1, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_SECOND));
|
| + }));
|
| + },
|
| +
|
| + function executeScriptInSubFrameIncludingAllFrames() {
|
| + chrome.tabs.executeScript(
|
| + tabId,
|
| + {frameId: ID_FRAME_SECOND, allFrames: true, code: 'document.URL'},
|
| + pass(function(results) {
|
| + assertEq(2, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_SECOND));
|
| + assertTrue(matchesAny(results, R_FRAME_THIRD));
|
| + }));
|
| + },
|
| +
|
| + function executeScriptInNestedFrame() {
|
| + chrome.tabs.executeScript(
|
| + tabId, {frameId: ID_FRAME_THIRD, code: 'document.URL'},
|
| + pass(function(results) {
|
| + assertEq(1, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_THIRD));
|
| + }));
|
| + },
|
| +
|
| + function executeScriptInNestedFrameIncludingAllFrames() {
|
| + chrome.tabs.executeScript(
|
| + tabId,
|
| + {frameId: ID_FRAME_THIRD, allFrames: true, code: 'document.URL'},
|
| + pass(function(results) {
|
| + assertEq(1, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_THIRD));
|
| + }));
|
| + },
|
| +
|
| + function executeScriptInFrameWithoutPermission() {
|
| + chrome.tabs.executeScript(
|
| + tabId, {frameId: ID_FRAME_NOPERMISSION, code: 'document.URL'},
|
| + fail(
|
| + 'Cannot access contents of url "http://c.com:' +
|
| + config.testServer.port + '/empty.html". Extension manifest ' +
|
| + 'must request permission to access this host.'));
|
| + },
|
| +
|
| + function executeScriptWithNonExistentFrameId() {
|
| + chrome.tabs.executeScript(
|
| + tabId, {frameId: 999999999, code: 'document.URL'},
|
| + fail('No frame with id 999999999 in tab ' + tabId + '.'));
|
| + },
|
| +
|
| + function executeScriptWithNegativeFrameId() {
|
| + try {
|
| + chrome.tabs.executeScript(
|
| + tabId, {frameId: -1, code: 'document.URL'}, function() {
|
| + chrome.test.fail(
|
| + 'executeScript should never have been executed!');
|
| + });
|
| + } catch (e) {
|
| + assertEq(
|
| + 'Invalid value for argument 2. Property \'frameId\': ' +
|
| + 'Value must not be less than 0.',
|
| + e.message);
|
| + chrome.test.succeed();
|
| + }
|
| + },
|
| +
|
| + function insertCSSInTopFrame() {
|
| + insertCSS(tabId, {frameId: 0}, pass(function(results) {
|
| + assertEq(1, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_TOP));
|
| + }));
|
| + },
|
| +
|
| + function insertCSSInTopFrameIncludingAllFrames() {
|
| + insertCSS(
|
| + tabId, {frameId: 0, matchAboutBlank: true, allFrames: true},
|
| + pass(function(results) {
|
| + assertEq(4, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_TOP));
|
| + assertTrue(matchesAny(results, R_FRAME_SRCDOC));
|
| + assertTrue(matchesAny(results, R_FRAME_SECOND));
|
| + assertTrue(matchesAny(results, R_FRAME_THIRD));
|
| + }));
|
| + },
|
| +
|
| + function insertCSSInSrcdocFrame() {
|
| + insertCSS(
|
| + tabId, {frameId: ID_FRAME_SRCDOC, matchAboutBlank: true},
|
| + pass(function(results) {
|
| + assertEq(1, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_SRCDOC));
|
| + }));
|
| + },
|
| +
|
| + function insertCSSInSrcdocFrameWithoutMatchAboutBlank() {
|
| + // TODO(robwu): Why is the origin serialized as "about:blank" instead of
|
| + // "about:srcdoc"?
|
| + chrome.tabs.insertCSS(
|
| + tabId, {frameId: ID_FRAME_SRCDOC, code: 'body{color:red;}'},
|
| + fail(
|
| + 'Cannot access "about:blank" at origin "' + testOrigin + '". ' +
|
| + 'Extension must have permission to access the frame\'s origin, ' +
|
| + 'and matchAboutBlank must be true.'));
|
| + },
|
| +
|
| + function insertCSSInSrcdocFrameIncludingAllFrames() {
|
| + insertCSS(
|
| + tabId,
|
| + {frameId: ID_FRAME_SRCDOC, matchAboutBlank: true, allFrames: true},
|
| + pass(function(results) {
|
| + assertEq(1, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_SRCDOC));
|
| + }));
|
| + },
|
| +
|
| + function insertCSSInSandboxedFrame() {
|
| + chrome.tabs.insertCSS(
|
| + tabId, {
|
| + frameId: ID_FRAME_UNREACHABLE,
|
| + matchAboutBlank: true,
|
| + code: 'body{color:red}'
|
| + },
|
| + fail(
|
| + 'Cannot access "about:blank" at origin "null". Extension must ' +
|
| + 'have permission to access the frame\'s origin, and ' +
|
| + 'matchAboutBlank must be true.'));
|
| + },
|
| +
|
| + function insertCSSInSubFrame() {
|
| + insertCSS(tabId, {frameId: ID_FRAME_SECOND}, pass(function(results) {
|
| + assertEq(1, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_SECOND));
|
| + }));
|
| + },
|
| +
|
| + function insertCSSInSubFrameIncludingAllFrames() {
|
| + insertCSS(
|
| + tabId, {frameId: ID_FRAME_SECOND, allFrames: true},
|
| + pass(function(results) {
|
| + assertEq(2, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_SECOND));
|
| + assertTrue(matchesAny(results, R_FRAME_THIRD));
|
| + }));
|
| + },
|
| +
|
| + function insertCSSInNestedFrame() {
|
| + insertCSS(tabId, {frameId: ID_FRAME_THIRD}, pass(function(results) {
|
| + assertEq(1, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_THIRD));
|
| + }));
|
| + },
|
| +
|
| + function insertCSSInNestedFrameIncludingAllFrames() {
|
| + insertCSS(
|
| + tabId, {frameId: ID_FRAME_THIRD, allFrames: true},
|
| + pass(function(results) {
|
| + assertEq(1, results.length);
|
| + assertTrue(matchesAny(results, R_FRAME_THIRD));
|
| + }));
|
| + },
|
| +
|
| + function insertCSSInFrameWithoutPermission() {
|
| + chrome.tabs.insertCSS(
|
| + tabId, {frameId: ID_FRAME_NOPERMISSION, code: 'body{color:red}'},
|
| + fail(
|
| + 'Cannot access contents of url "http://c.com:' +
|
| + config.testServer.port + '/empty.html". Extension manifest ' +
|
| + 'must request permission to access this host.'));
|
| + },
|
| +
|
| + function insertCSSWithNonExistentFrameId() {
|
| + chrome.tabs.insertCSS(
|
| + tabId, {frameId: 999999999, code: 'body{color:red}'},
|
| + fail('No frame with id 999999999 in tab ' + tabId + '.'));
|
| + },
|
| +
|
| + function insertCSSWithNegativeFrameId() {
|
| + try {
|
| + chrome.tabs.insertCSS(
|
| + tabId, {frameId: -1, code: 'body{color:red}'}, function() {
|
| + chrome.test.fail('insertCSS should never have been executed!');
|
| + });
|
| + } catch (e) {
|
| + assertEq(
|
| + 'Invalid value for argument 2. Property \'frameId\': ' +
|
| + 'Value must not be less than 0.',
|
| + e.message);
|
| + chrome.test.succeed();
|
| + }
|
| + },
|
| +
|
| + ]);
|
| +}
|
|
|