有没有一种简单的转换方法可以将chrome消息传递转换为safari消息传递语法
Is there a simple conversion method for converting chrome message passing to the safari message passing syntax?
我的Chrome扩展使用消息传递从后台页面上的扩展内置本地存储区域中检索各种值。
我喜欢chrome消息传递的一点是,它允许您在sendMessage调用中包含一个回调函数,如下所示:
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
相应的消息接收代码如下所示(Chrome扩展文档中的示例代码):
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
});
我正在尝试将我的扩展转换为Safari扩展格式,但我不知道如何将Chrome的sendMessage/onMessage函数映射到Safari的safari.self.tab.dispatchMessage(name, data)
消息处理功能
Safari的dispatchMessage函数调用中是否可以包含回调函数?如果没有,我应该如何绕过这个限制?
在只提供单向消息传递系统的环境中,您总是可以实现"带有回调的消息";通过将一个唯一的ID与每条消息关联起来,并将回调存储在一个字典中,该字典将这些ID映射到回调。
在这个答案的最后,我已经从我的跨浏览器Lyrics Here扩展的源代码中复制了Safari特定的存储模块,该扩展提供了以下API:
config.getItem(key, callback)
config.setItem(key, value, callback)
config.removeItem(key, callback)
config.clear(callback)
getItem
的回调包含与密钥相关联的值(如果找到)。其他回调接收一个布尔值,该布尔值告诉操作是否成功。
源代码带有注释,并包含一些片段来处理一些边缘情况。如果有什么不清楚的地方,可以向我提问。
config-safari.js(AMD)
// Adapter for maintaining preferences (Safari 5+)
// All methods are ASYNCHRONOUS
define('config-safari', function() {
var config = {};
var callbacks = {};
['getItem', 'setItem', 'removeItem', 'clear'].forEach(function(methodName) {
config[methodName] = function() {
var args = [].slice.call(arguments);
var callback = args.pop();
var messageID = Math.random();
callbacks[messageID] = callback;
var message = {
type: methodName,
messageID: messageID,
args: args
};
safari.self.tab.dispatchMessage('config-request', message);
};
});
config.init = function() {
if (typeof safari === 'undefined') {
// Safari bug: safari is undefined when current context is an iframe
// and src="javascript:''"
// This error is only expected on YouTube.
// config.getItem is triggered in main, so we just redefine
// it. Don't overwrite setItem, etc., so that errors are thrown
// when these methods are used.
config.getItem = function(key, callback){
callback();
};
return;
}
safari.self.addEventListener('message', function(event) {
if (event.name === 'config-reply') {
var messageID = event.message.messageID;
var callback = callbacks[messageID];
// Check if callback exists. It may not exist when the script is
// activated in multiple frames, because every frame receives the message
if (callback) {
delete callbacks[messageID];
callback(event.message.result);
}
}
}, true);
};
return config;
});
global.html片段:
<script>
(function(exports) {
var config = {};
config.getItem = function(key, callback) {
var result = safari.extension.settings.getItem(key);
if (typeof result === 'string') {
try {
result = JSON.parse(result);
} catch (e) {
// Extremely unlikely to happen, but don't neglect the possibility
console.log('config.getItem error: ' + e);
result = undefined;
}
}
callback(result);
};
// callback's argument: true on success, false otherwise
config.setItem = function(key, value, callback) {
var success = false;
try {
value = JSON.stringify(value);
// Safari (5.1.5) does not enforce the database quota,
// let's enforce it manually (ok, set the quota per key, since
// the performance issue only occur when a specific key has an outrageous high value)
// 1 MB should be sufficient.
if (value.length > 1e6) {
throw new Error('QUOTA_EXCEEDED_ERR: length=' + value.length);
}
safari.extension.settings.setItem(key, value);
success = true;
} catch (e) {
console.log('config.setItem error: ' + e);
}
callback(success);
};
// callback's argument: true on success, false otherwise
config.removeItem = function(key, callback) {
safari.extension.settings.removeItem(key);
callback(true);
};
// callback's argument: true on success, false otherwise
config.clear = function(callback) {
safari.extension.settings.clear();
callback(true);
};
// config's message handler
function handleConfigRequest(event) {
var args = event.message.args;
// Last argument: Always a callback
args.push(function(result) {
// Note: All of the config methods send a callback only once
// Behavior for calling the callback twice is undefined.
// Send a reply to trigger the callback at the sender's end
event.target.page.dispatchMessage('config-reply', {
messageID: event.message.messageID,
result: result
});
});
config[event.message.type].apply(config, args);
}
// Export
exports.handleConfigRequest = handleConfigRequest;
})(window);
</script>
<script>
safari.application.addEventListener('message', function(event) {
switch (event.name) {
case 'config-request':
handleConfigRequest(event);
break;
/* ... other things removed ... */
}
}, true);
</script>
相关文章:
- 为什么我得到Chrome本机消息“;找不到指定的本机消息传递主机&”;
- 有没有一种简单的转换方法可以将chrome消息传递转换为safari消息传递语法
- 基本的谷歌chrome扩展消息传递不起作用
- Chrome 扩展消息传递体系结构
- Chrome扩展消息传递:未发送响应
- Chrome 消息传递.未捕获错误:连接到扩展时出错
- 消息传递在 Chrome 19 中断开
- 将消息从 Chrome 扩展程序传递到网页
- Chrome 扩展程序:无法让消息传递在后台脚本和内容脚本之间正常工作
- 消息传递在chrome扩展中不起作用
- 如何动态地将chrome扩展ID发送到网页以进行消息传递
- Chrome扩展消息传递-如何传递HTML
- Chrome扩展通过消息传递与网页进行通信
- 内容脚本和背景页面之间的消息传递在chrome扩展是不工作,因为它应该是
- Chrome扩展消息传递与localStorage,值是未定义
- 实现跨扩展消息传递在chrome扩展和应用程序
- 谷歌Chrome扩展消息传递与run_at document_start
- Chrome应用程序消息传递和'Vs. load()计时
- 消息传递在chrome扩展不工作
- 内容脚本和弹出脚本之间的消息传递Chrome扩展