Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 <?xml version="1.0"?>
3 <!-- This Source Code Form is subject to the terms of the Mozilla Public
4 - License, v. 2.0. If a copy of the MPL was not distributed with this
5 - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
7 <!DOCTYPE bindings [
8 <!ENTITY % findBarDTD SYSTEM "chrome://global/locale/findbar.dtd" >
9 %findBarDTD;
10 ]>
12 <bindings id="browserBindings"
13 xmlns="http://www.mozilla.org/xbl"
14 xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
16 <binding id="browser" extends="xul:browser" role="outerdoc">
17 <content clickthrough="never">
18 <children/>
19 </content>
20 <implementation type="application/javascript" implements="nsIObserver, nsIDOMEventListener, nsIFrameRequestCallback, nsIMessageListener">
21 <property name="autoscrollEnabled">
22 <getter>
23 <![CDATA[
24 if (this.getAttribute("autoscroll") == "false")
25 return false;
27 var enabled = true;
28 try {
29 enabled = this.mPrefs.getBoolPref("general.autoScroll");
30 }
31 catch(ex) {
32 }
34 return enabled;
35 ]]>
36 </getter>
37 </property>
39 <property name="canGoBack"
40 onget="return this.webNavigation.canGoBack;"
41 readonly="true"/>
43 <property name="canGoForward"
44 onget="return this.webNavigation.canGoForward;"
45 readonly="true"/>
47 <method name="goBack">
48 <body>
49 <![CDATA[
50 var webNavigation = this.webNavigation;
51 if (webNavigation.canGoBack) {
52 try {
53 this.userTypedClear++;
54 webNavigation.goBack();
55 } finally {
56 if (this.userTypedClear)
57 this.userTypedClear--;
58 }
59 }
60 ]]>
61 </body>
62 </method>
64 <method name="goForward">
65 <body>
66 <![CDATA[
67 var webNavigation = this.webNavigation;
68 if (webNavigation.canGoForward) {
69 try {
70 this.userTypedClear++;
71 webNavigation.goForward();
72 } finally {
73 if (this.userTypedClear)
74 this.userTypedClear--;
75 }
76 }
77 ]]>
78 </body>
79 </method>
81 <method name="reload">
82 <body>
83 <![CDATA[
84 const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
85 const flags = nsIWebNavigation.LOAD_FLAGS_NONE;
86 this.reloadWithFlags(flags);
87 ]]>
88 </body>
89 </method>
91 <method name="reloadWithFlags">
92 <parameter name="aFlags"/>
93 <body>
94 <![CDATA[
95 this.webNavigation.reload(aFlags);
96 ]]>
97 </body>
98 </method>
100 <method name="stop">
101 <body>
102 <![CDATA[
103 const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
104 const flags = nsIWebNavigation.STOP_ALL;
105 this.webNavigation.stop(flags);
106 ]]>
107 </body>
108 </method>
110 <!-- throws exception for unknown schemes -->
111 <method name="loadURI">
112 <parameter name="aURI"/>
113 <parameter name="aReferrerURI"/>
114 <parameter name="aCharset"/>
115 <body>
116 <![CDATA[
117 const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
118 const flags = nsIWebNavigation.LOAD_FLAGS_NONE;
119 this.loadURIWithFlags(aURI, flags, aReferrerURI, aCharset);
120 ]]>
121 </body>
122 </method>
124 <!-- throws exception for unknown schemes -->
125 <method name="loadURIWithFlags">
126 <parameter name="aURI"/>
127 <parameter name="aFlags"/>
128 <parameter name="aReferrerURI"/>
129 <parameter name="aCharset"/>
130 <parameter name="aPostData"/>
131 <body>
132 <![CDATA[
133 if (!aURI)
134 aURI = "about:blank";
136 if (aCharset) {
137 try {
138 this.docShell.parentCharset = aCharset;
139 }
140 catch (e) {
141 }
142 }
144 if (!(aFlags & this.webNavigation.LOAD_FLAGS_FROM_EXTERNAL))
145 this.userTypedClear++;
147 try {
148 this.webNavigation.loadURI(aURI, aFlags, aReferrerURI, aPostData, null);
149 } finally {
150 if (this.userTypedClear)
151 this.userTypedClear--;
152 }
153 ]]>
154 </body>
155 </method>
157 <method name="goHome">
158 <body>
159 <![CDATA[
160 try {
161 this.loadURI(this.homePage);
162 }
163 catch (e) {
164 }
165 ]]>
166 </body>
167 </method>
169 <property name="homePage">
170 <getter>
171 <![CDATA[
172 var uri;
174 if (this.hasAttribute("homepage"))
175 uri = this.getAttribute("homepage");
176 else
177 uri = "http://www.mozilla.org/"; // widget pride
179 return uri;
180 ]]>
181 </getter>
182 <setter>
183 <![CDATA[
184 this.setAttribute("homepage", val);
185 return val;
186 ]]>
187 </setter>
188 </property>
190 <method name="gotoIndex">
191 <parameter name="aIndex"/>
192 <body>
193 <![CDATA[
194 try {
195 this.userTypedClear++;
196 this.webNavigation.gotoIndex(aIndex);
197 } finally {
198 if (this.userTypedClear)
199 this.userTypedClear--;
200 }
201 ]]>
202 </body>
203 </method>
205 <property name="currentURI"
206 onget="return this.webNavigation.currentURI;"
207 readonly="true"/>
209 <!--
210 Used by session restore to ensure that currentURI is set so
211 that switch-to-tab works before the tab is fully
212 restored. This function also invokes onLocationChanged
213 listeners in tabbrowser.xml.
214 -->
215 <method name="_setCurrentURI">
216 <parameter name="aURI"/>
217 <body><![CDATA[
218 this.docShell.setCurrentURI(aURI);
219 ]]></body>
220 </method>
222 <property name="documentURI"
223 onget="return this.contentDocument.documentURIObject;"
224 readonly="true"/>
226 <property name="documentContentType"
227 onget="return this.contentDocument ? this.contentDocument.contentType : null;"
228 readonly="true"/>
230 <property name="preferences"
231 onget="return this.mPrefs.QueryInterface(Components.interfaces.nsIPrefService);"
232 readonly="true"/>
234 <field name="_docShell">null</field>
236 <property name="docShell" readonly="true">
237 <getter><![CDATA[
238 if (this._docShell)
239 return this._docShell;
241 let frameLoader = this.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader;
242 if (!frameLoader)
243 return null;
244 this._docShell = frameLoader.docShell;
245 return this._docShell;
246 ]]></getter>
247 </property>
249 <field name="_loadContext">null</field>
251 <property name="loadContext" readonly="true">
252 <getter><![CDATA[
253 if (this._loadContext)
254 return this._loadContext;
256 let frameLoader = this.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader;
257 if (!frameLoader)
258 return null;
259 this._loadContext = frameLoader.loadContext;
260 return this._loadContext;
261 ]]></getter>
262 </property>
264 <property name="docShellIsActive">
265 <getter>
266 <![CDATA[
267 return this.docShell && this.docShell.isActive;
268 ]]>
269 </getter>
270 <setter>
271 <![CDATA[
272 if (this.docShell)
273 return this.docShell.isActive = val;
274 return false;
275 ]]>
276 </setter>
277 </property>
279 <property name="imageDocument"
280 readonly="true">
281 <getter>
282 <![CDATA[
283 var document = this.contentDocument;
284 if (!document || !(document instanceof Ci.nsIImageDocument))
285 return null;
287 try {
288 return {width: document.imageRequest.image.width, height: document.imageRequest.image.height };
289 } catch (e) {}
290 return null;
291 ]]>
292 </getter>
293 </property>
295 <property name="isRemoteBrowser"
296 onget="return (this.getAttribute('remote') == 'true');"
297 readonly="true"/>
299 <property name="messageManager"
300 onget="return this.QueryInterface(Components.interfaces.nsIFrameLoaderOwner).frameLoader.messageManager;"
301 readonly="true"/>
303 <field name="_webNavigation">null</field>
305 <property name="webNavigation"
306 readonly="true">
307 <getter>
308 <![CDATA[
309 if (!this._webNavigation)
310 this._webNavigation = this.docShell.QueryInterface(Components.interfaces.nsIWebNavigation);
311 return this._webNavigation;
312 ]]>
313 </getter>
314 </property>
316 <field name="_webBrowserFind">null</field>
318 <property name="webBrowserFind"
319 readonly="true">
320 <getter>
321 <![CDATA[
322 if (!this._webBrowserFind)
323 this._webBrowserFind = this.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebBrowserFind);
324 return this._webBrowserFind;
325 ]]>
326 </getter>
327 </property>
329 <method name="getTabBrowser">
330 <body>
331 <![CDATA[
332 var tabBrowser = this.parentNode;
333 while (tabBrowser && tabBrowser.localName != "tabbrowser")
334 tabBrowser = tabBrowser.parentNode;
335 return tabBrowser;
336 ]]>
337 </body>
338 </method>
340 <field name="_finder">null</field>
342 <property name="finder" readonly="true">
343 <getter><![CDATA[
344 if (!this._finder) {
345 if (!this.docShell)
346 return null;
348 let Finder = Components.utils.import("resource://gre/modules/Finder.jsm", {}).Finder;
349 this._finder = new Finder(this.docShell);
350 }
351 return this._finder;
352 ]]></getter>
353 </property>
355 <field name="_fastFind">null</field>
356 <property name="fastFind" readonly="true">
357 <getter><![CDATA[
358 if (!this._fastFind) {
359 if (!("@mozilla.org/typeaheadfind;1" in Components.classes))
360 return null;
362 var tabBrowser = this.getTabBrowser();
363 if (tabBrowser && "fastFind" in tabBrowser)
364 return this._fastFind = tabBrowser.fastFind;
366 if (!this.docShell)
367 return null;
369 this._fastFind = Components.classes["@mozilla.org/typeaheadfind;1"]
370 .createInstance(Components.interfaces.nsITypeAheadFind);
371 this._fastFind.init(this.docShell);
372 }
373 return this._fastFind;
374 ]]></getter>
375 </property>
377 <field name="_permanentKey">({})</field>
379 <property name="permanentKey" readonly="true"
380 onget="return this._permanentKey;"/>
382 <field name="_lastSearchString">null</field>
383 <field name="_lastSearchHighlight">false</field>
385 <property name="webProgress"
386 readonly="true"
387 onget="return this.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIWebProgress);"/>
389 <field name="_contentWindow">null</field>
391 <property name="contentWindow"
392 readonly="true"
393 onget="return this._contentWindow || (this._contentWindow = this.docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIDOMWindow));"/>
395 <property name="sessionHistory"
396 onget="return this.webNavigation.sessionHistory;"
397 readonly="true"/>
399 <property name="markupDocumentViewer"
400 onget="return this.docShell.contentViewer.QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);"
401 readonly="true"/>
403 <property name="contentViewerEdit"
404 onget="return this.docShell.contentViewer.QueryInterface(Components.interfaces.nsIContentViewerEdit);"
405 readonly="true"/>
407 <property name="contentViewerFile"
408 onget="return this.docShell.contentViewer.QueryInterface(Components.interfaces.nsIContentViewerFile);"
409 readonly="true"/>
411 <property name="contentDocument"
412 onget="return this.webNavigation.document;"
413 readonly="true"/>
415 <property name="contentTitle"
416 onget="return this.contentDocument.title;"
417 readonly="true"/>
419 <property name="characterSet"
420 onget="return this.contentDocument.characterSet;"
421 readonly="true"/>
423 <property name="contentPrincipal"
424 onget="return this.contentDocument.nodePrincipal;"
425 readonly="true"/>
427 <property name="showWindowResizer"
428 onset="if (val) this.setAttribute('showresizer', 'true');
429 else this.removeAttribute('showresizer');
430 return val;"
431 onget="return this.getAttribute('showresizer') == 'true';"/>
434 <property name="fullZoom">
435 <getter><![CDATA[
436 return this.markupDocumentViewer.fullZoom;
437 ]]></getter>
438 <setter><![CDATA[
439 this.markupDocumentViewer.fullZoom = val;
440 ]]></setter>
441 </property>
443 <property name="textZoom">
444 <getter><![CDATA[
445 return this.markupDocumentViewer.textZoom;
446 ]]></getter>
447 <setter><![CDATA[
448 this.markupDocumentViewer.textZoom = val;
449 ]]></setter>
450 </property>
452 <property name="isSyntheticDocument">
453 <getter><![CDATA[
454 return this.contentDocument.mozSyntheticDocument;
455 ]]></getter>
456 </property>
458 <field name="mPrefs" readonly="true">
459 Components.classes['@mozilla.org/preferences-service;1']
460 .getService(Components.interfaces.nsIPrefBranch);
461 </field>
463 <field name="mAtomService" readonly="true">
464 Components.classes['@mozilla.org/atom-service;1']
465 .getService(Components.interfaces.nsIAtomService);
466 </field>
468 <field name="_mStrBundle">null</field>
470 <property name="mStrBundle">
471 <getter>
472 <![CDATA[
473 if (!this._mStrBundle) {
474 // need to create string bundle manually instead of using <xul:stringbundle/>
475 // see bug 63370 for details
476 this._mStrBundle = Components.classes["@mozilla.org/intl/stringbundle;1"]
477 .getService(Components.interfaces.nsIStringBundleService)
478 .createBundle("chrome://global/locale/browser.properties");
479 }
480 return this._mStrBundle;
481 ]]></getter>
482 </property>
484 <method name="addProgressListener">
485 <parameter name="aListener"/>
486 <parameter name="aNotifyMask"/>
487 <body>
488 <![CDATA[
489 if (!aNotifyMask) {
490 aNotifyMask = Components.interfaces.nsIWebProgress.NOTIFY_ALL;
491 }
492 this.webProgress.addProgressListener(aListener, aNotifyMask);
493 ]]>
494 </body>
495 </method>
497 <method name="removeProgressListener">
498 <parameter name="aListener"/>
499 <body>
500 <![CDATA[
501 this.webProgress.removeProgressListener(aListener);
502 ]]>
503 </body>
504 </method>
506 <method name="attachFormFill">
507 <body>
508 <![CDATA[
509 if (!this.mFormFillAttached && this.hasAttribute("autocompletepopup")) {
510 // hoop up the form fill autocomplete controller
511 var controller = Components.classes["@mozilla.org/satchel/form-fill-controller;1"].
512 getService(Components.interfaces.nsIFormFillController);
514 var popup = document.getElementById(this.getAttribute("autocompletepopup"));
515 if (popup) {
516 controller.attachToBrowser(this.docShell, popup.QueryInterface(Components.interfaces.nsIAutoCompletePopup));
517 this.mFormFillAttached = true;
518 }
519 }
520 ]]>
521 </body>
522 </method>
524 <method name="detachFormFill">
525 <body>
526 <![CDATA[
527 if (this.mFormFillAttached) {
528 // hoop up the form fill autocomplete controller
529 var controller = Components.classes["@mozilla.org/satchel/form-fill-controller;1"].
530 getService(Components.interfaces.nsIFormFillController);
531 controller.detachFromBrowser(this.docShell);
533 this.mFormFillAttached = false;
534 }
535 ]]>
536 </body>
537 </method>
539 <method name="findChildShell">
540 <parameter name="aDocShell"/>
541 <parameter name="aSoughtURI"/>
542 <body>
543 <![CDATA[
544 if (aDocShell.QueryInterface(Components.interfaces.nsIWebNavigation)
545 .currentURI.spec == aSoughtURI.spec)
546 return aDocShell;
547 var node = aDocShell.QueryInterface(
548 Components.interfaces.nsIDocShellTreeItem);
549 for (var i = 0; i < node.childCount; ++i) {
550 var docShell = node.getChildAt(i);
551 docShell = this.findChildShell(docShell, aSoughtURI);
552 if (docShell)
553 return docShell;
554 }
555 return null;
556 ]]>
557 </body>
558 </method>
560 <method name="onPageShow">
561 <parameter name="aEvent"/>
562 <body>
563 <![CDATA[
564 this.attachFormFill();
565 ]]>
566 </body>
567 </method>
569 <method name="onPageHide">
570 <parameter name="aEvent"/>
571 <body>
572 <![CDATA[
573 // Delete the feeds cache if we're hiding the topmost page
574 // (as opposed to one of its iframes).
575 if (this.feeds && aEvent.target == this.contentDocument)
576 this.feeds = null;
577 if (!this.docShell || !this.fastFind)
578 return;
579 var tabBrowser = this.getTabBrowser();
580 if (!tabBrowser || !("fastFind" in tabBrowser) ||
581 tabBrowser.selectedBrowser == this)
582 this.fastFind.setDocShell(this.docShell);
583 ]]>
584 </body>
585 </method>
587 <method name="updateBlockedPopups">
588 <parameter name="aBlockedPopups"/>
589 <parameter name="aFreshPopup"/>
590 <body>
591 <![CDATA[
592 this.blockedPopups = aBlockedPopups;
593 if (aFreshPopup) {
594 this.blockedPopups.reported = false;
595 }
597 var event = document.createEvent("Events");
598 event.initEvent("DOMUpdatePageReport", true, true);
599 this.dispatchEvent(event);
600 ]]>
601 </body>
602 </method>
604 <method name="unblockPopup">
605 <parameter name="aPopupIndex"/>
606 <body><![CDATA[
607 this.messageManager.sendAsyncMessage("PopupBlocking:UnblockPopup",
608 {index: aPopupIndex});
609 ]]></body>
610 </method>
612 <field name="blockedPopups">null</field>
614 <!-- Obsolete name for blockedPopups. Used by metro and android. -->
615 <property name="pageReport"
616 onget="return this.blockedPopups;"
617 readonly="true"/>
619 <property name="securityUI">
620 <getter>
621 <![CDATA[
622 // Bug 666809 - SecurityUI support for e10s
623 if (!this.docShell)
624 return null;
626 if (!this.docShell.securityUI) {
627 const SECUREBROWSERUI_CONTRACTID = "@mozilla.org/secure_browser_ui;1";
628 if (!this.hasAttribute("disablesecurity") &&
629 SECUREBROWSERUI_CONTRACTID in Components.classes) {
630 var securityUI = Components.classes[SECUREBROWSERUI_CONTRACTID]
631 .createInstance(Components.interfaces.nsISecureBrowserUI);
632 securityUI.init(this.contentWindow);
633 }
634 }
636 return this.docShell.securityUI;
637 ]]>
638 </getter>
639 <setter>
640 <![CDATA[
641 this.docShell.securityUI = val;
642 ]]>
643 </setter>
644 </property>
646 <method name="adjustPriority">
647 <parameter name="adjustment"/>
648 <body><![CDATA[
649 let loadGroup = this.webNavigation.QueryInterface(Ci.nsIDocumentLoader)
650 .loadGroup.QueryInterface(Ci.nsISupportsPriority);
651 loadGroup.adjustPriority(adjustment);
652 ]]></body>
653 </method>
655 <!--
656 This field tracks the location bar state. The value that the user typed
657 in to the location bar may not be changed while this field is zero.
658 However invoking a load will temporarily increase this field to allow
659 the location bar to be updated to the new URL.
661 Case 1: Anchor scroll
662 The user appends the anchor to the URL. This sets the location bar
663 into typed state, and disables changes to the location bar. The user
664 then requests the scroll. loadURIWithFlags temporarily increases the
665 flag by 1 so that the anchor scroll's location change resets the
666 location bar state.
668 Case 2: Interrupted load
669 The user types in and submits the URL. This triggers an asynchronous
670 network load which increases the flag by 2. (The temporary increase
671 from loadURIWithFlags is not noticeable in this case.) When the load
672 is interrupted the flag returns to zero, and the location bar stays
673 in typed state.
675 Case 3: New load
676 This works like case 2, but as the load is not interrupted the
677 location changes while the flag is still 2 thus resetting the
678 location bar state.
680 Case 4: Corrected load
681 This is a combination of case 2 and case 3, except that the original
682 load is interrupted by the new load. Normally cancelling and starting
683 a new load would reset the flag to 0 and then increase it to 2 again.
684 However both actions occur as a consequence of the loadURIWithFlags
685 invocation, which adds its temporary increase in to the mix. Since
686 the new URL would have been typed in the flag would have been reset
687 before loadURIWithFlags incremented it. The interruption resets the
688 flag to 0 and increases it to 2. Although loadURIWithFlags will
689 decrement the flag it remains at 1 thus allowing the location bar
690 state to be reset when the new load changes the location.
691 This case also applies when loading into a new browser, as this
692 interrupts the default load of about:blank.
693 -->
694 <field name="userTypedClear">
695 1
696 </field>
698 <field name="_userTypedValue">
699 null
700 </field>
702 <property name="userTypedValue"
703 onget="return this._userTypedValue;">
704 <setter><![CDATA[
705 this.userTypedClear = 0;
706 this._userTypedValue = val;
707 return val;
708 ]]></setter>
709 </property>
711 <field name="mFormFillAttached">
712 false
713 </field>
715 <field name="isShowingMessage">
716 false
717 </field>
719 <field name="droppedLinkHandler">
720 null
721 </field>
723 <field name="mIconURL">null</field>
725 <!-- This is managed by the tabbrowser -->
726 <field name="lastURI">null</field>
728 <field name="mDestroyed">false</field>
730 <constructor>
731 <![CDATA[
732 try {
733 // |webNavigation.sessionHistory| will have been set by the frame
734 // loader when creating the docShell as long as this xul:browser
735 // doesn't have the 'disablehistory' attribute set.
736 if (this.docShell && this.webNavigation.sessionHistory) {
737 var os = Components.classes["@mozilla.org/observer-service;1"]
738 .getService(Components.interfaces.nsIObserverService);
739 os.addObserver(this, "browser:purge-session-history", false);
741 // enable global history if we weren't told otherwise
742 if (!this.hasAttribute("disableglobalhistory") && !this.isRemoteBrowser) {
743 try {
744 this.docShell.useGlobalHistory = true;
745 } catch(ex) {
746 // This can occur if the Places database is locked
747 Components.utils.reportError("Error enabling browser global history: " + ex);
748 }
749 }
750 }
751 }
752 catch (e) {
753 Components.utils.reportError(e);
754 }
755 try {
756 var securityUI = this.securityUI;
757 }
758 catch (e) {
759 }
761 // Listen for first load for lazy attachment to form fill controller
762 // (But we don't want to do this for remote browsers - the test infra
763 // might fire these events when they normally wouldn't.)
764 if (!this.isRemoteBrowser) {
765 this.addEventListener("pageshow", this.onPageShow, true);
766 this.addEventListener("pagehide", this.onPageHide, true);
767 }
769 if (this.messageManager) {
770 this.messageManager.addMessageListener("PopupBlocking:UpdateBlockedPopups", this);
771 this.messageManager.addMessageListener("Autoscroll:Start", this);
772 this.messageManager.addMessageListener("Autoscroll:Cancel", this);
773 this.messageManager.loadFrameScript("chrome://global/content/browser-content.js", true);
774 }
775 ]]>
776 </constructor>
778 <destructor>
779 <![CDATA[
780 this.destroy();
781 ]]>
782 </destructor>
784 <!-- This is necessary because the destructor doesn't always get called when
785 we are removed from a tabbrowser. This will be explicitly called by tabbrowser -->
786 <method name="destroy">
787 <body>
788 <![CDATA[
789 if (this.mDestroyed)
790 return;
791 this.mDestroyed = true;
793 if (this.docShell && this.webNavigation.sessionHistory) {
794 var os = Components.classes["@mozilla.org/observer-service;1"]
795 .getService(Components.interfaces.nsIObserverService);
796 try {
797 os.removeObserver(this, "browser:purge-session-history");
798 } catch (ex) {
799 // It's not clear why this sometimes throws an exception.
800 }
801 }
803 this.detachFormFill();
805 this._fastFind = null;
806 this._webBrowserFind = null;
808 // The feeds cache can keep the document inside this browser alive.
809 this.feeds = null;
811 this.lastURI = null;
813 if (!this.isRemoteBrowser) {
814 this.removeEventListener("pageshow", this.onPageShow, true);
815 this.removeEventListener("pagehide", this.onPageHide, true);
816 }
818 if (this._autoScrollNeedsCleanup) {
819 // we polluted the global scope, so clean it up
820 this._autoScrollPopup.parentNode.removeChild(this._autoScrollPopup);
821 }
822 ]]>
823 </body>
824 </method>
826 <!--
827 We call this _receiveMessage (and alias receiveMessage to it) so that
828 bindings that inherit from this one can delegate to it.
829 -->
830 <method name="_receiveMessage">
831 <parameter name="aMessage"/>
832 <body><![CDATA[
833 let data = aMessage.data;
834 switch (aMessage.name) {
835 case "PopupBlocking:UpdateBlockedPopups":
836 this.updateBlockedPopups(data.blockedPopups, data.freshPopup);
837 break;
838 case "Autoscroll:Start": {
839 if (!this.autoscrollEnabled) {
840 return false;
841 }
842 let pos = this.mapScreenCoordinatesFromContent(data.screenX, data.screenY);
843 this.startScroll(data.scrolldir, pos.x, pos.y);
844 return true;
845 }
846 case "Autoscroll:Cancel":
847 this._autoScrollPopup.hidePopup();
848 break;
849 }
850 ]]></body>
851 </method>
853 <method name="receiveMessage">
854 <parameter name="aMessage"/>
855 <body><![CDATA[
856 return this._receiveMessage(aMessage);
857 ]]></body>
858 </method>
860 <method name="observe">
861 <parameter name="aSubject"/>
862 <parameter name="aTopic"/>
863 <parameter name="aState"/>
864 <body>
865 <![CDATA[
866 if (aTopic != "browser:purge-session-history" || !this.sessionHistory)
867 return;
869 // place the entry at current index at the end of the history list, so it won't get removed
870 if (this.sessionHistory.index < this.sessionHistory.count - 1) {
871 var indexEntry = this.sessionHistory.getEntryAtIndex(this.sessionHistory.index, false);
872 this.sessionHistory.QueryInterface(Components.interfaces.nsISHistoryInternal);
873 indexEntry.QueryInterface(Components.interfaces.nsISHEntry);
874 this.sessionHistory.addEntry(indexEntry, true);
875 }
877 var purge = this.sessionHistory.count;
878 if (this.currentURI != "about:blank")
879 --purge; // Don't remove the page the user's staring at from shistory
881 if (purge > 0)
882 this.sessionHistory.PurgeHistory(purge);
883 ]]>
884 </body>
885 </method>
887 <field name="_AUTOSCROLL_SNAP">10</field>
888 <field name="_scrolling">false</field>
889 <field name="_startX">null</field>
890 <field name="_startY">null</field>
891 <field name="_autoScrollPopup">null</field>
892 <field name="_autoScrollNeedsCleanup">false</field>
894 <method name="stopScroll">
895 <body>
896 <![CDATA[
897 if (this._scrolling) {
898 this._scrolling = false;
899 window.removeEventListener("mousemove", this, true);
900 window.removeEventListener("mousedown", this, true);
901 window.removeEventListener("mouseup", this, true);
902 window.removeEventListener("contextmenu", this, true);
903 window.removeEventListener("keydown", this, true);
904 window.removeEventListener("keypress", this, true);
905 window.removeEventListener("keyup", this, true);
906 this.messageManager.sendAsyncMessage("Autoscroll:Stop");
907 }
908 ]]>
909 </body>
910 </method>
912 <method name="_createAutoScrollPopup">
913 <body>
914 <![CDATA[
915 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
916 var popup = document.createElementNS(XUL_NS, "panel");
917 popup.className = "autoscroller";
918 // We set this attribute on the element so that mousemove
919 // events can be handled by browser-content.js.
920 popup.setAttribute("mousethrough", "always");
921 return popup;
922 ]]>
923 </body>
924 </method>
926 <method name="startScroll">
927 <parameter name="scrolldir"/>
928 <parameter name="screenX"/>
929 <parameter name="screenY"/>
930 <body><![CDATA[
931 if (!this._autoScrollPopup) {
932 if (this.hasAttribute("autoscrollpopup")) {
933 // our creator provided a popup to share
934 this._autoScrollPopup = document.getElementById(this.getAttribute("autoscrollpopup"));
935 }
936 else {
937 // we weren't provided a popup; we have to use the global scope
938 this._autoScrollPopup = this._createAutoScrollPopup();
939 document.documentElement.appendChild(this._autoScrollPopup);
940 this._autoScrollNeedsCleanup = true;
941 }
942 }
944 // we need these attributes so themers don't need to create per-platform packages
945 if (screen.colorDepth > 8) { // need high color for transparency
946 // Exclude second-rate platforms
947 this._autoScrollPopup.setAttribute("transparent", !/BeOS|OS\/2/.test(navigator.appVersion));
948 // Enable translucency on Windows and Mac
949 this._autoScrollPopup.setAttribute("translucent", /Win|Mac/.test(navigator.platform));
950 }
952 this._autoScrollPopup.setAttribute("scrolldir", scrolldir);
953 this._autoScrollPopup.addEventListener("popuphidden", this, true);
954 this._autoScrollPopup.showPopup(document.documentElement,
955 screenX,
956 screenY,
957 "popup", null, null);
958 this._ignoreMouseEvents = true;
959 this._scrolling = true;
960 this._startX = screenX;
961 this._startY = screenY;
963 window.addEventListener("mousemove", this, true);
964 window.addEventListener("mousedown", this, true);
965 window.addEventListener("mouseup", this, true);
966 window.addEventListener("contextmenu", this, true);
967 window.addEventListener("keydown", this, true);
968 window.addEventListener("keypress", this, true);
969 window.addEventListener("keyup", this, true);
970 ]]>
971 </body>
972 </method>
974 <method name="handleEvent">
975 <parameter name="aEvent"/>
976 <body>
977 <![CDATA[
978 if (this._scrolling) {
979 switch(aEvent.type) {
980 case "mousemove": {
981 var x = aEvent.screenX - this._startX;
982 var y = aEvent.screenY - this._startY;
984 if ((x > this._AUTOSCROLL_SNAP || x < -this._AUTOSCROLL_SNAP) ||
985 (y > this._AUTOSCROLL_SNAP || y < -this._AUTOSCROLL_SNAP))
986 this._ignoreMouseEvents = false;
987 break;
988 }
989 case "mouseup":
990 case "mousedown":
991 case "contextmenu": {
992 if (!this._ignoreMouseEvents)
993 this._autoScrollPopup.hidePopup();
994 this._ignoreMouseEvents = false;
995 break;
996 }
997 case "popuphidden": {
998 this._autoScrollPopup.removeEventListener("popuphidden", this, true);
999 this.stopScroll();
1000 break;
1001 }
1002 case "keydown": {
1003 if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) {
1004 // the escape key will be processed by
1005 // nsXULPopupManager::KeyDown and the panel will be closed.
1006 // So, don't consume the key event here.
1007 break;
1008 }
1009 // don't break here. we need to eat keydown events.
1010 }
1011 case "keypress":
1012 case "keyup": {
1013 // All keyevents should be eaten here during autoscrolling.
1014 aEvent.stopPropagation();
1015 aEvent.preventDefault();
1016 break;
1017 }
1018 }
1019 }
1020 ]]>
1021 </body>
1022 </method>
1024 <!--
1025 For out-of-process code, event.screen[XY] is relative to the
1026 left/top of the content view. For in-process code,
1027 event.screen[XY] is relative to the left/top of the screen. We
1028 use this method to map screen coordinates received from a
1029 (possibly out-of-process) <browser> element to coordinates
1030 that are relative to the screen. This code handles the
1031 in-process case, where we return the coordinates unchanged.
1032 -->
1033 <method name="mapScreenCoordinatesFromContent">
1034 <parameter name="aScreenX"/>
1035 <parameter name="aScreenY"/>
1036 <body>
1037 <![CDATA[
1038 return { x: aScreenX, y: aScreenY };
1039 ]]>
1040 </body>
1041 </method>
1043 <method name="swapDocShells">
1044 <parameter name="aOtherBrowser"/>
1045 <body>
1046 <![CDATA[
1047 // We need to swap fields that are tied to our docshell or related to
1048 // the loaded page
1049 // Fields which are built as a result of notifactions (pageshow/hide,
1050 // DOMLinkAdded/Removed, onStateChange) should not be swapped here,
1051 // because these notifications are dispatched again once the docshells
1052 // are swapped.
1053 var fieldsToSwap = [
1054 "_docShell",
1055 "_webBrowserFind",
1056 "_contentWindow",
1057 "_webNavigation",
1058 "_permanentKey"
1059 ];
1061 var ourFieldValues = {};
1062 var otherFieldValues = {};
1063 for each (var field in fieldsToSwap) {
1064 ourFieldValues[field] = this[field];
1065 otherFieldValues[field] = aOtherBrowser[field];
1066 }
1068 if (window.PopupNotifications)
1069 PopupNotifications._swapBrowserNotifications(aOtherBrowser, this);
1071 this.QueryInterface(Components.interfaces.nsIFrameLoaderOwner)
1072 .swapFrameLoaders(aOtherBrowser);
1074 // Before we swap the actual docShell property we need to detach the
1075 // form fill controller from those docShells.
1076 this.detachFormFill();
1077 aOtherBrowser.detachFormFill();
1079 for each (var field in fieldsToSwap) {
1080 this[field] = otherFieldValues[field];
1081 aOtherBrowser[field] = ourFieldValues[field];
1082 }
1084 // Re-attach the docShells to the form fill controller.
1085 this.attachFormFill();
1086 aOtherBrowser.attachFormFill();
1088 // Null the current nsITypeAheadFind instances so that they're
1089 // lazily re-created on access. We need to do this because they
1090 // might have attached the wrong docShell.
1091 this._fastFind = aOtherBrowser._fastFind = null;
1092 ]]>
1093 </body>
1094 </method>
1095 </implementation>
1097 <handlers>
1098 <handler event="keypress" keycode="VK_F7" group="system">
1099 <![CDATA[
1100 if (event.defaultPrevented || !event.isTrusted)
1101 return;
1103 var isEnabled = this.mPrefs.getBoolPref("accessibility.browsewithcaret_shortcut.enabled");
1104 if (!isEnabled)
1105 return;
1107 // Toggle browse with caret mode
1108 var browseWithCaretOn = false;
1109 var warn = true;
1111 try {
1112 warn = this.mPrefs.getBoolPref("accessibility.warn_on_browsewithcaret");
1113 } catch (ex) {
1114 }
1116 try {
1117 browseWithCaretOn = this.mPrefs.getBoolPref("accessibility.browsewithcaret");
1118 } catch (ex) {
1119 }
1120 if (warn && !browseWithCaretOn) {
1121 var checkValue = {value:false};
1122 var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
1123 .getService(Components.interfaces.nsIPromptService);
1125 var buttonPressed = promptService.confirmEx(window,
1126 this.mStrBundle.GetStringFromName('browsewithcaret.checkWindowTitle'),
1127 this.mStrBundle.GetStringFromName('browsewithcaret.checkLabel'),
1128 promptService.STD_YES_NO_BUTTONS,
1129 null, null, null, this.mStrBundle.GetStringFromName('browsewithcaret.checkMsg'),
1130 checkValue);
1131 if (buttonPressed != 0)
1132 return;
1133 if (checkValue.value) {
1134 try {
1135 this.mPrefs.setBoolPref("accessibility.warn_on_browsewithcaret", false);
1136 }
1137 catch (ex) {
1138 }
1139 }
1140 }
1142 // Toggle the pref
1143 try {
1144 this.mPrefs.setBoolPref("accessibility.browsewithcaret",!browseWithCaretOn);
1145 } catch (ex) {
1146 }
1147 ]]>
1148 </handler>
1149 <handler event="dragover" group="system">
1150 <![CDATA[
1151 if (!this.droppedLinkHandler || event.defaultPrevented)
1152 return;
1154 // For drags that appear to be internal text (for example, tab drags),
1155 // set the dropEffect to 'none'. This prevents the drop even if some
1156 // other listener cancelled the event.
1157 var types = event.dataTransfer.types;
1158 if (types.contains("text/x-moz-text-internal") && !types.contains("text/plain")) {
1159 event.dataTransfer.dropEffect = "none";
1160 event.stopPropagation();
1161 event.preventDefault();
1162 }
1164 let linkHandler = Components.classes["@mozilla.org/content/dropped-link-handler;1"].
1165 getService(Components.interfaces.nsIDroppedLinkHandler);
1166 if (linkHandler.canDropLink(event, false))
1167 event.preventDefault();
1168 ]]>
1169 </handler>
1170 <handler event="drop" group="system">
1171 <![CDATA[
1172 if (!this.droppedLinkHandler || event.defaultPrevented)
1173 return;
1175 let name = { };
1176 let linkHandler = Components.classes["@mozilla.org/content/dropped-link-handler;1"].
1177 getService(Components.interfaces.nsIDroppedLinkHandler);
1178 try {
1179 // Pass true to prevent the dropping of javascript:/data: URIs
1180 var uri = linkHandler.dropLink(event, name, true);
1181 } catch (ex) {
1182 return;
1183 }
1185 if (uri) {
1186 this.droppedLinkHandler(event, uri, name.value);
1187 }
1188 ]]>
1189 </handler>
1190 </handlers>
1192 </binding>
1194 </bindings>