[英]Accessing background script object from content script
How to access background script objects form a content script inside chrome extension? 如何访问后台脚本对象在chrome扩展内形成内容脚本?
In content script I have: 在内容脚本中,我有:
// this will store settings
var settings = {};
// load settings from background
chrome.extension.sendMessage({
name: "get-settings"
}, function(response) {
debugger;
settings = response.data.settings;
});
Inside the background script I have: 在后台脚本中,我有:
var Settings = function() {
var me = this;
// internal, default
var settingList = {
serverUrl : "http://automatyka-pl.p4",
isRecordingEnabled : true,
isScanEnabled : true
};
this.get = function( key ) {
return settingList[key];
};
this.set = function( key , value ) {
if (settingList[key] != value) {
var setting = {};
setting[key] = value;
chrome.storage.sync.set(setting, function() {
settingList[key] = value;
});
}
return true;
};
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
if (request.name == 'get-settings') {
sendResponse({
data : {
settings : settings
}
});
return true;
}
});
var settings = new Settings();
Messaging works, i mean response is send but returned object is empty. 消息传递有效,我的意思是发送响应,但返回的对象为空。 Do you know how to solve that?
你知道怎么解决吗?
EDIT Based on your comments and answer will try to add different light to my question. 编辑根据您的评论和答案将尝试为我的问题添加不同的内容。
The actual problem is: How to access background "model" from content script . 实际的问题是: 如何从内容脚本访问后台“模型” 。
Lets assume that content script continuously responds to page DOM changes. 假设内容脚本持续响应页面DOM更改。 Any time changes are detected some processing is made inside content script .
每当检测到更改时,都会在内容脚本中进行一些处理。 But this processing is depended on extension setting.
但是此处理取决于扩展设置。 Those setting can be set via page action popup script which informs background model what those settings are.
可以通过页面操作弹出脚本来设置这些设置,该脚本会通知后台模型这些设置是什么。
So, any time page is processed with content script it should be aware of current settings stored inside background script . 因此,任何时候使用内容脚本处理页面时,都应该知道存储在后台脚本中的当前设置。
As already described pulling settings from background is an asynchronous process, so i need a callback for further processing inside content script. 如前所述,从后台提取设置是一个异步过程,因此我需要回调以进一步在内容脚本中进行处理。 Further processing must wait for settings (so this should be handled synchronously?).
进一步的处理必须等待设置(因此应该同步处理吗?)。
It's hard for my to imagine what program flow should look like in this case. 我很难想象这种情况下的程序流程是什么样的。
sendMessage doesn't transfer the object itself, but only its JSON-ifiable representation, effectively objReceived = JSON.parse(JSON.stringify(objSent))
, so since your object's settingList
is invisible outside function context it's lost during serialization. sendMessage不会传递对象本身,而只会传递其JSON可表示形式,即
objReceived = JSON.parse(JSON.stringify(objSent))
,因此,由于对象的settingList
在函数上下文之外是不可见的,因此在序列化过程中会丢失。
You can make it public by exposing a stringifiable property 您可以通过公开可字符串化的属性来将其公开
this.settingList = { foo: 'bar' };
that would be transferred to your content script successfully. 将会成功转移到您的内容脚本。
Since messaging is asynchronous , to use the response in the content script you should do it inside the response callback: 由于消息传递是异步的 ,因此要在内容脚本中使用响应,应在响应回调中进行响应:
// this will store the settings var settings = {}; // load settings from background chrome.runtime.sendMessage({ name: "get-settings" }, function(response) { settings = response.data.settings; onSettingsReady(); }); function onSettingsReady() { // put your logic here, settings are set at this point }
To know if settings changed outside your content-script, in settings setter in background.js send messages to your tab's content-script: 要知道设置是否在内容脚本之外更改,请在background.js的设置设置器中将消息发送到选项卡的内容脚本:
this.set = function( key , value ) { ... // notify active tab if settings changed chrome.tabs.query({"windowType":"normal"}, function(tabs){ for( id in tabs ){ if("id" in tabs[id]){ chrome.tabs.sendMessage(tabs[id].id,{"action":"update-settings","settings":settings}); } } }); return true; };
And in content-script listen and process this message: 然后在内容脚本中侦听并处理以下消息:
chrome.runtime.onMessage.addListener(function(msg){ if("action" in msg && msg.action == 'update-settings'){ // You are setting global settings variable, so on it will be visible in another functions too settings = msg.settings; } });
More details: https://developer.chrome.com/extensions/runtime#method-sendMessage . 更多详细信息: https : //developer.chrome.com/extensions/runtime#method-sendMessage 。
PS Use chrome.runtime.sendMessage
instead of chrome.extension.sendMessage
as the latter is deprecated in Chrome API and totally unsupported in WebExtensions API (Firefox/Edge). PS请使用
chrome.runtime.sendMessage
而不是chrome.extension.sendMessage
因为Chrome API不推荐使用chrome.extension.sendMessage
,WebExtensions API(Firefox / Edge)完全不支持后者。
It would probably make more sense to have another instance of Settings
in your content script. 在内容脚本中包含
Settings
另一个实例可能更有意义。
After all, chrome.storage
API is available in content scripts. 毕竟,内容脚本中提供了
chrome.storage
API。
Of course, you need to watch for changes made in other parts of the extension - but you should be doing so anyway, since you're using chrome.storage.sync
and its value can change independently by Chrome Sync. 当然,您需要注意在扩展程序其他部分所做的更改-但无论如何都应该这样做,因为您使用的是
chrome.storage.sync
,Chrome Sync可以独立更改其值。
So, proposed solution: 因此,建议的解决方案:
chrome.storage.onChanged
and process changes to update your settingList
as needed. chrome.storage.onChanged
并处理更改以根据需要更新您的settingList
。 Storage
logic to a separate JS "library", eg storage.js
Storage
逻辑移至单独的JS“库”,例如storage.js
storage.js
in your content script and use it normally. storage.js
并正常使用。 You may also want to adjust your storage logic so that saved data is actually taken into account - right now it's always the default. 您可能还需要调整存储逻辑,以便实际考虑保存的数据-现在,它始终是默认值。 You can do something like this:
您可以执行以下操作:
var defaultSettingList = {
serverUrl : "http://automatyka-pl.p4",
isRecordingEnabled : true,
isScanEnabled : true
};
var settingList = Object.assign({}, defaultSettingList);
chrome.storage.sync.get(defaultSettingList, function(data) {
settingList = Object.assign(settingList, data);
// At this point you probably should call the "ready" callback - initial
// load has to be async, no way around it
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.