XUL WebExtension:
XUL WebExtension, , , - . WebExtension XUL: . , , . WebExtensions , Firefox ( XUL).
:
storage.local ( .sync, ). script, , , 4 :
- storage.local options.js.
storage.onChanged. . / , . - storage.local options.js. options.js script, script .
getOptions() background.js options.js. - storage.local options.js.
chrome.runtime.sendMessage(), , . : storage.local, options.js optionsUpdated script, . script . [ , , . optionsUpdated - , .] chrome.runtime.sendMessage(), . : optionsData options.js , data . storage.local script. script optionsStored options.js. options.js , . [ , , . optionsData optionsStored - , .]
WebExtension, script.
. browser_action, , options_ui. . , , options_ui runtime.openOptionsPage(). , , .
background.js:
var useDirect=0;
var emailAddress='';
const useDirectTypes=[ 'Listen to chrome.storage changes'
,'Directly invoke functions in the background script from'
+ ' the options/panel code'
,'Send a message that data in storage.local was updated'
,'Send a message with all options data' ];
chrome.runtime.onMessage.addListener(receiveMessage);
function receiveMessage(message,sender,sendResponse){
console.log('Received message: ',message);
if(typeof message !== 'object' || !message.hasOwnProperty('type')){
return;
}
if(message.type === "optionsUpdated"){
getOptions();
}
if(message.type === "optionsData"){
saveOptionsSentAsData(message.data,function(){
console.log('Sending response back to options page/panel');
sendResponse({type:'optionsStored'});
getOptions();
});
return true;
}
}
function detectStorageChange(change){
console.log('Background.js: Detected storage change');
getOptions();
}
function listenToStorageChanges(){
chrome.storage.onChanged.addListener(detectStorageChange);
}
function stopListeningToStorageChanges(){
chrome.storage.onChanged.removeListener(detectStorageChange);
}
function getOptions(){
chrome.storage.local.get({
useDirect: 0,
emailAddress: ''
}, function(items) {
if(typeof items.useDirect !== 'number' || items.useDirect <0
|| items.useDirect >= useDirectTypes.length) {
items.useDirect=0;
}
useDirect = items.useDirect;
emailAddress = items.emailAddress;
console.log('useDirect=' + useDirectTypes[useDirect]);
console.log('email address=' + emailAddress);
});
}
function saveOptionsSentAsData(data,callback) {
chrome.storage.local.set(data, function() {
if(typeof callback === 'function'){
callback();
}
});
}
getOptions();
var isChrome = !! window.InstallTrigger
|| (!!chrome.extension.setUpdateUrlData
&& !!chrome.runtime.reload
&& !!chrome.runtime.restart);
if(!isChrome) {
window.alert('Open the console. isChrome=' + isChrome);
}
options.js:
function saveOptions(data, callback) {
chrome.storage.local.set(data, function() {
if(typeof callback === 'function'){
callback();
}
notifyOptionsSaved();
});
}
function optionsChanged() {
let useDirectValue = document.getElementById('useDirect').value;
let email = document.getElementById('email').value;
useDirectValue = +useDirectValue;
let optionData = {
useDirect: useDirectValue,
emailAddress: email
}
setBackgroundPageNotListeningToStorageChanges();
if(useDirectValue == 0 ) {
setBackgroundPageListeningToStorageChanges();
saveOptions(optionData);
} else if (useDirectValue == 1) {
saveOptions(optionData, function(){
let backgroundPage = chrome.extension.getBackgroundPage();
backgroundPage.getOptions();
});
} else if (useDirectValue == 2) {
saveOptions(optionData, function(){
chrome.runtime.sendMessage({type:'optionsUpdated'});
});
} else {
chrome.runtime.sendMessage({
type:'optionsData',
data: optionData
}, function(message){
if(typeof message === 'object' && message.hasOwnProperty('type')){
if(message.type === 'optionsStored') {
notifyOptionsSaved();
}
}
});
}
}
function setBackgroundPageListeningToStorageChanges(){
let backgroundPage = chrome.extension.getBackgroundPage();
chrome.storage.onChanged.addListener(backgroundPage.detectStorageChange);
}
function setBackgroundPageNotListeningToStorageChanges(){
let backgroundPage = chrome.extension.getBackgroundPage();
chrome.storage.onChanged.removeListener(backgroundPage.detectStorageChange);
}
function useStoredOptionsForDisplayInDOM() {
chrome.storage.local.get({
useDirect: 0,
emailAddress: ''
}, function(items) {
document.getElementById('useDirect').value = items.useDirect;
document.getElementById('email').value = items.emailAddress;
});
}
function notifyOptionsSaved(callback){
notifyStatusChange('Options saved.',callback);
}
function notifyStatusChange(newStatus,callback){
let status = document.getElementById('status');
status.textContent = newStatus;
setTimeout(function() {
status.textContent = '';
if(typeof callback === 'function'){
callback();
}
}, 1000);
}
document.addEventListener('DOMContentLoaded', useStoredOptionsForDisplayInDOM);
document.getElementById('optionsArea').addEventListener('change',optionsChanged);
chrome.storage.onChanged.addListener(useStoredOptionsForDisplayInDOM);
options.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebRequest Logging Options</title>
<style>
body: { padding: 10px; }
</style>
</head>
<body>
<div id="optionsArea">
Communication with background page:
<select id="useDirect">
<option value="0">Listen for storage changes</option>
<option value="1">Directly call background page functions</option>
<option value="2">Send a Message Updated storage.local</option>
<option value="3">Send a Message with all Data</option>
</select>
<div>Email:
<input id="email"></input>
</div>
</div>
<div id="status" style="top:0px;display:inline-block;"></div>
<script src="options.js"></script>
</body>
</html>
manifest.json:
{
"description": "Demonstrate an email field in options with various ways of communicating with the background script.",
"manifest_version": 2,
"name": "email-in-options-demo",
"version": "0.1",
"applications": {
"gecko": {
//Firefox: must define id to use option_ui:
"id": "email-in-options-demo@example.example",
"strict_min_version": "48.0"
}
},
"permissions": [
"storage"
],
"background": {
"scripts": [
"background.js"
]
},
"browser_action": {
"default_icon": {
"48": "myIcon.png"
},
"default_title": "Show panel",
"browser_style": true,
"default_popup": "options.html"
},
"options_ui": {
"page": "options.html",
"chrome_style": true
}
}
- WebRequest.onBeforeRequest script.