4

У меня есть страница настроек на моем WebExtension, но я не знаю, как получить значения параметров с помощью javascript.Страница настроек Firefox WebExtension

Текущий .xul-файла:

<?xml version="1.0"?> 
<!DOCTYPE mydialog SYSTEM "chrome://myaddon/locale/mydialog.dtd"> 

<vbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> 
    <setting type="string" pref="extensions.check.email" title="email" desc="please insert your email here" /> 
</vbox> 

Как Acces "Электронная почта" значение? Могу ли я просто написать что-то вроде «getPreferences (« email »)»?

+1

Предоставьте полный [mcve] (т. Е. Файл * manifest.json *), чтобы мы могли видеть, что вы на самом деле делаете. Очень необычно использовать XUL в надстройке WebExtensions (обычно что-то вроде этого будет HTML). Таким образом, только что вы делаете это, возникает достаточно вопросов, которые нам нужно понять больше о том, что происходит, чтобы обеспечить хорошую помощь. – Makyen

+0

Под «страницами настроек» вы имеете в виду страницу * параметров *, которую вы указали в ключе 'options_ui' в файле * manifest.json *? – Makyen

ответ

6

Не используйте XUL в WebExtension надстройку:
Если вы используете XUL изнутри WebExtension, то что-то, вероятно, неправильно. Если вы пишете WebExtension и начинаете делать XUL: сделайте шаг назад. Убедитесь, что это действительно, что вы должны делать. Одна из точек WebExtensions заключается в том, что она изолирует надстройку от внутренних компонентов Firefox (то есть от XUL).

Опции панели и страницы:
В общем, варианты должны быть сохранены в storage.local (или storage.sync, если поддерживается). Если вы пытаетесь общаться со страницы настроек или панель на ваш основной фон сценарий есть, по крайней мере, 4 несколько различных способов сделать это:

  1. Параметры сохраняются в storage.local в вариантов. js код. Фоновый код прослушивает события от storage.onChanged. Не нужно передавать сообщения туда и обратно. Нет необходимости в ваших вариантах/панельном коде, чтобы специально оповестить исходную страницу о произошедших изменениях.
  2. Опции хранятся в storage.local в options.js код. Затем options.js непосредственно вызывает функцию в вашем фоновом скрипте, чтобы фоновый скрипт перечитывал параметры. В приведенном ниже коде функция getOptions() в файле background.js напрямую вызывается кодом .js.
  3. Опции хранятся в storage.local в options.js код. Используйте chrome.runtime.sendMessage(), чтобы отправить сообщение на свою справочную страницу о том, что параметры были изменены. В приведенном ниже коде: после сохранения опций в storage.local, options.js отправляет сообщение optionsUpdated в фоновый скрипт, что параметры были обновлены. Затем фоновый скрипт перечитывает параметры. [Сообщение может быть любым, что вы хотите, это указывает на это. optionsUpdated - это то, что я выбрал в качестве сообщения в коде ниже.]
  4. Используйте chrome.runtime.sendMessage(), чтобы отправить сообщение со всеми опциями на страницу фона. В приведенном ниже коде: Сообщение optionsData отправляется с options.js код на исходную страницу при изменении параметров, который содержит полезную нагрузку data со всеми вариантами. Затем параметры сохраняются в хранилище.local в фоновом скрипте. После того, как параметры сохранены, фоновый скрипт отправляет сообщение optionsStored обратно в код options.js. Код options.js затем указывает пользователю, что параметры сохранены. [Сообщение может быть любым, что вы хотите, это указывает на это. optionsData и optionsStored - это то, что я выбрал в качестве сообщения в коде ниже.]

Ниже приведено WebExtension, которое демонстрирует эти четыре разных способа получения информации об измененных параметрах обратно в фоновый скрипт.

Примечание: в приведенном ниже коде используется кнопка browser_action для вызова панели с теми же параметрами, что и для options_ui. Это делается для демонстрации. Если у вас появится кнопка, которая откроет ваши параметры, возможно, вам лучше открыть страницу options_ui с помощью runtime.openOptionsPage(). Что вы делаете, зависит от пользовательского интерфейса, который вы хотите представить пользователю.

