Revert "[Extensions UserScripts] Set execution world at register/update"
This reverts commiteea5a242cd
. Reason for revert: Tentatively reverting this as possible culprit for tree closure for: https://ci.chromium.org/ui/p/chromium/builders/ci/Deterministic%20Linux/43385/overview Bug:1491273
Original change's description: > [Extensions UserScripts] Set execution world at register/update > > Add support for setting the execution world when registering and > updating user scripts. > > Bug: 1385165 > Change-Id: Ic510cf29373de2d4db910183f852b2889c9004c2 > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4877753 > Reviewed-by: Devlin Cronin <rdevlin.cronin@chromium.org> > Reviewed-by: Kelvin Jiang <kelvinjiang@chromium.org> > Commit-Queue: Emilia Paz <emiliapaz@chromium.org> > Cr-Commit-Position: refs/heads/main@{#1207186} Bug: 1385165 Change-Id: I9a154d5a2974ac0456dab0a66211a22d751f5cdf No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4924351 Reviewed-by: Emilia Paz <emiliapaz@chromium.org> Auto-Submit: Kevin Grosu <kgrosu@google.com> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com> Commit-Queue: Kevin Grosu <kgrosu@google.com> Owners-Override: Kevin Grosu <kgrosu@google.com> Cr-Commit-Position: refs/heads/main@{#1207348}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
71ec640c8d
commit
f990f87b36
chrome/test/data/extensions/api_test/user_scripts
get_scripts
persistent_scripts
register
update
extensions
browser
api
user_scripts
common
third_party/closure_compiler/externs
@ -12,8 +12,7 @@ chrome.test.runTests([
|
|||||||
matches: ['*://*/*'],
|
matches: ['*://*/*'],
|
||||||
excludeMatches: ['*://abc.com/*'],
|
excludeMatches: ['*://abc.com/*'],
|
||||||
allFrames: true,
|
allFrames: true,
|
||||||
js: [{file: 'empty.js'}],
|
js: [{file: 'empty.js'}]
|
||||||
world: chrome.userScripts.ExecutionWorld.MAIN
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'script2',
|
id: 'script2',
|
||||||
@ -35,16 +34,14 @@ chrome.test.runTests([
|
|||||||
excludeMatches: ['*://abc.com/*'],
|
excludeMatches: ['*://abc.com/*'],
|
||||||
allFrames: true,
|
allFrames: true,
|
||||||
js: [{file: 'empty.js'}],
|
js: [{file: 'empty.js'}],
|
||||||
runAt: 'document_idle',
|
runAt: 'document_idle'
|
||||||
world: chrome.userScripts.ExecutionWorld.MAIN
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'script2',
|
id: 'script2',
|
||||||
matches: ['*://requested.com/*'],
|
matches: ['*://requested.com/*'],
|
||||||
js: [{file: 'empty2.js'}],
|
js: [{file: 'empty2.js'}],
|
||||||
allFrames: false,
|
allFrames: false,
|
||||||
runAt: 'document_end',
|
runAt: 'document_end'
|
||||||
world: chrome.userScripts.ExecutionWorld.USER_SCRIPT
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -107,8 +104,7 @@ chrome.test.runTests([
|
|||||||
matches: ['*://*/*'],
|
matches: ['*://*/*'],
|
||||||
allFrames: false,
|
allFrames: false,
|
||||||
js: [{file: 'empty.js'}],
|
js: [{file: 'empty.js'}],
|
||||||
runAt: 'document_idle',
|
runAt: 'document_idle'
|
||||||
world: chrome.userScripts.ExecutionWorld.USER_SCRIPT
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
await chrome.userScripts.register(scriptsToRegister);
|
await chrome.userScripts.register(scriptsToRegister);
|
||||||
|
@ -52,16 +52,14 @@ async function runSecondSession() {
|
|||||||
matches: ['*://*/*'],
|
matches: ['*://*/*'],
|
||||||
js: [{file: 'user_script.js'}],
|
js: [{file: 'user_script.js'}],
|
||||||
allFrames: false,
|
allFrames: false,
|
||||||
runAt: 'document_end',
|
runAt: 'document_end'
|
||||||
world: 'USER_SCRIPT'
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'us2',
|
id: 'us2',
|
||||||
matches: ['*://*/*'],
|
matches: ['*://*/*'],
|
||||||
js: [{file: 'user_script_2.js'}],
|
js: [{file: 'user_script_2.js'}],
|
||||||
allFrames: false,
|
allFrames: false,
|
||||||
runAt: 'document_end',
|
runAt: 'document_end'
|
||||||
world: 'USER_SCRIPT'
|
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
// Copyright 2023 The Chromium Authors
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
// Changes the document's title based on the existence/value of
|
|
||||||
// window.mainWorldFlag, which is set by a script that's part of a web page.
|
|
||||||
document.title = window.mainWorldFlag === 'from main world' ?
|
|
||||||
'MAIN_WORLD' :
|
|
||||||
'USER_SCRIPTS_WORLD';
|
|
@ -4,31 +4,6 @@
|
|||||||
|
|
||||||
import { openTab, getInjectedElementIds } from '/_test_resources/test_util/tabs_util.js';
|
import { openTab, getInjectedElementIds } from '/_test_resources/test_util/tabs_util.js';
|
||||||
|
|
||||||
// Inject a script which changes the page's title based on the execution world
|
|
||||||
// it's running on, then call executeScript which checks the title.
|
|
||||||
async function runExecutionWorldTest(world, expectedTitle) {
|
|
||||||
await chrome.userScripts.unregister();
|
|
||||||
|
|
||||||
const scripts = [{
|
|
||||||
id: 'us1',
|
|
||||||
matches: ['*://*/*'],
|
|
||||||
js: [{file: 'inject_to_world.js'}],
|
|
||||||
runAt: 'document_end',
|
|
||||||
world
|
|
||||||
}];
|
|
||||||
await chrome.userScripts.register(scripts);
|
|
||||||
const config = await chrome.test.getConfig();
|
|
||||||
|
|
||||||
// After the scripts has been registered, navigate to a url where they will be
|
|
||||||
// injected.
|
|
||||||
const url = `http://requested.com:${
|
|
||||||
config.testServer.port}/extensions/main_world_script_flag.html`;
|
|
||||||
const tab = await openTab(url);
|
|
||||||
chrome.test.assertEq(expectedTitle, tab.title);
|
|
||||||
|
|
||||||
chrome.test.succeed();
|
|
||||||
}
|
|
||||||
|
|
||||||
chrome.test.runTests([
|
chrome.test.runTests([
|
||||||
// Tests that an error is returned when multiple user script entries in
|
// Tests that an error is returned when multiple user script entries in
|
||||||
// userScripts.register share the same ID.
|
// userScripts.register share the same ID.
|
||||||
@ -338,12 +313,6 @@ chrome.test.runTests([
|
|||||||
chrome.test.succeed();
|
chrome.test.succeed();
|
||||||
},
|
},
|
||||||
|
|
||||||
async function registerFile_ExecutionWorld() {
|
|
||||||
runExecutionWorldTest(chrome.userScripts.ExecutionWorld.MAIN, 'MAIN_WORLD');
|
|
||||||
runExecutionWorldTest(
|
|
||||||
chrome.userScripts.ExecutionWorld.USER_SCRIPT, 'USER_SCRIPT_WORLD');
|
|
||||||
},
|
|
||||||
|
|
||||||
// Tests that a file can be used both as a user script and content script.
|
// Tests that a file can be used both as a user script and content script.
|
||||||
async function fileUsedAsContentScript() {
|
async function fileUsedAsContentScript() {
|
||||||
await chrome.userScripts.unregister();
|
await chrome.userScripts.unregister();
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
// Copyright 2023 The Chromium Authors
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
|
||||||
// found in the LICENSE file.
|
|
||||||
|
|
||||||
// Changes the document's title based on the existence/value of
|
|
||||||
// window.mainWorldFlag, which is set by a script that's part of a web page.
|
|
||||||
document.title = window.mainWorldFlag === 'from main world' ?
|
|
||||||
'MAIN_WORLD' :
|
|
||||||
'USER_SCRIPT_WORLD';
|
|
@ -67,8 +67,7 @@ chrome.test.runTests([
|
|||||||
matches: ['*://*/*'],
|
matches: ['*://*/*'],
|
||||||
js: [{file: 'user_script.js'}],
|
js: [{file: 'user_script.js'}],
|
||||||
runAt: 'document_idle',
|
runAt: 'document_idle',
|
||||||
allFrames: false,
|
allFrames: false
|
||||||
world: 'USER_SCRIPT'
|
|
||||||
}];
|
}];
|
||||||
const registeredScripts = await chrome.userScripts.getScripts();
|
const registeredScripts = await chrome.userScripts.getScripts();
|
||||||
chrome.test.assertEq(expectedScripts, registeredScripts);
|
chrome.test.assertEq(expectedScripts, registeredScripts);
|
||||||
@ -112,8 +111,7 @@ chrome.test.runTests([
|
|||||||
matches: ['*://*/*'],
|
matches: ['*://*/*'],
|
||||||
js: [{file: 'user_script.js'}],
|
js: [{file: 'user_script.js'}],
|
||||||
runAt: 'document_idle',
|
runAt: 'document_idle',
|
||||||
allFrames: false,
|
allFrames: false
|
||||||
world: 'USER_SCRIPT'
|
|
||||||
}];
|
}];
|
||||||
const registeredScripts = await chrome.userScripts.getScripts();
|
const registeredScripts = await chrome.userScripts.getScripts();
|
||||||
chrome.test.assertEq(expectedScripts, registeredScripts);
|
chrome.test.assertEq(expectedScripts, registeredScripts);
|
||||||
@ -216,8 +214,7 @@ chrome.test.runTests([
|
|||||||
excludeMatches: ['*://def.com/*'],
|
excludeMatches: ['*://def.com/*'],
|
||||||
js: [{file: 'user_script_2.js'}],
|
js: [{file: 'user_script_2.js'}],
|
||||||
runAt: 'document_end',
|
runAt: 'document_end',
|
||||||
allFrames: false,
|
allFrames: false
|
||||||
world: 'USER_SCRIPT'
|
|
||||||
}];
|
}];
|
||||||
registeredScripts = await chrome.userScripts.getScripts();
|
registeredScripts = await chrome.userScripts.getScripts();
|
||||||
chrome.test.assertEq(expectedScripts, registeredScripts);
|
chrome.test.assertEq(expectedScripts, registeredScripts);
|
||||||
@ -237,56 +234,6 @@ chrome.test.runTests([
|
|||||||
chrome.test.succeed();
|
chrome.test.succeed();
|
||||||
},
|
},
|
||||||
|
|
||||||
// Tests that calling userScripts.update with a specific ID updates such
|
|
||||||
// script and injects the script in the corresponding world.
|
|
||||||
async function scriptUpdated_World() {
|
|
||||||
await chrome.userScripts.unregister();
|
|
||||||
|
|
||||||
// Register user script with a file that changes the document title based on
|
|
||||||
// its execution world.
|
|
||||||
const scriptsToRegister = [{
|
|
||||||
id: 'us1',
|
|
||||||
matches: ['*://hostperms-a.com/*'],
|
|
||||||
js: [{file: 'inject_to_world.js'}],
|
|
||||||
world: 'MAIN'
|
|
||||||
}];
|
|
||||||
await chrome.userScripts.register(scriptsToRegister);
|
|
||||||
|
|
||||||
// Verify user script was registered.
|
|
||||||
let registeredScripts = await chrome.userScripts.getScripts();
|
|
||||||
chrome.test.assertEq(1, registeredScripts.length);
|
|
||||||
|
|
||||||
// Verify script file is injected in the main world.
|
|
||||||
const config = await chrome.test.getConfig();
|
|
||||||
const url = `http://hostperms-a.com:${
|
|
||||||
config.testServer.port}/extensions/main_world_script_flag.html`;
|
|
||||||
let tab = await openTab(url);
|
|
||||||
chrome.test.assertEq('MAIN_WORLD', tab.title);
|
|
||||||
|
|
||||||
// Update user script world.
|
|
||||||
var scriptsToUpdate =
|
|
||||||
[{id: 'us1', js: [{file: 'inject_to_world.js'}], world: 'USER_SCRIPT'}];
|
|
||||||
await chrome.userScripts.update(scriptsToUpdate);
|
|
||||||
|
|
||||||
// Verify user script was updated.
|
|
||||||
const expectedScripts = [{
|
|
||||||
id: 'us1',
|
|
||||||
matches: ['*://hostperms-a.com/*'],
|
|
||||||
js: [{file: 'inject_to_world.js'}],
|
|
||||||
runAt: 'document_idle',
|
|
||||||
allFrames: false,
|
|
||||||
world: 'USER_SCRIPT'
|
|
||||||
}];
|
|
||||||
registeredScripts = await chrome.userScripts.getScripts();
|
|
||||||
chrome.test.assertEq(expectedScripts, registeredScripts);
|
|
||||||
|
|
||||||
// Verify script file is injected in the user script world.
|
|
||||||
tab = await openTab(url);
|
|
||||||
chrome.test.assertEq('USER_SCRIPT_WORLD', tab.title);
|
|
||||||
|
|
||||||
chrome.test.succeed();
|
|
||||||
},
|
|
||||||
|
|
||||||
// Test that if two userScript.update calls are made in quick succession,
|
// Test that if two userScript.update calls are made in quick succession,
|
||||||
// then both calls should succeed in updating their scripts and the old
|
// then both calls should succeed in updating their scripts and the old
|
||||||
// version of these scripts are overwritten.
|
// version of these scripts are overwritten.
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/functional/bind.h"
|
#include "base/functional/bind.h"
|
||||||
#include "base/notreached.h"
|
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
||||||
#include "base/types/optional_util.h"
|
#include "base/types/optional_util.h"
|
||||||
#include "extensions/browser/api/scripting/scripting_constants.h"
|
#include "extensions/browser/api/scripting/scripting_constants.h"
|
||||||
@ -18,7 +17,6 @@
|
|||||||
#include "extensions/browser/user_script_manager.h"
|
#include "extensions/browser/user_script_manager.h"
|
||||||
#include "extensions/common/api/extension_types.h"
|
#include "extensions/common/api/extension_types.h"
|
||||||
#include "extensions/common/api/user_scripts.h"
|
#include "extensions/common/api/user_scripts.h"
|
||||||
#include "extensions/common/mojom/execution_world.mojom-shared.h"
|
|
||||||
#include "extensions/common/user_script.h"
|
#include "extensions/common/user_script.h"
|
||||||
#include "extensions/common/utils/content_script_utils.h"
|
#include "extensions/common/utils/content_script_utils.h"
|
||||||
#include "extensions/common/utils/extension_types_utils.h"
|
#include "extensions/common/utils/extension_types_utils.h"
|
||||||
@ -35,30 +33,6 @@ constexpr char kInvalidSourceError[] =
|
|||||||
constexpr char kMatchesMissingError[] =
|
constexpr char kMatchesMissingError[] =
|
||||||
"User script with ID '*' must specify 'matches'.";
|
"User script with ID '*' must specify 'matches'.";
|
||||||
|
|
||||||
mojom::ExecutionWorld ConvertExecutionWorld(
|
|
||||||
api::user_scripts::ExecutionWorld world) {
|
|
||||||
switch (world) {
|
|
||||||
// Execution world defaults to `kUserScript` when it's not provided.
|
|
||||||
case api::user_scripts::EXECUTION_WORLD_NONE:
|
|
||||||
case api::user_scripts::EXECUTION_WORLD_USER_SCRIPT:
|
|
||||||
return mojom::ExecutionWorld::kUserScript;
|
|
||||||
case api::user_scripts::EXECUTION_WORLD_MAIN:
|
|
||||||
return mojom::ExecutionWorld::kMain;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
api::user_scripts::ExecutionWorld ConvertExecutionWorldForAPI(
|
|
||||||
mojom::ExecutionWorld world) {
|
|
||||||
switch (world) {
|
|
||||||
case mojom::ExecutionWorld::kUserScript:
|
|
||||||
return api::user_scripts::EXECUTION_WORLD_USER_SCRIPT;
|
|
||||||
case mojom::ExecutionWorld::kMain:
|
|
||||||
return api::user_scripts::EXECUTION_WORLD_MAIN;
|
|
||||||
case mojom::ExecutionWorld::kIsolated:
|
|
||||||
NOTREACHED_NORETURN() << "ISOLATED worlds are not supported in this API.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<UserScript> ParseUserScript(
|
std::unique_ptr<UserScript> ParseUserScript(
|
||||||
const Extension& extension,
|
const Extension& extension,
|
||||||
const api::user_scripts::RegisteredUserScript& user_script,
|
const api::user_scripts::RegisteredUserScript& user_script,
|
||||||
@ -124,8 +98,6 @@ std::unique_ptr<UserScript> ParseUserScript(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result->set_execution_world(ConvertExecutionWorld(user_script.world));
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,8 +137,6 @@ api::user_scripts::RegisteredUserScript CreateRegisteredUserScriptInfo(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
script_info.world = ConvertExecutionWorldForAPI(script.execution_world());
|
|
||||||
|
|
||||||
return script_info;
|
return script_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -432,10 +402,6 @@ std::unique_ptr<UserScript> UserScriptsUpdateFunction::ApplyUpdate(
|
|||||||
original_script.js = std::move(new_script.js);
|
original_script.js = std::move(new_script.js);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_script.world) {
|
|
||||||
original_script.world = std::move(new_script.world);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<UserScript> parsed_script =
|
std::unique_ptr<UserScript> parsed_script =
|
||||||
ParseUserScript(*extension(), original_script, parse_error);
|
ParseUserScript(*extension(), original_script, parse_error);
|
||||||
return parsed_script;
|
return parsed_script;
|
||||||
|
@ -120,12 +120,8 @@
|
|||||||
"id": "ExecutionWorld",
|
"id": "ExecutionWorld",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"nodoc": true,
|
"nodoc": true,
|
||||||
"enum": [
|
"enum": ["ISOLATED", "MAIN"],
|
||||||
"ISOLATED",
|
"description": "The JavaScript world for a script to execute within. Can either be an isolated world, unique to this extension, or the main world of the DOM which is shared with the page's JavaScript."
|
||||||
"MAIN",
|
|
||||||
"USER_SCRIPT"
|
|
||||||
],
|
|
||||||
"description": "The JavaScript world for a script to execute within. Can either be an isolated world unique to this extension, the main world of the DOM which is shared with the page's JavaScript, or a user scripts world that is only available for scripts registered with the User Scripts API."
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -5,16 +5,6 @@
|
|||||||
// Use the <code>userScripts</code> API to execute user scripts in the User
|
// Use the <code>userScripts</code> API to execute user scripts in the User
|
||||||
// Scripts context.
|
// Scripts context.
|
||||||
namespace userScripts {
|
namespace userScripts {
|
||||||
// The JavaScript world for a user script to execute within.
|
|
||||||
enum ExecutionWorld {
|
|
||||||
// Specifies the execution environment of the DOM, which is the execution
|
|
||||||
// environment shared with the host page's JavaScript.
|
|
||||||
MAIN,
|
|
||||||
// Specifies the execution enviroment that is specific to user scripts and
|
|
||||||
// is exempt from the page's CSP.
|
|
||||||
USER_SCRIPT
|
|
||||||
};
|
|
||||||
|
|
||||||
// The source of the script to inject.
|
// The source of the script to inject.
|
||||||
dictionary ScriptSource {
|
dictionary ScriptSource {
|
||||||
// A string containing the JavaScript code to inject. Exactly one of
|
// A string containing the JavaScript code to inject. Exactly one of
|
||||||
@ -62,9 +52,6 @@ namespace userScripts {
|
|||||||
// Specifies when JavaScript files are injected into the web page. The
|
// Specifies when JavaScript files are injected into the web page. The
|
||||||
// preferred and default value is <code>document_idle</code>.
|
// preferred and default value is <code>document_idle</code>.
|
||||||
extensionTypes.RunAt? runAt;
|
extensionTypes.RunAt? runAt;
|
||||||
// The JavaScript execution environment to run the script in. The default is
|
|
||||||
// <code>`USER_SCRIPT`</code>.
|
|
||||||
ExecutionWorld? world;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// An object used to filter user scripts for ${ref:getScripts}.
|
// An object used to filter user scripts for ${ref:getScripts}.
|
||||||
|
@ -3,8 +3,6 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "extensions/common/utils/extension_types_utils.h"
|
#include "extensions/common/utils/extension_types_utils.h"
|
||||||
#include "extensions/common/api/extension_types.h"
|
|
||||||
#include "extensions/common/mojom/execution_world.mojom-shared.h"
|
|
||||||
|
|
||||||
namespace extensions {
|
namespace extensions {
|
||||||
|
|
||||||
@ -53,9 +51,6 @@ mojom::ExecutionWorld ConvertExecutionWorld(
|
|||||||
break; // Default to mojom::ExecutionWorld::kIsolated.
|
break; // Default to mojom::ExecutionWorld::kIsolated.
|
||||||
case api::extension_types::ExecutionWorld::kMain:
|
case api::extension_types::ExecutionWorld::kMain:
|
||||||
execution_world = mojom::ExecutionWorld::kMain;
|
execution_world = mojom::ExecutionWorld::kMain;
|
||||||
break;
|
|
||||||
case api::extension_types::ExecutionWorld::kUserScript:
|
|
||||||
execution_world = mojom::ExecutionWorld::kUserScript;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return execution_world;
|
return execution_world;
|
||||||
@ -69,7 +64,7 @@ api::extension_types::ExecutionWorld ConvertExecutionWorldForAPI(
|
|||||||
case mojom::ExecutionWorld::kMain:
|
case mojom::ExecutionWorld::kMain:
|
||||||
return api::extension_types::ExecutionWorld::kMain;
|
return api::extension_types::ExecutionWorld::kMain;
|
||||||
case mojom::ExecutionWorld::kUserScript:
|
case mojom::ExecutionWorld::kUserScript:
|
||||||
return api::extension_types::ExecutionWorld::kUserScript;
|
NOTREACHED() << "UserScript worlds are not supported in this API.";
|
||||||
}
|
}
|
||||||
|
|
||||||
NOTREACHED();
|
NOTREACHED();
|
||||||
|
@ -114,5 +114,4 @@ chrome.extensionTypes.DocumentLifecycle = {
|
|||||||
chrome.extensionTypes.ExecutionWorld = {
|
chrome.extensionTypes.ExecutionWorld = {
|
||||||
ISOLATED: 'ISOLATED',
|
ISOLATED: 'ISOLATED',
|
||||||
MAIN: 'MAIN',
|
MAIN: 'MAIN',
|
||||||
USER_SCRIPT: 'USER_SCRIPT',
|
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user