Safari Extension Questions

前端 未结 4 1184
萌比男神i
萌比男神i 2021-02-05 17:43

I\'m in the process of building my first Safari extension--a very simple one--but I\'ve run into a couple of problems. The extension boils down to a single, injected script that

相关标签:
4条回答
  • 2021-02-05 18:25

    EDIT: like you said in your initial post update, the injected script doesn't have the same kind of access that a global HTML page would have. This is my working solution, imagine you want to know the value of setting "foo" in the injected script:

    Injected script code:

    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
    

    Global HTML code:

    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);
    

    Hope this helps !


    Initial post: I'm having the same 2nd problem as you, I can't access my settings (or secureSettings) from an injected script. In my case the script is loaded after page load, but even that way I can't use safari.extension.settings.

    The only way it works is with a toolbar/button, the HTML behind that element can getItem and setItem as expected.

    My conclusion is that, for some reason, injected scripts can't access settings (actually, they don't even seem to have access to the safari element). Bug or intended feature, that's left to figure out.

    0 讨论(0)
  • 2021-02-05 18:27

    Like everyone else at this point, I'm still climbing the learning curve, but here's how I've handled this problem:

    I have a simple extension with no chrome and one injected end script (script.js). For the purpose of loading settings I've added a simple global page (proxy.html). When script.js is injected, it sends a getSettings message to proxy.html. proxy.html responds with a setSettings message, and script.js continues initialization.

    The most helpful page I've found in the docs on this topic is 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" );
    }() )
    
    0 讨论(0)
  • 2021-02-05 18:31

    run into the same problem, but the answer is easier than you can imagine: include the script in your global html.

    <!DOCTYPE HTML>
    <script type="text/javascript" src="cleanup.js"></script>
    <script>
    …
    </script>
    

    then you can access the settings as described in documentation safari.extension.settings.myKey

    you can also upvote @Travis, because I got the idea from his post

    //EDIT:
    actually I don't really know whats wrong. Calling the settings as the first command works, but not at a later time. Additionally it seems to corrupting my complete script after the 2. injection. Need verification if it's only in my (difficult?) script.

    //EDIT2:
    now I got it to work to get back the settings object via dispatchMessage()

    in your 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");
    

    and in global.html

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

    relying on this apple documentation

    0 讨论(0)
  • 2021-02-05 18:37

    It took me several days, but I think I found a workable solution using the canLoad() messaging method. My injection script retrieves settings by calling the global HTML page like this:

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

    My global HTML file, in turn, returns those settings as:

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

    It's still a bit more "hacky" than I'd like. I can't seem to simply return the settings object itself, so I have to compile a new object by retrieving each setting manually. Not ideal, but it does seem to be effective.

    0 讨论(0)
提交回复
热议问题