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]; |
| 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 |