background.js:

var useDirect=0; //Holds the state of how we communicate with options.js 
var emailAddress=''; //The email address from options. 
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' ]; 


//Register the message listener 
chrome.runtime.onMessage.addListener(receiveMessage); 

function receiveMessage(message,sender,sendResponse){ 
    //Receives a message that must be an object with a property 'type'. 
    // This format is imposed because in a larger extension we may 
    // be using messages for multiple purposes. Having the 'type' 
    // provides a defined way for other parts of the extension to 
    // both indicate the purpose of the message and send arbitrary 
    // data (other properties in the object). 
    console.log('Received message: ',message); 
    if(typeof message !== 'object' || !message.hasOwnProperty('type')){ 
     //Message does not have the format we have imposed for our use. 
     //Message is not one we understand. 
     return; 
    } 
    if(message.type === "optionsUpdated"){ 
     //The options have been updated and stored by options.js. 
     //Re-read all options. 
     getOptions(); 
    } 
    if(message.type === "optionsData"){ 
     saveOptionsSentAsData(message.data,function(){ 
      //Callback function executed once data is stored in storage.local 
      console.log('Sending response back to options page/panel'); 
      //Send a message back to options.js that the data has been stored. 
      sendResponse({type:'optionsStored'}); 
      //Re-read all options. 
      getOptions(); 
     }); 
     //Return true to leave the message channel open so we can 
     // asynchronously send a message back to options.js that the 
     // data has actually been stored. 
     return true; 
    } 
} 

function detectStorageChange(change){ 
    //Ignore the change information. Just re-get all options 
    console.log('Background.js: Detected storage change'); 
    getOptions(); 
} 

function listenToStorageChanges(){ 
    chrome.storage.onChanged.addListener(detectStorageChange); 
} 

function stopListeningToStorageChanges(){ 
    chrome.storage.onChanged.removeListener(detectStorageChange); 
} 

function getOptions(){ 
    //Options are normally in storage.sync (sync'ed across the profile). 
    //This example is using storage.local. 
    //Firefox does not currently support storage.sync. 
    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) { 
    //Options data received as a message from options.js is 
    // stored in storeage.local. 
    chrome.storage.local.set(data, function() { 
     //Invoke a callback function if we were passed one. 
     if(typeof callback === 'function'){ 
      callback(); 
     } 
    }); 
} 

//Read the options stored from prior runs of the extension. 
getOptions(); 

//On Firefox, open the Browser Console: 
//To determine if this is Chrome, multiple methods which are not implemented 
// in Firefox are checked. Multiple ones are used as Firefox will eventually 
// support more APIs. 
var isChrome = !! window.InstallTrigger 
       || (!!chrome.extension.setUpdateUrlData 
       && !!chrome.runtime.reload 
       && !!chrome.runtime.restart); 
if(!isChrome) { 
    //In Firefox cause the Browser Console to open by using alert() 
    window.alert('Open the console. isChrome=' + isChrome); 
} 

options.js:

// Saves options to chrome.storage.local. 
// It is recommended by Google that options be saved to chrome.storage.sync. 
// Firefox does not yet support storage.sync. 
function saveOptions(data, callback) { 
    chrome.storage.local.set(data, function() { 
     if(typeof callback === 'function'){ 
      callback(); 
     } 
     // Update status to let user know options were saved. 
     notifyOptionsSaved(); 
    }); 
} 

