summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@gmail.com>2018-02-02 20:44:40 +0100
committerwolfbeast <mcwerewolf@gmail.com>2018-02-02 20:44:40 +0100
commit4bf1a2a1cb61a165c0540208098070222eafdfff (patch)
tree41e81fdf433c32c263cb2fad07f87812e30c747a
parentc0c702a5e3284e843e680064b4c6a7280242c567 (diff)
parentb80de6fe930792c94c9e64dd3867ffb1d663f16f (diff)
downloadUXP-4bf1a2a1cb61a165c0540208098070222eafdfff.tar
UXP-4bf1a2a1cb61a165c0540208098070222eafdfff.tar.gz
UXP-4bf1a2a1cb61a165c0540208098070222eafdfff.tar.lz
UXP-4bf1a2a1cb61a165c0540208098070222eafdfff.tar.xz
UXP-4bf1a2a1cb61a165c0540208098070222eafdfff.zip
Merge branch 'ported-moebius'
-rw-r--r--browser/app/profile/firefox.js8
-rw-r--r--browser/themes/shared/customizableui/panelUI.inc.css59
-rw-r--r--browser/themes/shared/customizableui/whimsy.pngbin6639 -> 0 bytes
-rw-r--r--browser/themes/shared/customizableui/whimsy@2x.pngbin18370 -> 0 bytes
-rw-r--r--browser/themes/shared/jar.inc.mn2
-rw-r--r--dom/base/nsJSEnvironment.cpp5
-rw-r--r--dom/base/nsScriptLoader.cpp5
-rw-r--r--dom/canvas/CanvasRenderingContext2D.cpp73
-rw-r--r--dom/system/NetworkGeolocationProvider.js41
-rw-r--r--editor/composer/nsEditorSpellCheck.cpp300
-rw-r--r--js/src/jsapi.cpp11
-rw-r--r--js/src/jsapi.h3
-rw-r--r--modules/libpref/init/all.js9
-rw-r--r--netwerk/base/security-prefs.js16
-rw-r--r--parser/htmlparser/nsExpatDriver.cpp14
-rw-r--r--parser/htmlparser/nsExpatDriver.h7
-rw-r--r--security/manager/ssl/nsNSSComponent.cpp31
-rw-r--r--toolkit/mozapps/update/nsUpdateService.js14
18 files changed, 304 insertions, 294 deletions
diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js
index 82f8e45a5..465b5349f 100644
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -40,7 +40,7 @@ pref("extensions.checkCompatibility.temporaryThemeOverride_minAppVersion", "29.0
pref("xpinstall.customConfirmationUI", true);
// Preferences for AMO integration
-pref("extensions.getAddons.cache.enabled", true);
+pref("extensions.getAddons.cache.enabled", false);
pref("extensions.getAddons.maxResults", 15);
pref("extensions.getAddons.get.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/guid:%IDS%?src=firefox&appOS=%OS%&appVersion=%VERSION%");
pref("extensions.getAddons.getWithPerformance.url", "https://services.addons.mozilla.org/%LOCALE%/firefox/api/%API_VERSION%/search/guid:%IDS%?src=firefox&appOS=%OS%&appVersion=%VERSION%&tMain=%TIME_MAIN%&tFirstPaint=%TIME_FIRST_PAINT%&tSessionRestored=%TIME_SESSION_RESTORED%");
@@ -1249,11 +1249,7 @@ pref("plain_text.wrap_long_lines", true);
pref("dom.debug.propagate_gesture_events_through_content", false);
// The request URL of the GeoLocation backend.
-#ifdef RELEASE_OR_BETA
-pref("geo.wifi.uri", "https://www.googleapis.com/geolocation/v1/geolocate?key=%GOOGLE_API_KEY%");
-#else
-pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%");
-#endif
+pref("geo.wifi.uri", "http://ip-api.com/json/?fields=lat,lon,status,message");
#ifdef XP_MACOSX
#ifdef RELEASE_OR_BETA
diff --git a/browser/themes/shared/customizableui/panelUI.inc.css b/browser/themes/shared/customizableui/panelUI.inc.css
index b46110ab5..b0bb05415 100644
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -28,65 +28,6 @@
height: 128px;
}
-#PanelUI-popup #PanelUI-contents:empty::before {
- content: "";
- background-image: url(chrome://browser/skin/customizableui/whimsy.png);
- background-size: 64px 64px;
- display: block;
- width: 64px;
- height: 64px;
- position: absolute;
- transition: transform 1s ease-out;
- animation: whimsyMoveX 3.05s linear 0s infinite alternate,
- whimsyMoveY 3.4s linear 0s infinite alternate;
-}
-
-#PanelUI-popup #PanelUI-contents:not(:hover):empty::before {
- filter: grayscale(100%);
-}
-
-#PanelUI-popup #PanelUI-contents:active:empty::before {
- animation: whimsyMoveX 3.05s linear 0s infinite alternate,
- whimsyMoveY 3.4s linear 0s infinite alternate,
- whimsyRotate 1s linear 0s infinite normal;
-}
-
-#PanelUI-popup #PanelUI-contents:-moz-locale-dir(rtl):empty::before {
- animation: whimsyMoveXRTL 3.05s linear 0s infinite alternate,
- whimsyMoveY 3.4s linear 0s infinite alternate;
-}
-
-#PanelUI-popup #PanelUI-contents:-moz-locale-dir(rtl):active:empty::before {
- animation: whimsyMoveXRTL 3.05s linear 0s infinite alternate,
- whimsyMoveY 3.4s linear 0s infinite alternate,
- whimsyRotate 1s linear 0s infinite normal;
-}
-
-@media (min-resolution: 2dppx) {
- #PanelUI-popup #PanelUI-contents:empty::before {
- background-image: url(chrome://browser/skin/customizableui/whimsy@2x.png);
- }
-}
-
-@keyframes whimsyMoveX {
- /* These values are adjusted for the padding on the panel. */
- from { margin-left: -15px; } to { margin-left: calc(100% - 49px); }
-}
-
-@keyframes whimsyMoveXRTL {
- /* These values are adjusted for the padding on the panel. */
- from { margin-right: -15px; } to { margin-right: calc(100% - 49px); }
-}
-
-@keyframes whimsyMoveY {
- /* These values are adjusted for the padding and height of the panel. */
- from { margin-top: -.5em; } to { margin-top: calc(64px - .5em); }
-}
-
-@keyframes whimsyRotate {
- to { transform: perspective(5000px) rotateY(360deg); }
-}
-
#PanelUI-button {
margin-inline-start: 2px;
border-inline-start: 1px solid;
diff --git a/browser/themes/shared/customizableui/whimsy.png b/browser/themes/shared/customizableui/whimsy.png
deleted file mode 100644
index 2e9fdd7eb..000000000
--- a/browser/themes/shared/customizableui/whimsy.png
+++ /dev/null
Binary files differ
diff --git a/browser/themes/shared/customizableui/whimsy@2x.png b/browser/themes/shared/customizableui/whimsy@2x.png
deleted file mode 100644
index 61f55f60f..000000000
--- a/browser/themes/shared/customizableui/whimsy@2x.png
+++ /dev/null
Binary files differ
diff --git a/browser/themes/shared/jar.inc.mn b/browser/themes/shared/jar.inc.mn
index f99f8de3c..dcc1e9dd9 100644
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -48,8 +48,6 @@
skin/classic/browser/customizableui/subView-arrow-back-inverted@2x.png (../shared/customizableui/subView-arrow-back-inverted@2x.png)
skin/classic/browser/customizableui/subView-arrow-back-inverted-rtl.png (../shared/customizableui/subView-arrow-back-inverted-rtl.png)
skin/classic/browser/customizableui/subView-arrow-back-inverted-rtl@2x.png (../shared/customizableui/subView-arrow-back-inverted-rtl@2x.png)
- skin/classic/browser/customizableui/whimsy.png (../shared/customizableui/whimsy.png)
- skin/classic/browser/customizableui/whimsy@2x.png (../shared/customizableui/whimsy@2x.png)
skin/classic/browser/downloads/contentAreaDownloadsView.css (../shared/downloads/contentAreaDownloadsView.css)
skin/classic/browser/downloads/download-blocked.svg (../shared/downloads/download-blocked.svg)
skin/classic/browser/downloads/menubutton-dropmarker.svg (../shared/downloads/menubutton-dropmarker.svg)
diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp
index b273d00c9..576f3052a 100644
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2282,6 +2282,7 @@ SetMemoryGCModePrefChangedCallback(const char* aPrefName, void* aClosure)
{
bool enableZoneGC = Preferences::GetBool("javascript.options.mem.gc_per_zone");
bool enableIncrementalGC = Preferences::GetBool("javascript.options.mem.gc_incremental");
+ bool enableGenerationalGC = Preferences::GetBool("javascript.options.mem.gc_generational");
JSGCMode mode;
if (enableIncrementalGC) {
mode = JSGC_MODE_INCREMENTAL;
@@ -2291,6 +2292,7 @@ SetMemoryGCModePrefChangedCallback(const char* aPrefName, void* aClosure)
mode = JSGC_MODE_GLOBAL;
}
JS_SetGCParameter(sContext, JSGC_MODE, mode);
+ JS_SetGGCMode(sContext, enableGenerationalGC);
}
static void
@@ -2485,6 +2487,9 @@ nsJSContext::EnsureStatics()
Preferences::RegisterCallbackAndCall(SetMemoryGCSliceTimePrefChangedCallback,
"javascript.options.mem.gc_incremental_slice_ms");
+ Preferences::RegisterCallbackAndCall(SetMemoryGCModePrefChangedCallback,
+ "javascript.options.mem.gc_generational");
+
Preferences::RegisterCallbackAndCall(SetMemoryGCCompactingPrefChangedCallback,
"javascript.options.mem.gc_compacting");
diff --git a/dom/base/nsScriptLoader.cpp b/dom/base/nsScriptLoader.cpp
index 6c732db6c..a6d20e363 100644
--- a/dom/base/nsScriptLoader.cpp
+++ b/dom/base/nsScriptLoader.cpp
@@ -2630,7 +2630,10 @@ nsScriptLoader::PrepareLoadedRequest(nsScriptLoadRequest* aRequest,
}
nsAutoCString sourceMapURL;
- rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-SourceMap"), sourceMapURL);
+ rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("SourceMap"), sourceMapURL);
+ if (NS_FAILED(rv)) {
+ rv = httpChannel->GetResponseHeader(NS_LITERAL_CSTRING("X-SourceMap"), sourceMapURL);
+ }
if (NS_SUCCEEDED(rv)) {
aRequest->mHasSourceMapURL = true;
aRequest->mSourceMapURL = NS_ConvertUTF8toUTF16(sourceMapURL);
diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp
index 2ed39627e..b0a430fe4 100644
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -68,6 +68,8 @@
#include "CanvasImageCache.h"
#include <algorithm>
+#include <stdlib.h>
+#include <time.h>
#include "jsapi.h"
#include "jsfriendapi.h"
@@ -2083,6 +2085,18 @@ CanvasRenderingContext2D::GetInputStream(const char* aMimeType,
return NS_ERROR_FAILURE;
}
+ bool PoisonData = Preferences::GetBool("canvas.poisondata",false);
+ if (PoisonData) {
+ srand(time(NULL));
+ // Image buffer is always a packed BGRA array (BGRX -> BGR[FF])
+ // so always 4-byte pixels.
+ // GetImageBuffer => SurfaceToPackedBGRA [=> ConvertBGRXToBGRA]
+ for (int32_t j = 0; j < mWidth * mHeight * 4; ++j) {
+ if (imageBuffer[j] !=0 && imageBuffer[j] != 255)
+ imageBuffer[j] += rand() % 3 - 1;
+ }
+ }
+
return ImageEncoder::GetInputStream(mWidth, mHeight, imageBuffer.get(),
format, encoder, aEncoderOptions,
aStream);
@@ -5698,6 +5712,14 @@ CanvasRenderingContext2D::GetImageData(JSContext* aCx, double aSx,
return imageData.forget();
}
+inline uint8_t PoisonValue(uint8_t v)
+{
+ if (v==0 || v==255)
+ return v; //don't fuzz edges to prevent overflow/underflow
+
+ return v + rand() %3 -1;
+}
+
nsresult
CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
int32_t aX,
@@ -5712,6 +5734,10 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
MOZ_ASSERT(aWidth && aHeight);
+ bool PoisonData = Preferences::GetBool("canvas.poisondata",false);
+ if (PoisonData)
+ srand(time(NULL));
+
CheckedInt<uint32_t> len = CheckedInt<uint32_t>(aWidth) * aHeight * 4;
if (!len.isValid()) {
return NS_ERROR_DOM_INDEX_SIZE_ERR;
@@ -5784,21 +5810,31 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
uint8_t* dst = data + dstWriteRect.y * (aWidth * 4) + dstWriteRect.x * 4;
+ uint8_t a,r,g,b;
+
if (mOpaque) {
for (int32_t j = 0; j < dstWriteRect.height; ++j) {
for (int32_t i = 0; i < dstWriteRect.width; ++i) {
// XXX Is there some useful swizzle MMX we can use here?
#if MOZ_LITTLE_ENDIAN
- uint8_t b = *src++;
- uint8_t g = *src++;
- uint8_t r = *src++;
+ b = *src++;
+ g = *src++;
+ r = *src++;
src++;
#else
src++;
- uint8_t r = *src++;
- uint8_t g = *src++;
- uint8_t b = *src++;
+ r = *src++;
+ g = *src++;
+ b = *src++;
#endif
+
+ // Poison data for trackers if enabled
+ if (PoisonData) {
+ PoisonValue(r);
+ PoisonValue(g);
+ PoisonValue(b);
+ }
+
*dst++ = r;
*dst++ = g;
*dst++ = b;
@@ -5812,16 +5848,25 @@ CanvasRenderingContext2D::GetImageDataArray(JSContext* aCx,
for (int32_t i = 0; i < dstWriteRect.width; ++i) {
// XXX Is there some useful swizzle MMX we can use here?
#if MOZ_LITTLE_ENDIAN
- uint8_t b = *src++;
- uint8_t g = *src++;
- uint8_t r = *src++;
- uint8_t a = *src++;
+ b = *src++;
+ g = *src++;
+ r = *src++;
+ a = *src++;
#else
- uint8_t a = *src++;
- uint8_t r = *src++;
- uint8_t g = *src++;
- uint8_t b = *src++;
+ a = *src++;
+ r = *src++;
+ g = *src++;
+ b = *src++;
#endif
+
+ // Poison data for trackers if enabled
+ if (PoisonData) {
+ PoisonValue(a);
+ PoisonValue(r);
+ PoisonValue(g);
+ PoisonValue(b);
+ }
+
// Convert to non-premultiplied color
*dst++ = gfxUtils::sUnpremultiplyTable[a * 256 + r];
*dst++ = gfxUtils::sUnpremultiplyTable[a * 256 + g];
diff --git a/dom/system/NetworkGeolocationProvider.js b/dom/system/NetworkGeolocationProvider.js
index ea2abe55f..ad15ed802 100644
--- a/dom/system/NetworkGeolocationProvider.js
+++ b/dom/system/NetworkGeolocationProvider.js
@@ -219,9 +219,20 @@ WifiGeoCoordsObject.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsIDOMGeoPositionCoords])
};
-function WifiGeoPositionObject(lat, lng, acc) {
+function WifiGeoPositionObject(lat, lng, acc, cc, tz, zip, city, rc, region, country, isp, org, as) {
this.coords = new WifiGeoCoordsObject(lat, lng, acc, 0, 0);
this.address = null;
+ this.countrycode = cc;
+ this.timezone = tz;
+ this.zipcode = zip;
+ this.postalcode = zip;
+ this.city = city;
+ this.regioncode = rc;
+ this.region = region;
+ this.country = country;
+ this.isp = isp;
+ this.org = org;
+ this.as = as;
this.timestamp = Date.now();
}
@@ -431,41 +442,54 @@ WifiGeoPositionProvider.prototype = {
let xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
- this.notifyListener("locationUpdatePending");
+ // XXX: Dead code?
+ // this.notifyListener("locationUpdatePending");
try {
- xhr.open("POST", url, true);
+ xhr.open("GET", url, true);
xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;
} catch (e) {
this.notifyListener("notifyError",
[POSITION_UNAVAILABLE]);
return;
}
- xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
xhr.responseType = "json";
xhr.mozBackgroundRequest = true;
xhr.timeout = Services.prefs.getIntPref("geo.wifi.xhr.timeout");
+
xhr.ontimeout = (function() {
LOG("Location request XHR timed out.")
this.notifyListener("notifyError",
[POSITION_UNAVAILABLE]);
}).bind(this);
+
xhr.onerror = (function() {
this.notifyListener("notifyError",
[POSITION_UNAVAILABLE]);
}).bind(this);
+
xhr.onload = (function() {
LOG("server returned status: " + xhr.status + " --> " + JSON.stringify(xhr.response));
if ((xhr.channel instanceof Ci.nsIHttpChannel && xhr.status != 200) ||
- !xhr.response || !xhr.response.location) {
+ !xhr.response || xhr.response.status == 'fail') {
this.notifyListener("notifyError",
[POSITION_UNAVAILABLE]);
return;
}
- let newLocation = new WifiGeoPositionObject(xhr.response.location.lat,
- xhr.response.location.lng,
- xhr.response.accuracy);
+ let newLocation = new WifiGeoPositionObject(xhr.response.lat,
+ xhr.response.lon,
+ null, //accuracy not provided
+ xhr.response.countryCode,
+ xhr.response.timezone,
+ xhr.response.zip,
+ xhr.response.city,
+ xhr.response.region,
+ xhr.response.regionName,
+ xhr.response.country,
+ xhr.response.isp,
+ xhr.response.org,
+ xhr.response.as);
this.notifyListener("update", [newLocation]);
gCachedRequest = new CachedRequest(newLocation, data.cellTowers, data.wifiAccessPoints);
@@ -478,6 +502,7 @@ WifiGeoPositionProvider.prototype = {
notifyListener: function(listenerFunc, args) {
args = args || [];
+ LOG("Notify listener " + listenerFunc);
try {
this.listener[listenerFunc].apply(this.listener, args);
} catch(e) {
diff --git a/editor/composer/nsEditorSpellCheck.cpp b/editor/composer/nsEditorSpellCheck.cpp
index 7cae48c1f..790480034 100644
--- a/editor/composer/nsEditorSpellCheck.cpp
+++ b/editor/composer/nsEditorSpellCheck.cpp
@@ -594,45 +594,24 @@ nsEditorSpellCheck::SetCurrentDictionary(const nsAString& aDictionary)
// Ignore pending dictionary fetchers by increasing this number.
mDictionaryFetcherGroup++;
- uint32_t flags = 0;
- mEditor->GetFlags(&flags);
- if (!(flags & nsIPlaintextEditor::eEditorMailMask)) {
- if (!aDictionary.IsEmpty() && (mPreferredLang.IsEmpty() ||
- !mPreferredLang.Equals(aDictionary,
- nsCaseInsensitiveStringComparator()))) {
- // When user sets dictionary manually, we store this value associated
- // with editor url, if it doesn't match the document language exactly.
- // For example on "en" sites, we need to store "en-GB", otherwise
- // the language might jump back to en-US although the user explicitly
- // chose otherwise.
- StoreCurrentDictionary(mEditor, aDictionary);
-#ifdef DEBUG_DICT
- printf("***** Writing content preferences for |%s|\n",
- NS_ConvertUTF16toUTF8(aDictionary).get());
-#endif
- } else {
- // If user sets a dictionary matching the language defined by
- // document, we consider content pref has been canceled, and we clear it.
- ClearCurrentDictionary(mEditor);
-#ifdef DEBUG_DICT
- printf("***** Clearing content preferences for |%s|\n",
- NS_ConvertUTF16toUTF8(aDictionary).get());
-#endif
- }
-
- // Also store it in as a preference, so we can use it as a fallback.
- // We don't want this for mail composer because it uses
- // "spellchecker.dictionary" as a preference.
- Preferences::SetString("spellchecker.dictionary", aDictionary);
-#ifdef DEBUG_DICT
- printf("***** Storing spellchecker.dictionary |%s|\n",
- NS_ConvertUTF16toUTF8(aDictionary).get());
-#endif
+ if (mPreferredLang.IsEmpty() ||
+ !mPreferredLang.Equals(aDictionary, nsCaseInsensitiveStringComparator())) {
+ // When user sets dictionary manually, we store this value associated
+ // with editor url, if it doesn't match the document language exactly.
+ // For example on "en" sites, we need to store "en-GB", otherwise
+ // the language might jump back to en-US although the user explicitly
+ // chose otherwise.
+ StoreCurrentDictionary(mEditor, aDictionary);
+ } else {
+ // If user sets a dictionary matching the language defined by
+ // document, we consider content pref has been canceled, and we clear it.
+ ClearCurrentDictionary(mEditor);
}
}
return mSpellChecker->SetCurrentDictionary(aDictionary);
}
+
NS_IMETHODIMP
nsEditorSpellCheck::UninitSpellChecker()
{
@@ -771,23 +750,16 @@ nsEditorSpellCheck::DictionaryFetched(DictionaryFetcher* aFetcher)
/*
* We try to derive the dictionary to use based on the following priorities:
- * 1) Content preference, so the language the user set for the site before.
- * (Introduced in bug 678842 and corrected in bug 717433.)
- * 2) Language set by the website, or any other dictionary that partly
- * matches that. (Introduced in bug 338427.)
- * Eg. if the website is "en-GB", a user who only has "en-US" will get
- * that. If the website is generic "en", the user will get one of the
- * "en-*" installed, (almost) at random.
- * However, we prefer what is stored in "spellchecker.dictionary",
- * so if the user chose "en-AU" before, they will get "en-AU" on a plain
- * "en" site. (Introduced in bug 682564.)
- * 3) The value of "spellchecker.dictionary" which reflects a previous
- * language choice of the user (on another site).
- * (This was the original behaviour before the aforementioned bugs
- * landed).
- * 4) The user's locale.
- * 5) Use the current dictionary that is currently set.
- * 6) The content of the "LANG" environment variable (if set).
+ * 1) Content preference: the language the user set for the site before.
+ * 2) The value of "spellchecker.dictionary.override" which reflects a
+ * global choice of language explicitly set by the user.
+ * 3) Language set by the website, or any other dictionary that partly matches that.
+ * Eg. if the website is "en-GB", a user who only has "en-US" will get that.
+ * If the website is generic "en", the user will get one of the "en-*" installed,
+ * pretty much at random.
+ * 4) The user's locale
+ * 5) Leave the current dictionary set.
+ * 6) The content of the "LANG" environment variable (if set)
* 7) The first spell check dictionary installed.
*/
@@ -795,131 +767,100 @@ nsEditorSpellCheck::DictionaryFetched(DictionaryFetcher* aFetcher)
// https://html.spec.whatwg.org/#attr-lang
// This is used in SetCurrentDictionary.
mPreferredLang.Assign(aFetcher->mRootContentLang);
-#ifdef DEBUG_DICT
- printf("***** mPreferredLang (element) |%s|\n",
- NS_ConvertUTF16toUTF8(mPreferredLang).get());
-#endif
// If no luck, try the "Content-Language" header.
if (mPreferredLang.IsEmpty()) {
mPreferredLang.Assign(aFetcher->mRootDocContentLang);
-#ifdef DEBUG_DICT
- printf("***** mPreferredLang (content-language) |%s|\n",
- NS_ConvertUTF16toUTF8(mPreferredLang).get());
-#endif
}
-
- // Auxiliary status.
- nsresult rv2;
-
- // We obtain a list of available dictionaries.
- nsTArray<nsString> dictList;
- rv2 = mSpellChecker->GetDictionaryList(&dictList);
- NS_ENSURE_SUCCESS(rv2, rv2);
-
+
// Priority 1:
+ // Get language from content prefs, if set.
// If we successfully fetched a dictionary from content prefs, do not go
// further. Use this exact dictionary.
- // Don't use content preferences for editor with eEditorMailMask flag.
nsAutoString dictName;
- uint32_t flags;
- mEditor->GetFlags(&flags);
- if (!(flags & nsIPlaintextEditor::eEditorMailMask)) {
- dictName.Assign(aFetcher->mDictionary);
- if (!dictName.IsEmpty()) {
- if (NS_SUCCEEDED(TryDictionary(dictName, dictList, DICT_NORMAL_COMPARE))) {
-#ifdef DEBUG_DICT
- printf("***** Assigned from content preferences |%s|\n",
- NS_ConvertUTF16toUTF8(dictName).get());
-#endif
-
- // We take an early exit here, so let's not forget to clear the word
- // list.
- DeleteSuggestedWordList();
- return NS_OK;
- }
- // May be dictionary was uninstalled ?
- // Clear the content preference and continue.
- ClearCurrentDictionary(mEditor);
+ dictName.Assign(aFetcher->mDictionary);
+ if (!dictName.IsEmpty()) {
+ if (NS_SUCCEEDED(SetCurrentDictionary(dictName))) {
+ // We take an early exit here, so clear the suggested word list.
+ DeleteSuggestedWordList();
+ return NS_OK;
}
+ // Maybe the dictionary was uninstalled ?
+ // Clear the content preference and continue.
+ ClearCurrentDictionary(mEditor);
}
-
+
// Priority 2:
- // After checking the content preferences, we use the language of the element
- // or document.
- dictName.Assign(mPreferredLang);
-#ifdef DEBUG_DICT
- printf("***** Assigned from element/doc |%s|\n",
- NS_ConvertUTF16toUTF8(dictName).get());
-#endif
-
- // Get the preference value.
+ // Get global preferred language from preferences, if set.
nsAutoString preferredDict;
- preferredDict = Preferences::GetLocalizedString("spellchecker.dictionary");
+ preferredDict = Preferences::GetLocalizedString("spellchecker.dictionary.override");
+ if (!preferredDict.IsEmpty()) {
+ dictName.Assign(preferredDict);
+ }
- // The following will be driven by this status. Once we were able to set a
+ // Priority 3:
+ // Get language from element/doc, if set.
+ if (dictName.IsEmpty() && !mPreferredLang.IsEmpty()) {
+ dictName.Assign(mPreferredLang);
+ }
+
+ // Auxiliary status value
+ nsresult rv2;
+
+ // Obtain a list of available dictionaries to check against.
+ nsTArray<nsString> dictList;
+ rv2 = mSpellChecker->GetDictionaryList(&dictList);
+ NS_ENSURE_SUCCESS(rv2, rv2);
+ int32_t i, dictCount = dictList.Length();
+
+ // The following will be driven by this status. Once we are able to set a
// dictionary successfully, we're done. So we start with a "failed" status.
- nsresult rv = NS_ERROR_NOT_AVAILABLE;
-
+ nsresult rv = NS_ERROR_FAILURE;
+
if (!dictName.IsEmpty()) {
- // RFC 5646 explicitly states that matches should be case-insensitive.
- rv = TryDictionary (dictName, dictList, DICT_COMPARE_CASE_INSENSITIVE);
-
- if (NS_FAILED(rv)) {
-#ifdef DEBUG_DICT
- printf("***** Setting of |%s| failed (or it wasn't available)\n",
- NS_ConvertUTF16toUTF8(dictName).get());
-#endif
+ for (i = 0; i < dictCount; i++) {
+ nsAutoString dictStr(dictList.ElementAt(i));
+ if (dictName.Equals(dictStr, nsCaseInsensitiveStringComparator())) {
+ // First let's correct any problems due to non-matching case.
+ // This applies to both a user-set override and document language.
+ // RFC 5646 explicitly states that matches should be case-insensitive.
+ dictName.Assign(dictStr);
+ // Try to set it. Doing this inside this loop avoids trying to set a
+ // dictionary that isn't available.
+ rv = SetCurrentDictionary(dictName);
+ break;
+ }
+ }
+ if (NS_FAILED(rv)) {
// Required dictionary was not available. Try to get a dictionary
- // matching at least language part of dictName.
+ // matching at least the language part of dictName:
nsAutoString langCode;
int32_t dashIdx = dictName.FindChar('-');
- if (dashIdx != -1) {
+ if (dashIdx != -1) {
langCode.Assign(Substring(dictName, 0, dashIdx));
} else {
langCode.Assign(dictName);
}
- // Try dictionary.spellchecker preference, if it starts with langCode,
- // so we don't just get any random dictionary matching the language.
- if (!preferredDict.IsEmpty() &&
- nsStyleUtil::DashMatchCompare(preferredDict, langCode, nsDefaultStringComparator())) {
-#ifdef DEBUG_DICT
- printf("***** Trying preference value |%s| since it matches language code\n",
- NS_ConvertUTF16toUTF8(preferredDict).get());
-#endif
- rv = TryDictionary (preferredDict, dictList,
- DICT_COMPARE_CASE_INSENSITIVE);
- }
+ nsDefaultStringComparator comparator;
- if (NS_FAILED(rv)) {
- // Use any dictionary with the required language.
-#ifdef DEBUG_DICT
- printf("***** Trying to find match for language code |%s|\n",
- NS_ConvertUTF16toUTF8(langCode).get());
-#endif
- rv = TryDictionary (langCode, dictList, DICT_COMPARE_DASHMATCH);
+ // Loop over available dictionaries; if we find one with the required
+ // language, use it.
+ for (i = 0; i < dictCount; i++) {
+ nsAutoString dictStr(dictList.ElementAt(i));
+ if (nsStyleUtil::DashMatchCompare(dictStr, langCode, comparator) &&
+ NS_SUCCEEDED(rv = SetCurrentDictionary(dictStr))) {
+ break;
+ }
}
}
}
-
- // Priority 3:
- // If the document didn't supply a dictionary or the setting failed,
- // try the user preference next.
- if (NS_FAILED(rv)) {
- if (!preferredDict.IsEmpty()) {
-#ifdef DEBUG_DICT
- printf("***** Trying preference value |%s|\n",
- NS_ConvertUTF16toUTF8(preferredDict).get());
-#endif
- rv = TryDictionary (preferredDict, dictList, DICT_NORMAL_COMPARE);
- }
- }
-
+
// Priority 4:
- // As next fallback, try the current locale.
- if (NS_FAILED(rv)) {
+ // Content prefs, override and document didn't give us a valid dictionary
+ // name, so we just get the current locale and try to use that.
+ if (NS_FAILED (rv)) {
nsCOMPtr<nsIXULChromeRegistry> packageRegistry =
mozilla::services::GetXULChromeRegistryService();
@@ -929,69 +870,57 @@ nsEditorSpellCheck::DictionaryFetched(DictionaryFetcher* aFetcher)
false, utf8DictName);
dictName.Assign(EmptyString());
AppendUTF8toUTF16(utf8DictName, dictName);
-#ifdef DEBUG_DICT
- printf("***** Trying locale |%s|\n",
- NS_ConvertUTF16toUTF8(dictName).get());
-#endif
- rv = TryDictionary (dictName, dictList, DICT_COMPARE_CASE_INSENSITIVE);
+ // Try to set it, if it's in the list.
+ for (i = 0; i < dictCount; i++) {
+ nsAutoString dictStr(dictList.ElementAt(i));
+ if (dictStr.Equals(dictName)) {
+ rv = SetCurrentDictionary(dictName);
+ break;
+ }
+ }
}
}
-
+
if (NS_FAILED(rv)) {
- // Still no success.
+ // Still no success. Further fallback attempts required.
- // Priority 5:
- // If we have a current dictionary, don't try anything else.
+ // Priority 5:
+ // If we have a current dictionary, don't try anything else.
nsAutoString currentDictionary;
rv2 = GetCurrentDictionary(currentDictionary);
-#ifdef DEBUG_DICT
- if (NS_SUCCEEDED(rv2)) {
- printf("***** Retrieved current dict |%s|\n",
- NS_ConvertUTF16toUTF8(currentDictionary).get());
- }
-#endif
-
+
if (NS_FAILED(rv2) || currentDictionary.IsEmpty()) {
+ // We don't have a current dictionary.
// Priority 6:
// Try to get current dictionary from environment variable LANG.
- // LANG = language[_territory][.charset]
+ // LANG = language[_territory][.codeset]
char* env_lang = getenv("LANG");
- if (env_lang) {
+ if (env_lang != nullptr) {
nsString lang = NS_ConvertUTF8toUTF16(env_lang);
+
// Strip trailing charset, if there is any.
int32_t dot_pos = lang.FindChar('.');
if (dot_pos != -1) {
lang = Substring(lang, 0, dot_pos);
}
-
+
+ // Convert underscore to dash.
int32_t underScore = lang.FindChar('_');
if (underScore != -1) {
lang.Replace(underScore, 1, '-');
-#ifdef DEBUG_DICT
- printf("***** Trying LANG from environment |%s|\n",
- NS_ConvertUTF16toUTF8(lang).get());
-#endif
- nsAutoString lang2;
- lang2.Assign(lang);
- rv = TryDictionary(lang2, dictList, DICT_COMPARE_CASE_INSENSITIVE);
+ // Only attempt to set if a _territory is present.
+ rv = SetCurrentDictionary(lang);
}
}
-
+
// Priority 7:
- // If it does not work, pick the first one.
- if (NS_FAILED(rv) && !dictList.IsEmpty()) {
- nsAutoString firstInList;
- firstInList.Assign(dictList[0]);
- rv = TryDictionary(firstInList, dictList, DICT_NORMAL_COMPARE);
-#ifdef DEBUG_DICT
- printf("***** Trying first of list |%s|\n",
- NS_ConvertUTF16toUTF8(dictList[0]).get());
- if (NS_SUCCEEDED(rv)) {
- printf ("***** Setting worked.\n");
+ // If LANG does not work either, pick the first one.
+ if (NS_FAILED(rv)) {
+ if (dictList.Length() > 0) {
+ rv = SetCurrentDictionary(dictList[0]);
}
-#endif
}
- }
+ }
}
// If an error was thrown while setting the dictionary, just
@@ -999,6 +928,7 @@ nsEditorSpellCheck::DictionaryFetched(DictionaryFetcher* aFetcher)
// up. The user can manually reset the language to their choice on
// the dialog if it is wrong.
+ // Dictionary has changed, so delete the suggested word list.
DeleteSuggestedWordList();
return NS_OK;
diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp
index a99d08951..e4e86effa 100644
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -1410,6 +1410,17 @@ JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value)
MOZ_ALWAYS_TRUE(cx->gc.setParameter(key, value, lock));
}
+JS_PUBLIC_API(void)
+JS_SetGGCMode(JSContext* cx, bool enabled)
+{
+ // Control GGC
+ if (enabled && !cx->gc.isGenerationalGCEnabled()) {
+ cx->gc.enableGenerationalGC();
+ } else if (!enabled && cx->gc.isGenerationalGCEnabled()) {
+ cx->gc.disableGenerationalGC();
+ }
+}
+
JS_PUBLIC_API(uint32_t)
JS_GetGCParameter(JSContext* cx, JSGCParamKey key)
{
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index 46aa15947..6700a6c51 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1768,6 +1768,9 @@ typedef enum JSGCParamKey {
extern JS_PUBLIC_API(void)
JS_SetGCParameter(JSContext* cx, JSGCParamKey key, uint32_t value);
+extern JS_PUBLIC_API(void)
+JS_SetGGCMode(JSContext* cx, bool enabled);
+
extern JS_PUBLIC_API(uint32_t)
JS_GetGCParameter(JSContext* cx, JSGCParamKey key);
diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js
index 72eb8524e..0a92c6d17 100644
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -1117,6 +1117,9 @@ pref("print.print_via_parent", false);
// in a document.
pref("extensions.spellcheck.inline.max-misspellings", 500);
+// Predefined convenience pref for overriding the dictionary
+pref("spellchecker.dictionary.override", "");
+
// Prefs used by libeditor. Prefs specific to seamonkey composer
// belong in comm-central/editor/ui/composer.js
@@ -1142,6 +1145,7 @@ pref("dom.disable_window_open_feature.menubar", false);
pref("dom.disable_window_open_feature.resizable", true);
pref("dom.disable_window_open_feature.minimizable", false);
pref("dom.disable_window_open_feature.status", true);
+pref("dom.disable_window_showModalDialog", true);
pref("dom.allow_scripts_to_close_windows", false);
@@ -1258,6 +1262,7 @@ pref("javascript.options.mem.max", -1);
pref("javascript.options.mem.gc_per_zone", true);
pref("javascript.options.mem.gc_incremental", true);
pref("javascript.options.mem.gc_incremental_slice_ms", 10);
+pref("javascript.options.mem.gc_generational", true);
pref("javascript.options.mem.gc_compacting", true);
pref("javascript.options.mem.log", false);
pref("javascript.options.mem.notify", false);
@@ -4444,6 +4449,10 @@ pref("image.multithreaded_decoding.limit", -1);
// cache.
pref("canvas.image.cache.limit", 0);
+// Allow track-fobics to deliberately poison canvas data for
+// toDataURL() and getImageData()
+pref("canvas.poisondata", false);
+
// WebGL prefs
#ifdef ANDROID
// Disable MSAA on mobile.
diff --git a/netwerk/base/security-prefs.js b/netwerk/base/security-prefs.js
index 9f42745f7..329a4c6b7 100644
--- a/netwerk/base/security-prefs.js
+++ b/netwerk/base/security-prefs.js
@@ -17,6 +17,7 @@ pref("security.ssl.false_start.require-npn", false);
pref("security.ssl.enable_npn", true);
pref("security.ssl.enable_alpn", true);
+// TLS 1.0-1.2 cipher suites
pref("security.ssl3.ecdhe_rsa_aes_128_gcm_sha256", true);
pref("security.ssl3.ecdhe_ecdsa_aes_128_gcm_sha256", true);
pref("security.ssl3.ecdhe_ecdsa_chacha20_poly1305_sha256", true);
@@ -27,11 +28,20 @@ pref("security.ssl3.ecdhe_rsa_aes_128_sha", true);
pref("security.ssl3.ecdhe_ecdsa_aes_128_sha", true);
pref("security.ssl3.ecdhe_rsa_aes_256_sha", true);
pref("security.ssl3.ecdhe_ecdsa_aes_256_sha", true);
-pref("security.ssl3.dhe_rsa_aes_128_sha", true);
-pref("security.ssl3.dhe_rsa_aes_256_sha", true);
+pref("security.ssl3.dhe_rsa_camellia_256_sha", true);
+pref("security.ssl3.dhe_rsa_camellia_128_sha", true);
+pref("security.ssl3.rsa_aes_256_gcm_sha384", true);
+pref("security.ssl3.rsa_aes_256_sha256", true);
+pref("security.ssl3.rsa_camellia_128_sha", true);
+pref("security.ssl3.rsa_camellia_256_sha", true);
pref("security.ssl3.rsa_aes_128_sha", true);
pref("security.ssl3.rsa_aes_256_sha", true);
-pref("security.ssl3.rsa_des_ede3_sha", true);
+// Weak / deprecated
+pref("security.ssl3.dhe_rsa_aes_256_sha", false);
+pref("security.ssl3.dhe_rsa_aes_128_sha", false);
+pref("security.ssl3.rsa_aes_128_gcm_sha256", false);
+pref("security.ssl3.rsa_aes_128_sha256", false);
+pref("security.ssl3.rsa_des_ede3_sha", false);
pref("security.content.signature.root_hash",
"97:E8:BA:9C:F1:2F:B3:DE:53:CC:42:A4:E6:57:7E:D6:4D:F4:93:C2:47:B4:14:FE:A0:36:81:8D:38:23:56:0E");
diff --git a/parser/htmlparser/nsExpatDriver.cpp b/parser/htmlparser/nsExpatDriver.cpp
index 8882ec593..9cf888f69 100644
--- a/parser/htmlparser/nsExpatDriver.cpp
+++ b/parser/htmlparser/nsExpatDriver.cpp
@@ -338,6 +338,9 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsExpatDriver)
NS_IMPL_CYCLE_COLLECTION(nsExpatDriver, mSink, mExtendedSink)
+// We store the tagdepth in a Uint8, so make sure the limit fits in a Uint8.
+PR_STATIC_ASSERT(MAX_XML_TREE_DEPTH <= UINT8_MAX);
+
nsExpatDriver::nsExpatDriver()
: mExpatParser(nullptr),
mInCData(false),
@@ -345,6 +348,7 @@ nsExpatDriver::nsExpatDriver()
mInExternalDTD(false),
mMadeFinalCallToExpat(false),
mIsFinalChunk(false),
+ mTagDepth(0),
mInternalState(NS_OK),
mExpatBuffered(0),
mCatalogData(nullptr),
@@ -359,7 +363,7 @@ nsExpatDriver::~nsExpatDriver()
}
}
-nsresult
+void
nsExpatDriver::HandleStartElement(const char16_t *aValue,
const char16_t **aAtts)
{
@@ -377,13 +381,16 @@ nsExpatDriver::HandleStartElement(const char16_t *aValue,
}
if (mSink) {
+ if (++mTagDepth == MAX_XML_TREE_DEPTH) {
+ MaybeStopParser(NS_ERROR_HTMLPARSER_HIERARCHYTOODEEP);
+ return;
+ }
+
nsresult rv = mSink->
HandleStartElement(aValue, aAtts, attrArrayLength,
XML_GetCurrentLineNumber(mExpatParser));
MaybeStopParser(rv);
}
-
- return NS_OK;
}
nsresult
@@ -395,6 +402,7 @@ nsExpatDriver::HandleEndElement(const char16_t *aValue)
if (mSink && mInternalState != NS_ERROR_HTMLPARSER_STOPPARSING) {
nsresult rv = mSink->HandleEndElement(aValue);
+ --mTagDepth;
MaybeStopParser(rv);
}
diff --git a/parser/htmlparser/nsExpatDriver.h b/parser/htmlparser/nsExpatDriver.h
index 1bf022ade..0d62bd09d 100644
--- a/parser/htmlparser/nsExpatDriver.h
+++ b/parser/htmlparser/nsExpatDriver.h
@@ -16,6 +16,9 @@
#include "nsIParser.h"
#include "nsCycleCollectionParticipant.h"
+// Tree depth limit for XML-based files (xml/svg/etc.)
+#define MAX_XML_TREE_DEPTH 200
+
class nsIExpatSink;
class nsIExtendedExpatSink;
struct nsCatalogData;
@@ -37,7 +40,7 @@ public:
const char16_t *aBase,
const char16_t *aSystemId,
const char16_t *aPublicId);
- nsresult HandleStartElement(const char16_t *aName, const char16_t **aAtts);
+ void HandleStartElement(const char16_t *aName, const char16_t **aAtts);
nsresult HandleEndElement(const char16_t *aName);
nsresult HandleCharacterData(const char16_t *aCData, const uint32_t aLength);
nsresult HandleComment(const char16_t *aName);
@@ -119,6 +122,8 @@ private:
// Whether we're sure that we won't be getting more buffers to parse from
// Necko
bool mIsFinalChunk;
+
+ uint8_t mTagDepth;
nsresult mInternalState;
diff --git a/security/manager/ssl/nsNSSComponent.cpp b/security/manager/ssl/nsNSSComponent.cpp
index d53f846ed..1bcdcc1b0 100644
--- a/security/manager/ssl/nsNSSComponent.cpp
+++ b/security/manager/ssl/nsNSSComponent.cpp
@@ -1344,12 +1344,16 @@ static const CipherPref sCipherPrefs[] = {
{ "security.ssl3.ecdhe_ecdsa_aes_256_sha",
TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, true },
- { "security.ssl3.dhe_rsa_aes_128_sha",
- TLS_DHE_RSA_WITH_AES_128_CBC_SHA, true },
-
+ { "security.ssl3.dhe_rsa_camellia_256_sha",
+ TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA, true},
{ "security.ssl3.dhe_rsa_aes_256_sha",
TLS_DHE_RSA_WITH_AES_256_CBC_SHA, true },
+ { "security.ssl3.dhe_rsa_camellia_128_sha",
+ TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA, true },
+ { "security.ssl3.dhe_rsa_aes_128_sha",
+ TLS_DHE_RSA_WITH_AES_128_CBC_SHA, true },
+
{ "security.tls13.aes_128_gcm_sha256",
TLS_AES_128_GCM_SHA256, true },
{ "security.tls13.chacha20_poly1305_sha256",
@@ -1357,12 +1361,27 @@ static const CipherPref sCipherPrefs[] = {
{ "security.tls13.aes_256_gcm_sha384",
TLS_AES_256_GCM_SHA384, true },
+ // Deprecated (RSA key exchange):
+ { "security.ssl3.rsa_aes_256_gcm_sha384",
+ TLS_RSA_WITH_AES_256_GCM_SHA384, true },
+ { "security.ssl3.rsa_aes_256_sha256",
+ TLS_RSA_WITH_AES_256_CBC_SHA256, true },
+ {"security.ssl3.rsa_camellia_128_sha",
+ TLS_RSA_WITH_CAMELLIA_128_CBC_SHA, true },
+ {"security.ssl3.rsa_camellia_256_sha",
+ TLS_RSA_WITH_CAMELLIA_256_CBC_SHA, true },
{ "security.ssl3.rsa_aes_128_sha",
- TLS_RSA_WITH_AES_128_CBC_SHA, true }, // deprecated (RSA key exchange)
+ TLS_RSA_WITH_AES_128_CBC_SHA, true },
{ "security.ssl3.rsa_aes_256_sha",
- TLS_RSA_WITH_AES_256_CBC_SHA, true }, // deprecated (RSA key exchange)
+ TLS_RSA_WITH_AES_256_CBC_SHA, true },
+
+// Expensive/deprecated/weak
+ { "security.ssl3.rsa_aes_128_gcm_sha256",
+ TLS_RSA_WITH_AES_128_GCM_SHA256, false }, // Deprecated
+ { "security.ssl3.rsa_aes_128_sha256",
+ TLS_RSA_WITH_AES_128_CBC_SHA256, false }, // Deprecated
{ "security.ssl3.rsa_des_ede3_sha",
- TLS_RSA_WITH_3DES_EDE_CBC_SHA, true }, // deprecated (RSA key exchange, 3DES)
+ TLS_RSA_WITH_3DES_EDE_CBC_SHA, false }, // Weak (3DES)
// All the rest are disabled
diff --git a/toolkit/mozapps/update/nsUpdateService.js b/toolkit/mozapps/update/nsUpdateService.js
index 10eb1d100..e23ab3f40 100644
--- a/toolkit/mozapps/update/nsUpdateService.js
+++ b/toolkit/mozapps/update/nsUpdateService.js
@@ -2395,14 +2395,16 @@ UpdateService.prototype = {
let lastCheckCode = AUSTLMY.CHK_NO_COMPAT_UPDATE_FOUND;
updates.forEach(function(aUpdate) {
- // Ignore updates for older versions of the application and updates for
- // the same version of the application with the same build ID.
+ // Ignore updates for older versions of the applications and updates for
+ // the same version or build id of the application
if (vc.compare(aUpdate.appVersion, Services.appinfo.version) < 0 ||
- vc.compare(aUpdate.appVersion, Services.appinfo.version) == 0 &&
- aUpdate.buildID == Services.appinfo.appBuildID) {
+ (vc.compare(aUpdate.appVersion, Services.appinfo.version) == 0 &&
+ aUpdate.buildID <= Services.appinfo.appBuildID) ||
+ (vc.compare(aUpdate.appVersion, Services.appinfo.version) == 0 &&
+ aUpdate.buildID == undefined)) {
LOG("UpdateService:selectUpdate - skipping update because the " +
- "update's application version is less than the current " +
- "application version");
+ "update's application version is less than or equal to " +
+ "the current application version.");
lastCheckCode = AUSTLMY.CHK_UPDATE_PREVIOUS_VERSION;
return;
}