NetworkPrioritizer.jsm
Go to the documentation of this file.
1 /* ***** BEGIN LICENSE BLOCK *****
2  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3  *
4  * The contents of this file are subject to the Mozilla Public License Version
5  * 1.1 (the "License"); you may not use this file except in compliance with
6  * the License. You may obtain a copy of the License at
7  * http://www.mozilla.org/MPL/
8  *
9  * Software distributed under the License is distributed on an "AS IS" basis,
10  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11  * for the specific language governing rights and limitations under the
12  * License.
13  *
14  * The Original Code is mozilla.org code.
15  *
16  * The Initial Developer of the Original Code is Mozilla Corporation.
17  * Portions created by the Initial Developer are Copyright (C) 2009
18  * the Initial Developer. All Rights Reserved.
19  *
20  * Contributor(s):
21  * Paul O’Shannessy <paul@oshannessy.com> (original author)
22  *
23  * Alternatively, the contents of this file may be used under the terms of
24  * either the GNU General Public License Version 2 or later (the "GPL"), or
25  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26  * in which case the provisions of the GPL or the LGPL are applicable instead
27  * of those above. If you wish to allow use of your version of this file only
28  * under the terms of either the GPL or the LGPL, and not to allow others to
29  * use your version of this file under the terms of the MPL, indicate your
30  * decision by deleting the provisions above and replace them with the notice
31  * and other provisions required by the GPL or the LGPL. If you do not delete
32  * the provisions above, a recipient may use your version of this file under
33  * the terms of any one of the MPL, the GPL or the LGPL.
34  *
35  * ***** END LICENSE BLOCK ***** */
36 
37 /*
38  * This module adjusts network priority for tabs in a way that gives 'important'
39  * tabs a higher priority. There are 3 levels of priority. Each is listed below
40  * with the priority adjustment used.
41  *
42  * Highest (-10): Selected tab in the focused window.
43  * Medium (0): Background tabs in the focused window.
44  * Selected tab in background windows.
45  * Lowest (+10): Background tabs in background windows.
46  */
47 
48 let EXPORTED_SYMBOLS = ["trackBrowserWindow"];
49 
50 const Ci = Components.interfaces;
51 
52 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
53 
54 
55 // Lazy getters
56 XPCOMUtils.defineLazyServiceGetter(this, "_focusManager",
57  "@mozilla.org/focus-manager;1",
58  "nsIFocusManager");
59 
60 
61 // Constants
62 const TAB_EVENTS = ["TabOpen", "TabSelect"];
63 const WINDOW_EVENTS = ["activate", "unload"];
64 // PRIORITY DELTA is -10 because lower priority value is actually a higher priority
65 const PRIORITY_DELTA = -10;
66 
67 
68 // Variables
70 let _windows = [];
71 
72 
73 // Exported symbol
74 function trackBrowserWindow(aWindow) {
75  WindowHelper.addWindow(aWindow);
76 }
77 
78 
79 // Global methods
80 function _handleEvent(aEvent) {
81  switch (aEvent.type) {
82  case "TabOpen":
83  BrowserHelper.onOpen(aEvent.target.linkedBrowser);
84  break;
85  case "TabSelect":
86  BrowserHelper.onSelect(aEvent.target.linkedBrowser);
87  break;
88  case "activate":
89  WindowHelper.onActivate(aEvent.target);
90  break;
91  case "unload":
92  WindowHelper.removeWindow(aEvent.currentTarget);
93  break;
94  }
95 }
96 
97 
98 // Methods that impact a browser. Put into single object for organization.
100  onOpen: function(aBrowser) {
101  // If the tab is in the focused window, leave priority as it is
102  if (aBrowser.ownerDocument.defaultView != _lastFocusedWindow)
103  this.decreasePriority(aBrowser);
104  },
105 
106  onSelect: function(aBrowser) {
107  let windowEntry = WindowHelper.getEntry(aBrowser.ownerDocument.defaultView);
108  if (windowEntry.lastSelectedBrowser)
109  this.decreasePriority(windowEntry.lastSelectedBrowser);
110  this.increasePriority(aBrowser);
111 
112  windowEntry.lastSelectedBrowser = aBrowser;
113  },
114 
115  // Auxiliary methods
116  getLoadgroup: function(aBrowser) {
117  return aBrowser.webNavigation.QueryInterface(Ci.nsIDocumentLoader)
118  .loadGroup.QueryInterface(Ci.nsISupportsPriority);
119  },
120 
121  increasePriority: function(aBrowser) {
122  this.getLoadgroup(aBrowser).adjustPriority(PRIORITY_DELTA);
123  },
124 
125  decreasePriority: function(aBrowser) {
126  this.getLoadgroup(aBrowser).adjustPriority(PRIORITY_DELTA * -1);
127  }
128 };
129 
130 
131 // Methods that impact a window. Put into single object for organization.
133  addWindow: function(aWindow) {
134  // Build internal data object
135  _windows.push({ window: aWindow, lastSelectedBrowser: null });
136 
137  // Add event listeners
138  TAB_EVENTS.forEach(function(event) {
139  aWindow.gBrowser.tabContainer.addEventListener(event, _handleEvent, false);
140  });
141  WINDOW_EVENTS.forEach(function(event) {
142  aWindow.addEventListener(event, _handleEvent, false);
143  });
144 
145  // This gets called AFTER activate event, so if this is the focused window
146  // we want to activate it. Otherwise, deprioritize it.
147  if (aWindow == _focusManager.activeWindow)
148  this.handleFocusedWindow(aWindow);
149  else
150  this.decreasePriority(aWindow);
151 
152  // Select the selected tab
153  BrowserHelper.onSelect(aWindow.gBrowser.selectedBrowser);
154  },
155 
156  removeWindow: function(aWindow) {
157  if (aWindow == _lastFocusedWindow)
158  _lastFocusedWindow = null;
159 
160  // Delete this window from our tracking
161  _windows.splice(this.getEntryIndex(aWindow), 1);
162 
163  // Remove the event listeners
164  TAB_EVENTS.forEach(function(event) {
165  aWindow.gBrowser.tabContainer.removeEventListener(event, _handleEvent, false);
166  });
167  WINDOW_EVENTS.forEach(function(event) {
168  aWindow.removeEventListener(event, _handleEvent, false);
169  });
170  },
171 
172  onActivate: function(aWindow, aHasFocus) {
173  // If this window was the last focused window, we don't need to do anything
174  if (aWindow == _lastFocusedWindow)
175  return;
176 
177  // handleFocusedWindow will deprioritize the current window
178  this.handleFocusedWindow(aWindow);
179 
180  // Lastly we should increase priority for this window
181  this.increasePriority(aWindow);
182  },
183 
184  handleFocusedWindow: function(aWindow) {
185  // If we have a last focused window, we need to deprioritize it first
186  if (_lastFocusedWindow)
187  this.decreasePriority(_lastFocusedWindow);
188 
189  // aWindow is now focused
190  _lastFocusedWindow = aWindow;
191  },
192 
193  // Auxiliary methods
194  increasePriority: function(aWindow) {
195  aWindow.gBrowser.browsers.forEach(function(aBrowser) {
196  BrowserHelper.increasePriority(aBrowser);
197  });
198  },
199 
200  decreasePriority: function(aWindow) {
201  aWindow.gBrowser.browsers.forEach(function(aBrowser) {
202  BrowserHelper.decreasePriority(aBrowser);
203  });
204  },
205 
206  getEntry: function(aWindow) {
207  return _windows[this.getEntryIndex(aWindow)];
208  },
209 
210  getEntryIndex: function(aWindow) {
211  // Assumes that every object has a unique window & it's in the array
212  for (let i = 0; i < _windows.length; i++)
213  if (_windows[i].window == aWindow)
214  return i;
215  }
216 };
217 
function _handleEvent(aEvent)
let EXPORTED_SYMBOLS
const PRIORITY_DELTA
var event
let _lastFocusedWindow
let window
const Ci
function trackBrowserWindow(aWindow)
let _windows
let WindowHelper
return null
Definition: FeedWriter.js:1143
_updateTextAndScrollDataForTab aBrowser
_dialogDatepicker onSelect
let BrowserHelper
_getSelectedPageStyle s i
const TAB_EVENTS
const WINDOW_EVENTS