Left: | ||
Right: |
OLD | NEW |
---|---|
1 /* | 1 /* |
2 * This file is part of Adblock Plus <https://adblockplus.org/>, | 2 * This file is part of Adblock Plus <https://adblockplus.org/>, |
3 * Copyright (C) 2006-2016 Eyeo GmbH | 3 * Copyright (C) 2006-2016 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 { |
20 /* Context menus */ | 20 /* Context menus */ |
21 | 21 |
22 var contextMenuItems = new ext.PageMap(); | 22 var contextMenuItems = new ext.PageMap(); |
23 var lastContextMenuTab; | |
23 | 24 |
24 var ContextMenus = function(page) | 25 var ContextMenus = function(page) |
25 { | 26 { |
26 this._page = page; | 27 this._page = page; |
27 }; | 28 }; |
28 ContextMenus.prototype = { | 29 ContextMenus.prototype = { |
29 create: function(item) | 30 create: function(item) |
30 { | 31 { |
31 var items = contextMenuItems.get(this._page); | 32 var items = contextMenuItems.get(this._page); |
32 if (!items) | 33 if (!items) |
33 contextMenuItems.set(this._page, items = []); | 34 contextMenuItems.set(this._page, items = []); |
34 | 35 |
35 items.push(item); | 36 items.push(item); |
36 }, | 37 }, |
37 remove: function(item) | 38 remove: function(item) |
38 { | 39 { |
39 let items = contextMenuItems.get(this._page); | 40 let items = contextMenuItems.get(this._page); |
40 if (items) | 41 if (items) |
41 { | 42 { |
42 let index = items.indexOf(item); | 43 let index = items.indexOf(item); |
43 if (index != -1) | 44 if (index != -1) |
44 items.splice(index, 1); | 45 items.splice(index, 1); |
45 } | 46 } |
46 } | 47 } |
47 }; | 48 }; |
48 | 49 |
49 safari.application.addEventListener("contextmenu", function(event) | 50 safari.application.addEventListener("contextmenu", function(event) |
50 { | 51 { |
52 lastContextMenuTab = event.target; | |
53 | |
51 if (!event.userInfo) | 54 if (!event.userInfo) |
52 return; | 55 return; |
53 | 56 |
54 var pageId = event.userInfo.pageId; | 57 var documentId = event.userInfo.documentId; |
55 if (!pageId) | 58 if (!documentId) |
56 return; | 59 return; |
57 | 60 |
58 var page = pages[event.userInfo.pageId]; | 61 var page = pages[event.target._documentLookup[documentId].pageId]; |
59 var items = contextMenuItems.get(page); | 62 var items = contextMenuItems.get(page); |
60 if (!items) | 63 if (!items) |
61 return; | 64 return; |
62 | 65 |
63 var context = event.userInfo.tagName; | 66 var context = event.userInfo.tagName; |
64 if (context == "img") | 67 if (context == "img") |
65 context = "image"; | 68 context = "image"; |
66 | 69 |
67 for (var i = 0; i < items.length; i++) | 70 for (var i = 0; i < items.length; i++) |
68 { | 71 { |
69 // Supported contexts are: all, audio, image, video | 72 // Supported contexts are: all, audio, image, video |
70 var menuItem = items[i]; | 73 var menuItem = items[i]; |
71 if (menuItem.contexts.indexOf("all") == -1 && menuItem.contexts.indexOf(co ntext) == -1) | 74 if (menuItem.contexts.indexOf("all") == -1 && menuItem.contexts.indexOf(co ntext) == -1) |
72 continue; | 75 continue; |
73 | 76 |
74 event.contextMenu.appendContextMenuItem(i, menuItem.title); | 77 event.contextMenu.appendContextMenuItem(i, menuItem.title); |
75 } | 78 } |
76 }); | 79 }); |
77 | 80 |
78 safari.application.addEventListener("command", function(event) | 81 safari.application.addEventListener("command", function(event) |
79 { | 82 { |
80 var page = pages[event.userInfo.pageId]; | 83 var documentId = event.userInfo.documentId; |
84 var page = pages[lastContextMenuTab._documentLookup[documentId].pageId]; | |
81 var items = contextMenuItems.get(page); | 85 var items = contextMenuItems.get(page); |
82 | 86 |
83 items[event.command].onclick(page); | 87 items[event.command].onclick(page); |
84 }); | 88 }); |
85 | 89 |
86 | 90 |
87 /* Browser actions */ | 91 /* Browser actions */ |
88 | 92 |
89 var toolbarItemProperties = {}; | 93 var toolbarItemProperties = {}; |
90 | 94 |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
197 this.browserAction = new BrowserAction(this); | 201 this.browserAction = new BrowserAction(this); |
198 this.contextMenus = new ContextMenus(this); | 202 this.contextMenus = new ContextMenus(this); |
199 }; | 203 }; |
200 Page.prototype = { | 204 Page.prototype = { |
201 get url() | 205 get url() |
202 { | 206 { |
203 return this._frames[0].url; | 207 return this._frames[0].url; |
204 }, | 208 }, |
205 sendMessage: function(message, responseCallback) | 209 sendMessage: function(message, responseCallback) |
206 { | 210 { |
207 this._messageProxy.sendMessage(message, responseCallback, {pageId: this.id }); | 211 var documentIds = []; |
212 for (var documentId in this._tab._documentLookup) | |
213 if (this._tab._documentLookup[documentId].pageId == this.id) | |
214 documentIds.push(documentId); | |
215 | |
216 this._messageProxy.sendMessage(message, responseCallback, | |
217 {targetDocuments: documentIds}); | |
208 } | 218 } |
209 }; | 219 }; |
210 | 220 |
211 ext.getPage = function(id) | 221 ext.getPage = function(id) |
212 { | 222 { |
213 return pages[id]; | 223 return pages[id]; |
214 }; | 224 }; |
215 | 225 |
216 var isPageActive = function(page) | 226 var isPageActive = function(page) |
217 { | 227 { |
218 var tab = page._tab; | 228 var tab = page._tab; |
219 var win = tab.browserWindow; | 229 var win = tab.browserWindow; |
220 return win && tab == win.activeTab && page == tab._visiblePage; | 230 return win && tab == win.activeTab && page == tab._visiblePage; |
221 }; | 231 }; |
222 | 232 |
223 var forgetPage = function(id) | 233 var forgetPage = function(id) |
224 { | 234 { |
225 ext.pages.onRemoved._dispatch(id); | 235 ext.pages.onRemoved._dispatch(id); |
226 | 236 |
227 ext._removeFromAllPageMaps(id); | 237 ext._removeFromAllPageMaps(id); |
228 | 238 |
229 delete pages[id]._tab._pages[id]; | 239 var tab = pages[id]._tab; |
240 | |
241 for (var documentId in tab._documentLookup) | |
242 { | |
243 if (tab._documentLookup[documentId].pageId == id) | |
244 delete tab._documentLookup[documentId]; | |
kzar
2016/03/18 14:23:03
Is it safe to delete from an Object whilst iterati
Sebastian Noack
2016/03/18 19:32:51
According to MDN deleting the element currently vi
| |
245 } | |
246 | |
247 delete tab._pages[id]; | |
230 delete pages[id]; | 248 delete pages[id]; |
231 }; | 249 }; |
232 | 250 |
233 var replacePage = function(page) | 251 var replacePage = function(page) |
234 { | 252 { |
235 var tab = page._tab; | 253 var tab = page._tab; |
236 tab._visiblePage = page; | 254 tab._visiblePage = page; |
237 | 255 |
238 for (var id in tab._pages) | 256 for (var id in tab._pages) |
239 { | 257 { |
240 if (id != page.id) | 258 if (id != page.id) |
241 forgetPage(id); | 259 forgetPage(id); |
242 } | 260 } |
243 | 261 |
244 if (isPageActive(page)) | 262 if (isPageActive(page)) |
245 updateToolbarItemForPage(page, tab.browserWindow); | 263 updateToolbarItemForPage(page, tab.browserWindow); |
246 }; | 264 }; |
247 | 265 |
248 var addPage = function(tab, url, prerendered) | 266 var addPage = function(tab, url, prerendered) |
249 { | 267 { |
250 var pageId = ++pageCounter; | 268 var pageId = ++pageCounter; |
251 | 269 |
252 if (!('_pages' in tab)) | 270 if (!('_pages' in tab)) |
253 tab._pages = Object.create(null); | 271 tab._pages = Object.create(null); |
254 | 272 |
273 if (!('_documentLookup' in tab)) | |
274 tab._documentLookup = Object.create(null); | |
275 | |
255 var page = new Page(pageId, tab, url); | 276 var page = new Page(pageId, tab, url); |
256 pages[pageId] = tab._pages[pageId] = page; | 277 pages[pageId] = tab._pages[pageId] = page; |
257 | 278 |
258 // When a new page is shown, forget the previous page associated | 279 // When a new page is shown, forget the previous page associated |
259 // with its tab, and reset the toolbar item if necessary. | 280 // with its tab, and reset the toolbar item if necessary. |
260 // Note that it wouldn't be sufficient to do that when the old | 281 // Note that it wouldn't be sufficient to do that when the old |
261 // page is unloading, because Safari dispatches window.onunload | 282 // page is unloading, because Safari dispatches window.onunload |
262 // only when reloading the page or following links, but not when | 283 // only when reloading the page or following links, but not when |
263 // you enter a new URL in the address bar. | 284 // you enter a new URL in the address bar. |
264 if (!prerendered) | 285 if (!prerendered) |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
333 // use Safari's extension API to detect existing tabs. | 354 // use Safari's extension API to detect existing tabs. |
334 safari.application.browserWindows.forEach(function(win) | 355 safari.application.browserWindows.forEach(function(win) |
335 { | 356 { |
336 for (var i = 0; i < win.tabs.length; i++) | 357 for (var i = 0; i < win.tabs.length; i++) |
337 { | 358 { |
338 var tab = win.tabs[i]; | 359 var tab = win.tabs[i]; |
339 var url = tab.url; | 360 var url = tab.url; |
340 | 361 |
341 // For the new tab page the url property is undefined. | 362 // For the new tab page the url property is undefined. |
342 if (url) | 363 if (url) |
343 addPage(tab, url, false); | 364 { |
365 var pageId = addPage(tab, url, false); | |
366 tab.page.dispatchMessage("requestDocumentId", {pageId: pageId}); | |
367 } | |
344 } | 368 } |
345 }); | 369 }); |
346 | 370 |
347 | 371 |
348 /* Web requests */ | 372 /* Web requests */ |
349 | 373 |
350 ext.webRequest = { | 374 ext.webRequest = { |
351 onBeforeRequest: new ext._EventTarget(), | 375 onBeforeRequest: new ext._EventTarget(), |
352 handlerBehaviorChanged: function() | 376 handlerBehaviorChanged: function() |
353 { | 377 { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
418 return function() | 442 return function() |
419 { | 443 { |
420 var page = pages[pageId]; | 444 var page = pages[pageId]; |
421 if (!page) | 445 if (!page) |
422 return; | 446 return; |
423 | 447 |
424 var objects = proxy.cache.get(page); | 448 var objects = proxy.cache.get(page); |
425 if (!objects) | 449 if (!objects) |
426 return; | 450 return; |
427 | 451 |
452 var targetDocument; | |
453 for (var documentId in page._tab._documentLookup) | |
454 { | |
455 var result = page._tab._documentLookup[documentId]; | |
456 if (result.pageId == pageId && result.frameId == frameId) | |
457 { | |
458 targetDocument = documentId; | |
459 break; | |
460 } | |
461 } | |
462 if (!targetDocument) | |
463 return; | |
464 | |
428 page._tab.page.dispatchMessage("proxyCallback", | 465 page._tab.page.dispatchMessage("proxyCallback", |
429 { | 466 { |
430 pageId: pageId, | 467 targetDocuments: [targetDocument], |
431 frameId: frameId, | |
432 callbackId: callbackId, | 468 callbackId: callbackId, |
433 contextId: proxy.registerObject(this, objects), | 469 contextId: proxy.registerObject(this, objects), |
434 args: proxy.serializeSequence(arguments, objects) | 470 args: proxy.serializeSequence(arguments, objects) |
435 }); | 471 }); |
436 }; | 472 }; |
437 }, | 473 }, |
438 deserialize: function(spec, objects, pageId, memo) | 474 deserialize: function(spec, objects, pageId, frameId, memo) |
439 { | 475 { |
440 switch (spec.type) | 476 switch (spec.type) |
441 { | 477 { |
442 case "value": | 478 case "value": |
443 return spec.value; | 479 return spec.value; |
444 case "hosted": | 480 case "hosted": |
445 return objects[spec.objectId]; | 481 return objects[spec.objectId]; |
446 case "callback": | 482 case "callback": |
447 return this.createCallback(spec.callbackId, pageId, spec.frameId); | 483 return this.createCallback(spec.callbackId, pageId, frameId); |
448 case "object": | 484 case "object": |
449 case "array": | 485 case "array": |
450 if (!memo) | 486 if (!memo) |
451 memo = {specs: [], objects: []}; | 487 memo = {specs: [], objects: []}; |
452 | 488 |
453 var idx = memo.specs.indexOf(spec); | 489 var idx = memo.specs.indexOf(spec); |
454 if (idx != -1) | 490 if (idx != -1) |
455 return memo.objects[idx]; | 491 return memo.objects[idx]; |
456 | 492 |
457 var obj; | 493 var obj; |
458 if (spec.type == "array") | 494 if (spec.type == "array") |
459 obj = []; | 495 obj = []; |
460 else | 496 else |
461 obj = {}; | 497 obj = {}; |
462 | 498 |
463 memo.specs.push(spec); | 499 memo.specs.push(spec); |
464 memo.objects.push(obj); | 500 memo.objects.push(obj); |
465 | 501 |
466 if (spec.type == "array") | 502 if (spec.type == "array") |
467 for (var i = 0; i < spec.items.length; i++) | 503 for (var i = 0; i < spec.items.length; i++) |
468 obj.push(this.deserialize(spec.items[i], objects, pageId, memo)); | 504 obj.push(this.deserialize(spec.items[i], objects, |
505 pageId, frameId, memo)); | |
469 else | 506 else |
470 for (var k in spec.properties) | 507 for (var k in spec.properties) |
471 obj[k] = this.deserialize(spec.properties[k], objects, pageId, mem o); | 508 obj[k] = this.deserialize(spec.properties[k], objects, |
509 pageId, frameId, memo); | |
472 | 510 |
473 return obj; | 511 return obj; |
474 } | 512 } |
475 }, | 513 }, |
476 getObjectCache: function(page) | 514 getObjectCache: function(page) |
477 { | 515 { |
478 var objects = this.cache.get(page); | 516 var objects = this.cache.get(page); |
479 if (!objects) | 517 if (!objects) |
480 { | 518 { |
481 objects = [window]; | 519 objects = [window]; |
(...skipping 21 matching lines...) Expand all Loading... | |
503 var value = obj[message.property]; | 541 var value = obj[message.property]; |
504 } | 542 } |
505 catch (e) | 543 catch (e) |
506 { | 544 { |
507 return this.fail(e); | 545 return this.fail(e); |
508 } | 546 } |
509 | 547 |
510 return {succeed: true, result: this.serialize(value, objects)}; | 548 return {succeed: true, result: this.serialize(value, objects)}; |
511 case "setProperty": | 549 case "setProperty": |
512 var obj = objects[message.objectId]; | 550 var obj = objects[message.objectId]; |
513 var value = this.deserialize(message.value, objects, message.pageId); | 551 var value = this.deserialize(message.value, objects, |
552 message.pageId, message.frameId); | |
514 | 553 |
515 try | 554 try |
516 { | 555 { |
517 obj[message.property] = value; | 556 obj[message.property] = value; |
518 } | 557 } |
519 catch (e) | 558 catch (e) |
520 { | 559 { |
521 return this.fail(e); | 560 return this.fail(e); |
522 } | 561 } |
523 | 562 |
524 return {succeed: true}; | 563 return {succeed: true}; |
525 case "callFunction": | 564 case "callFunction": |
526 var func = objects[message.functionId]; | 565 var func = objects[message.functionId]; |
527 var context = objects[message.contextId]; | 566 var context = objects[message.contextId]; |
528 | 567 |
529 var args = []; | 568 var args = []; |
530 for (var i = 0; i < message.args.length; i++) | 569 for (var i = 0; i < message.args.length; i++) |
531 args.push(this.deserialize(message.args[i], objects, message.pageId) ); | 570 args.push(this.deserialize(message.args[i], objects, |
571 message.pageId, message.frameId)); | |
532 | 572 |
533 try | 573 try |
534 { | 574 { |
535 var result = func.apply(context, args); | 575 var result = func.apply(context, args); |
536 } | 576 } |
537 catch (e) | 577 catch (e) |
538 { | 578 { |
539 return this.fail(e); | 579 return this.fail(e); |
540 } | 580 } |
541 | 581 |
(...skipping 21 matching lines...) Expand all Loading... | |
563 return objectInfo; | 603 return objectInfo; |
564 } | 604 } |
565 } | 605 } |
566 }; | 606 }; |
567 | 607 |
568 | 608 |
569 /* Message processing */ | 609 /* Message processing */ |
570 | 610 |
571 safari.application.addEventListener("message", function(event) | 611 safari.application.addEventListener("message", function(event) |
572 { | 612 { |
613 var tab = event.target; | |
614 var message = event.message; | |
615 var sender; | |
616 if ("documentId" in message && "_documentLookup" in tab) | |
617 { | |
618 sender = tab._documentLookup[message.documentId]; | |
619 if (sender) | |
620 { | |
621 sender.page = pages[sender.pageId]; | |
622 sender.frame = sender.page._frames[sender.frameId]; | |
623 } | |
624 } | |
625 | |
573 switch (event.name) | 626 switch (event.name) |
574 { | 627 { |
575 case "canLoad": | 628 case "canLoad": |
576 switch (event.message.category) | 629 switch (message.category) |
577 { | 630 { |
578 case "loading": | |
579 var tab = event.target; | |
580 var message = event.message; | |
581 | |
582 var pageId; | |
583 var frameId; | |
584 | |
585 if (message.isTopLevel) | |
586 { | |
587 pageId = addPage(tab, message.url, message.isPrerendered); | |
588 frameId = 0; | |
589 | |
590 ext.pages.onLoading._dispatch(pages[pageId]); | |
591 } | |
592 else | |
593 { | |
594 var page; | |
595 var parentFrame; | |
596 | |
597 var lastPageId; | |
598 var lastPage; | |
599 var lastPageTopLevelFrame; | |
600 | |
601 // find the parent frame and its page for this sub frame, | |
602 // by matching its referrer with the URL of frames previously | |
603 // loaded in the same tab. If there is more than one match, | |
604 // the most recent loaded page and frame is preferred. | |
605 for (var curPageId in tab._pages) | |
606 { | |
607 var curPage = pages[curPageId]; | |
608 | |
609 for (var i = 0; i < curPage._frames.length; i++) | |
610 { | |
611 var curFrame = curPage._frames[i]; | |
612 | |
613 if (curFrame.url.href == message.referrer) | |
614 { | |
615 pageId = curPageId; | |
616 page = curPage; | |
617 parentFrame = curFrame; | |
618 } | |
619 | |
620 if (i == 0) | |
621 { | |
622 lastPageId = curPageId; | |
623 lastPage = curPage; | |
624 lastPageTopLevelFrame = curFrame; | |
625 } | |
626 } | |
627 } | |
628 | |
629 // if we can't find the parent frame and its page, fall back to | |
630 // the page most recently loaded in the tab and its top level fram e | |
631 if (!page) | |
632 { | |
633 pageId = lastPageId; | |
634 page = lastPage; | |
635 parentFrame = lastPageTopLevelFrame; | |
636 } | |
637 | |
638 frameId = page._frames.length; | |
639 page._frames.push({url: new URL(message.url), parent: parentFrame} ); | |
640 } | |
641 event.message = {pageId: pageId, frameId: frameId}; | |
642 break; | |
643 case "webRequest": | 631 case "webRequest": |
644 var page = pages[event.message.pageId]; | |
645 var frame = page._frames[event.message.frameId]; | |
646 | |
647 var results = ext.webRequest.onBeforeRequest._dispatch( | 632 var results = ext.webRequest.onBeforeRequest._dispatch( |
648 new URL(event.message.url, frame.url), | 633 new URL(message.url, sender.frame.url), |
649 event.message.type, page, frame | 634 message.type, sender.page, sender.frame |
650 ); | 635 ); |
651 | 636 |
652 event.message = (results.indexOf(false) == -1); | 637 event.message = (results.indexOf(false) == -1); |
653 break; | 638 break; |
654 case "proxy": | 639 case "proxy": |
655 event.message = backgroundPageProxy.handleMessage(event.message); | 640 message.pageId = sender.pageId; |
641 message.frameId = sender.frameId; | |
642 event.message = backgroundPageProxy.handleMessage(message); | |
656 break; | 643 break; |
657 case "request": | 644 case "request": |
658 var page = pages[event.message.pageId]; | |
659 var sender = {page: page, frame: page._frames[event.message.frameId] }; | |
660 | |
661 var response = null; | 645 var response = null; |
662 var sendResponse = function(message) { response = message; }; | 646 var sendResponse = function(message) { response = message; }; |
663 | 647 |
664 ext.onMessage._dispatch(event.message.payload, sender, sendResponse) ; | 648 ext.onMessage._dispatch(message.payload, sender, sendResponse); |
665 | 649 |
666 event.message = response; | 650 event.message = response; |
667 break; | 651 break; |
668 } | 652 } |
669 break; | 653 break; |
670 case "request": | 654 case "request": |
671 var page = pages[event.message.pageId]; | 655 sender.page._messageProxy.handleRequest(message, sender); |
672 var sender = {page: page, frame: page._frames[event.message.frameId]}; | |
673 page._messageProxy.handleRequest(event.message, sender); | |
674 break; | 656 break; |
675 case "response": | 657 case "response": |
676 pages[event.message.pageId]._messageProxy.handleResponse(event.message); | 658 // All documents within a page have the same pageId and that's all we |
659 // care about here. | |
660 var pageId = tab._documentLookup[message.targetDocuments[0]].pageId; | |
661 pages[pageId]._messageProxy.handleResponse(message); | |
677 break; | 662 break; |
678 case "replaced": | 663 case "replaced": |
679 // when a prerendered page is shown, forget the previous page | 664 // when a prerendered page is shown, forget the previous page |
680 // associated with its tab, and reset the toolbar item if necessary. | 665 // associated with its tab, and reset the toolbar item if necessary. |
681 // Note that it wouldn't be sufficient to do that when the old | 666 // Note that it wouldn't be sufficient to do that when the old |
682 // page is unloading, because Safari dispatches window.onunload | 667 // page is unloading, because Safari dispatches window.onunload |
683 // only when reloading the page or following links, but not when | 668 // only when reloading the page or following links, but not when |
684 // the current page is replaced with a prerendered page. | 669 // the current page is replaced with a prerendered page. |
685 replacePage(pages[event.message.pageId]); | 670 replacePage(sender.page); |
671 break; | |
672 case "loading": | |
673 var pageId; | |
674 var frameId; | |
675 var documentId = message.documentId; | |
676 | |
677 if (message.isTopLevel) | |
678 { | |
679 pageId = addPage(tab, message.url, message.isPrerendered); | |
680 frameId = 0; | |
681 | |
682 ext.pages.onLoading._dispatch(pages[pageId]); | |
683 } | |
684 else | |
685 { | |
686 var page; | |
687 var parentFrame; | |
688 | |
689 var lastPageId; | |
690 var lastPage; | |
691 var lastPageTopLevelFrame; | |
692 | |
693 // find the parent frame and its page for this sub frame, | |
694 // by matching its referrer with the URL of frames previously | |
695 // loaded in the same tab. If there is more than one match, | |
696 // the most recent loaded page and frame is preferred. | |
697 for (var curPageId in tab._pages) | |
698 { | |
699 var curPage = pages[curPageId]; | |
700 | |
701 for (var i = 0; i < curPage._frames.length; i++) | |
702 { | |
703 var curFrame = curPage._frames[i]; | |
704 | |
705 if (curFrame.url.href == message.referrer) | |
706 { | |
707 pageId = curPageId; | |
708 page = curPage; | |
709 parentFrame = curFrame; | |
710 } | |
711 | |
712 if (i == 0) | |
713 { | |
714 lastPageId = curPageId; | |
715 lastPage = curPage; | |
716 lastPageTopLevelFrame = curFrame; | |
717 } | |
718 } | |
719 } | |
720 | |
721 // if we can't find the parent frame and its page, fall back to | |
722 // the page most recently loaded in the tab and its top level frame | |
723 if (!page) | |
724 { | |
725 pageId = lastPageId; | |
726 page = lastPage; | |
727 parentFrame = lastPageTopLevelFrame; | |
728 } | |
729 | |
730 frameId = page._frames.length; | |
731 page._frames.push({url: new URL(message.url), parent: parentFrame}); | |
732 } | |
733 | |
734 tab._documentLookup[documentId] = {pageId: pageId, frameId: frameId}; | |
735 break; | |
736 case "documentId": | |
737 tab._documentLookup[message.documentId] = { | |
738 pageId: message.pageId, frameId: 0 | |
739 }; | |
686 break; | 740 break; |
687 } | 741 } |
688 }); | 742 }); |
689 | 743 |
690 | 744 |
691 /* Storage */ | 745 /* Storage */ |
692 | 746 |
693 ext.storage = { | 747 ext.storage = { |
694 get: function(keys, callback) | 748 get: function(keys, callback) |
695 { | 749 { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
762 /* Windows */ | 816 /* Windows */ |
763 ext.windows = { | 817 ext.windows = { |
764 // Safari doesn't provide as rich a windows API as Chrome does, so instead | 818 // Safari doesn't provide as rich a windows API as Chrome does, so instead |
765 // of chrome.windows.create we have to fall back to just opening a new tab. | 819 // of chrome.windows.create we have to fall back to just opening a new tab. |
766 create: function(createData, callback) | 820 create: function(createData, callback) |
767 { | 821 { |
768 ext.pages.open(createData.url, callback); | 822 ext.pages.open(createData.url, callback); |
769 } | 823 } |
770 }; | 824 }; |
771 })(); | 825 })(); |
OLD | NEW |