-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b25a56b
commit c12182c
Showing
8 changed files
with
308 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# chrome.userScripts API | ||
|
||
This sample demonstrates using the [`chrome.userScripts`](https://developer.chrome.com/docs/extensions/reference/scripting/) API to inject JavaScript into web pages. | ||
|
||
## Overview | ||
|
||
Once this extension is installed, clicking this extension's action icon will open an options page. | ||
|
||
<img src="screenshot.png" height=250 alt="Screenshot showing the chrome.userScripts API demo running in Chrome."> | ||
|
||
## Running this extension | ||
|
||
1. Clone this repository. | ||
2. Load this directory in Chrome as an [unpacked extension](https://developer.chrome.com/docs/extensions/mv3/getstarted/development-basics/#load-unpacked). | ||
3. Click the extension's action icon to open the options page. | ||
4. Once a user script has been configured, visit https://example.com/. | ||
|
||
## Features | ||
|
||
This sample allows you to inject the following: | ||
|
||
- Files | ||
- Arbitrary code | ||
|
||
## Implementation Notes | ||
|
||
The User Scripts API requires developer mode. We check for this by attempting to access `chrome.userScripts`, which throws an error on property access if it is disabled. | ||
|
||
When a change is made on the options page, we use the `chrome.userScripts` API to update the user script registration. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"name": "User Scripts API Demo", | ||
"version": "1.0", | ||
"manifest_version": 3, | ||
"description": "Uses the chrome.userScripts API to inject JavaScript into web pages.", | ||
"background": { | ||
"service_worker": "sw.js" | ||
}, | ||
"permissions": ["storage", "userScripts"], | ||
"host_permissions": ["https://example.com/*"], | ||
"action": {}, | ||
"options_ui": { | ||
"page": "options.html", | ||
"open_in_tab": false | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
Copyright 2023 Google LLC | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
https://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
html { | ||
padding: 0 10px; | ||
} | ||
|
||
#warning { | ||
display: none; | ||
margin-bottom: 30px; | ||
} | ||
|
||
label { | ||
display: flex; | ||
align-items: center; | ||
} | ||
|
||
label input { | ||
margin-right: 10px; | ||
} | ||
|
||
textarea { | ||
resize: none; | ||
width: calc(100% - 35px); | ||
border: 2px solid black; | ||
background: rgb(34, 34, 34); | ||
padding: 15px; | ||
color: white; | ||
} | ||
|
||
textarea:focus { | ||
border: 2px solid grey; | ||
outline: none; | ||
} | ||
|
||
button { | ||
margin: 20px 0; | ||
} | ||
|
||
/* Hide custom script textarea by default */ | ||
#custom-script-wrapper { | ||
display: none; | ||
} | ||
|
||
/* Only show custom script textarea when custom type is selected */ | ||
form:has(input[name='type'][value='custom']:checked) #custom-script-wrapper { | ||
display: block; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
<!-- | ||
Copyright 2023 Google LLC | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
https://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
--> | ||
|
||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<title>User Scripts API Demo</title> | ||
<link rel="stylesheet" type="text/css" href="options.css" /> | ||
<script defer src="options.js"></script> | ||
</head> | ||
<body> | ||
<div id="warning"> | ||
<p> | ||
⚠️ To use the User Scripts API, you need to first enable developer mode | ||
at <b>chrome://extensions</b>. | ||
</p> | ||
<a href="">Reload</a> | ||
</div> | ||
<form id="settings-form"> | ||
<h1>Settings</h1> | ||
<h2>Type</h2> | ||
<label> | ||
<input type="radio" name="type" value="file" /> | ||
<span>File</span> | ||
</label> | ||
<label> | ||
<input type="radio" name="type" value="custom" /> | ||
<span>Custom text</span> | ||
</label> | ||
<div id="custom-script-wrapper"> | ||
<h2>Custom script</h2> | ||
<textarea | ||
name="custom-script" | ||
draggable="false" | ||
rows="8" | ||
placeholder="alert('hi');" | ||
></textarea> | ||
</div> | ||
<button type="button" id="save-button">Save & Enable</button> | ||
</form> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// Copyright 2023 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
const USER_SCRIPT_ID = 'default'; | ||
const SAVE_BUTTON_ID = 'save-button'; | ||
|
||
const FORM_ID = 'settings-form'; | ||
const FORM = document.getElementById(FORM_ID); | ||
|
||
const TYPE_INPUT_NAME = 'type'; | ||
const SCRIPT_TEXTAREA_NAME = 'custom-script'; | ||
|
||
/** | ||
* Checks if the user has developer mode enabled, which is required to use the | ||
* User Scripts API. | ||
* | ||
* @returns If the chrome.userScripts API is available. | ||
*/ | ||
function isUserScriptsAvailable() { | ||
try { | ||
// Property access which throws if developer mode is not enabled. | ||
chrome.userScripts; | ||
return true; | ||
} catch { | ||
// Not available, so hide UI and show error. | ||
document.getElementById('warning').style.display = 'block'; | ||
FORM.style.display = 'none'; | ||
return false; | ||
} | ||
} | ||
|
||
async function updateUi() { | ||
if (!isUserScriptsAvailable()) return; | ||
|
||
// Access settings from storage with default values. | ||
const { type, script } = await chrome.storage.local.get({ | ||
type: 'file', | ||
script: "alert('hi');" | ||
}); | ||
|
||
// Update UI with current values. | ||
FORM.elements[TYPE_INPUT_NAME].value = type; | ||
FORM.elements[SCRIPT_TEXTAREA_NAME].value = script; | ||
} | ||
|
||
async function onSave() { | ||
if (!isUserScriptsAvailable()) return; | ||
|
||
// Get values from form. | ||
const type = FORM.elements[TYPE_INPUT_NAME].value; | ||
const script = FORM.elements[SCRIPT_TEXTAREA_NAME].value; | ||
|
||
// Save to storage. | ||
chrome.storage.local.set({ | ||
type, | ||
script | ||
}); | ||
|
||
// Unregister existing script. | ||
try { | ||
await chrome.userScripts.unregister({ ids: [USER_SCRIPT_ID] }); | ||
} catch { | ||
// This might be our first time registering a script. | ||
} | ||
|
||
// Register new script. | ||
switch (type) { | ||
case 'file': | ||
await chrome.userScripts.register([ | ||
{ | ||
id: USER_SCRIPT_ID, | ||
matches: ['https://example.com/*'], | ||
js: [{ file: 'user-script.js' }] | ||
} | ||
]); | ||
break; | ||
case 'custom': | ||
await chrome.userScripts.register([ | ||
{ | ||
id: USER_SCRIPT_ID, | ||
matches: ['https://example.com/*'], | ||
js: [{ code: script }] | ||
} | ||
]); | ||
break; | ||
default: | ||
console.warn('Unknown type:', type); | ||
return; | ||
} | ||
} | ||
|
||
// Update UI immediately, and on any storage changes. | ||
updateUi(); | ||
chrome.storage.local.onChanged.addListener(updateUi); | ||
|
||
// Register listener for save button click. | ||
document.getElementById(SAVE_BUTTON_ID).addEventListener('click', onSave); |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
// Copyright 2023 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
chrome.runtime.onInstalled.addListener(({ reason }) => { | ||
if (reason == chrome.runtime.OnInstalledReason.INSTALL) { | ||
chrome.runtime.openOptionsPage(); | ||
} | ||
}); | ||
|
||
chrome.action.onClicked.addListener(() => { | ||
chrome.runtime.openOptionsPage(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// Copyright 2023 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// https://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
alert('Hello World!'); |