function optionsChanged() { 
    //Get the selected option values from the DOM 
    let useDirectValue = document.getElementById('useDirect').value; 
    let email = document.getElementById('email').value; 
    useDirectValue = +useDirectValue; //Force to number, not string 
    //Put all the option data in a single object 
    let optionData = { 
     useDirect: useDirectValue, 
     emailAddress: email 
    } 
    setBackgroundPageNotListeningToStorageChanges(); 
    if(useDirectValue == 0) { 
     //Use listening to storage changes 
     //console.log('Going to listen for storage changes'); 
     setBackgroundPageListeningToStorageChanges(); 
     saveOptions(optionData); 
    } else if (useDirectValue == 1) { 
     //We save the options in the options page, or popup 
     saveOptions(optionData, function(){ 
      //After the save is complete: 
      //The getOptions() functon already exists to retrieve options from 
      // storage.local upon startup of the extension. It is easiest to use that. 
      // We could remove and add the listener here, but that code already 
      // exists in background.js. There is no reason to duplicate the code here. 
      let backgroundPage = chrome.extension.getBackgroundPage(); 
      backgroundPage.getOptions(); 
     }); 
    } else if (useDirectValue == 2) { 
     //We save the options in the options page, or popup 
     saveOptions(optionData, function(){ 
      //Send a message to background.js that options in storage.local were updated. 
      chrome.runtime.sendMessage({type:'optionsUpdated'}); 
     }); 
    } else { 
     //Send all the options data to background.js and let it be dealt with there. 
     chrome.runtime.sendMessage({ 
      type:'optionsData', 
      data: optionData 
     }, function(message){ 
      //Get a message back that may indicate we have stored the data. 
      if(typeof message === 'object' && message.hasOwnProperty('type')){ 
       if(message.type === 'optionsStored') { 
        //The message received back indicated the option data has 
        // been stored by background.js. 
        //Notify the user that the options have been saved. 
        notifyOptionsSaved(); 
       } 
      } 
     }); 
    } 
} 

function setBackgroundPageListeningToStorageChanges(){ 
    //Normally the listener would be set up once, and only once, within the 
    // background page script. We are doing it here to demonstrate switing 
    // between the different methods of notification. 
    let backgroundPage = chrome.extension.getBackgroundPage(); 
    //either add the listener directly: 
    chrome.storage.onChanged.addListener(backgroundPage.detectStorageChange); 
    //or let the background page add it: 
    //backgroundPage.listenToStorageChanges(); 
} 

function setBackgroundPageNotListeningToStorageChanges(){ 
    //Normally the listener would be set up once, and only once, within the 
    // background page script. We are doing it here to demonstrate switing 
    // between the different methods of notification. 
    let backgroundPage = chrome.extension.getBackgroundPage(); 
    //either remove the listener directly: 
    chrome.storage.onChanged.removeListener(backgroundPage.detectStorageChange); 
    //or let the background page add it: 
    //backgroundPage.stopListeningToStorageChanges(); 
} 

// Restores select box and input using the preferences 
// stored in chrome.storage. 
function useStoredOptionsForDisplayInDOM() { 
    chrome.storage.local.get({ 
     useDirect: 0, 
     emailAddress: '' 
    }, function(items) { 
     //Store retrieved options as the selected values in the DOM 
     document.getElementById('useDirect').value = items.useDirect; 
     document.getElementById('email').value = items.emailAddress; 
    }); 
    //notifyStatusChange('Option read'); 
} 

function notifyOptionsSaved(callback){ 
    //Notify the user that the options have been saved 
    notifyStatusChange('Options saved.',callback); 
} 

function notifyStatusChange(newStatus,callback){ 
    let status = document.getElementById('status'); 
    status.textContent = newStatus; 
    //Clear the notification after a second 
    setTimeout(function() { 
     status.textContent = ''; 
     if(typeof callback === 'function'){ 
      callback(); 
     } 
    }, 1000); 
} 

document.addEventListener('DOMContentLoaded', useStoredOptionsForDisplayInDOM); 
document.getElementById('optionsArea').addEventListener('change',optionsChanged); 
//In order to track the change if this is open in _both_ the browser_action panel 
// and the add-on options page, we need to listen for changes to storage. 
// There is already a function which reads all of the options, so don't 
// use the information as to what changed, just that a change occurred. 
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 protected]", 
      "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 
    } 
} 

Код выше, основан на коде в моем ответе на Update WebExtension webRequest.onBeforeRequest listener URL settings from separate script.

Смежные вопросы