| Index: safari/ext/content.js | 
| diff --git a/safari/ext/content.js b/safari/ext/content.js | 
| index 164d1a4d9574b6b1e4ef569a15260b2f313f57db..74206aa17458d8a8b6182c91e3f07f525460dcec 100644 | 
| --- a/safari/ext/content.js | 
| +++ b/safari/ext/content.js | 
| @@ -28,6 +28,17 @@ | 
| var beforeLoadEvent = document.createEvent("Event"); | 
| beforeLoadEvent.initEvent("beforeload"); | 
|  | 
| +  // Decide if we should use the new content blocker API or not. (Note when the | 
| +  // API is used Safari breaks the canLoad function, making it either throw an | 
| +  // exception or return true when used.) | 
| +  var usingContentBlockerAPI = true; | 
| +  try { | 
| +    if (safari.self.tab.canLoad(beforeLoadEvent, | 
| +                                {category: "usingContentBlockerAPI"}) != true) | 
| +      usingContentBlockerAPI = false; | 
| +  } | 
| +  catch (e) { }; | 
| + | 
| var isTopLevel; | 
| var isPrerendered; | 
| var documentId; | 
| @@ -60,83 +71,87 @@ | 
| notifyFrameLoading(); | 
| }); | 
|  | 
| -  // Notify the background page when a prerendered page is displayed. That way | 
| -  // the existing page of the tab can be replaced with this new one. | 
| -  if (isTopLevel && isPrerendered) | 
| +  if (!usingContentBlockerAPI) | 
| { | 
| -    var onVisibilitychange = function() | 
| +    // Notify the background page when a prerendered page is displayed. That way | 
| +    // the existing page of the tab can be replaced with this new one. | 
| +    if (isTopLevel && isPrerendered) | 
| { | 
| -      safari.self.tab.dispatchMessage("replaced", {documentId: documentId}); | 
| -      document.removeEventListener("visibilitychange", onVisibilitychange); | 
| -    }; | 
| -    document.addEventListener("visibilitychange", onVisibilitychange); | 
| -  } | 
| - | 
| +      var onVisibilitychange = function() | 
| +      { | 
| +        safari.self.tab.dispatchMessage("replaced", {documentId: documentId}); | 
| +        document.removeEventListener("visibilitychange", onVisibilitychange); | 
| +      }; | 
| +      document.addEventListener("visibilitychange", onVisibilitychange); | 
| +    } | 
|  | 
| /* Web requests */ | 
|  | 
| -  document.addEventListener("beforeload", function(event) | 
| -  { | 
| -    // we don't block non-HTTP requests anyway, so we can bail out | 
| -    // without asking the background page. This is even necessary | 
| -    // because passing large data (like a photo encoded as data: URL) | 
| -    // to the background page, freezes Safari. | 
| -    if (/^(?!https?:)[\w-]+:/.test(event.url)) | 
| -      return; | 
| +    document.addEventListener("beforeload", function(event) | 
| +    { | 
| +      // we don't block non-HTTP requests anyway, so we can bail out | 
| +      // without asking the background page. This is even necessary | 
| +      // because passing large data (like a photo encoded as data: URL) | 
| +      // to the background page, freezes Safari. | 
| +      if (/^(?!https?:)[\w-]+:/.test(event.url)) | 
| +        return; | 
|  | 
| -    var type = "OTHER"; | 
| -    var eventName = "error"; | 
| +      var type = "OTHER"; | 
| +      var eventName = "error"; | 
|  | 
| -    switch(event.target.localName) | 
| -    { | 
| -      case "frame": | 
| -      case "iframe": | 
| -        type = "SUBDOCUMENT"; | 
| -        eventName = "load"; | 
| -        break; | 
| -      case "img": | 
| -      case "input": | 
| -        type = "IMAGE"; | 
| -        break; | 
| -      case "video": | 
| -      case "audio": | 
| -      case "source": | 
| -        type = "MEDIA"; | 
| -        break; | 
| -      case "object": | 
| -      case "embed": | 
| -        type = "OBJECT"; | 
| -        break; | 
| -      case "script": | 
| -        type = "SCRIPT"; | 
| -        break; | 
| -      case "link": | 
| -        if (/\bstylesheet\b/i.test(event.target.rel)) | 
| -          type = "STYLESHEET"; | 
| -        break; | 
| -    } | 
| +      switch(event.target.localName) | 
| +      { | 
| +        case "frame": | 
| +        case "iframe": | 
| +          type = "SUBDOCUMENT"; | 
| +          eventName = "load"; | 
| +          break; | 
| +        case "img": | 
| +        case "input": | 
| +          type = "IMAGE"; | 
| +          break; | 
| +        case "video": | 
| +        case "audio": | 
| +        case "source": | 
| +          type = "MEDIA"; | 
| +          break; | 
| +        case "object": | 
| +        case "embed": | 
| +          type = "OBJECT"; | 
| +          break; | 
| +        case "script": | 
| +          type = "SCRIPT"; | 
| +          break; | 
| +        case "link": | 
| +          if (/\bstylesheet\b/i.test(event.target.rel)) | 
| +            type = "STYLESHEET"; | 
| +          break; | 
| +      } | 
|  | 
| -    if (!safari.self.tab.canLoad(event, { | 
| -        category: "webRequest", | 
| -        url: event.url, | 
| -        type: type, | 
| -        documentId: documentId})) | 
| -    { | 
| -      event.preventDefault(); | 
| - | 
| -      // Safari doesn't dispatch the expected events for elements that have been | 
| -      // prevented from loading by having their "beforeload" event cancelled. | 
| -      // That is a "load" event for blocked frames, and an "error" event for | 
| -      // other blocked elements. We need to dispatch those events manually here | 
| -      // to avoid breaking element collapsing and pages that rely on those events. | 
| -      setTimeout(function() | 
| +      if (!safari.self.tab.canLoad( | 
| +        event, { | 
| +          category: "webRequest", | 
| +          url: event.url, | 
| +          type: type, | 
| +          documentId: documentId})) | 
| { | 
| -        var evt = document.createEvent("Event"); | 
| -        evt.initEvent(eventName); | 
| -        event.target.dispatchEvent(evt); | 
| -      }, 0); | 
| -    } | 
| -  }, true); | 
| +        event.preventDefault(); | 
| + | 
| +        // Safari doesn't dispatch the expected events for elements that have | 
| +        // been prevented from loading by having their "beforeload" event | 
| +        // cancelled. That is a "load" event for blocked frames, and an "error" | 
| +        // event for other blocked elements. We need to dispatch those events | 
| +        // manually here to avoid breaking element collapsing and pages that | 
| +        // rely on those events. | 
| +        setTimeout(function() | 
| +        { | 
| +          var evt = document.createEvent("Event"); | 
| +          evt.initEvent(eventName); | 
| +          event.target.dispatchEvent(evt); | 
| +        }, 0); | 
| +      } | 
| +    }, true); | 
| +  } | 
|  | 
|  | 
| /* Context menus */ | 
|  |