Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: safari/background.js

Issue 16067002: Added Safari Support (Closed)
Left Patch Set: Added missing copyright disclaimers and websql implementation Created Oct. 23, 2013, 2:46 p.m.
Right Patch Set: Bugfixes Created Nov. 15, 2013, 8:58 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « popupBlocker.js ('k') | safari/common.js » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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-2013 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 *
14 * You should have received a copy of the GNU General Public License 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/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 (function() { 18 (function()
19 {
19 /* Tabs */ 20 /* Tabs */
20 21
21 var TabEventTarget = function() { 22 var TabEventTarget = function()
23 {
22 WrappedEventTarget.apply(this, arguments); 24 WrappedEventTarget.apply(this, arguments);
23 }; 25 };
24 TabEventTarget.prototype = { 26 TabEventTarget.prototype = {
25 __proto__: WrappedEventTarget.prototype, 27 __proto__: WrappedEventTarget.prototype,
26 _wrapListener: function(listener) { 28 _wrapListener: function(listener)
27 return function(event) { 29 {
28 listener(new Tab(event.target)); 30 return function(event)
31 {
32 if (event.target instanceof SafariBrowserTab)
33 listener(new Tab(event.target));
29 }; 34 };
30 } 35 }
31 }; 36 };
32 37
33 Tab = function(tab) { 38 Tab = function(tab)
39 {
34 this._tab = tab; 40 this._tab = tab;
35 41
36 this._eventTarget = tab; 42 this._eventTarget = tab;
37 this._messageDispatcher = tab.page; 43 this._messageDispatcher = tab.page;
38 44
39 this.url = tab.url;
40
41 this.onBeforeNavigate = new TabEventTarget(tab, "beforeNavigate", false); 45 this.onBeforeNavigate = new TabEventTarget(tab, "beforeNavigate", false);
42 this.onCompleted = new TabEventTarget(tab, "navigate", false); 46 this.onCompleted = new TabEventTarget(tab, "navigate", false);
43 this.onActivated = new TabEventTarget(tab, "activate", false); 47 this.onActivated = new TabEventTarget(tab, "activate", false);
44 this.onRemoved = new TabEventTarget(tab, "close", false); 48 this.onRemoved = new TabEventTarget(tab, "close", false);
45 }; 49 };
46 Tab.prototype = { 50 Tab.prototype = {
47 close: function() { 51 get url()
52 {
53 return this._tab.url;
54 },
55 close: function()
56 {
48 this._tab.close(); 57 this._tab.close();
49 }, 58 },
50 activate: function() { 59 activate: function()
60 {
51 this._tab.activate(); 61 this._tab.activate();
52 }, 62 },
53 sendMessage: sendMessage, 63 sendMessage: sendMessage,
54 pageAction: { 64 pageAction: {
55 // there are no page actions in safari, so we use toolbar items instead 65 // there are no page actions in safari, so we use toolbar items instead
56 setIcon: function(path) { 66 setIcon: function(path)
67 {
57 safari.extension.toolbarItems[0].image = safari.extension.baseURI + path ; 68 safari.extension.toolbarItems[0].image = safari.extension.baseURI + path ;
58 }, 69 },
59 setTitle: function(title) { 70 setTitle: function(title)
71 {
60 safari.extension.toolbarItems[0].toolTip = title; 72 safari.extension.toolbarItems[0].toolTip = title;
61 }, 73 },
62 74
63 // toolbar items in safari can"t get hidden 75 // toolbar items in safari can"t get hidden
64 hide: function() {}, 76 hide: function() {},
65 show: function() {} 77 show: function() {}
66 } 78 }
67 }; 79 };
68 80
69 TabMap = function() { 81 TabMap = function()
82 {
70 this._tabs = []; 83 this._tabs = [];
71 this._values = []; 84 this._values = [];
72 85
73 this._onClosed = this._onClosed.bind(this); 86 this._onClosed = this._onClosed.bind(this);
74 }; 87 };
75 TabMap.prototype = { 88 TabMap.prototype =
89 {
76 get: function(tab) { 90 get: function(tab) {
77 var idx; 91 var idx;
78 92
79 if (!tab || (idx = this._tabs.indexOf(tab._tab)) == -1) 93 if (!tab || (idx = this._tabs.indexOf(tab._tab)) == -1)
80 return null; 94 return null;
81 95
82 return this._values[idx]; 96 return this._values[idx];
83 }, 97 },
84 set: function(tab, value) { 98 set: function(tab, value)
99 {
85 var idx = this._tabs.indexOf(tab._tab); 100 var idx = this._tabs.indexOf(tab._tab);
86 101
87 if (idx != -1) 102 if (idx != -1)
88 this._values[idx] = value; 103 this._values[idx] = value;
89 else { 104 else
105 {
90 this._tabs.push(tab._tab); 106 this._tabs.push(tab._tab);
91 this._values.push(value); 107 this._values.push(value);
92 108
93 tab._tab.addEventListener("close", this._onClosed, false); 109 tab._tab.addEventListener("close", this._onClosed, false);
94 } 110 }
95 }, 111 },
96 has: function(tab) { 112 has: function(tab)
113 {
97 return this._tabs.indexOf(tab._tab) != -1; 114 return this._tabs.indexOf(tab._tab) != -1;
98 }, 115 },
99 clear: function() { 116 clear: function()
117 {
100 while (this._tabs.length > 0) 118 while (this._tabs.length > 0)
101 this._delete(this._tabs[0]); 119 this._delete(this._tabs[0]);
102 }, 120 },
103 _delete: function(tab) { 121 _delete: function(tab)
122 {
104 var idx = this._tabs.indexOf(tab); 123 var idx = this._tabs.indexOf(tab);
105 124
106 if (idx != -1) { 125 if (idx != -1)
126 {
107 this._tabs.splice(idx, 1); 127 this._tabs.splice(idx, 1);
108 this._values.splice(idx, 1); 128 this._values.splice(idx, 1);
109 129
110 tab.removeEventListener("close", this._onClosed, false); 130 tab.removeEventListener("close", this._onClosed, false);
111 } 131 }
112 }, 132 },
113 _onClosed: function(event) { 133 _onClosed: function(event)
134 {
114 this._delete(event.target); 135 this._delete(event.target);
115 } 136 }
116 }; 137 };
117 TabMap.prototype["delete"] = function(tab) { 138 TabMap.prototype["delete"] = function(tab)
139 {
118 this._delete(tab._tab); 140 this._delete(tab._tab);
119 }; 141 };
120 142
121 143
122 /* Windows */ 144 /* Windows */
123 145
124 Window = function(win) { 146 Window = function(win)
147 {
125 this._win = win; 148 this._win = win;
126 this.visible = win.visible;
127 } 149 }
128 Window.prototype = { 150 Window.prototype = {
129 getAllTabs: function(callback) { 151 get visible()
130 callback(this._win.tabs.map(function(tab) { 152 {
131 return new Tab(tab); 153 return this._win.visible;
132 })); 154 },
133 }, 155 getAllTabs: function(callback)
134 getActiveTab: function(callback) { 156 {
157 callback(this._win.tabs.map(function(tab) { return new Tab(tab); }));
158 },
159 getActiveTab: function(callback)
160 {
135 callback(new Tab(this._win.activeTab)); 161 callback(new Tab(this._win.activeTab));
136 }, 162 },
137 openTab: function(url, callback) { 163 openTab: function(url, callback)
164 {
138 var tab = this._win.openTab(); 165 var tab = this._win.openTab();
139 tab.url = url; 166 tab.url = url;
140 167
141 if (callback) 168 if (callback)
142 callback(new Tab(tab)); 169 callback(new Tab(tab));
143 } 170 }
144 }; 171 };
145 172
146 if (safari.extension.globalPage.contentWindow == window) { 173 if (safari.extension.globalPage.contentWindow == window)
174 {
147 /* Background page proxy */ 175 /* Background page proxy */
148 176
149 var proxy = { 177 var proxy = {
150 tabs: [], 178 tabs: [],
151 objects: [], 179 objects: [],
152 180
153 registerObject: function(obj, objects) { 181 registerObject: function(obj, objects)
182 {
154 var objectId = objects.indexOf(obj); 183 var objectId = objects.indexOf(obj);
155 184
156 if (objectId == -1) 185 if (objectId == -1)
157 objectId = objects.push(obj) - 1; 186 objectId = objects.push(obj) - 1;
158 187
159 return objectId; 188 return objectId;
160 }, 189 },
161 serializeSequence: function(sequence, objects, memo) { 190 serializeSequence: function(sequence, objects, memo)
191 {
162 if (!memo) 192 if (!memo)
163 memo = {specs: [], arrays: []}; 193 memo = {specs: [], arrays: []};
164 194
165 var items = []; 195 var items = [];
166 for (var i = 0; i < sequence.length; i++) 196 for (var i = 0; i < sequence.length; i++)
167 items.push(this.serialize(sequence[i], objects, memo)); 197 items.push(this.serialize(sequence[i], objects, memo));
168 198
169 return items; 199 return items;
170 }, 200 },
171 serialize: function(obj, objects, memo) { 201 serialize: function(obj, objects, memo)
172 if (typeof obj == "function") 202 {
173 return {type: "function", objectId: this.registerObject(obj, objects)} ; 203 if (typeof obj == "object" && obj != null || typeof obj == "function")
174 204 {
175 if (typeof obj == "object" && obj != null) { 205 if (obj.constructor == Array)
176 if (obj.constructor == Array) { 206 {
177 if (!memo) 207 if (!memo)
178 memo = {specs: [], arrays: []}; 208 memo = {specs: [], arrays: []};
179 209
180 var idx = memo.arrays.indexOf(obj); 210 var idx = memo.arrays.indexOf(obj);
181 if (idx != -1) 211 if (idx != -1)
182 return memo.specs[idx]; 212 return memo.specs[idx];
183 213
184 var spec = {type: "array"}; 214 var spec = {type: "array"};
185 memo.specs.push(spec); 215 memo.specs.push(spec);
186 memo.arrays.push(obj); 216 memo.arrays.push(obj);
187 217
188 spec.items = this.serializeSequence(obj, objects, memo); 218 spec.items = this.serializeSequence(obj, objects, memo);
189 return spec; 219 return spec;
190 } 220 }
191 221
192 if (obj.constructor != Date) 222 if (obj.constructor != Date && obj.constructor != RegExp)
193 if (obj.constructor != RegExp)
194 return {type: "object", objectId: this.registerObject(obj, objects)} ; 223 return {type: "object", objectId: this.registerObject(obj, objects)} ;
195 } 224 }
196 225
197 return {type: "value", value: obj}; 226 return {type: "value", value: obj};
198 }, 227 },
199 createCallback: function(callbackId, tab) { 228 createCallback: function(callbackId, tab)
229 {
200 var proxy = this; 230 var proxy = this;
201 231
202 return function() { 232 return function()
233 {
203 var idx = proxy.tabs.indexOf(tab); 234 var idx = proxy.tabs.indexOf(tab);
204 235
205 if (idx != -1) { 236 if (idx != -1) {
206 var objects = proxy.objects[idx]; 237 var objects = proxy.objects[idx];
207 238
208 tab.page.dispatchMessage("proxyCallback", { 239 tab.page.dispatchMessage("proxyCallback",
240 {
209 callbackId: callbackId, 241 callbackId: callbackId,
210 contextId: proxy.registerObject(this, objects), 242 contextId: proxy.registerObject(this, objects),
211 args: proxy.serializeSequence(arguments, objects) 243 args: proxy.serializeSequence(arguments, objects)
212 }); 244 });
213 } 245 }
214 }; 246 };
215 }, 247 },
216 deserialize: function(spec, objects, tab, memo) { 248 deserialize: function(spec, objects, tab, memo)
217 switch (spec.type) { 249 {
250 switch (spec.type)
251 {
218 case "value": 252 case "value":
219 return spec.value; 253 return spec.value;
220 case "hosted": 254 case "hosted":
221 return objects[spec.objectId]; 255 return objects[spec.objectId];
222 case "callback": 256 case "callback":
223 return this.createCallback(spec.callbackId, tab); 257 return this.createCallback(spec.callbackId, tab);
224 case "object": 258 case "object":
225 case "array": 259 case "array":
226 if (!memo) 260 if (!memo)
227 memo = {specs: [], objects: []}; 261 memo = {specs: [], objects: []};
(...skipping 14 matching lines...) Expand all
242 if (spec.type == "array") 276 if (spec.type == "array")
243 for (var i = 0; i < spec.items.length; i++) 277 for (var i = 0; i < spec.items.length; i++)
244 obj.push(this.deserialize(spec.items[i], objects, tab, memo)); 278 obj.push(this.deserialize(spec.items[i], objects, tab, memo));
245 else 279 else
246 for (var k in spec.properties) 280 for (var k in spec.properties)
247 obj[k] = this.deserialize(spec.properties[k], objects, tab, memo ); 281 obj[k] = this.deserialize(spec.properties[k], objects, tab, memo );
248 282
249 return obj; 283 return obj;
250 } 284 }
251 }, 285 },
252 createObjectCache: function(tab) { 286 createObjectCache: function(tab)
287 {
253 var objects = [window]; 288 var objects = [window];
254 289
255 this.tabs.push(tab); 290 this.tabs.push(tab);
256 this.objects.push(objects); 291 this.objects.push(objects);
257 292
258 tab.addEventListener("close", function() { 293 tab.addEventListener("close", function()
294 {
259 var idx = this.tabs.indexOf(tab); 295 var idx = this.tabs.indexOf(tab);
260 296
261 if (idx != -1) { 297 if (idx != -1)
298 {
262 this.tabs.splice(idx, 1); 299 this.tabs.splice(idx, 1);
263 this.objects.splice(idx, 1); 300 this.objects.splice(idx, 1);
264 } 301 }
265 }.bind(this)); 302 }.bind(this));
266 303
267 return objects; 304 return objects;
268 }, 305 },
269 getObjectCache: function(tab) { 306 getObjectCache: function(tab)
307 {
270 var idx = this.tabs.indexOf(tab); 308 var idx = this.tabs.indexOf(tab);
271 var objects; 309 var objects;
272 310
273 if (idx != -1) 311 if (idx != -1)
274 objects = this.objects[idx]; 312 objects = this.objects[idx];
275 else 313 else
276 objects = this.objects[idx] = this.createObjectCache(tab); 314 objects = this.objects[idx] = this.createObjectCache(tab);
277 315
278 return objects; 316 return objects;
279 }, 317 },
280 fail: function(error) { 318 fail: function(error)
319 {
281 if (error instanceof Error) 320 if (error instanceof Error)
282 error = error.message; 321 error = error.message;
283 return {succeed: false, error: error}; 322 return {succeed: false, error: error};
284 }, 323 },
285 _handleMessage: function(message, tab) { 324 _handleMessage: function(message, tab)
325 {
286 var objects = this.getObjectCache(tab); 326 var objects = this.getObjectCache(tab);
287 327
288 switch (message.type) { 328 switch (message.type)
329 {
289 case "getProperty": 330 case "getProperty":
290 var obj = objects[message.objectId]; 331 var obj = objects[message.objectId];
291 332
292 try { 333 try
334 {
293 var value = obj[message.property]; 335 var value = obj[message.property];
294 } catch (e) { 336 }
337 catch (e)
338 {
295 return this.fail(e); 339 return this.fail(e);
296 } 340 }
297 341
298 return {succeed: true, result: this.serialize(value, objects)}; 342 return {succeed: true, result: this.serialize(value, objects)};
299 case "setProperty": 343 case "setProperty":
300 var obj = objects[message.objectId]; 344 var obj = objects[message.objectId];
301 var value = this.deserialize(message.value, objects, tab); 345 var value = this.deserialize(message.value, objects, tab);
302 346
303 try { 347 try
348 {
304 obj[message.property] = value; 349 obj[message.property] = value;
305 } catch (e) { 350 }
351 catch (e)
352 {
306 return this.fail(e); 353 return this.fail(e);
307 } 354 }
308 355
309 return {succeed: true}; 356 return {succeed: true};
310 case "callFunction": 357 case "callFunction":
311 var func = objects[message.functionId]; 358 var func = objects[message.functionId];
312 var context = objects[message.contextId]; 359 var context = objects[message.contextId];
313 360
314 var args = []; 361 var args = [];
315 for (var i = 0; i < message.args.length; i++) 362 for (var i = 0; i < message.args.length; i++)
316 args.push(this.deserialize(message.args[i], objects, tab)); 363 args.push(this.deserialize(message.args[i], objects, tab));
317 364
318 try { 365 try
366 {
319 var result = func.apply(context, args); 367 var result = func.apply(context, args);
320 } catch (e) { 368 }
369 catch (e)
370 {
321 return this.fail(e); 371 return this.fail(e);
322 } 372 }
323 373
324 return {succeed: true, result: this.serialize(result, objects)}; 374 return {succeed: true, result: this.serialize(result, objects)};
325 case "inspectObject": 375 case "inspectObject":
326 var obj = objects[message.objectId]; 376 var obj = objects[message.objectId];
327 377 var objectInfo = {properties: {}, isFunction: typeof obj == "functio n"};
328 var prototype = Object.getPrototypeOf(obj); 378
329 var prototypeId; 379 Object.getOwnPropertyNames(obj).forEach(function(prop)
330 if (prototype != null) 380 {
331 prototypeId = this.registerObject(prototype, objects); 381 objectInfo.properties[prop] = {
332 else 382 enumerable: Object.prototype.propertyIsEnumerable.call(obj, prop )
333 prototypeId = null; 383 };
334
335 var properties = {};
336 Object.getOwnPropertyNames(obj).forEach(function(prop) {
337 if (obj != Object.prototype || prop == "constructor")
338 properties[prop] = {
339 enumerable: Object.getOwnPropertyDescriptor(obj, prop).enumera ble
340 };
341 }); 384 });
342 385
343 return {prototypeId: prototypeId, properties: properties}; 386 if (obj.__proto__)
387 objectInfo.prototypeId = this.registerObject(obj.__proto__, object s);
388
389 if (obj == Object.prototype)
390 objectInfo.prototypeOf = "Object";
391 if (obj == Function.prototype)
392 objectInfo.prototypeOf = "Function";
393
394 return objectInfo;
344 } 395 }
345 } 396 }
346 }; 397 };
347 398
348 399
349 /* Web request blocking */ 400 /* Web request blocking */
350 401
351 ext.webRequest = { 402 ext.webRequest = {
352 onBeforeRequest: { 403 onBeforeRequest: {
353 _listeners: [], 404 _listeners: [],
354 _urlPatterns: [], 405 _urlPatterns: [],
355 406
356 _handleMessage: function(message, tab) { 407 _handleMessage: function(message, tab)
408 {
357 tab = new Tab(tab); 409 tab = new Tab(tab);
358 410
359 for (var i = 0; i < this._listeners.length; i++) { 411 for (var i = 0; i < this._listeners.length; i++)
412 {
360 var regex = this._urlPatterns[i]; 413 var regex = this._urlPatterns[i];
361 414
362 if (!regex || regex.test(message)) 415 if ((!regex || regex.test(message.url)) && this._listeners[i](messag e.url, message.type, tab, 0, -1) === false)
363 if (this._listeners[i](message.url, message.type, tab, 0, -1) === fa lse) {
364 return false; 416 return false;
365 }
366 } 417 }
367 418
368 return true; 419 return true;
369 }, 420 },
370 addListener: function(listener, urls) { 421 addListener: function(listener, urls)
422 {
371 var regex; 423 var regex;
372 424
373 if (urls) 425 if (urls)
374 regex = new RegExp("^(?:" + urls.map(function(url) { 426 regex = new RegExp("^(?:" + urls.map(function(url)
375 return url.split("*").map(function(s) { 427 {
428 return url.split("*").map(function(s)
429 {
376 return s.replace(/([.?+^$[\]\\(){}|-])/g, "\\$1"); 430 return s.replace(/([.?+^$[\]\\(){}|-])/g, "\\$1");
377 }).join(".*"); 431 }).join(".*");
378 }).join("|") + ")($|[?#])"); 432 }).join("|") + ")($|[?#])");
379 433
380 this._listeners.push(listener); 434 this._listeners.push(listener);
381 this._urlPatterns.push(regex); 435 this._urlPatterns.push(regex);
382 }, 436 },
383 removeListener: function(listener) { 437 removeListener: function(listener)
438 {
384 var idx = this._listeners.indexOf(listener); 439 var idx = this._listeners.indexOf(listener);
385 440
386 if (idx != -1) { 441 if (idx != -1)
442 {
387 this._listeners.splice(idx, 1); 443 this._listeners.splice(idx, 1);
388 this._urlPatterns.splice(idx, 1); 444 this._urlPatterns.splice(idx, 1);
389 } 445 }
390 } 446 }
391 }, 447 },
392 handlerBehaviorChanged: function() {} 448 handlerBehaviorChanged: function() {}
393 }; 449 };
394 450
395 451
396 /* Synchronous messaging */ 452 /* Synchronous messaging */
397 453
398 safari.application.addEventListener("message", function(event) { 454 safari.application.addEventListener("message", function(event)
399 if (event.name == "canLoad") { 455 {
456 if (event.name == "canLoad")
457 {
400 var handler; 458 var handler;
401 459
402 switch (event.message.type) { 460 switch (event.message.type)
461 {
403 case "proxy": 462 case "proxy":
404 handler = proxy; 463 handler = proxy;
405 break; 464 break;
406 case "webRequest": 465 case "webRequest":
407 handler = ext.webRequest.onBeforeRequest; 466 handler = ext.webRequest.onBeforeRequest;
408 break; 467 break;
409 } 468 }
410 469
411 event.message = handler._handleMessage(event.message.payload, event.targ et); 470 event.message = handler._handleMessage(event.message.payload, event.targ et);
412 } 471 }
413 }, true); 472 }, true);
414 } 473 }
415 474
416 475
417 /* API */ 476 /* API */
418 477
419 ext.windows = { 478 ext.windows = {
420 getAll: function(callback) { 479 getAll: function(callback)
421 callback(safari.application.browserWindows.map(function(win) { 480 {
481 callback(safari.application.browserWindows.map(function(win)
482 {
422 return new Window(win); 483 return new Window(win);
423 })); 484 }));
424 }, 485 },
425 getLastFocused: function(callback) { 486 getLastFocused: function(callback)
487 {
426 callback(new Window(safari.application.activeBrowserWindow)); 488 callback(new Window(safari.application.activeBrowserWindow));
427 } 489 }
428 }; 490 };
429 491
430 ext.tabs = { 492 ext.tabs = {
431 onBeforeNavigate: new TabEventTarget(safari.application, "beforeNavigate", t rue), 493 onBeforeNavigate: new TabEventTarget(safari.application, "beforeNavigate", t rue),
432 onCompleted: new TabEventTarget(safari.application, "navigate", t rue), 494 onCompleted: new TabEventTarget(safari.application, "navigate", true),
433 onActivated: new TabEventTarget(safari.application, "activate", t rue), 495 onActivated: new TabEventTarget(safari.application, "activate", true),
434 onRemoved: new TabEventTarget(safari.application, "close", t rue) 496 onRemoved: new TabEventTarget(safari.application, "close", true)
435 }; 497 };
436 498
437 ext.backgroundPage = { 499 ext.backgroundPage = {
438 getWindow: function() { 500 getWindow: function()
501 {
439 return safari.extension.globalPage.contentWindow; 502 return safari.extension.globalPage.contentWindow;
440 } 503 }
441 }; 504 };
442 505
443 ext.onMessage = new MessageEventTarget(safari.application); 506 ext.onMessage = new MessageEventTarget(safari.application);
507
508
509 // Safari will load the bubble once, and then show it everytime the icon is
510 // clicked. While Chrome loads it everytime you click the icon. So in order to
511 // force the same behavior in Safari, we are going to reload the page of the
512 // bubble everytime it is shown.
513 if (safari.extension.globalPage.contentWindow != window)
514 safari.application.addEventListener("popover", function()
515 {
516 document.documentElement.style.display = "none";
517 document.location.reload();
518 }, true);
444 })(); 519 })();
LEFTRIGHT

Powered by Google App Engine
This is Rietveld