Search code examples
safarisafari-extension

Safari Extension Questions


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 attempts to bypass the native feed handler and redirect to an http:// URI. My issues so far are twofold:

  1. The "whitelist" isn't working the way I'd expect. Since all feeds are shown under the "feed://" protocol, I've tried to capture that in the whitelist as "feed://*/*" (with nothing in the blacklist), but I end up in a request loop that I can't understand. If I set blacklist values of "http://*/*" and "https://*/*", everything works as expected.
  2. I can't figure out how to access my settings from my injected script. The script creates a beforeload event handler, but can't access my settings using the safari.extension.settings path indicated in the documentation.

I haven't found anything in Apple's documentation to indicate that settings shouldn't be available from my script. Since extensions are such a new feature, even Google returns limited relevant results and most of those are from the official documentation.

What am I missing?

UPDATE So I'm hoping that the documentation is incomplete because it's borderline abysmal, but I've learned a bit about settings. It turns out that, from injection scripts, the SafariExtensionSettings object isn't available. Injection scripts only have access to the SafariContentExtension object (which isn't useful at all), but it's aliased in exactly the same manner (safari.extension.settings)--bad idea, IMO. As stated in the injection script documentation:

Important: When you use safari.extension from within an injected script, you are not addressing the SafariExtension class. You are addressing the SafariContentExtension class.

You have to use the messaging system to talk to a global HTML file which has access to the settings. It's kind of loopy, but I have a message being sent to a global.html file that retrieves the settings and will send a message back to my injection script as soon as I figure out how to go about doing that.

Since I'm doing all of my work before the document loads, all of the methods I've found to send message back rely on a page object that I don't have.


Solution

  • 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.