Safari扩展问题

12

我正在构建我的第一个Safari扩展程序——一个非常简单的扩展程序——但是我遇到了一些问题。该扩展程序归结为一个单一的注入脚本,试图绕过本地feed处理程序并重定向到http:// URI。到目前为止,我的问题有两个:

  1. “白名单”没有按照我预期的方式工作。由于所有的feed都在“feed://”协议下显示,我尝试在白名单中捕获它们,如“feed:/// *”(黑名单中没有任何内容),但我陷入了一个无法理解的请求循环中。如果我将黑名单值设置为"http://*/*"和"https://*/*",则一切正常。
  2. 我不知道如何从我的注入脚本中访问我的设置。该脚本创建了一个beforeload事件处理程序,但无法使用文档中指示的safari.extension.settings路径访问我的设置。

我没有找到任何苹果公司的文档说明设置不能从我的脚本中获得。由于扩展是一个全新的功能,即使是Google也只返回有限的相关结果,其中大部分都来自官方文档。

我缺少什么?

更新 因此,我希望文档不完整,因为它几乎糟糕透顶,但是我了解了一些设置。事实证明,从注入脚本中,SafariExtensionSettings对象不可用。注入脚本只能访问SafariContentExtension对象(根本没有用处),但它的别名与之完全相同(safari.extension.settings)——在我看来这是个坏主意。如文档中所述:注入脚本文档

重要提示:当你在注入脚本中使用safari.extension时,你实际上是在调用SafariContentExtension类而不是SafariExtension类。
你需要使用消息传递系统与一个可以访问设置的全局HTML文件进行通信。虽然有点绕,但我正在发送一条消息到一个名为global.html的文件上,该文件将检索设置,并在我想出如何操作之后向我的注入脚本发送一条消息回复。
由于我所有的工作都是在文档加载前完成的,所以我找到的所有发送消息的方法都依赖于一个我没有的页面对象来进行消息的回传。
4个回答

6

和其他人一样,我还在学习过程中,但是我已经处理了这个问题:

我有一个简单的扩展程序,没有chrome,只有一个注入的结束脚本(script.js)。为了加载设置,我添加了一个简单的全局页面(proxy.html)。当script.js被注入时,它会向proxy.html发送一个getSettings消息。proxy.html会响应一个setSettings消息,然后script.js继续初始化。

在这个主题的文档中,我发现最有帮助的页面是Messages and Proxies

proxy.html:

<!doctype html>
<html lang="en">
<head>
  <script type="text/javascript">
    safari.application.addEventListener( "message", function( e ) {
      if( e.name === "getSettings" ) {
        e.target.page.dispatchMessage( "setSettings", {
          sort_keys: safari.extension.settings.getItem( "sort_keys" )
        } );
      }
    }, false );
  </script>
</head>
<body></body>
</html>

script.js:

( function() {
  var settings, init = function() {
    // do extension stuff
  };

  // listen for an incoming setSettings message
  safari.self.addEventListener( "message", function( e ) {
    if( e.name === "setSettings" ) {
      settings = e.message;
      init();
    }
  }, false );

  // ask proxy.html for settings
  safari.self.tab.dispatchMessage( "getSettings" );
}() )

Rick,你真是救星!非常感谢你。 - Juraj Ivan

3

编辑:就像您在初始帖子更新中所说的那样,注入的脚本没有全局HTML页面所具有的相同访问权限。这是我的工作解决方案,假设您想要知道在注入的脚本中设置“foo”的值:

注入的脚本代码:

function getMessage(msgEvent) {

    if (msgEvent.name == "settingValueIs")
        alert("Value for asked setting is: " + msgEvent.message);

}

safari.self.tab.dispatchMessage("getSettingValue", "foo"); // ask for value
safari.self.addEventListener("message", getMessage, false); // wait for reply

全局 HTML 代码:

function respondToMessage(messageEvent) {

    if (messageEvent.name == "getSettingValue") {

           // getItem("foo");
        var value = safari.extension.settings.getItem(messageEvent.message);
        // return value of foo to injected script
           safari.application.activeBrowserWindow.activeTab.page.dispatchMessage("settingValueIs", value);

    } 

}

safari.application.addEventListener("message",respondToMessage,false);

希望这能帮到你!

原始帖子:我和你一样遇到了第二个问题,无法从注入的脚本中访问我的设置(或secureSettings)。在我的情况下,脚本是在页面加载后加载的,但即使这样我也不能使用。

唯一有效的方法是使用工具栏/按钮,在该元素后面的HTML可以像预期的那样使用getItem和setItem。

我的结论是,由于某种原因,注入的脚本无法访问设置(实际上,它们甚至似乎无法访问元素)。是错误还是有意为之,需要进一步研究。


请看我上面添加的更新。我现在知道为什么你不能访问设置,并且甚至指出了如何进入它们(即使对于其他原因它对我来说也无法工作)。 - Rob Wilkerson
我刚找到了一个解决方案,已在上方发布给你或任何遇到相同问题的人。也许你可以根据自己的情况进行调整! - Mars
感谢更新。在我的情况下,所有工作都是在“beforeload”完成的,因此页面对象未定义,这似乎意味着“dispatchMessage()”方法不可用。我仍在寻找解决方法。 - Rob Wilkerson

2

我花了几天的时间,但我认为我已经找到了一个可行的解决方案,使用canLoad()消息传递方法。我的注入脚本通过调用全局HTML页面来检索设置,如下所示:

settings = safari.self.tab.canLoad( event );

我的全局HTML文件将这些设置返回为:

settings = {
  'setting1': safari.extension.settings.getItem( 'setting1' )
}

msgEvent.message = settings;

这仍然比我想象的要“hacky”一些。我似乎无法简单地返回设置对象本身,因此必须通过逐个检索每个设置来编译一个新对象。虽然不理想,但似乎很有效。


1
遇到了相同的问题,但答案比你想象的要简单:将脚本包含在全局 HTML 中即可。
<!DOCTYPE HTML>
<script type="text/javascript" src="cleanup.js"></script>
<script></script>

然后您可以按照文档中描述的方式访问设置 safari.extension.settings.myKey

您还可以为@Travis点赞,因为我从他的帖子中得到了灵感。

//编辑:
实际上我不知道出了什么问题。第一条命令调用设置是有效的,但稍后就无效了。此外,在第二次注入后,它似乎会破坏我的整个脚本。需要验证是否只在我的(困难?)脚本中出现。

//编辑2:
现在我通过dispatchMessage()成功获取了设置对象。

在您的injected.js中。

function gotSettings(msgEvent) {
   if (msgEvent.name === "SETTINGS") {
      setts = msgEvent.message;
      alert(setts.mySetting1);
      // run the programm
   }
}

safari.self.addEventListener("message", gotSettings, false);
safari.self.tab.dispatchMessage("getSettings");

并且在global.html

switch (event.name) {
case "getSettings":
   // send the settings data
   event.target.page.dispatchMessage("SETTINGS", safari.extension.settings);

依赖于this苹果文档


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接