addon-sdk/source/lib/sdk/tabs/utils.js

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 'use strict';
     6 module.metadata = {
     7   'stability': 'unstable'
     8 };
    11 // NOTE: This file should only deal with xul/native tabs
    14 const { Ci } = require('chrome');
    15 const { defer } = require("../lang/functional");
    16 const { windows, isBrowser } = require('../window/utils');
    17 const { isPrivateBrowsingSupported } = require('../self');
    18 const { isGlobalPBSupported } = require('../private-browsing/utils');
    20 // Bug 834961: ignore private windows when they are not supported
    21 function getWindows() windows(null, { includePrivate: isPrivateBrowsingSupported || isGlobalPBSupported });
    23 const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
    25 // Define predicate functions that can be used to detech weather
    26 // we deal with fennec tabs or firefox tabs.
    28 // Predicate to detect whether tab is XUL "Tab" node.
    29 const isXULTab = tab =>
    30   tab instanceof Ci.nsIDOMNode &&
    31   tab.nodeName === "tab" &&
    32   tab.namespaceURI === XUL_NS;
    33 exports.isXULTab = isXULTab;
    35 // Predicate to detecet whether given tab is a fettec tab.
    36 // Unfortunately we have to guess via duck typinng of:
    37 // http://mxr.mozilla.org/mozilla-central/source/mobile/android/chrome/content/browser.js#2583
    38 const isFennecTab = tab =>
    39   tab &&
    40   tab.QueryInterface &&
    41   Ci.nsIBrowserTab &&
    42   tab.QueryInterface(Ci.nsIBrowserTab) === tab;
    43 exports.isFennecTab = isFennecTab;
    45 const isTab = x => isXULTab(x) || isFennecTab(x);
    46 exports.isTab = isTab;
    48 function activateTab(tab, window) {
    49   let gBrowser = getTabBrowserForTab(tab);
    51   // normal case
    52   if (gBrowser) {
    53     gBrowser.selectedTab = tab;
    54   }
    55   // fennec ?
    56   else if (window && window.BrowserApp) {
    57     window.BrowserApp.selectTab(tab);
    58   }
    59   return null;
    60 }
    61 exports.activateTab = activateTab;
    63 function getTabBrowser(window) {
    64   return window.gBrowser;
    65 }
    66 exports.getTabBrowser = getTabBrowser;
    68 function getTabContainer(window) {
    69   return getTabBrowser(window).tabContainer;
    70 }
    71 exports.getTabContainer = getTabContainer;
    73 /**
    74  * Returns the tabs for the `window` if given, or the tabs
    75  * across all the browser's windows otherwise.
    76  *
    77  * @param {nsIWindow} [window]
    78  *    A reference to a window
    79  *
    80  * @returns {Array} an array of Tab objects
    81  */
    82 function getTabs(window) {
    83   if (arguments.length === 0) {
    84     return getWindows().filter(isBrowser).reduce(function(tabs, window) {
    85       return tabs.concat(getTabs(window))
    86     }, []);
    87   }
    89   // fennec
    90   if (window.BrowserApp)
    91     return window.BrowserApp.tabs;
    93   // firefox - default
    94   return Array.slice(getTabContainer(window).children);
    95 }
    96 exports.getTabs = getTabs;
    98 function getActiveTab(window) {
    99   return getSelectedTab(window);
   100 }
   101 exports.getActiveTab = getActiveTab;
   103 function getOwnerWindow(tab) {
   104   // normal case
   105   if (tab.ownerDocument)
   106     return tab.ownerDocument.defaultView;
   108   // try fennec case
   109   return getWindowHoldingTab(tab);
   110 }
   111 exports.getOwnerWindow = getOwnerWindow;
   113 // fennec
   114 function getWindowHoldingTab(rawTab) {
   115   for each (let window in getWindows()) {
   116     // this function may be called when not using fennec,
   117     // but BrowserApp is only defined on Fennec
   118     if (!window.BrowserApp)
   119       continue;
   121     for each (let tab in window.BrowserApp.tabs) {
   122       if (tab === rawTab)
   123         return window;
   124     }
   125   }
   127   return null;
   128 }
   130 function openTab(window, url, options) {
   131   options = options || {};
   133   // fennec?
   134   if (window.BrowserApp) {
   135     return window.BrowserApp.addTab(url, {
   136       selected: options.inBackground ? false : true,
   137       pinned: options.isPinned || false,
   138       isPrivate: options.isPrivate || false
   139     });
   140   }
   142   // firefox
   143   let newTab = window.gBrowser.addTab(url);
   144   if (!options.inBackground) {
   145     activateTab(newTab);
   146   }
   147   return newTab;
   148 };
   149 exports.openTab = openTab;
   151 function isTabOpen(tab) {
   152   // try normal case then fennec case
   153   return !!((tab.linkedBrowser) || getWindowHoldingTab(tab));
   154 }
   155 exports.isTabOpen = isTabOpen;
   157 function closeTab(tab) {
   158   let gBrowser = getTabBrowserForTab(tab);
   159   // normal case?
   160   if (gBrowser) {
   161     // Bug 699450: the tab may already have been detached
   162     if (!tab.parentNode)
   163       return;
   164     return gBrowser.removeTab(tab);
   165   }
   167   let window = getWindowHoldingTab(tab);
   168   // fennec?
   169   if (window && window.BrowserApp) {
   170     // Bug 699450: the tab may already have been detached
   171     if (!tab.browser)
   172       return;
   173     return window.BrowserApp.closeTab(tab);
   174   }
   175   return null;
   176 }
   177 exports.closeTab = closeTab;
   179 function getURI(tab) {
   180   if (tab.browser) // fennec
   181     return tab.browser.currentURI.spec;
   182   return tab.linkedBrowser.currentURI.spec;
   183 }
   184 exports.getURI = getURI;
   186 function getTabBrowserForTab(tab) {
   187   let outerWin = getOwnerWindow(tab);
   188   if (outerWin)
   189     return getOwnerWindow(tab).gBrowser;
   190   return null;
   191 }
   192 exports.getTabBrowserForTab = getTabBrowserForTab;
   194 function getBrowserForTab(tab) {
   195   if (tab.browser) // fennec
   196     return tab.browser;
   198   return tab.linkedBrowser;
   199 }
   200 exports.getBrowserForTab = getBrowserForTab;
   202 function getTabId(tab) {
   203   if (tab.browser) // fennec
   204     return tab.id
   206   return String.split(tab.linkedPanel, 'panel').pop();
   207 }
   208 exports.getTabId = getTabId;
   210 function getTabForId(id) {
   211   return getTabs().find(tab => getTabId(tab) === id) || null;
   212 }
   213 exports.getTabForId = getTabForId;
   215 function getTabTitle(tab) {
   216   return getBrowserForTab(tab).contentDocument.title || tab.label || "";
   217 }
   218 exports.getTabTitle = getTabTitle;
   220 function setTabTitle(tab, title) {
   221   title = String(title);
   222   if (tab.browser)
   223     tab.browser.contentDocument.title = title;
   224   tab.label = String(title);
   225 }
   226 exports.setTabTitle = setTabTitle;
   228 function getTabContentWindow(tab) {
   229   return getBrowserForTab(tab).contentWindow;
   230 }
   231 exports.getTabContentWindow = getTabContentWindow;
   233 /**
   234  * Returns all tabs' content windows across all the browsers' windows
   235  */
   236 function getAllTabContentWindows() {
   237   return getTabs().map(getTabContentWindow);
   238 }
   239 exports.getAllTabContentWindows = getAllTabContentWindows;
   241 // gets the tab containing the provided window
   242 function getTabForContentWindow(window) {
   243   // Retrieve the topmost frame container. It can be either <xul:browser>,
   244   // <xul:iframe/> or <html:iframe/>. But in our case, it should be xul:browser.
   245   let browser;
   246   try {
   247     browser = window.QueryInterface(Ci.nsIInterfaceRequestor)
   248                     .getInterface(Ci.nsIWebNavigation)
   249                     .QueryInterface(Ci.nsIDocShell)
   250                     .chromeEventHandler;
   251   } catch(e) {
   252     // Bug 699450: The tab may already have been detached so that `window` is
   253     // in a almost destroyed state and can't be queryinterfaced anymore.
   254   }
   256   // Is null for toplevel documents
   257   if (!browser) {
   258     return null;
   259   }
   261   // Retrieve the owner window, should be browser.xul one
   262   let chromeWindow = browser.ownerDocument.defaultView;
   264   // Ensure that it is top-level browser window.
   265   // We need extra checks because of Mac hidden window that has a broken
   266   // `gBrowser` global attribute.
   267   if ('gBrowser' in chromeWindow && chromeWindow.gBrowser &&
   268       'browsers' in chromeWindow.gBrowser) {
   269     // Looks like we are on Firefox Desktop
   270     // Then search for the position in tabbrowser in order to get the tab object
   271     let browsers = chromeWindow.gBrowser.browsers;
   272     let i = browsers.indexOf(browser);
   273     if (i !== -1)
   274       return chromeWindow.gBrowser.tabs[i];
   275     return null;
   276   }
   277   // Fennec
   278   else if ('BrowserApp' in chromeWindow) {
   279     return getTabForWindow(window);
   280   }
   282   return null;
   283 }
   284 exports.getTabForContentWindow = getTabForContentWindow;
   286 // used on fennec
   287 function getTabForWindow(window) {
   288   for each (let { BrowserApp } in getWindows()) {
   289     if (!BrowserApp)
   290       continue;
   292     for each (let tab in BrowserApp.tabs) {
   293       if (tab.browser.contentWindow == window.top)
   294         return tab;
   295     }
   296   }
   297   return null;
   298 }
   300 function getTabURL(tab) {
   301   if (tab.browser) // fennec
   302     return String(tab.browser.currentURI.spec);
   303   return String(getBrowserForTab(tab).currentURI.spec);
   304 }
   305 exports.getTabURL = getTabURL;
   307 function setTabURL(tab, url) {
   308   url = String(url);
   309   if (tab.browser)
   310     return tab.browser.loadURI(url);
   311   return getBrowserForTab(tab).loadURI(url);
   312 }
   313 // "TabOpen" event is fired when it's still "about:blank" is loaded in the
   314 // changing `location` property of the `contentDocument` has no effect since
   315 // seems to be either ignored or overridden by internal listener, there for
   316 // location change is enqueued for the next turn of event loop.
   317 exports.setTabURL = defer(setTabURL);
   319 function getTabContentType(tab) {
   320   return getBrowserForTab(tab).contentDocument.contentType;
   321 }
   322 exports.getTabContentType = getTabContentType;
   324 function getSelectedTab(window) {
   325   if (window.BrowserApp) // fennec?
   326     return window.BrowserApp.selectedTab;
   327   if (window.gBrowser)
   328     return window.gBrowser.selectedTab;
   329   return null;
   330 }
   331 exports.getSelectedTab = getSelectedTab;
   334 function getTabForBrowser(browser) {
   335   for each (let window in getWindows()) {
   336     // this function may be called when not using fennec
   337     if (!window.BrowserApp)
   338       continue;
   340     for each (let tab in window.BrowserApp.tabs) {
   341       if (tab.browser === browser)
   342         return tab;
   343     }
   344   }
   345   return null;
   346 }
   347 exports.getTabForBrowser = getTabForBrowser;
   349 function pin(tab) {
   350   let gBrowser = getTabBrowserForTab(tab);
   351   // TODO: Implement Fennec support
   352   if (gBrowser) gBrowser.pinTab(tab);
   353 }
   354 exports.pin = pin;
   356 function unpin(tab) {
   357   let gBrowser = getTabBrowserForTab(tab);
   358   // TODO: Implement Fennec support
   359   if (gBrowser) gBrowser.unpinTab(tab);
   360 }
   361 exports.unpin = unpin;
   363 function isPinned(tab) !!tab.pinned
   364 exports.isPinned = isPinned;
   366 function reload(tab) {
   367   let gBrowser = getTabBrowserForTab(tab);
   368   // Firefox
   369   if (gBrowser) gBrowser.unpinTab(tab);
   370   // Fennec
   371   else if (tab.browser) tab.browser.reload();
   372 }
   373 exports.reload = reload
   375 function getIndex(tab) {
   376   let gBrowser = getTabBrowserForTab(tab);
   377   // Firefox
   378   if (gBrowser) {
   379     let document = getBrowserForTab(tab).contentDocument;
   380     return gBrowser.getBrowserIndexForDocument(document);
   381   }
   382   // Fennec
   383   else {
   384     let window = getWindowHoldingTab(tab)
   385     let tabs = window.BrowserApp.tabs;
   386     for (let i = tabs.length; i >= 0; i--)
   387       if (tabs[i] === tab) return i;
   388   }
   389 }
   390 exports.getIndex = getIndex;
   392 function move(tab, index) {
   393   let gBrowser = getTabBrowserForTab(tab);
   394   // Firefox
   395   if (gBrowser) gBrowser.moveTabTo(tab, index);
   396   // TODO: Implement fennec support
   397 }
   398 exports.move = move;

mercurial