diff --git a/application/palemoon/modules/WindowsJumpLists.jsm b/application/palemoon/modules/WindowsJumpLists.jsm index 39f5c33f0a..6badc39076 100644 --- a/application/palemoon/modules/WindowsJumpLists.jsm +++ b/application/palemoon/modules/WindowsJumpLists.jsm @@ -149,18 +149,18 @@ this.WinTaskbarJumpList = */ startup: function() { - // exit if this isn't win7 or higher. - if (!this._initTaskbar()) + // Exit if there's something wrong with getting the taskbar service. + if (!this._initTaskbar()) { return; + } // Win shell shortcut maintenance. If we've gone through an update, // this will update any pinned taskbar shortcuts. Not specific to // jump lists, but this was a convienent place to call it. try { - // dev builds may not have helper.exe, ignore failures. + // builds may not have helper.exe, ignore failures. this._shortcutMaintenance(); - } catch (ex) { - } + } catch(ex) {} // Store our task list config data this._tasks = tasksCfg; @@ -177,8 +177,9 @@ this.WinTaskbarJumpList = update: function() { // are we disabled via prefs? don't do anything! - if (!this._enabled) + if (!this._enabled) { return; + } // do what we came here to do, update the taskbar jumplist this._buildList(); @@ -235,18 +236,22 @@ this.WinTaskbarJumpList = return; } - if (!this._startBuild()) + if (!this._startBuild()) { return; + } - if (this._showTasks) + if (this._showTasks) { this._buildTasks(); + } // Space for frequent items takes priority over recent. - if (this._showFrequent) + if (this._showFrequent) { this._buildFrequent(); + } - if (this._showRecent) + if (this._showRecent) { this._buildRecent(); + } this._commitBuild(); }, @@ -256,8 +261,8 @@ this.WinTaskbarJumpList = */ _startBuild: function() { - var removedItems = Cc["@mozilla.org/array;1"]. - createInstance(Ci.nsIMutableArray); + var removedItems = Cc["@mozilla.org/array;1"] + .createInstance(Ci.nsIMutableArray); this._builder.abortListBuild(); if (this._builder.initListBuild(removedItems)) { // Prior to building, delete removed items from history. @@ -277,20 +282,24 @@ this.WinTaskbarJumpList = var items = Cc["@mozilla.org/array;1"]. createInstance(Ci.nsIMutableArray); this._tasks.forEach(function(task) { - if ((this._shuttingDown && !task.close) || (!this._shuttingDown && !task.open)) + if ((this._shuttingDown && !task.close) || + (!this._shuttingDown && !task.open)) { return; + } var item = this._getHandlerAppItem(task.title, task.description, task.args, task.iconIndex, null); items.appendElement(item, false); }, this); - if (items.length > 0) + if (items.length > 0) { this._builder.addListToBuild(this._builder.JUMPLIST_CATEGORY_TASKS, items); + } }, _buildCustom: function(title, items) { - if (items.length > 0) + if (items.length > 0) { this._builder.addListToBuild(this._builder.JUMPLIST_CATEGORY_CUSTOMLIST, items, title); + } }, _buildFrequent: function() { @@ -329,8 +338,7 @@ this.WinTaskbarJumpList = items.appendElement(shortcut, false); this._frequentHashList.push(aResult.uri); }, - this - ); + this); }, _buildRecent: function() { @@ -374,8 +382,7 @@ this.WinTaskbarJumpList = items.appendElement(shortcut, false); count++; }, - this - ); + this); }, _deleteActiveJumpList: function() { @@ -386,22 +393,25 @@ this.WinTaskbarJumpList = * Jump list item creation helpers */ - _getHandlerAppItem: function(name, description, - args, iconIndex, - faviconPageUri) { + _getHandlerAppItem: function(name, + description, + args, + iconIndex, + faviconPageUri) { var file = Services.dirsvc.get("XREExeF", Ci.nsILocalFile); var handlerApp = Cc["@mozilla.org/uriloader/local-handler-app;1"]. createInstance(Ci.nsILocalHandlerApp); handlerApp.executable = file; // handlers default to the leaf name if a name is not specified - if (name && name.length != 0) + if (name && name.length != 0) { handlerApp.name = name; + } handlerApp.detailedDescription = description; handlerApp.appendParameter(args); - var item = Cc["@mozilla.org/windows-jumplistshortcut;1"]. - createInstance(Ci.nsIJumpListShortcut); + var item = Cc["@mozilla.org/windows-jumplistshortcut;1"] + .createInstance(Ci.nsIJumpListShortcut); item.app = handlerApp; item.iconIndex = iconIndex; item.faviconPageUri = faviconPageUri; @@ -409,8 +419,8 @@ this.WinTaskbarJumpList = }, _getSeparatorItem: function() { - var item = Cc["@mozilla.org/windows-jumplistseparator;1"]. - createInstance(Ci.nsIJumpListSeparator); + var item = Cc["@mozilla.org/windows-jumplistseparator;1"] + .createInstance(Ci.nsIJumpListSeparator); return item; }, @@ -449,8 +459,9 @@ this.WinTaskbarJumpList = }, _clearHistory: function(items) { - if (!items) + if (!items) { return; + } var URIsToRemove = []; var e = items.enumerate(); while (e.hasMoreElements()) { @@ -459,7 +470,7 @@ this.WinTaskbarJumpList = try { // in case we get a bad uri let uriSpec = oldItem.app.getParameter(0); URIsToRemove.push(NetUtil.newURI(uriSpec)); - } catch (err) { } + } catch(err) {} } } if (URIsToRemove.length > 0) { @@ -512,8 +523,7 @@ this.WinTaskbarJumpList = this._timer.initWithCallback(this, _prefs.getIntPref(PREF_TASKBAR_REFRESH)*1000, this._timer.TYPE_REPEATING_SLACK); - } - else if ((!this._enabled || this._shuttingDown) && this._timer) { + } else if ((!this._enabled || this._shuttingDown) && this._timer) { this._timer.cancel(); delete this._timer; } @@ -524,8 +534,7 @@ this.WinTaskbarJumpList = if (this._enabled && !this._shuttingDown && !this._hasIdleObserver) { _idle.addIdleObserver(this, IDLE_TIMEOUT_SECONDS); this._hasIdleObserver = true; - } - else if ((!this._enabled || this._shuttingDown) && this._hasIdleObserver) { + } else if ((!this._enabled || this._shuttingDown) && this._hasIdleObserver) { _idle.removeIdleObserver(this, IDLE_TIMEOUT_SECONDS); this._hasIdleObserver = false; } @@ -551,31 +560,32 @@ this.WinTaskbarJumpList = observe: function(aSubject, aTopic, aData) { switch (aTopic) { case "nsPref:changed": - if (this._enabled == true && !_prefs.getBoolPref(PREF_TASKBAR_ENABLED)) + if (this._enabled == true && !_prefs.getBoolPref(PREF_TASKBAR_ENABLED)) { this._deleteActiveJumpList(); + } this._refreshPrefs(); this._updateTimer(); this._updateIdleObserver(); this.update(); - break; + break; case "profile-before-change": this._shutdown(); - break; + break; case "browser:purge-session-history": this.update(); - break; + break; case "idle": if (this._timer) { this._timer.cancel(); delete this._timer; } - break; + break; case "back": this._updateTimer(); - break; + break; } }, }; diff --git a/application/palemoon/modules/WindowsPreviewPerTab.jsm b/application/palemoon/modules/WindowsPreviewPerTab.jsm index 4b5030ad40..7ceb642380 100644 --- a/application/palemoon/modules/WindowsPreviewPerTab.jsm +++ b/application/palemoon/modules/WindowsPreviewPerTab.jsm @@ -82,13 +82,14 @@ function _imageFromURI(uri, privateMode, callback) { // Ignore channels which do not support nsIPrivateBrowsingChannel } NetUtil.asyncFetch(channel, function(inputStream, resultCode) { - if (!Components.isSuccessCode(resultCode)) + if (!Components.isSuccessCode(resultCode)) { return; + } try { let out_img = { value: null }; imgTools.decodeImageData(inputStream, channel.contentType, out_img); callback(out_img.value); - } catch (e) { + } catch(e) { // We failed, so use the default favicon (only if this wasn't the default // favicon). let defaultURI = PlacesUtils.favicons.defaultFavicon; @@ -211,7 +212,7 @@ PreviewController.prototype = { testCacheBrowserDims: function () { let dims = this.browserDims; return this._cachedWidth == dims.width && - this._cachedHeight == dims.height; + this._cachedHeight == dims.height; }, /** @@ -343,10 +344,10 @@ PreviewController.prototype = { XPCOMUtils.defineLazyGetter(PreviewController.prototype, "canvasPreviewFlags", function () { let canvasInterface = Ci.nsIDOMCanvasRenderingContext2D; - return canvasInterface.DRAWWINDOW_DRAW_VIEW - | canvasInterface.DRAWWINDOW_DRAW_CARET - | canvasInterface.DRAWWINDOW_ASYNC_DECODE_IMAGES - | canvasInterface.DRAWWINDOW_DO_NOT_FLUSH; + return canvasInterface.DRAWWINDOW_DRAW_VIEW | + canvasInterface.DRAWWINDOW_DRAW_CARET | + canvasInterface.DRAWWINDOW_ASYNC_DECODE_IMAGES | + canvasInterface.DRAWWINDOW_DO_NOT_FLUSH; }); // TabWindow @@ -363,18 +364,21 @@ function TabWindow(win) { this.previews = new Map(); - for (let i = 0; i < this.tabEvents.length; i++) + for (let i = 0; i < this.tabEvents.length; i++) { this.tabbrowser.tabContainer.addEventListener(this.tabEvents[i], this, false); + } - for (let i = 0; i < this.winEvents.length; i++) + for (let i = 0; i < this.winEvents.length; i++) { this.win.addEventListener(this.winEvents[i], this, false); + } this.tabbrowser.addTabsProgressListener(this); AeroPeek.windows.push(this); let tabs = this.tabbrowser.tabs; - for (let i = 0; i < tabs.length; i++) + for (let i = 0; i < tabs.length; i++) { this.newTab(tabs[i]); + } this.updateTabOrdering(); AeroPeek.checkPreviewCount(); @@ -394,14 +398,17 @@ TabWindow.prototype = { this.tabbrowser.removeTabsProgressListener(this); - for (let i = 0; i < this.winEvents.length; i++) + for (let i = 0; i < this.winEvents.length; i++) { this.win.removeEventListener(this.winEvents[i], this, false); + } - for (let i = 0; i < this.tabEvents.length; i++) + for (let i = 0; i < this.tabEvents.length; i++) { this.tabbrowser.tabContainer.removeEventListener(this.tabEvents[i], this, false); + } - for (let i = 0; i < tabs.length; i++) + for (let i = 0; i < tabs.length; i++) { this.removeTab(tabs[i]); + } let idx = AeroPeek.windows.indexOf(this.win.gTaskbarTabGroup); AeroPeek.windows.splice(idx, 1); @@ -411,6 +418,7 @@ TabWindow.prototype = { get width () { return this.win.innerWidth; }, + get height () { return this.win.innerHeight; }, @@ -421,7 +429,8 @@ TabWindow.prototype = { }, testCacheDims: function () { - return this._cachedWidth == this.width && this._cachedHeight == this.height; + return this._cachedWidth == this.width && + this._cachedHeight == this.height; }, // Invoked when the given tab is added to this window @@ -437,9 +446,9 @@ TabWindow.prototype = { createTabPreview: function (controller) { let docShell = this.win - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell); + .QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell); let preview = AeroPeek.taskbar.createTaskbarTabPreview(docShell, controller); preview.visible = AeroPeek.enabled; preview.active = this.tabbrowser.selectedTab == controller.tab; @@ -466,9 +475,8 @@ TabWindow.prototype = { set enabled (enable) { this._enabled = enable; - // Because making a tab visible requires that the tab it is next to be - // visible, it is far simpler to unset the 'next' tab and recreate them all - // at once. + // Because making a tab visible requires the tab it is next to be visible, + // it is far simpler to unset the 'next' tab and recreate them all at once. for (let [, preview] of this.previews) { preview.move(null); preview.visible = enable; @@ -521,8 +529,9 @@ TabWindow.prototype = { this.updateTabOrdering(); break; case "resize": - if (!AeroPeek._prefenabled) + if (!AeroPeek._prefenabled) { return; + } this.onResize(); break; } @@ -594,6 +603,7 @@ TabWindow.prototype = { directRequestProtocols: new Set([ "file", "chrome", "resource", "about" ]), + onLinkIconAvailable: function (aBrowser, aIconURL) { let self = this; let requestURL = null; @@ -603,7 +613,7 @@ TabWindow.prototype = { let urlObject = NetUtil.newURI(aIconURL); shouldRequestFaviconURL = !this.directRequestProtocols.has(urlObject.scheme); - } catch (ex) {} + } catch(ex) {} requestURL = shouldRequestFaviconURL ? "moz-anno:favicon:" + aIconURL : @@ -662,12 +672,14 @@ this.AeroPeek = { cacheLifespan: 20, initialize: function () { - if (!(WINTASKBAR_CONTRACTID in Cc)) + if (!(WINTASKBAR_CONTRACTID in Cc)) { return; + } this.taskbar = Cc[WINTASKBAR_CONTRACTID].getService(Ci.nsIWinTaskbar); this.available = this.taskbar.available; - if (!this.available) + if (!this.available) { return; + } this.prefs.addObserver(TOGGLE_PREF_NAME, this, true); this.enabled = this._prefenabled = this.prefs.getBoolPref(TOGGLE_PREF_NAME); @@ -677,8 +689,9 @@ this.AeroPeek = { destroy: function destroy() { this._enabled = false; - if (this.cacheTimer) + if (this.cacheTimer) { this.cacheTimer.cancel(); + } }, get enabled() { @@ -686,8 +699,9 @@ this.AeroPeek = { }, set enabled(enable) { - if (this._enabled == enable) + if (this._enabled == enable) { return; + } this._enabled = enable; @@ -771,22 +785,25 @@ this.AeroPeek = { onOpenWindow: function (win) { // This occurs when the taskbar service is not available (xp, vista) - if (!this.available || !this._prefenabled) + if (!this.available || !this._prefenabled) { return; + } win.gTaskbarTabGroup = new TabWindow(win); }, onCloseWindow: function (win) { // This occurs when the taskbar service is not available (xp, vista) - if (!this.available || !this._prefenabled) + if (!this.available || !this._prefenabled) { return; + } win.gTaskbarTabGroup.destroy(); delete win.gTaskbarTabGroup; - if (this.windows.length == 0) + if (this.windows.length == 0) { this.destroy(); + } }, resetCacheTimer: function () { @@ -804,11 +821,13 @@ this.AeroPeek = { } switch (aTopic) { case "nsPref:changed": - if (aData == CACHE_EXPIRATION_TIME_PREF_NAME) + if (aData == CACHE_EXPIRATION_TIME_PREF_NAME) { break; + } - if (aData == DISABLE_THRESHOLD_PREF_NAME) + if (aData == DISABLE_THRESHOLD_PREF_NAME) { this.maxpreviews = this.prefs.getIntPref(DISABLE_THRESHOLD_PREF_NAME); + } // Might need to enable/disable ourselves this.checkPreviewCount(); break; diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index e1f023b105..0ceb70a304 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -820,6 +820,8 @@ nsDocShell::nsDocShell() , mParentCharsetSource(0) , mJSRunToCompletionDepth(0) , mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE) + , mStateFloodGuardCount(0) + , mStateFloodGuardReported(false) { AssertOriginAttributesMatchPrivateBrowsing(); mHistoryID = ++gDocshellIDCounter; @@ -11833,6 +11835,27 @@ nsDocShell::SetReferrerPolicy(uint32_t aReferrerPolicy) // nsDocShell: Session History //***************************************************************************** +bool +nsDocShell::IsStateChangeFlooding() +{ + // Issue #1688: Let's copy Firefox's strategy for state flooding here, so + // that our implementations are interoperable. + if (mStateFloodGuardCount > kStateUpdateLimit) { + TimeStamp now = TimeStamp::Now(); + + if (now - mStateFloodGuardUpdated > TimeDuration::FromSeconds(kRefreshTimeSecs)) { + mStateFloodGuardCount = 0; + mStateFloodGuardUpdated = now; + mStateFloodGuardReported = false; + return false; + } + return true; + } + + mStateFloodGuardCount++; + return false; +} + NS_IMETHODIMP nsDocShell::AddState(JS::Handle aData, const nsAString& aTitle, const nsAString& aURL, bool aReplace, JSContext* aCx) @@ -11897,6 +11920,24 @@ nsDocShell::AddState(JS::Handle aData, const nsAString& aTitle, nsCOMPtr document = GetDocument(); NS_ENSURE_TRUE(document, NS_ERROR_FAILURE); + // If we're being flooded with state change requests, we should abort early + // from the state change logic. + if (IsStateChangeFlooding()) { + // Report a warning to the console to tell developers why their navigations + // failed. + // Do this only if not yet marked reported so we only report it once per + // flood interval. + if (!mStateFloodGuardReported) { + nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("PushState"), + document, + nsContentUtils::eDOM_PROPERTIES, + "PushStateFloodingPrevented"); + mStateFloodGuardReported = true; + } + return NS_OK; + } + // Step A: Serialize aData using structured clone. // https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate // step 5. diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index 93a1ba68df..019a7e4ab6 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -1049,6 +1049,15 @@ private: // as constants in the nsIDocShell.idl file. uint32_t mTouchEventsOverride; + // Keep track how how many history state changes we're getting, to catch & + // prevent flooding. + int32_t mStateFloodGuardCount; + mozilla::TimeStamp mStateFloodGuardUpdated; + bool mStateFloodGuardReported; + // We have a limit of pushing 50 states to history every 10 seconds. + const int32_t kStateUpdateLimit = 50; + const double kRefreshTimeSecs = 10.0; + // Separate function to do the actual name (i.e. not _top, _self etc.) // searching for FindItemWithName. nsresult DoFindItemWithName(const nsAString& aName, @@ -1064,6 +1073,10 @@ private: void MaybeNotifyKeywordSearchLoading(const nsString& aProvider, const nsString& aKeyword); + // Helper method for AddState which checks for excessive calls to PushState or + // ReplaceState. + bool IsStateChangeFlooding(); + #ifdef DEBUG // We're counting the number of |nsDocShells| to help find leaks static unsigned long gNumberOfDocShells; diff --git a/dom/crypto/WebCryptoTask.cpp b/dom/crypto/WebCryptoTask.cpp index 57fb3c3c86..122afd793b 100644 --- a/dom/crypto/WebCryptoTask.cpp +++ b/dom/crypto/WebCryptoTask.cpp @@ -690,6 +690,7 @@ private: case CKM_AES_GCM: gcmParams.pIv = mIv.Elements(); gcmParams.ulIvLen = mIv.Length(); + gcmParams.ulIvBits = gcmParams.ulIvLen * 8; gcmParams.pAAD = mAad.Elements(); gcmParams.ulAADLen = mAad.Length(); gcmParams.ulTagBits = mTagLength; diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties index 6bd3aac947..1f43a4389f 100644 --- a/dom/locales/en-US/chrome/dom/dom.properties +++ b/dom/locales/en-US/chrome/dom/dom.properties @@ -316,3 +316,5 @@ LargeAllocationRelatedBrowsingContexts=A Large-Allocation header was ignored due LargeAllocationInIFrame=A Large-Allocation header was ignored due to the load occuring within an iframe. # LOCALIZATION NOTE: Do not translate "Large-Allocation", as it is a literal header name LargeAllocationNonE10S=A Large-Allocation header was ignored due to the document not being loaded out of process. +# LOCALIZATION NOTE: Do not translate "pushState" and "replaceState" +PushStateFloodingPrevented=Call to pushState or replaceState ignored due to excessive calls within a short timeframe.