Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 /* | 1 /* |
2 * This file is part of Adblock Plus <http://adblockplus.org/>, | 2 * This file is part of Adblock Plus <http://adblockplus.org/>, |
3 * Copyright (C) 2006-2013 Eyeo GmbH | 3 * Copyright (C) 2006-2014 Eyeo GmbH |
4 * | 4 * |
5 * Adblock Plus is free software: you can redistribute it and/or modify | 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 | 6 * it under the terms of the GNU General Public License version 3 as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
8 * | 8 * |
9 * Adblock Plus is distributed in the hope that it will be useful, | 9 * Adblock Plus is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 * GNU General Public License for more details. | 12 * GNU General Public License for more details. |
13 * | 13 * |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
54 sendMessage: function(message, responseCallback) | 54 sendMessage: function(message, responseCallback) |
55 { | 55 { |
56 sendMessage(this._id, message, responseCallback); | 56 sendMessage(this._id, message, responseCallback); |
57 } | 57 } |
58 }; | 58 }; |
59 | 59 |
60 ext.pages = { | 60 ext.pages = { |
61 open: function(url, callback) | 61 open: function(url, callback) |
62 { | 62 { |
63 if (callback) | 63 if (callback) |
64 chrome.tabs.create({url: url}, function(tab) { callback(new Page(tab)); }); | 64 { |
65 chrome.tabs.create({url: url}, function(openedTab) | |
66 { | |
67 var onUpdated = function(tabId, changeInfo, tab) | |
68 { | |
69 if (tabId == openedTab.id && changeInfo.status == "complete") | |
70 { | |
71 chrome.tabs.onUpdated.removeListener(onUpdated); | |
72 callback(new Page(tab)); | |
73 } | |
74 }; | |
75 chrome.tabs.onUpdated.addListener(onUpdated); | |
76 }); | |
77 } | |
65 else | 78 else |
66 chrome.tabs.create({url: url}); | 79 chrome.tabs.create({url: url}); |
67 }, | 80 }, |
68 query: function(info, callback) | 81 query: function(info, callback) |
69 { | 82 { |
70 var rawInfo = {}; | 83 var rawInfo = {}; |
71 var visibleWindow = null; | |
72 | |
73 for (var property in info) | 84 for (var property in info) |
74 { | 85 { |
75 switch (property) | 86 switch (property) |
76 { | 87 { |
77 case "active": | 88 case "active": |
78 case "lastFocusedWindow": | 89 case "lastFocusedWindow": |
79 rawInfo[property] = info[property]; | 90 rawInfo[property] = info[property]; |
80 break; | |
81 case "visibleWindow": | |
82 visibleWindow = info[property]; | |
83 break; | |
84 } | 91 } |
85 } | 92 } |
86 | 93 |
87 chrome.tabs.query(rawInfo, function(tabs) | 94 chrome.tabs.query(rawInfo, function(tabs) |
88 { | 95 { |
89 if (visibleWindow != null && tabs.length > 0) | 96 callback(tabs.map(function(tab) |
90 { | 97 { |
91 var windows = {__proto__: null}; | 98 return new Page(tab); |
92 var pending = 0; | 99 })); |
93 | |
94 for (var i = 0; i < tabs.length; i++) | |
95 { | |
96 var windowId = tabs[i].windowId; | |
97 if (!(windowId in windows)) | |
98 { | |
99 windows[windowId] = null; | |
100 pending++; | |
101 | |
102 chrome.windows.get(windowId, null, function(win) | |
103 { | |
104 if (visibleWindow != (win.state != "minimized")) | |
Wladimir Palant
2014/04/04 14:00:35
That's quite a bit of code just to exclude minimiz
Sebastian Noack
2014/04/07 13:15:25
We need that for the icon animation, in order to a
Wladimir Palant
2014/04/11 13:02:35
It seems that the original code was only animating
Sebastian Noack
2014/04/11 14:47:45
Done.
| |
105 { | |
106 for (var j = 0; j < tabs.length; j++) | |
107 { | |
108 if (tabs[j].windowId == win.id) | |
109 tabs.splice(j--, 1); | |
110 } | |
111 } | |
112 | |
113 if (--pending == 0) | |
114 callback(tabs.map(function(tab) | |
115 { | |
116 return new Page(tab); | |
117 })); | |
118 }); | |
119 } | |
120 } | |
121 } | |
122 else | |
123 { | |
124 callback(tabs.map(function(tab) | |
125 { | |
126 return new Page(tab); | |
127 })); | |
128 } | |
129 }); | 100 }); |
130 }, | 101 }, |
131 onLoading: new ext._EventTarget() | 102 onLoading: new ext._EventTarget() |
132 }; | 103 }; |
133 | 104 |
134 chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) | 105 chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) |
135 { | 106 { |
136 if (changeInfo.status == "loading") | 107 if (changeInfo.status == "loading") |
137 ext.pages.onLoading._dispatch(new Page(tab)); | 108 ext.pages.onLoading._dispatch(new Page(tab)); |
138 }); | 109 }); |
139 | 110 |
140 chrome.webNavigation.onBeforeNavigate.addListener(function(details) | 111 chrome.webNavigation.onBeforeNavigate.addListener(function(details) |
141 { | 112 { |
142 if (details.frameId == 0) | 113 if (details.frameId == 0) |
143 ext._removeFromAllPageMaps(details.tabId); | 114 ext._removeFromAllPageMaps(details.tabId); |
144 }); | 115 }); |
Wladimir Palant
2014/04/04 14:00:35
Just wondering: will this also be triggered for na
Sebastian Noack
2014/04/07 13:15:25
It isn't triggered for javascript: URLs entered in
Wladimir Palant
2014/04/11 13:02:35
I did some testing and it seems that using onBefor
| |
145 | 116 |
146 chrome.tabs.onRemoved.addListener(function(tabId) | 117 chrome.tabs.onRemoved.addListener(function(tabId) |
147 { | 118 { |
148 ext._removeFromAllPageMaps(tabId); | 119 ext._removeFromAllPageMaps(tabId); |
149 delete framesOfTabs[tabId]; | 120 delete framesOfTabs[tabId]; |
150 }); | 121 }); |
151 | 122 |
152 | 123 |
153 /* Browser actions */ | 124 /* Browser actions */ |
154 | 125 |
155 var BrowserAction = function(tabId) | 126 var BrowserAction = function(tabId) |
156 { | 127 { |
157 this._tabId = tabId; | 128 this._tabId = tabId; |
158 }; | 129 }; |
159 BrowserAction.prototype = { | 130 BrowserAction.prototype = { |
160 setIcon: function(path) | 131 setIcon: function(path) |
161 { | 132 { |
162 chrome.browserAction.setIcon({tabId: this._tabId, path: path}); | 133 var paths = {}; |
134 for (var i = 1; i <= 2; i++) | |
135 { | |
136 var size = i * 19; | |
137 paths[size] = path.replace("$size", size); | |
138 } | |
139 | |
140 chrome.browserAction.setIcon({tabId: this._tabId, path: paths}); | |
163 }, | 141 }, |
164 setBadge: function(badge) | 142 setBadge: function(badge) |
165 { | 143 { |
166 if (!badge) | 144 if (!badge) |
167 { | 145 { |
168 chrome.browserAction.setBadgeText({ | 146 chrome.browserAction.setBadgeText({ |
169 tabId: this._tabId, | 147 tabId: this._tabId, |
170 text: "" | 148 text: "" |
171 }); | 149 }); |
172 return; | 150 return; |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
249 | 227 |
250 /* Web requests */ | 228 /* Web requests */ |
251 | 229 |
252 ext.webRequest = { | 230 ext.webRequest = { |
253 onBeforeRequest: new ext._EventTarget(true), | 231 onBeforeRequest: new ext._EventTarget(true), |
254 handlerBehaviorChanged: chrome.webRequest.handlerBehaviorChanged | 232 handlerBehaviorChanged: chrome.webRequest.handlerBehaviorChanged |
255 }; | 233 }; |
256 | 234 |
257 chrome.webRequest.onBeforeRequest.addListener(function(details) | 235 chrome.webRequest.onBeforeRequest.addListener(function(details) |
258 { | 236 { |
259 // the high-level code isn't interested in requests that aren't related | 237 try |
260 // to a tab and since those can only be handled in Chrome, we ignore | 238 { |
261 // them here instead of in the browser independent high-level code. | 239 // the high-level code isn't interested in requests that aren't related |
262 if (details.tabId == -1) | 240 // to a tab and since those can only be handled in Chrome, we ignore |
263 return; | 241 // them here instead of in the browser independent high-level code. |
264 | 242 if (details.tabId == -1) |
265 var page = new Page({id: details.tabId}); | |
266 var frames = framesOfTabs[details.tabId]; | |
267 | |
268 if (!frames) | |
269 { | |
270 frames = framesOfTabs[details.tabId] = []; | |
271 | |
272 // assume that the first request belongs to the top frame. Chrome | |
273 // may give the top frame the type "object" instead of "main_frame". | |
274 // https://code.google.com/p/chromium/issues/detail?id=281711 | |
275 if (frameId == 0) | |
276 details.type = "main_frame"; | |
277 } | |
278 | |
279 var frameId; | |
280 if (details.type == "main_frame" || details.type == "sub_frame") | |
281 { | |
282 frameId = details.parentFrameId; | |
283 frames[details.frameId] = {url: details.url, parent: frameId}; | |
284 | |
285 // the high-level code isn't interested in top frame requests and | |
286 // since those can only be handled in Chrome, we ignore them here | |
287 // instead of in the browser independent high-level code. | |
288 if (details.type == "main_frame") | |
289 return; | 243 return; |
290 } | 244 |
291 else | 245 var page = new Tab({id: details.tabId}); |
292 frameId = details.frameId; | 246 var frames = framesOfTabs[details.tabId]; |
293 | 247 |
294 if (!(frameId in frames)) | 248 if (!frames) |
295 { | 249 { |
296 // the high-level code relies on the frame. So ignore the request if we | 250 frames = framesOfTabs[details.tabId] = []; |
297 // don't even know the top-level frame. That can happen for example when | 251 |
298 // the extension was just (re)loaded. | 252 // assume that the first request belongs to the top frame. Chrome |
299 if (!(0 in frames)) | 253 // may give the top frame the type "object" instead of "main_frame". |
300 return; | 254 // https://code.google.com/p/chromium/issues/detail?id=281711 |
301 | 255 if (frameId == 0) |
302 // however when the src of the frame is a javascript: or data: URL, we | 256 details.type = "main_frame"; |
303 // don't know the frame either. But since we know the top-level frame we | 257 } |
304 // can just pretend that we are in the top-level frame, in order to have | 258 |
305 // at least most domain-based filter rules working. | 259 var frameId; |
306 frameId = 0; | 260 if (details.type == "main_frame" || details.type == "sub_frame") |
307 if (details.type == "sub_frame") | 261 { |
308 frames[details.frameId].parent = frameId; | 262 frameId = details.parentFrameId; |
309 } | 263 frames[details.frameId] = {url: details.url, parent: frameId}; |
310 | 264 |
311 var frame = new Frame({frameId: frameId, tabId: details.tabId}); | 265 // the high-level code isn't interested in top frame requests and |
312 | 266 // since those can only be handled in Chrome, we ignore them here |
313 if (!ext.webRequest.onBeforeRequest._dispatch(details.url, details.type, pag e, frame)) | 267 // instead of in the browser independent high-level code. |
314 return {cancel: true}; | 268 if (details.type == "main_frame") |
269 return; | |
270 } | |
271 else | |
272 frameId = details.frameId; | |
273 | |
274 if (!(frameId in frames)) | |
275 { | |
276 // the high-level code relies on the frame. So ignore the request if we | |
277 // don't even know the top-level frame. That can happen for example when | |
278 // the extension was just (re)loaded. | |
279 if (!(0 in frames)) | |
280 return; | |
281 | |
282 // however when the src of the frame is a javascript: or data: URL, we | |
283 // don't know the frame either. But since we know the top-level frame we | |
284 // can just pretend that we are in the top-level frame, in order to have | |
285 // at least most domain-based filter rules working. | |
286 frameId = 0; | |
287 if (details.type == "sub_frame") | |
288 frames[details.frameId].parent = frameId; | |
289 } | |
290 | |
291 var frame = new Frame({id: frameId, tabId: details.tabId}); | |
292 | |
293 if (!ext.webRequest.onBeforeRequest._dispatch(details.url, details.type, p age, frame)) | |
294 return {cancel: true}; | |
295 } | |
296 catch (e) | |
297 { | |
298 // recent versions of Chrome cancel the request when an error occurs in | |
299 // the onBeforeRequest listener. However in our case it is preferred, to | |
300 // let potentially some ads through, rather than blocking legit requests. | |
301 console.error(e); | |
302 } | |
315 }, {urls: ["<all_urls>"]}, ["blocking"]); | 303 }, {urls: ["<all_urls>"]}, ["blocking"]); |
316 | 304 |
317 | 305 |
318 /* Context menus */ | 306 /* Context menus */ |
319 | 307 |
320 var contextMenuItems = []; | 308 var contextMenuItems = []; |
321 var isContextMenuHidden = true; | 309 var isContextMenuHidden = true; |
322 | 310 |
323 ext.contextMenus = { | 311 ext.contextMenus = { |
324 addMenuItem: function(title, contexts, onclick) | 312 addMenuItem: function(title, contexts, onclick) |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
370 | 358 |
371 /* Message passing */ | 359 /* Message passing */ |
372 | 360 |
373 ext._setupMessageListener(function(sender) | 361 ext._setupMessageListener(function(sender) |
374 { | 362 { |
375 return { | 363 return { |
376 page: new Page(sender.tab), | 364 page: new Page(sender.tab), |
377 frame: new Frame({url: sender.url, tabId: sender.tab.id}) | 365 frame: new Frame({url: sender.url, tabId: sender.tab.id}) |
378 }; | 366 }; |
379 }); | 367 }); |
368 | |
369 | |
370 /* Storage */ | |
371 | |
372 ext.storage = localStorage; | |
380 })(); | 373 })(); |
LEFT | RIGHT |