Wed, 31 Dec 2014 06:55:50 +0100
Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2
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/. */
5 // Progress heartbeat timer duration (ms)
6 const kHeartbeatDuration = 1000;
7 // Start and end progress screen css margins as percentages
8 const kProgressMarginStart = 30;
9 const kProgressMarginEnd = 70;
11 const WebProgress = {
12 get _identityBox() { return document.getElementById("identity-box"); },
14 init: function init() {
15 messageManager.addMessageListener("Content:StateChange", this);
16 messageManager.addMessageListener("Content:LocationChange", this);
17 messageManager.addMessageListener("Content:SecurityChange", this);
19 Elements.progress.addEventListener("transitionend", this, true);
20 Elements.tabList.addEventListener("TabSelect", this, true);
22 let urlBar = document.getElementById("urlbar-edit");
23 urlBar.addEventListener("input", this, false);
25 return this;
26 },
28 receiveMessage: function receiveMessage(aMessage) {
29 let json = aMessage.json;
30 let tab = Browser.getTabForBrowser(aMessage.target);
32 switch (aMessage.name) {
33 case "Content:StateChange": {
34 if (json.stateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
35 if (json.stateFlags & Ci.nsIWebProgressListener.STATE_START)
36 this._windowStart(json, tab);
37 else if (json.stateFlags & Ci.nsIWebProgressListener.STATE_STOP)
38 this._windowStop(json, tab);
39 }
41 if (json.stateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK) {
42 if (json.stateFlags & Ci.nsIWebProgressListener.STATE_START)
43 this._networkStart(json, tab);
44 else if (json.stateFlags & Ci.nsIWebProgressListener.STATE_STOP)
45 this._networkStop(json, tab);
46 }
48 this._progressStep(tab);
49 break;
50 }
52 case "Content:LocationChange": {
53 this._locationChange(json, tab);
54 this._progressStep(tab);
55 break;
56 }
58 case "Content:SecurityChange": {
59 this._securityChange(json, tab);
60 this._progressStep(tab);
61 break;
62 }
63 }
64 },
66 handleEvent: function handleEvent(aEvent) {
67 switch (aEvent.type) {
68 case "transitionend":
69 this._progressTransEnd(aEvent);
70 break;
71 case "TabSelect":
72 this._onTabSelect(aEvent);
73 break;
74 case "input":
75 this._onUrlBarInput(aEvent);
76 break;
77 }
78 },
80 _securityChange: function _securityChange(aJson, aTab) {
81 let state = aJson.state;
82 let nsIWebProgressListener = Ci.nsIWebProgressListener;
84 if (state & nsIWebProgressListener.STATE_IDENTITY_EV_TOPLEVEL) {
85 aTab._identityState = "verifiedIdentity";
86 } else if (state & nsIWebProgressListener.STATE_IS_SECURE) {
87 aTab._identityState = "verifiedDomain";
88 } else {
89 aTab._identityState = "";
90 }
92 if (aTab == Browser.selectedTab) {
93 this._identityBox.className = aTab._identityState;
94 }
95 },
97 _locationChange: function _locationChange(aJson, aTab) {
98 let spec = aJson.location;
99 let location = spec.split("#")[0]; // Ignore fragment identifier changes.
101 if (aTab == Browser.selectedTab) {
102 BrowserUI.updateURI();
103 BrowserUI.update();
104 BrowserUI.updateStartURIAttributes(aJson.location);
105 }
107 let locationHasChanged = (location != aTab.browser.lastLocation);
108 if (locationHasChanged) {
109 Browser.getNotificationBox(aTab.browser).removeTransientNotifications();
110 aTab.browser.lastLocation = location;
111 aTab.browser.userTypedValue = "";
112 aTab.browser.appIcon = { href: null, size:-1 };
114 #ifdef MOZ_CRASHREPORTER
115 if (CrashReporter.enabled)
116 CrashReporter.annotateCrashReport("URL", spec);
117 #endif
118 }
120 let event = document.createEvent("UIEvents");
121 event.initUIEvent("URLChanged", true, false, window, locationHasChanged);
122 aTab.browser.dispatchEvent(event);
123 },
125 _networkStart: function _networkStart(aJson, aTab) {
126 aTab.startLoading();
128 if (aTab == Browser.selectedTab) {
129 // NO_STARTUI_VISIBILITY since the current uri for the tab has not
130 // been updated yet. If we're coming off of the start page, this
131 // would briefly show StartUI until _locationChange is called.
132 BrowserUI.update(BrowserUI.NO_STARTUI_VISIBILITY);
133 }
134 },
136 _networkStop: function _networkStop(aJson, aTab) {
137 aTab.endLoading();
139 if (aTab == Browser.selectedTab) {
140 BrowserUI.update();
141 }
142 },
144 _windowStart: function _windowStart(aJson, aTab) {
145 this._progressStart(aJson, aTab);
146 },
148 _windowStop: function _windowStop(aJson, aTab) {
149 this._progressStop(aJson, aTab);
150 },
152 _progressStart: function _progressStart(aJson, aTab) {
153 // We will get multiple calls from _windowStart, so
154 // only process once.
155 if (aTab._progressActive)
156 return;
158 aTab._progressActive = true;
160 // 'Whoosh' in
161 aTab._progressCount = kProgressMarginStart;
162 this._showProgressBar(aTab);
163 },
165 _showProgressBar: function (aTab) {
166 // display the track
167 if (aTab == Browser.selectedTab) {
168 Elements.progressContainer.removeAttribute("collapsed");
169 Elements.progress.style.width = aTab._progressCount + "%";
170 Elements.progress.removeAttribute("fade");
171 }
173 // Create a pulse timer to keep things moving even if we don't
174 // collect any state changes.
175 setTimeout(function() {
176 WebProgress._progressStepTimer(aTab);
177 }, kHeartbeatDuration, this);
178 },
180 _stepProgressCount: function _stepProgressCount(aTab) {
181 // Step toward the end margin in smaller slices as we get closer
182 let left = kProgressMarginEnd - aTab._progressCount;
183 let step = left * .05;
184 aTab._progressCount += Math.ceil(step);
186 // Don't go past the 'whoosh out' margin.
187 if (aTab._progressCount > kProgressMarginEnd) {
188 aTab._progressCount = kProgressMarginEnd;
189 }
190 },
192 _progressStep: function _progressStep(aTab) {
193 if (!aTab._progressActive)
194 return;
195 this._stepProgressCount(aTab);
196 if (aTab == Browser.selectedTab) {
197 Elements.progress.style.width = aTab._progressCount + "%";
198 }
199 },
201 _progressStepTimer: function _progressStepTimer(aTab) {
202 if (!aTab._progressActive)
203 return;
204 this._progressStep(aTab);
206 setTimeout(function() {
207 WebProgress._progressStepTimer(aTab);
208 }, kHeartbeatDuration, this);
209 },
211 _progressStop: function _progressStop(aJson, aTab) {
212 aTab._progressActive = false;
213 // 'Whoosh out' and fade
214 if (aTab == Browser.selectedTab) {
215 Elements.progress.style.width = "100%";
216 Elements.progress.setAttribute("fade", true);
217 }
218 },
220 _progressTransEnd: function _progressTransEnd(aEvent) {
221 if (!Elements.progress.hasAttribute("fade"))
222 return;
223 // Close out fade finished, reset
224 if (aEvent.propertyName == "opacity") {
225 Elements.progress.style.width = "0px";
226 Elements.progressContainer.setAttribute("collapsed", true);
227 }
228 },
230 _onTabSelect: function(aEvent) {
231 let tab = Browser.getTabFromChrome(aEvent.originalTarget);
232 this._identityBox.className = tab._identityState || "";
233 if (tab._progressActive) {
234 this._showProgressBar(tab);
235 } else {
236 Elements.progress.setAttribute("fade", true);
237 Elements.progressContainer.setAttribute("collapsed", true);
238 }
239 },
241 _onUrlBarInput: function(aEvent) {
242 Browser.selectedTab._identityState = this._identityBox.className = "";
243 },
244 };