| OLD | NEW | 
|---|
|  | (Empty) | 
| 1 /* |  | 
| 2  * This file is part of Adblock Plus <https://adblockplus.org/>, |  | 
| 3  * Copyright (C) 2006-2016 Eyeo GmbH |  | 
| 4  * |  | 
| 5  * Adblock Plus is free software: you can redistribute it and/or modify |  | 
| 6  * it under the terms of the GNU General Public License version 3 as |  | 
| 7  * published by the Free Software Foundation. |  | 
| 8  * |  | 
| 9  * Adblock Plus is distributed in the hope that it will be useful, |  | 
| 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of |  | 
| 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the |  | 
| 12  * GNU General Public License for more details. |  | 
| 13  * |  | 
| 14  * You should have received a copy of the GNU General Public License |  | 
| 15  * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>. |  | 
| 16  */ |  | 
| 17 |  | 
| 18 (function() |  | 
| 19 { |  | 
| 20   // the safari object is missing in frames created from javascript: URLs. |  | 
| 21   // So we have to fallback to the safari object from the parent frame. |  | 
| 22   if (!("safari" in window)) |  | 
| 23     window.safari = window.parent.safari; |  | 
| 24 |  | 
| 25 |  | 
| 26   /* Intialization */ |  | 
| 27 |  | 
| 28   var beforeLoadEvent = document.createEvent("Event"); |  | 
| 29   beforeLoadEvent.initEvent("beforeload", false, true); |  | 
| 30 |  | 
| 31   // Decide if we should use the new content blocker API or not. (Note when the |  | 
| 32   // API is used Safari breaks the canLoad function, making it either throw an |  | 
| 33   // exception or return true when used.) |  | 
| 34   var usingContentBlockerAPI = true; |  | 
| 35   try |  | 
| 36   { |  | 
| 37     if (safari.self.tab.canLoad(beforeLoadEvent, |  | 
| 38                                 {category: "request", |  | 
| 39                                  payload: {type: "prefs.get", |  | 
| 40                                            key: "safariContentBlocker"}}) != tru
     e) |  | 
| 41       usingContentBlockerAPI = false; |  | 
| 42   } |  | 
| 43   catch (e) |  | 
| 44   { |  | 
| 45   } |  | 
| 46 |  | 
| 47   var isTopLevel; |  | 
| 48   var isPrerendered; |  | 
| 49   var documentId; |  | 
| 50   function notifyFrameLoading() |  | 
| 51   { |  | 
| 52     isTopLevel = window == window.top; |  | 
| 53     isPrerendered = document.visibilityState == "prerender"; |  | 
| 54     documentId = Math.random().toString().substr(2); |  | 
| 55 |  | 
| 56     // Notify the background page that this frame is loading, generating |  | 
| 57     // ourselves a random documentId while we're at it. That way the background |  | 
| 58     // page can communicate with us reliably, despite limitations in Safari's |  | 
| 59     // extension API. |  | 
| 60     safari.self.tab.dispatchMessage("loading",  { |  | 
| 61       url: window.location.href, |  | 
| 62       referrer: document.referrer, |  | 
| 63       isTopLevel: isTopLevel, |  | 
| 64       isPrerendered: isPrerendered, |  | 
| 65       documentId: documentId, |  | 
| 66       legacyAPISupported: "canLoad" in safari.self.tab && |  | 
| 67                           "onbeforeload" in Element.prototype |  | 
| 68     }); |  | 
| 69   } |  | 
| 70 |  | 
| 71   // We must notify the background page when this page is first loadeding (now) |  | 
| 72   // but also when it is re-shown (if the user uses the back button to return to |  | 
| 73   // this page in the future). |  | 
| 74   notifyFrameLoading(); |  | 
| 75   window.addEventListener("pageshow", function(event) |  | 
| 76   { |  | 
| 77     if (event.persisted) |  | 
| 78       notifyFrameLoading(); |  | 
| 79   }); |  | 
| 80 |  | 
| 81   // Notify the background page when a prerendered page is displayed. That way |  | 
| 82   // the existing page of the tab can be replaced with this new one. |  | 
| 83   if (isTopLevel && isPrerendered) |  | 
| 84   { |  | 
| 85     var onVisibilitychange = function() |  | 
| 86     { |  | 
| 87       safari.self.tab.dispatchMessage("replaced", {documentId: documentId}); |  | 
| 88       document.removeEventListener("visibilitychange", onVisibilitychange); |  | 
| 89     }; |  | 
| 90     document.addEventListener("visibilitychange", onVisibilitychange); |  | 
| 91   } |  | 
| 92 |  | 
| 93   /* Web requests */ |  | 
| 94 |  | 
| 95   if (!usingContentBlockerAPI) |  | 
| 96   { |  | 
| 97     document.addEventListener("beforeload", function(event) |  | 
| 98     { |  | 
| 99       // we don't block non-HTTP requests anyway, so we can bail out |  | 
| 100       // without asking the background page. This is even necessary |  | 
| 101       // because passing large data (like a photo encoded as data: URL) |  | 
| 102       // to the background page, freezes Safari. |  | 
| 103       if (/^(?!https?:)[\w-]+:/.test(event.url)) |  | 
| 104         return; |  | 
| 105 |  | 
| 106       var type = "OTHER"; |  | 
| 107       var eventName = "error"; |  | 
| 108 |  | 
| 109       switch(event.target.localName) |  | 
| 110       { |  | 
| 111         case "frame": |  | 
| 112         case "iframe": |  | 
| 113           type = "SUBDOCUMENT"; |  | 
| 114           eventName = "load"; |  | 
| 115           break; |  | 
| 116         case "img": |  | 
| 117         case "input": |  | 
| 118           type = "IMAGE"; |  | 
| 119           break; |  | 
| 120         case "video": |  | 
| 121         case "audio": |  | 
| 122         case "source": |  | 
| 123           type = "MEDIA"; |  | 
| 124           break; |  | 
| 125         case "object": |  | 
| 126         case "embed": |  | 
| 127           type = "OBJECT"; |  | 
| 128           break; |  | 
| 129         case "script": |  | 
| 130           type = "SCRIPT"; |  | 
| 131           break; |  | 
| 132         case "link": |  | 
| 133           if (/\bstylesheet\b/i.test(event.target.rel)) |  | 
| 134             type = "STYLESHEET"; |  | 
| 135           break; |  | 
| 136       } |  | 
| 137 |  | 
| 138       if (!safari.self.tab.canLoad( |  | 
| 139         event, { |  | 
| 140           category: "webRequest", |  | 
| 141           url: event.url, |  | 
| 142           type: type, |  | 
| 143           documentId: documentId})) |  | 
| 144       { |  | 
| 145         event.preventDefault(); |  | 
| 146 |  | 
| 147         // Safari doesn't dispatch the expected events for elements that have |  | 
| 148         // been prevented from loading by having their "beforeload" event |  | 
| 149         // cancelled. That is a "load" event for blocked frames, and an "error" |  | 
| 150         // event for other blocked elements. We need to dispatch those events |  | 
| 151         // manually here to avoid breaking element collapsing and pages that |  | 
| 152         // rely on those events. |  | 
| 153         setTimeout(function() |  | 
| 154         { |  | 
| 155           var evt = document.createEvent("Event"); |  | 
| 156           evt.initEvent(eventName, false, false); |  | 
| 157           event.target.dispatchEvent(evt); |  | 
| 158         }); |  | 
| 159       } |  | 
| 160     }, true); |  | 
| 161   } |  | 
| 162 |  | 
| 163 |  | 
| 164   /* Context menus */ |  | 
| 165 |  | 
| 166   document.addEventListener("contextmenu", function(event) |  | 
| 167   { |  | 
| 168     var element = event.srcElement; |  | 
| 169     safari.self.tab.setContextMenuEventUserInfo(event, { |  | 
| 170       documentId: documentId, |  | 
| 171       tagName: element.localName |  | 
| 172     }); |  | 
| 173   }); |  | 
| 174 |  | 
| 175 |  | 
| 176   /* Background page */ |  | 
| 177 |  | 
| 178   ext.backgroundPage = { |  | 
| 179     sendMessage: function(message, responseCallback) |  | 
| 180     { |  | 
| 181       messageProxy.sendMessage(message, responseCallback, |  | 
| 182                                {documentId: documentId}); |  | 
| 183     }, |  | 
| 184     sendMessageSync: function(message) |  | 
| 185     { |  | 
| 186       return safari.self.tab.canLoad( |  | 
| 187         beforeLoadEvent, |  | 
| 188         { |  | 
| 189           category: "request", |  | 
| 190           documentId: documentId, |  | 
| 191           payload: message |  | 
| 192         } |  | 
| 193       ); |  | 
| 194     } |  | 
| 195   }; |  | 
| 196 |  | 
| 197 |  | 
| 198   /* Message processing */ |  | 
| 199 |  | 
| 200   var messageProxy = new ext._MessageProxy(safari.self.tab); |  | 
| 201 |  | 
| 202   safari.self.addEventListener("message", function(event) |  | 
| 203   { |  | 
| 204     if (event.name == "requestDocumentId" && isTopLevel) |  | 
| 205     { |  | 
| 206       safari.self.tab.dispatchMessage("documentId",  { |  | 
| 207         pageId: event.message.pageId, |  | 
| 208         documentId: documentId |  | 
| 209       }); |  | 
| 210     } |  | 
| 211     else if (event.message.targetDocuments.indexOf(documentId) != -1) |  | 
| 212     { |  | 
| 213       switch (event.name) |  | 
| 214       { |  | 
| 215         case "request": |  | 
| 216           messageProxy.handleRequest(event.message, {}); |  | 
| 217           break; |  | 
| 218         case "response": |  | 
| 219           messageProxy.handleResponse(event.message); |  | 
| 220           break; |  | 
| 221       } |  | 
| 222     } |  | 
| 223   }); |  | 
| 224 |  | 
| 225 |  | 
| 226   /* Detecting extension reload/disable/uninstall (not supported on Safari) */ |  | 
| 227 |  | 
| 228   ext.onExtensionUnloaded = { |  | 
| 229     addListener: function() {}, |  | 
| 230     removeListener: function() {} |  | 
| 231   }; |  | 
| 232 })(); |  | 
| OLD | NEW | 
|---|