|
1 # -*- Mode: javascript; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 # This Source Code Form is subject to the terms of the Mozilla Public |
|
3 # License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 # file, You can obtain one at http://mozilla.org/MPL/2.0/. |
|
5 |
|
6 // Services = object with smart getters for common XPCOM services |
|
7 Components.utils.import("resource://gre/modules/Services.jsm"); |
|
8 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); |
|
9 Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); |
|
10 Components.utils.import("resource:///modules/RecentWindow.jsm"); |
|
11 |
|
12 XPCOMUtils.defineLazyGetter(this, "BROWSER_NEW_TAB_URL", function () { |
|
13 const PREF = "browser.newtab.url"; |
|
14 |
|
15 function getNewTabPageURL() { |
|
16 if (!Services.prefs.prefHasUserValue(PREF)) { |
|
17 if (PrivateBrowsingUtils.isWindowPrivate(window) && |
|
18 !PrivateBrowsingUtils.permanentPrivateBrowsing) |
|
19 return "about:privatebrowsing"; |
|
20 } |
|
21 let url = Services.prefs.getComplexValue(PREF, Ci.nsISupportsString).data; |
|
22 return url || "about:blank"; |
|
23 } |
|
24 |
|
25 function update() { |
|
26 BROWSER_NEW_TAB_URL = getNewTabPageURL(); |
|
27 } |
|
28 |
|
29 Services.prefs.addObserver(PREF, update, false); |
|
30 |
|
31 addEventListener("unload", function onUnload() { |
|
32 removeEventListener("unload", onUnload); |
|
33 Services.prefs.removeObserver(PREF, update); |
|
34 }); |
|
35 |
|
36 return getNewTabPageURL(); |
|
37 }); |
|
38 |
|
39 var TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab"; |
|
40 |
|
41 var gBidiUI = false; |
|
42 |
|
43 /** |
|
44 * Determines whether the given url is considered a special URL for new tabs. |
|
45 */ |
|
46 function isBlankPageURL(aURL) { |
|
47 return aURL == "about:blank" || aURL == BROWSER_NEW_TAB_URL; |
|
48 } |
|
49 |
|
50 function getBrowserURL() |
|
51 { |
|
52 return "chrome://browser/content/browser.xul"; |
|
53 } |
|
54 |
|
55 function getTopWin(skipPopups) { |
|
56 // If this is called in a browser window, use that window regardless of |
|
57 // whether it's the frontmost window, since commands can be executed in |
|
58 // background windows (bug 626148). |
|
59 if (top.document.documentElement.getAttribute("windowtype") == "navigator:browser" && |
|
60 (!skipPopups || top.toolbar.visible)) |
|
61 return top; |
|
62 |
|
63 let isPrivate = PrivateBrowsingUtils.isWindowPrivate(window); |
|
64 return RecentWindow.getMostRecentBrowserWindow({private: isPrivate, |
|
65 allowPopups: !skipPopups}); |
|
66 } |
|
67 |
|
68 function openTopWin(url) { |
|
69 /* deprecated */ |
|
70 openUILinkIn(url, "current"); |
|
71 } |
|
72 |
|
73 function getBoolPref(prefname, def) |
|
74 { |
|
75 try { |
|
76 return Services.prefs.getBoolPref(prefname); |
|
77 } |
|
78 catch(er) { |
|
79 return def; |
|
80 } |
|
81 } |
|
82 |
|
83 /* openUILink handles clicks on UI elements that cause URLs to load. |
|
84 * |
|
85 * As the third argument, you may pass an object with the same properties as |
|
86 * accepted by openUILinkIn, plus "ignoreButton" and "ignoreAlt". |
|
87 */ |
|
88 function openUILink(url, event, aIgnoreButton, aIgnoreAlt, aAllowThirdPartyFixup, |
|
89 aPostData, aReferrerURI) { |
|
90 let params; |
|
91 |
|
92 if (aIgnoreButton && typeof aIgnoreButton == "object") { |
|
93 params = aIgnoreButton; |
|
94 |
|
95 // don't forward "ignoreButton" and "ignoreAlt" to openUILinkIn |
|
96 aIgnoreButton = params.ignoreButton; |
|
97 aIgnoreAlt = params.ignoreAlt; |
|
98 delete params.ignoreButton; |
|
99 delete params.ignoreAlt; |
|
100 } else { |
|
101 params = { |
|
102 allowThirdPartyFixup: aAllowThirdPartyFixup, |
|
103 postData: aPostData, |
|
104 referrerURI: aReferrerURI, |
|
105 initiatingDoc: event ? event.target.ownerDocument : null |
|
106 }; |
|
107 } |
|
108 |
|
109 let where = whereToOpenLink(event, aIgnoreButton, aIgnoreAlt); |
|
110 openUILinkIn(url, where, params); |
|
111 } |
|
112 |
|
113 |
|
114 /* whereToOpenLink() looks at an event to decide where to open a link. |
|
115 * |
|
116 * The event may be a mouse event (click, double-click, middle-click) or keypress event (enter). |
|
117 * |
|
118 * On Windows, the modifiers are: |
|
119 * Ctrl new tab, selected |
|
120 * Shift new window |
|
121 * Ctrl+Shift new tab, in background |
|
122 * Alt save |
|
123 * |
|
124 * Middle-clicking is the same as Ctrl+clicking (it opens a new tab). |
|
125 * |
|
126 * Exceptions: |
|
127 * - Alt is ignored for menu items selected using the keyboard so you don't accidentally save stuff. |
|
128 * (Currently, the Alt isn't sent here at all for menu items, but that will change in bug 126189.) |
|
129 * - Alt is hard to use in context menus, because pressing Alt closes the menu. |
|
130 * - Alt can't be used on the bookmarks toolbar because Alt is used for "treat this as something draggable". |
|
131 * - The button is ignored for the middle-click-paste-URL feature, since it's always a middle-click. |
|
132 */ |
|
133 function whereToOpenLink( e, ignoreButton, ignoreAlt ) |
|
134 { |
|
135 // This method must treat a null event like a left click without modifier keys (i.e. |
|
136 // e = { shiftKey:false, ctrlKey:false, metaKey:false, altKey:false, button:0 }) |
|
137 // for compatibility purposes. |
|
138 if (!e) |
|
139 return "current"; |
|
140 |
|
141 var shift = e.shiftKey; |
|
142 var ctrl = e.ctrlKey; |
|
143 var meta = e.metaKey; |
|
144 var alt = e.altKey && !ignoreAlt; |
|
145 |
|
146 // ignoreButton allows "middle-click paste" to use function without always opening in a new window. |
|
147 var middle = !ignoreButton && e.button == 1; |
|
148 var middleUsesTabs = getBoolPref("browser.tabs.opentabfor.middleclick", true); |
|
149 |
|
150 // Don't do anything special with right-mouse clicks. They're probably clicks on context menu items. |
|
151 |
|
152 #ifdef XP_MACOSX |
|
153 if (meta || (middle && middleUsesTabs)) |
|
154 #else |
|
155 if (ctrl || (middle && middleUsesTabs)) |
|
156 #endif |
|
157 return shift ? "tabshifted" : "tab"; |
|
158 |
|
159 if (alt && getBoolPref("browser.altClickSave", false)) |
|
160 return "save"; |
|
161 |
|
162 if (shift || (middle && !middleUsesTabs)) |
|
163 return "window"; |
|
164 |
|
165 return "current"; |
|
166 } |
|
167 |
|
168 /* openUILinkIn opens a URL in a place specified by the parameter |where|. |
|
169 * |
|
170 * |where| can be: |
|
171 * "current" current tab (if there aren't any browser windows, then in a new window instead) |
|
172 * "tab" new tab (if there aren't any browser windows, then in a new window instead) |
|
173 * "tabshifted" same as "tab" but in background if default is to select new tabs, and vice versa |
|
174 * "window" new window |
|
175 * "save" save to disk (with no filename hint!) |
|
176 * |
|
177 * aAllowThirdPartyFixup controls whether third party services such as Google's |
|
178 * I Feel Lucky are allowed to interpret this URL. This parameter may be |
|
179 * undefined, which is treated as false. |
|
180 * |
|
181 * Instead of aAllowThirdPartyFixup, you may also pass an object with any of |
|
182 * these properties: |
|
183 * allowThirdPartyFixup (boolean) |
|
184 * postData (nsIInputStream) |
|
185 * referrerURI (nsIURI) |
|
186 * relatedToCurrent (boolean) |
|
187 * skipTabAnimation (boolean) |
|
188 */ |
|
189 function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI) { |
|
190 var params; |
|
191 |
|
192 if (arguments.length == 3 && typeof arguments[2] == "object") { |
|
193 params = aAllowThirdPartyFixup; |
|
194 } else { |
|
195 params = { |
|
196 allowThirdPartyFixup: aAllowThirdPartyFixup, |
|
197 postData: aPostData, |
|
198 referrerURI: aReferrerURI |
|
199 }; |
|
200 } |
|
201 |
|
202 params.fromChrome = true; |
|
203 |
|
204 openLinkIn(url, where, params); |
|
205 } |
|
206 |
|
207 function openLinkIn(url, where, params) { |
|
208 if (!where || !url) |
|
209 return; |
|
210 |
|
211 var aFromChrome = params.fromChrome; |
|
212 var aAllowThirdPartyFixup = params.allowThirdPartyFixup; |
|
213 var aPostData = params.postData; |
|
214 var aCharset = params.charset; |
|
215 var aReferrerURI = params.referrerURI; |
|
216 var aRelatedToCurrent = params.relatedToCurrent; |
|
217 var aDisableMCB = params.disableMCB; |
|
218 var aInBackground = params.inBackground; |
|
219 var aDisallowInheritPrincipal = params.disallowInheritPrincipal; |
|
220 var aInitiatingDoc = params.initiatingDoc; |
|
221 var aIsPrivate = params.private; |
|
222 var aSkipTabAnimation = params.skipTabAnimation; |
|
223 |
|
224 if (where == "save") { |
|
225 if (!aInitiatingDoc) { |
|
226 Components.utils.reportError("openUILink/openLinkIn was called with " + |
|
227 "where == 'save' but without initiatingDoc. See bug 814264."); |
|
228 return; |
|
229 } |
|
230 saveURL(url, null, null, true, null, aReferrerURI, aInitiatingDoc); |
|
231 return; |
|
232 } |
|
233 const Cc = Components.classes; |
|
234 const Ci = Components.interfaces; |
|
235 |
|
236 var w = getTopWin(); |
|
237 if ((where == "tab" || where == "tabshifted") && |
|
238 w && !w.toolbar.visible) { |
|
239 w = getTopWin(true); |
|
240 aRelatedToCurrent = false; |
|
241 } |
|
242 |
|
243 if (!w || where == "window") { |
|
244 var sa = Cc["@mozilla.org/supports-array;1"]. |
|
245 createInstance(Ci.nsISupportsArray); |
|
246 |
|
247 var wuri = Cc["@mozilla.org/supports-string;1"]. |
|
248 createInstance(Ci.nsISupportsString); |
|
249 wuri.data = url; |
|
250 |
|
251 let charset = null; |
|
252 if (aCharset) { |
|
253 charset = Cc["@mozilla.org/supports-string;1"] |
|
254 .createInstance(Ci.nsISupportsString); |
|
255 charset.data = "charset=" + aCharset; |
|
256 } |
|
257 |
|
258 var allowThirdPartyFixupSupports = Cc["@mozilla.org/supports-PRBool;1"]. |
|
259 createInstance(Ci.nsISupportsPRBool); |
|
260 allowThirdPartyFixupSupports.data = aAllowThirdPartyFixup; |
|
261 |
|
262 sa.AppendElement(wuri); |
|
263 sa.AppendElement(charset); |
|
264 sa.AppendElement(aReferrerURI); |
|
265 sa.AppendElement(aPostData); |
|
266 sa.AppendElement(allowThirdPartyFixupSupports); |
|
267 |
|
268 let features = "chrome,dialog=no,all"; |
|
269 if (aIsPrivate) { |
|
270 features += ",private"; |
|
271 } |
|
272 |
|
273 Services.ww.openWindow(w || window, getBrowserURL(), null, features, sa); |
|
274 return; |
|
275 } |
|
276 |
|
277 let loadInBackground = where == "current" ? false : aInBackground; |
|
278 if (loadInBackground == null) { |
|
279 loadInBackground = aFromChrome ? |
|
280 false : |
|
281 getBoolPref("browser.tabs.loadInBackground"); |
|
282 } |
|
283 |
|
284 if (where == "current" && w.gBrowser.selectedTab.pinned) { |
|
285 try { |
|
286 let uriObj = Services.io.newURI(url, null, null); |
|
287 if (!uriObj.schemeIs("javascript") && |
|
288 w.gBrowser.currentURI.host != uriObj.host) { |
|
289 where = "tab"; |
|
290 loadInBackground = false; |
|
291 } |
|
292 } catch (err) { |
|
293 where = "tab"; |
|
294 loadInBackground = false; |
|
295 } |
|
296 } |
|
297 |
|
298 // Raise the target window before loading the URI, since loading it may |
|
299 // result in a new frontmost window (e.g. "javascript:window.open('');"). |
|
300 w.focus(); |
|
301 |
|
302 switch (where) { |
|
303 case "current": |
|
304 let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE; |
|
305 if (aAllowThirdPartyFixup) { |
|
306 flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; |
|
307 flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; |
|
308 } |
|
309 if (aDisallowInheritPrincipal) |
|
310 flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER; |
|
311 w.gBrowser.loadURIWithFlags(url, flags, aReferrerURI, null, aPostData); |
|
312 break; |
|
313 case "tabshifted": |
|
314 loadInBackground = !loadInBackground; |
|
315 // fall through |
|
316 case "tab": |
|
317 let browser = w.gBrowser; |
|
318 browser.loadOneTab(url, { |
|
319 referrerURI: aReferrerURI, |
|
320 charset: aCharset, |
|
321 postData: aPostData, |
|
322 inBackground: loadInBackground, |
|
323 allowThirdPartyFixup: aAllowThirdPartyFixup, |
|
324 relatedToCurrent: aRelatedToCurrent, |
|
325 skipAnimation: aSkipTabAnimation, |
|
326 disableMCB: aDisableMCB}); |
|
327 break; |
|
328 } |
|
329 |
|
330 w.gBrowser.selectedBrowser.focus(); |
|
331 |
|
332 if (!loadInBackground && w.isBlankPageURL(url)) |
|
333 w.focusAndSelectUrlBar(); |
|
334 } |
|
335 |
|
336 // Used as an onclick handler for UI elements with link-like behavior. |
|
337 // e.g. onclick="checkForMiddleClick(this, event);" |
|
338 function checkForMiddleClick(node, event) { |
|
339 // We should be using the disabled property here instead of the attribute, |
|
340 // but some elements that this function is used with don't support it (e.g. |
|
341 // menuitem). |
|
342 if (node.getAttribute("disabled") == "true") |
|
343 return; // Do nothing |
|
344 |
|
345 if (event.button == 1) { |
|
346 /* Execute the node's oncommand or command. |
|
347 * |
|
348 * XXX: we should use node.oncommand(event) once bug 246720 is fixed. |
|
349 */ |
|
350 var target = node.hasAttribute("oncommand") ? node : |
|
351 node.ownerDocument.getElementById(node.getAttribute("command")); |
|
352 var fn = new Function("event", target.getAttribute("oncommand")); |
|
353 fn.call(target, event); |
|
354 |
|
355 // If the middle-click was on part of a menu, close the menu. |
|
356 // (Menus close automatically with left-click but not with middle-click.) |
|
357 closeMenus(event.target); |
|
358 } |
|
359 } |
|
360 |
|
361 // Closes all popups that are ancestors of the node. |
|
362 function closeMenus(node) |
|
363 { |
|
364 if ("tagName" in node) { |
|
365 if (node.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" |
|
366 && (node.tagName == "menupopup" || node.tagName == "popup")) |
|
367 node.hidePopup(); |
|
368 |
|
369 closeMenus(node.parentNode); |
|
370 } |
|
371 } |
|
372 |
|
373 // Gather all descendent text under given document node. |
|
374 function gatherTextUnder ( root ) |
|
375 { |
|
376 var text = ""; |
|
377 var node = root.firstChild; |
|
378 var depth = 1; |
|
379 while ( node && depth > 0 ) { |
|
380 // See if this node is text. |
|
381 if ( node.nodeType == Node.TEXT_NODE ) { |
|
382 // Add this text to our collection. |
|
383 text += " " + node.data; |
|
384 } else if ( node instanceof HTMLImageElement) { |
|
385 // If it has an "alt" attribute, add that. |
|
386 var altText = node.getAttribute( "alt" ); |
|
387 if ( altText && altText != "" ) { |
|
388 text += " " + altText; |
|
389 } |
|
390 } |
|
391 // Find next node to test. |
|
392 // First, see if this node has children. |
|
393 if ( node.hasChildNodes() ) { |
|
394 // Go to first child. |
|
395 node = node.firstChild; |
|
396 depth++; |
|
397 } else { |
|
398 // No children, try next sibling (or parent next sibling). |
|
399 while ( depth > 0 && !node.nextSibling ) { |
|
400 node = node.parentNode; |
|
401 depth--; |
|
402 } |
|
403 if ( node.nextSibling ) { |
|
404 node = node.nextSibling; |
|
405 } |
|
406 } |
|
407 } |
|
408 // Strip leading and tailing whitespace. |
|
409 text = text.trim(); |
|
410 // Compress remaining whitespace. |
|
411 text = text.replace( /\s+/g, " " ); |
|
412 return text; |
|
413 } |
|
414 |
|
415 function getShellService() |
|
416 { |
|
417 var shell = null; |
|
418 try { |
|
419 shell = Components.classes["@mozilla.org/browser/shell-service;1"] |
|
420 .getService(Components.interfaces.nsIShellService); |
|
421 } catch (e) { |
|
422 } |
|
423 return shell; |
|
424 } |
|
425 |
|
426 function isBidiEnabled() { |
|
427 // first check the pref. |
|
428 if (getBoolPref("bidi.browser.ui", false)) |
|
429 return true; |
|
430 |
|
431 // then check intl.uidirection.<locale> |
|
432 var chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"]. |
|
433 getService(Components.interfaces.nsIXULChromeRegistry); |
|
434 if (chromeReg.isLocaleRTL("global")) |
|
435 return true; |
|
436 |
|
437 // now see if the system locale is an RTL one. |
|
438 var rv = false; |
|
439 |
|
440 try { |
|
441 var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"] |
|
442 .getService(Components.interfaces.nsILocaleService); |
|
443 var systemLocale = localeService.getSystemLocale().getCategory("NSILOCALE_CTYPE").substr(0,3); |
|
444 |
|
445 switch (systemLocale) { |
|
446 case "ar-": |
|
447 case "he-": |
|
448 case "fa-": |
|
449 case "ug-": |
|
450 case "ur-": |
|
451 case "syr": |
|
452 rv = true; |
|
453 Services.prefs.setBoolPref("bidi.browser.ui", true); |
|
454 } |
|
455 } catch (e) {} |
|
456 |
|
457 return rv; |
|
458 } |
|
459 |
|
460 function openAboutDialog() { |
|
461 var enumerator = Services.wm.getEnumerator("Browser:About"); |
|
462 while (enumerator.hasMoreElements()) { |
|
463 // Only open one about window (Bug 599573) |
|
464 let win = enumerator.getNext(); |
|
465 if (win.closed) { |
|
466 continue; |
|
467 } |
|
468 win.focus(); |
|
469 return; |
|
470 } |
|
471 |
|
472 #ifdef XP_WIN |
|
473 var features = "chrome,centerscreen,dependent"; |
|
474 #elifdef XP_MACOSX |
|
475 var features = "chrome,resizable=no,minimizable=no"; |
|
476 #else |
|
477 var features = "chrome,centerscreen,dependent,dialog=no"; |
|
478 #endif |
|
479 window.openDialog("chrome://browser/content/aboutDialog.xul", "", features); |
|
480 } |
|
481 |
|
482 function openPreferences(paneID, extraArgs) |
|
483 { |
|
484 function switchToAdvancedSubPane(doc) { |
|
485 if (extraArgs && extraArgs["advancedTab"]) { |
|
486 let advancedPaneTabs = doc.getElementById("advancedPrefs"); |
|
487 advancedPaneTabs.selectedTab = doc.getElementById(extraArgs["advancedTab"]); |
|
488 } |
|
489 } |
|
490 |
|
491 if (getBoolPref("browser.preferences.inContent")) { |
|
492 let win = Services.wm.getMostRecentWindow("navigator:browser"); |
|
493 if (!win) { |
|
494 return; |
|
495 } |
|
496 |
|
497 let newLoad = !win.switchToTabHavingURI("about:preferences", true); |
|
498 let browser = win.gBrowser.selectedBrowser; |
|
499 |
|
500 function switchToPane() { |
|
501 if (paneID) { |
|
502 browser.contentWindow.selectCategory(paneID); |
|
503 } |
|
504 switchToAdvancedSubPane(browser.contentDocument); |
|
505 } |
|
506 |
|
507 if (newLoad) { |
|
508 browser.addEventListener("load", function onload() { |
|
509 browser.removeEventListener("load", onload, true); |
|
510 switchToPane(); |
|
511 }, true); |
|
512 } else { |
|
513 switchToPane(); |
|
514 } |
|
515 } else { |
|
516 var instantApply = getBoolPref("browser.preferences.instantApply", false); |
|
517 var features = "chrome,titlebar,toolbar,centerscreen" + (instantApply ? ",dialog=no" : ",modal"); |
|
518 |
|
519 var win = Services.wm.getMostRecentWindow("Browser:Preferences"); |
|
520 if (win) { |
|
521 win.focus(); |
|
522 if (paneID) { |
|
523 var pane = win.document.getElementById(paneID); |
|
524 win.document.documentElement.showPane(pane); |
|
525 } |
|
526 |
|
527 switchToAdvancedSubPane(win.document); |
|
528 } else { |
|
529 openDialog("chrome://browser/content/preferences/preferences.xul", |
|
530 "Preferences", features, paneID, extraArgs); |
|
531 } |
|
532 } |
|
533 } |
|
534 |
|
535 function openAdvancedPreferences(tabID) |
|
536 { |
|
537 openPreferences("paneAdvanced", { "advancedTab" : tabID }); |
|
538 } |
|
539 |
|
540 /** |
|
541 * Opens the troubleshooting information (about:support) page for this version |
|
542 * of the application. |
|
543 */ |
|
544 function openTroubleshootingPage() |
|
545 { |
|
546 openUILinkIn("about:support", "tab"); |
|
547 } |
|
548 |
|
549 #ifdef MOZ_SERVICES_HEALTHREPORT |
|
550 /** |
|
551 * Opens the troubleshooting information (about:support) page for this version |
|
552 * of the application. |
|
553 */ |
|
554 function openHealthReport() |
|
555 { |
|
556 openUILinkIn("about:healthreport", "tab"); |
|
557 } |
|
558 #endif |
|
559 |
|
560 /** |
|
561 * Opens the feedback page for this version of the application. |
|
562 */ |
|
563 function openFeedbackPage() |
|
564 { |
|
565 var url = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"] |
|
566 .getService(Components.interfaces.nsIURLFormatter) |
|
567 .formatURLPref("app.feedback.baseURL"); |
|
568 openUILinkIn(url, "tab"); |
|
569 } |
|
570 |
|
571 function openTourPage() |
|
572 { |
|
573 let scope = {} |
|
574 Components.utils.import("resource:///modules/UITour.jsm", scope); |
|
575 openUILinkIn(scope.UITour.url, "tab"); |
|
576 } |
|
577 |
|
578 function buildHelpMenu() |
|
579 { |
|
580 // Enable/disable the "Report Web Forgery" menu item. |
|
581 if (typeof gSafeBrowsing != "undefined") |
|
582 gSafeBrowsing.setReportPhishingMenu(); |
|
583 } |
|
584 |
|
585 function isElementVisible(aElement) |
|
586 { |
|
587 if (!aElement) |
|
588 return false; |
|
589 |
|
590 // If aElement or a direct or indirect parent is hidden or collapsed, |
|
591 // height, width or both will be 0. |
|
592 var bo = aElement.boxObject; |
|
593 return (bo.height > 0 && bo.width > 0); |
|
594 } |
|
595 |
|
596 function makeURLAbsolute(aBase, aUrl) |
|
597 { |
|
598 // Note: makeURI() will throw if aUri is not a valid URI |
|
599 return makeURI(aUrl, null, makeURI(aBase)).spec; |
|
600 } |
|
601 |
|
602 /** |
|
603 * openNewTabWith: opens a new tab with the given URL. |
|
604 * |
|
605 * @param aURL |
|
606 * The URL to open (as a string). |
|
607 * @param aDocument |
|
608 * Note this parameter is now ignored. There is no security check & no |
|
609 * referrer header derived from aDocument (null case). |
|
610 * @param aPostData |
|
611 * Form POST data, or null. |
|
612 * @param aEvent |
|
613 * The triggering event (for the purpose of determining whether to open |
|
614 * in the background), or null. |
|
615 * @param aAllowThirdPartyFixup |
|
616 * If true, then we allow the URL text to be sent to third party services |
|
617 * (e.g., Google's I Feel Lucky) for interpretation. This parameter may |
|
618 * be undefined in which case it is treated as false. |
|
619 * @param [optional] aReferrer |
|
620 * This will be used as the referrer. There will be no security check. |
|
621 */ |
|
622 function openNewTabWith(aURL, aDocument, aPostData, aEvent, |
|
623 aAllowThirdPartyFixup, aReferrer) { |
|
624 |
|
625 // As in openNewWindowWith(), we want to pass the charset of the |
|
626 // current document over to a new tab. |
|
627 let originCharset = null; |
|
628 if (document.documentElement.getAttribute("windowtype") == "navigator:browser") |
|
629 originCharset = gBrowser.selectedBrowser.characterSet; |
|
630 |
|
631 openLinkIn(aURL, aEvent && aEvent.shiftKey ? "tabshifted" : "tab", |
|
632 { charset: originCharset, |
|
633 postData: aPostData, |
|
634 allowThirdPartyFixup: aAllowThirdPartyFixup, |
|
635 referrerURI: aReferrer }); |
|
636 } |
|
637 |
|
638 /** |
|
639 * @param aDocument |
|
640 * Note this parameter is ignored. See openNewTabWith() |
|
641 */ |
|
642 function openNewWindowWith(aURL, aDocument, aPostData, aAllowThirdPartyFixup, aReferrer) { |
|
643 // Extract the current charset menu setting from the current document and |
|
644 // use it to initialize the new browser window... |
|
645 let originCharset = null; |
|
646 if (document.documentElement.getAttribute("windowtype") == "navigator:browser") |
|
647 originCharset = gBrowser.selectedBrowser.characterSet; |
|
648 |
|
649 openLinkIn(aURL, "window", |
|
650 { charset: originCharset, |
|
651 postData: aPostData, |
|
652 allowThirdPartyFixup: aAllowThirdPartyFixup, |
|
653 referrerURI: aReferrer }); |
|
654 } |
|
655 |
|
656 // aCalledFromModal is optional |
|
657 function openHelpLink(aHelpTopic, aCalledFromModal, aWhere) { |
|
658 var url = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"] |
|
659 .getService(Components.interfaces.nsIURLFormatter) |
|
660 .formatURLPref("app.support.baseURL"); |
|
661 url += aHelpTopic; |
|
662 |
|
663 var where = aWhere; |
|
664 if (!aWhere) |
|
665 where = aCalledFromModal ? "window" : "tab"; |
|
666 |
|
667 openUILinkIn(url, where); |
|
668 } |
|
669 |
|
670 function openPrefsHelp() { |
|
671 // non-instant apply prefwindows are usually modal, so we can't open in the topmost window, |
|
672 // since its probably behind the window. |
|
673 var instantApply = getBoolPref("browser.preferences.instantApply"); |
|
674 |
|
675 var helpTopic = document.getElementsByTagName("prefwindow")[0].currentPane.helpTopic; |
|
676 openHelpLink(helpTopic, !instantApply); |
|
677 } |
|
678 |
|
679 function trimURL(aURL) { |
|
680 // This function must not modify the given URL such that calling |
|
681 // nsIURIFixup::createFixupURI with the result will produce a different URI. |
|
682 return aURL /* remove single trailing slash for http/https/ftp URLs */ |
|
683 .replace(/^((?:http|https|ftp):\/\/[^/]+)\/$/, "$1") |
|
684 /* remove http:// unless the host starts with "ftp\d*\." or contains "@" */ |
|
685 .replace(/^http:\/\/((?!ftp\d*\.)[^\/@]+(?:\/|$))/, "$1"); |
|
686 } |