From 20cc8b92e4b7b5d98b7bb1ff3d9c2e9bddca9ad1 Mon Sep 17 00:00:00 2001 From: Lootyhoof Date: Fri, 15 Mar 2019 22:53:09 +0000 Subject: [PATCH 01/16] Draw a border when hiding the tab bar --- application/palemoon/themes/linux/browser.css | 11 +++++++++ application/palemoon/themes/osx/browser.css | 11 +++++++++ .../palemoon/themes/windows/browser.css | 24 +++++++++++++------ 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/application/palemoon/themes/linux/browser.css b/application/palemoon/themes/linux/browser.css index b545b06cb1..933067c2bc 100644 --- a/application/palemoon/themes/linux/browser.css +++ b/application/palemoon/themes/linux/browser.css @@ -1607,6 +1607,17 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action- background-image: linear-gradient(to top, rgba(0,0,0,.3) 1px, rgba(0,0,0,.05) 1px, transparent 50%); } +/* When the tab bar is collapsed, show a 1px border in its place. */ +#TabsToolbar[collapsed="true"] { + visibility: visible; + height: 1px; + border-bottom-width: 1px; + /* !important here to override border-style: none on the toolbar */ + border-bottom-style: solid !important; + border-bottom-color: ThreeDShadow; + overflow: hidden; +} + .tabbrowser-tab, .tabs-newtab-button { position: static; diff --git a/application/palemoon/themes/osx/browser.css b/application/palemoon/themes/osx/browser.css index ddf050785f..20e8c5eacb 100644 --- a/application/palemoon/themes/osx/browser.css +++ b/application/palemoon/themes/osx/browser.css @@ -1630,6 +1630,17 @@ richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url- background-image: linear-gradient(to top, @toolbarShadowColor@ 1px, rgba(0,0,0,.05) 1px, transparent 50%); } +/* When the tab bar is collapsed, show a 1px border in its place. */ +#TabsToolbar[collapsed="true"] { + visibility: visible; + height: 1px; + border-bottom-width: 1px; + /* !important here to override border-style: none on the toolbar */ + border-bottom-style: solid !important; + border-bottom-color: ThreeDShadow; + overflow: hidden; +} + @media (-moz-mac-lion-theme) { #main-window[sizemode=normal] #TabsToolbar { padding-left: 2px; diff --git a/application/palemoon/themes/windows/browser.css b/application/palemoon/themes/windows/browser.css index 56a8318da2..8a47e67ce1 100644 --- a/application/palemoon/themes/windows/browser.css +++ b/application/palemoon/themes/windows/browser.css @@ -31,6 +31,8 @@ %endif :root { + --toolbox-after-color: ThreeDShadow; + --toolbar-custom-color: hsl(210,75%,92%); --toolbar-highlight-top: rgba(255,255,255,.5); --toolbar-highlight-bottom: transparent; @@ -91,7 +93,7 @@ display: -moz-box; -moz-box-ordinal-group: 101; /* tabs toolbar is 100 */ height: 1px; - background-color: ThreeDShadow; + background-color: var(--toolbox-after-color); } #navigator-toolbox[tabsontop=false]::after, #main-window[disablechrome] #navigator-toolbox::after { @@ -1841,6 +1843,17 @@ richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action- background-image: linear-gradient(to top, @toolbarShadowColor@ 1px, rgba(0,0,0,.05) 1px, transparent 50%); } +/* When the tab bar is collapsed, show a 1px border in its place. */ +#TabsToolbar[collapsed="true"] { + visibility: visible; + height: 1px; + border-bottom-width: 1px; + /* !important here to override border-style: none on the toolbar */ + border-bottom-style: solid !important; + border-bottom-color: var(--toolbox-after-color); + overflow: hidden; +} + .tabbrowser-tab, .tabs-newtab-button { -moz-appearance: none; @@ -3044,20 +3057,17 @@ toolbar[brighttext] #addonbar-closebutton { @media (-moz-os-version: windows-vista), (-moz-os-version: windows-win7) { - #navigator-toolbox:not(:-moz-lwtheme)::after { - background-color: #aabccf; + :root { + --toolbox-after-color: #aabccf; } } @media (-moz-os-version: windows-win8), (-moz-os-version: windows-win10) { :root { + --toolbox-after-color: #bcbcbc; --toolbar-custom-color: hsl(210,0%,92%); } - - #navigator-toolbox:not(:-moz-lwtheme)::after { - background-color: #bcbcbc; - } } #navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme), From e3b3cc12d2474d4e7bcf32bc1cd9df9b180846aa Mon Sep 17 00:00:00 2001 From: Lootyhoof Date: Fri, 15 Mar 2019 23:10:59 +0000 Subject: [PATCH 02/16] Don't modify toolbox-after-color in lwthemes --- application/palemoon/themes/windows/browser.css | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/application/palemoon/themes/windows/browser.css b/application/palemoon/themes/windows/browser.css index 8a47e67ce1..aae36c5399 100644 --- a/application/palemoon/themes/windows/browser.css +++ b/application/palemoon/themes/windows/browser.css @@ -3057,7 +3057,7 @@ toolbar[brighttext] #addonbar-closebutton { @media (-moz-os-version: windows-vista), (-moz-os-version: windows-win7) { - :root { + :root:not(:-moz-lwtheme) { --toolbox-after-color: #aabccf; } } @@ -3065,9 +3065,12 @@ toolbar[brighttext] #addonbar-closebutton { @media (-moz-os-version: windows-win8), (-moz-os-version: windows-win10) { :root { - --toolbox-after-color: #bcbcbc; --toolbar-custom-color: hsl(210,0%,92%); } + + :root:not(:-moz-lwtheme) { + --toolbox-after-color: #bcbcbc; + } } #navigator-toolbox[tabsontop=true] #urlbar:not(:-moz-lwtheme), From d82c60d3d8bc07077f3d95e997bb0febbbcc70f6 Mon Sep 17 00:00:00 2001 From: Olli Pettay Date: Thu, 21 Mar 2019 09:02:04 +0100 Subject: [PATCH 03/16] Remove harmless assertions by using IgnoredErrorResult. --- dom/html/HTMLTableElement.cpp | 15 ++++++--------- dom/html/HTMLTableSectionElement.cpp | 2 +- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/dom/html/HTMLTableElement.cpp b/dom/html/HTMLTableElement.cpp index ec1b7cecb7..c5b7696cfd 100644 --- a/dom/html/HTMLTableElement.cpp +++ b/dom/html/HTMLTableElement.cpp @@ -421,11 +421,10 @@ HTMLTableElement::CreateTHead() void HTMLTableElement::DeleteTHead() { - HTMLTableSectionElement* tHead = GetTHead(); + RefPtr tHead = GetTHead(); if (tHead) { - mozilla::ErrorResult rv; + mozilla::IgnoredErrorResult rv; nsINode::RemoveChild(*tHead, rv); - MOZ_ASSERT(!rv.Failed()); } } @@ -452,11 +451,10 @@ HTMLTableElement::CreateTFoot() void HTMLTableElement::DeleteTFoot() { - HTMLTableSectionElement* tFoot = GetTFoot(); + RefPtr tFoot = GetTFoot(); if (tFoot) { - mozilla::ErrorResult rv; + mozilla::IgnoredErrorResult rv; nsINode::RemoveChild(*tFoot, rv); - MOZ_ASSERT(!rv.Failed()); } } @@ -483,11 +481,10 @@ HTMLTableElement::CreateCaption() void HTMLTableElement::DeleteCaption() { - HTMLTableCaptionElement* caption = GetCaption(); + RefPtr caption = GetCaption(); if (caption) { - mozilla::ErrorResult rv; + mozilla::IgnoredErrorResult rv; nsINode::RemoveChild(*caption, rv); - MOZ_ASSERT(!rv.Failed()); } } diff --git a/dom/html/HTMLTableSectionElement.cpp b/dom/html/HTMLTableSectionElement.cpp index c7b0665ddc..e99597636e 100644 --- a/dom/html/HTMLTableSectionElement.cpp +++ b/dom/html/HTMLTableSectionElement.cpp @@ -122,7 +122,7 @@ HTMLTableSectionElement::DeleteRow(int32_t aValue, ErrorResult& aError) refIndex = (uint32_t)aValue; } - nsINode* row = rows->Item(refIndex); + nsCOMPtr row = rows->Item(refIndex); if (!row) { aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; From eb32b5d7e414e979ca67a3bfd00a4a592964259e Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Thu, 21 Mar 2019 09:53:24 +0100 Subject: [PATCH 04/16] Pref the use of unboxed plain objects in JS and disable by default. This should be all that's needed for #1017, but verification of impact is definitely desired. --- js/src/jit/JitOptions.cpp | 2 +- js/src/jsapi.cpp | 3 +++ js/src/jsapi.h | 25 +++++++++++++------------ js/xpconnect/src/XPCJSContext.cpp | 4 ++++ modules/libpref/init/all.js | 1 + 5 files changed, 22 insertions(+), 13 deletions(-) diff --git a/js/src/jit/JitOptions.cpp b/js/src/jit/JitOptions.cpp index eb5a6c1c22..b9a7c7b276 100644 --- a/js/src/jit/JitOptions.cpp +++ b/js/src/jit/JitOptions.cpp @@ -222,7 +222,7 @@ DefaultJitOptions::DefaultJitOptions() } // Toggles whether unboxed plain objects can be created by the VM. - SET_DEFAULT(disableUnboxedObjects, false); + SET_DEFAULT(disableUnboxedObjects, true); // Test whether Atomics are allowed in asm.js code. SET_DEFAULT(asmJSAtomicsEnable, false); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 37d023bd4a..6114b81576 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -6410,6 +6410,9 @@ JS_SetGlobalJitCompilerOption(JSContext* cx, JSJitCompilerOption opt, uint32_t v } jit::JitOptions.jumpThreshold = value; break; + case JSJITCOMPILER_UNBOXED_OBJECTS: + jit::JitOptions.disableUnboxedObjects = !value; + break; case JSJITCOMPILER_ASMJS_ATOMICS_ENABLE: jit::JitOptions.asmJSAtomicsEnable = !!value; break; diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 005d2278e4..1f726f2e54 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -5783,19 +5783,20 @@ JS_SetParallelParsingEnabled(JSContext* cx, bool enabled); extern JS_PUBLIC_API(void) JS_SetOffthreadIonCompilationEnabled(JSContext* cx, bool enabled); -#define JIT_COMPILER_OPTIONS(Register) \ - Register(BASELINE_WARMUP_TRIGGER, "baseline.warmup.trigger") \ - Register(ION_WARMUP_TRIGGER, "ion.warmup.trigger") \ - Register(ION_GVN_ENABLE, "ion.gvn.enable") \ - Register(ION_FORCE_IC, "ion.forceinlineCaches") \ - Register(ION_ENABLE, "ion.enable") \ +#define JIT_COMPILER_OPTIONS(Register) \ + Register(BASELINE_WARMUP_TRIGGER, "baseline.warmup.trigger") \ + Register(ION_WARMUP_TRIGGER, "ion.warmup.trigger") \ + Register(ION_GVN_ENABLE, "ion.gvn.enable") \ + Register(ION_FORCE_IC, "ion.forceinlineCaches") \ + Register(ION_ENABLE, "ion.enable") \ Register(ION_INTERRUPT_WITHOUT_SIGNAL, "ion.interrupt-without-signals") \ - Register(ION_CHECK_RANGE_ANALYSIS, "ion.check-range-analysis") \ - Register(BASELINE_ENABLE, "baseline.enable") \ - Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable") \ - Register(JUMP_THRESHOLD, "jump-threshold") \ - Register(ASMJS_ATOMICS_ENABLE, "asmjs.atomics.enable") \ - Register(WASM_TEST_MODE, "wasm.test-mode") \ + Register(ION_CHECK_RANGE_ANALYSIS, "ion.check-range-analysis") \ + Register(BASELINE_ENABLE, "baseline.enable") \ + Register(OFFTHREAD_COMPILATION_ENABLE, "offthread-compilation.enable") \ + Register(JUMP_THRESHOLD, "jump-threshold") \ + Register(UNBOXED_OBJECTS, "unboxed_objects") \ + Register(ASMJS_ATOMICS_ENABLE, "asmjs.atomics.enable") \ + Register(WASM_TEST_MODE, "wasm.test-mode") \ Register(WASM_FOLD_OFFSETS, "wasm.fold-offsets") typedef enum JSJitCompilerOption { diff --git a/js/xpconnect/src/XPCJSContext.cpp b/js/xpconnect/src/XPCJSContext.cpp index 0243d80e36..bde949a960 100644 --- a/js/xpconnect/src/XPCJSContext.cpp +++ b/js/xpconnect/src/XPCJSContext.cpp @@ -1427,6 +1427,8 @@ ReloadPrefsCallback(const char* pref, void* data) bool extraWarnings = Preferences::GetBool(JS_OPTIONS_DOT_STR "strict"); + bool unboxedObjects = Preferences::GetBool(JS_OPTIONS_DOT_STR "unboxed_objects"); + sSharedMemoryEnabled = Preferences::GetBool(JS_OPTIONS_DOT_STR "shared_memory"); #ifdef DEBUG @@ -1455,6 +1457,8 @@ ReloadPrefsCallback(const char* pref, void* data) useBaselineEager ? 0 : -1); JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_ION_WARMUP_TRIGGER, useIonEager ? 0 : -1); + JS_SetGlobalJitCompilerOption(cx, JSJITCOMPILER_UNBOXED_OBJECTS, + unboxedObjects); } XPCJSContext::~XPCJSContext() diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 9242c5a4a1..00dff10c05 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1264,6 +1264,7 @@ pref("javascript.options.strict", false); #ifdef DEBUG pref("javascript.options.strict.debug", false); #endif +pref("javascript.options.unboxed_objects", false); pref("javascript.options.baselinejit", true); pref("javascript.options.ion", true); pref("javascript.options.asmjs", true); From c6e54b5208ee1eff7d0ff1c03b73b9282bccd25a Mon Sep 17 00:00:00 2001 From: "Nicolas B. Pierron" Date: Thu, 21 Mar 2019 21:28:10 +0100 Subject: [PATCH 05/16] Force expected crashes on unexpected magic values. --- js/public/Value.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/js/public/Value.h b/js/public/Value.h index 01666ed4e1..7c4f833e3d 100644 --- a/js/public/Value.h +++ b/js/public/Value.h @@ -567,8 +567,11 @@ class MOZ_NON_PARAM alignas(8) Value } bool isMagic(JSWhyMagic why) const { - MOZ_ASSERT_IF(isMagic(), data.s.payload.why == why); - return isMagic(); + if (!isMagic()) { + return false; + } + MOZ_RELEASE_ASSERT(data.s.payload.why == why); + return true; } JS::TraceKind traceKind() const { From ca54bbe536947b32fe9f9d55baaa6336c4889b37 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Fri, 22 Mar 2019 12:06:40 +0100 Subject: [PATCH 06/16] Check for dead wrappers in CallerGetterImpl/CallerSetterImpl. This also removes code duplication by making CallerSetterImpl call CallerGetterImpl. --- js/src/jsfun.cpp | 58 ++++++++++-------------------------------------- 1 file changed, 12 insertions(+), 46 deletions(-) diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 863871df93..98311be2f0 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -288,6 +288,12 @@ CallerGetterImpl(JSContext* cx, const CallArgs& args) return true; } + if (JS_IsDeadWrapper(callerObj)) { + JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, + JSMSG_DEAD_OBJECT); + return false; + } + JSFunction* callerFun = &callerObj->as(); MOZ_ASSERT(!callerFun->isBuiltin(), "non-builtin iterator returned a builtin?"); @@ -314,54 +320,14 @@ CallerSetterImpl(JSContext* cx, const CallArgs& args) { MOZ_ASSERT(IsFunction(args.thisv())); - // Beware! This function can be invoked on *any* function! It can't - // assume it'll never be invoked on natives, strict mode functions, bound - // functions, or anything else that ordinarily has immutable .caller - // defined with [[ThrowTypeError]]. - RootedFunction fun(cx, &args.thisv().toObject().as()); - if (!CallerRestrictions(cx, fun)) - return false; + // We just have to return |undefined|, but first we call CallerGetterImpl + // because we need the same strict-mode and security checks. + + if (!CallerGetterImpl(cx, args)) { + return false; + } - // Return |undefined| unless an error must be thrown. args.rval().setUndefined(); - - // We can almost just return |undefined| here -- but if the caller function - // was strict mode code, we still have to throw a TypeError. This requires - // computing the caller, checking that no security boundaries are crossed, - // and throwing a TypeError if the resulting caller is strict. - - NonBuiltinScriptFrameIter iter(cx); - if (!AdvanceToActiveCallLinear(cx, iter, fun)) - return true; - - ++iter; - while (!iter.done() && iter.isEvalFrame()) - ++iter; - - if (iter.done() || !iter.isFunctionFrame()) - return true; - - RootedObject caller(cx, iter.callee(cx)); - if (!cx->compartment()->wrap(cx, &caller)) { - cx->clearPendingException(); - return true; - } - - // If we don't have full access to the caller, or the caller is not strict, - // return undefined. Otherwise throw a TypeError. - JSObject* callerObj = CheckedUnwrap(caller); - if (!callerObj) - return true; - - JSFunction* callerFun = &callerObj->as(); - MOZ_ASSERT(!callerFun->isBuiltin(), "non-builtin iterator returned a builtin?"); - - if (callerFun->strict()) { - JS_ReportErrorFlagsAndNumberASCII(cx, JSREPORT_ERROR, GetErrorMessage, nullptr, - JSMSG_CALLER_IS_STRICT); - return false; - } - return true; } From 8a3be2de8703f49705507f34fbf23223a0f66008 Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Fri, 22 Mar 2019 12:10:37 +0100 Subject: [PATCH 07/16] Check child container count in NotifyRefreshDriverCreated. --- dom/smil/nsSMILAnimationController.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dom/smil/nsSMILAnimationController.cpp b/dom/smil/nsSMILAnimationController.cpp index 0dd616346f..69956203e0 100644 --- a/dom/smil/nsSMILAnimationController.cpp +++ b/dom/smil/nsSMILAnimationController.cpp @@ -233,7 +233,7 @@ void nsSMILAnimationController::NotifyRefreshDriverCreated( nsRefreshDriver* aRefreshDriver) { - if (!mPauseState) { + if (!mPauseState && mChildContainerTable.Count()) { MaybeStartSampling(aRefreshDriver); } } From 90966a20a13d00fdc74bed6489c63ff13ed04f32 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Fri, 22 Mar 2019 12:44:26 +0100 Subject: [PATCH 08/16] Clean up nsOSHelperAppService. About time we stopped looking at Netscape 4.x entries in the registry ;) Also, assume the application association API is present in Windows and use that instead of reading from the registry directly. --- .../exthandler/win/nsOSHelperAppService.cpp | 192 ++++++------------ 1 file changed, 57 insertions(+), 135 deletions(-) diff --git a/uriloader/exthandler/win/nsOSHelperAppService.cpp b/uriloader/exthandler/win/nsOSHelperAppService.cpp index f01f3b49b5..48b6f1795d 100644 --- a/uriloader/exthandler/win/nsOSHelperAppService.cpp +++ b/uriloader/exthandler/win/nsOSHelperAppService.cpp @@ -29,8 +29,6 @@ #define LOG(args) MOZ_LOG(mLog, mozilla::LogLevel::Debug, args) // helper methods: forward declarations... -static nsresult GetExtensionFrom4xRegistryInfo(const nsACString& aMimeType, - nsString& aFileExtension); static nsresult GetExtensionFromWindowsMimeDatabase(const nsACString& aMimeType, nsString& aFileExtension); @@ -77,79 +75,45 @@ static nsresult GetExtensionFromWindowsMimeDatabase(const nsACString& aMimeType, return NS_OK; } -// We have a serious problem!! I have this content type and the windows registry only gives me -// helper apps based on extension. Right now, we really don't have a good place to go for -// trying to figure out the extension for a particular mime type....One short term hack is to look -// this information in 4.x (it's stored in the windows regsitry). -static nsresult GetExtensionFrom4xRegistryInfo(const nsACString& aMimeType, - nsString& aFileExtension) -{ - nsCOMPtr regKey = - do_CreateInstance("@mozilla.org/windows-registry-key;1"); - if (!regKey) - return NS_ERROR_NOT_AVAILABLE; - - nsresult rv = regKey-> - Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, - NS_LITERAL_STRING("Software\\Netscape\\Netscape Navigator\\Suffixes"), - nsIWindowsRegKey::ACCESS_QUERY_VALUE); - if (NS_FAILED(rv)) - return NS_ERROR_NOT_AVAILABLE; - - rv = regKey->ReadStringValue(NS_ConvertASCIItoUTF16(aMimeType), - aFileExtension); - if (NS_FAILED(rv)) - return NS_OK; - - aFileExtension.Insert(char16_t('.'), 0); - - // this may be a comma separated list of extensions...just take the - // first one for now... - - int32_t pos = aFileExtension.FindChar(char16_t(',')); - if (pos > 0) { - // we have a comma separated list of types... - // truncate everything after the first comma (including the comma) - aFileExtension.Truncate(pos); - } - - return NS_OK; -} - nsresult nsOSHelperAppService::OSProtocolHandlerExists(const char * aProtocolScheme, bool * aHandlerExists) { // look up the protocol scheme in the windows registry....if we find a match then we have a handler for it... *aHandlerExists = false; if (aProtocolScheme && *aProtocolScheme) { - // Vista: use new application association interface - if (mAppAssoc) { - wchar_t * pResult = nullptr; - NS_ConvertASCIItoUTF16 scheme(aProtocolScheme); - // We are responsible for freeing returned strings. - HRESULT hr = mAppAssoc->QueryCurrentDefault(scheme.get(), - AT_URLPROTOCOL, AL_EFFECTIVE, - &pResult); - if (SUCCEEDED(hr)) { - CoTaskMemFree(pResult); - *aHandlerExists = true; + NS_ENSURE_TRUE(mAppAssoc, NS_ERROR_NOT_AVAILABLE); + wchar_t * pResult = nullptr; + NS_ConvertASCIItoUTF16 scheme(aProtocolScheme); + // We are responsible for freeing returned strings. + HRESULT hr = mAppAssoc->QueryCurrentDefault(scheme.get(), + AT_URLPROTOCOL, AL_EFFECTIVE, + &pResult); + if (SUCCEEDED(hr)) { + CoTaskMemFree(pResult); + // Check the registry to see if it's a valid handler. + nsCOMPtr regKey = do_CreateInstance("@mozilla.org/windows-registry-key;1"); + if (!regKey) { + return NS_ERROR_NOT_AVAILABLE; } - return NS_OK; - } - HKEY hKey; - LONG err = ::RegOpenKeyExW(HKEY_CLASSES_ROOT, - NS_ConvertASCIItoUTF16(aProtocolScheme).get(), - 0, - KEY_QUERY_VALUE, - &hKey); - if (err == ERROR_SUCCESS) - { - err = ::RegQueryValueExW(hKey, L"URL Protocol", - nullptr, nullptr, nullptr, nullptr); - *aHandlerExists = (err == ERROR_SUCCESS); - // close the key - ::RegCloseKey(hKey); + nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT, + nsDependentString(scheme.get()), + nsIWindowsRegKey::ACCESS_QUERY_VALUE); + if (NS_FAILED(rv)) { + // Open will fail if the registry key path doesn't exist. + return NS_OK; + } + + bool hasValue; + rv = regKey->HasValue(NS_LITERAL_STRING("URL Protocol"), &hasValue); + if (NS_FAILED(rv)) { + return NS_ERROR_FAILURE; + } + if (!hasValue) { + return NS_OK; + } + + *aHandlerExists = true; } } @@ -180,40 +144,21 @@ NS_IMETHODIMP nsOSHelperAppService::GetApplicationDescription(const nsACString& } } - if (mAppAssoc) { - // Vista: use new application association interface - wchar_t * pResult = nullptr; - // We are responsible for freeing returned strings. - HRESULT hr = mAppAssoc->QueryCurrentDefault(buf.get(), - AT_URLPROTOCOL, AL_EFFECTIVE, - &pResult); - if (SUCCEEDED(hr)) { - nsCOMPtr app; - nsAutoString appInfo(pResult); - CoTaskMemFree(pResult); - if (NS_SUCCEEDED(GetDefaultAppInfo(appInfo, _retval, getter_AddRefs(app)))) - return NS_OK; - } - return NS_ERROR_NOT_AVAILABLE; + NS_ENSURE_TRUE(mAppAssoc, NS_ERROR_NOT_AVAILABLE); + wchar_t * pResult = nullptr; + // We are responsible for freeing returned strings. + HRESULT hr = mAppAssoc->QueryCurrentDefault(buf.get(), + AT_URLPROTOCOL, AL_EFFECTIVE, + &pResult); + if (SUCCEEDED(hr)) { + nsCOMPtr app; + nsAutoString appInfo(pResult); + CoTaskMemFree(pResult); + if (NS_SUCCEEDED(GetDefaultAppInfo(appInfo, _retval, getter_AddRefs(app)))) + return NS_OK; } - nsCOMPtr app; - GetDefaultAppInfo(buf, _retval, getter_AddRefs(app)); - - if (!_retval.Equals(buf)) - return NS_OK; - - // Fall back to full path - buf.AppendLiteral("\\shell\\open\\command"); - nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT, - buf, - nsIWindowsRegKey::ACCESS_QUERY_VALUE); - if (NS_FAILED(rv)) - return NS_ERROR_NOT_AVAILABLE; - - rv = regKey->ReadStringValue(EmptyString(), _retval); - - return NS_SUCCEEDED(rv) ? NS_OK : NS_ERROR_NOT_AVAILABLE; + return NS_ERROR_NOT_AVAILABLE; } // GetMIMEInfoFromRegistry: This function obtains the values of some of the nsIMIMEInfo @@ -421,36 +366,18 @@ already_AddRefed nsOSHelperAppService::GetByExtension(const nsAFl bool found; // Retrieve the default application for this extension - if (mAppAssoc) { - // Vista: use the new application association COM interfaces - // for resolving helpers. - nsString assocType(fileExtToUse); - wchar_t * pResult = nullptr; - HRESULT hr = mAppAssoc->QueryCurrentDefault(assocType.get(), - AT_FILEEXTENSION, AL_EFFECTIVE, - &pResult); - if (SUCCEEDED(hr)) { - found = true; - appInfo.Assign(pResult); - CoTaskMemFree(pResult); - } - else { - found = false; - } - } - else - { - nsCOMPtr regKey = - do_CreateInstance("@mozilla.org/windows-registry-key;1"); - if (!regKey) - return nullptr; - nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT, - fileExtToUse, - nsIWindowsRegKey::ACCESS_QUERY_VALUE); - if (NS_SUCCEEDED(rv)) { - found = NS_SUCCEEDED(regKey->ReadStringValue(EmptyString(), - appInfo)); - } + NS_ENSURE_TRUE(mAppAssoc, nullptr); + nsString assocType(fileExtToUse); + wchar_t * pResult = nullptr; + HRESULT hr = mAppAssoc->QueryCurrentDefault(assocType.get(), + AT_FILEEXTENSION, AL_EFFECTIVE, + &pResult); + if (SUCCEEDED(hr)) { + found = true; + appInfo.Assign(pResult); + CoTaskMemFree(pResult); + } else { + found = false; } // Bug 358297 - ignore the default handler, force the user to choose app @@ -496,14 +423,9 @@ already_AddRefed nsOSHelperAppService::GetMIMEInfoFromOS(const nsAC * We'll do extension-based lookup for this type later in this function. */ if (!aMIMEType.LowerCaseEqualsLiteral(APPLICATION_OCTET_STREAM)) { - // (1) try to use the windows mime database to see if there is a mapping to a file extension - // (2) try to see if we have some left over 4.x registry info we can peek at... + // try to use the windows mime database to see if there is a mapping to a file extension GetExtensionFromWindowsMimeDatabase(aMIMEType, fileExtension); LOG(("Windows mime database: extension '%s'\n", fileExtension.get())); - if (fileExtension.IsEmpty()) { - GetExtensionFrom4xRegistryInfo(aMIMEType, fileExtension); - LOG(("4.x Registry: extension '%s'\n", fileExtension.get())); - } } // If we found an extension for the type, do the lookup RefPtr mi; From ac1a607eb0dfab73e8aeeeee981f1cb1c5d1cd83 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Fri, 22 Mar 2019 13:11:18 +0100 Subject: [PATCH 09/16] Extend origin-clean algorithm (DiD). --- dom/canvas/CanvasRenderingContext2D.cpp | 7 +++++++ dom/canvas/CanvasRenderingContext2D.h | 4 +--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index a750c69b07..4849fda57e 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -6329,6 +6329,13 @@ CanvasRenderingContext2D::ShouldForceInactiveLayer(LayerManager* aManager) return !aManager->CanUseCanvasLayerForSize(GetSize()); } +void CanvasRenderingContext2D::SetWriteOnly() { + mWriteOnly = true; + if (mCanvasElement) { + mCanvasElement->SetWriteOnly(); + } +} + NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CanvasPath, AddRef) NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CanvasPath, Release) diff --git a/dom/canvas/CanvasRenderingContext2D.h b/dom/canvas/CanvasRenderingContext2D.h index 46758ec882..d4f295a03f 100644 --- a/dom/canvas/CanvasRenderingContext2D.h +++ b/dom/canvas/CanvasRenderingContext2D.h @@ -1156,9 +1156,7 @@ protected: // For the origin-clean algorithm (mWriteOnly == !origin-clean) // See https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html - void SetWriteOnly() { - mWriteOnly = true; - } + void SetWriteOnly(); bool IsWriteOnly() const { return mWriteOnly; From 4105e6bba47788f49cee4ff6d8fc3b915429658b Mon Sep 17 00:00:00 2001 From: Jon Coppeard Date: Fri, 22 Mar 2019 13:17:31 +0100 Subject: [PATCH 10/16] Reset nursery position when it's disabled. --- js/src/gc/Nursery.cpp | 1 + js/src/gc/Nursery.h | 1 + 2 files changed, 2 insertions(+) diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp index ea4350fb86..93a0eb6a8b 100644 --- a/js/src/gc/Nursery.cpp +++ b/js/src/gc/Nursery.cpp @@ -210,6 +210,7 @@ js::Nursery::disable() return; updateNumChunks(0); currentEnd_ = 0; + position_ = 0; runtime()->gc.storeBuffer.disable(); } diff --git a/js/src/gc/Nursery.h b/js/src/gc/Nursery.h index 0d215d9975..a839a49790 100644 --- a/js/src/gc/Nursery.h +++ b/js/src/gc/Nursery.h @@ -245,6 +245,7 @@ class Nursery // Free space remaining, not counting chunk trailers. MOZ_ALWAYS_INLINE size_t freeSpace() const { + MOZ_ASSERT(isEnabled()); MOZ_ASSERT(currentEnd_ - position_ <= NurseryChunkUsableSize); return (currentEnd_ - position_) + (numChunks() - currentChunk_ - 1) * NurseryChunkUsableSize; From c7295cf476b5485b23cb6053041f6c1828c12e5d Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Fri, 22 Mar 2019 13:28:32 +0100 Subject: [PATCH 11/16] Guard against re-entrancy in nsStringStream. --- xpcom/io/nsStringStream.cpp | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/xpcom/io/nsStringStream.cpp b/xpcom/io/nsStringStream.cpp index b65242c143..60da385cc9 100644 --- a/xpcom/io/nsStringStream.cpp +++ b/xpcom/io/nsStringStream.cpp @@ -22,6 +22,7 @@ #include "nsIClassInfoImpl.h" #include "mozilla/Attributes.h" #include "mozilla/ipc/InputStreamUtils.h" +#include "mozilla/ReentrantMonitor.h" #include "nsIIPCSerializableInputStream.h" using namespace mozilla::ipc; @@ -50,6 +51,7 @@ public: NS_DECL_NSICLONEABLEINPUTSTREAM nsStringInputStream() + : mMon("nsStringInputStream") { Clear(); } @@ -89,6 +91,8 @@ private: nsDependentCSubstring mData; uint32_t mOffset; + + mozilla::ReentrantMonitor mMon; }; // This class needs to support threadsafe refcounting since people often @@ -126,6 +130,8 @@ nsStringInputStream::GetType(uint16_t* aType) NS_IMETHODIMP nsStringInputStream::GetData(nsACString& data) { + ReentrantMonitorAutoEnter lock(mMon); + // The stream doesn't have any data when it is closed. We could fake it // and return an empty string here, but it seems better to keep this return // value consistent with the behavior of the other 'getter' methods. @@ -140,6 +146,8 @@ nsStringInputStream::GetData(nsACString& data) NS_IMETHODIMP nsStringInputStream::SetData(const nsACString& aData) { + ReentrantMonitorAutoEnter lock(mMon); + mData.Assign(aData); mOffset = 0; return NS_OK; @@ -159,6 +167,8 @@ nsStringInputStream::ToString(char** aResult) NS_IMETHODIMP nsStringInputStream::SetData(const char* aData, int32_t aDataLen) { + ReentrantMonitorAutoEnter lock(mMon); + if (NS_WARN_IF(!aData)) { return NS_ERROR_INVALID_ARG; } @@ -170,6 +180,8 @@ nsStringInputStream::SetData(const char* aData, int32_t aDataLen) NS_IMETHODIMP nsStringInputStream::AdoptData(char* aData, int32_t aDataLen) { + ReentrantMonitorAutoEnter lock(mMon); + if (NS_WARN_IF(!aData)) { return NS_ERROR_INVALID_ARG; } @@ -181,6 +193,8 @@ nsStringInputStream::AdoptData(char* aData, int32_t aDataLen) NS_IMETHODIMP nsStringInputStream::ShareData(const char* aData, int32_t aDataLen) { + ReentrantMonitorAutoEnter lock(mMon); + if (NS_WARN_IF(!aData)) { return NS_ERROR_INVALID_ARG; } @@ -197,6 +211,8 @@ nsStringInputStream::ShareData(const char* aData, int32_t aDataLen) NS_IMETHODIMP_(size_t) nsStringInputStream::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) { + ReentrantMonitorAutoEnter lock(mMon); + size_t n = aMallocSizeOf(this); n += mData.SizeOfExcludingThisIfUnshared(aMallocSizeOf); return n; @@ -209,6 +225,8 @@ nsStringInputStream::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) NS_IMETHODIMP nsStringInputStream::Close() { + ReentrantMonitorAutoEnter lock(mMon); + Clear(); return NS_OK; } @@ -216,6 +234,8 @@ nsStringInputStream::Close() NS_IMETHODIMP nsStringInputStream::Available(uint64_t* aLength) { + ReentrantMonitorAutoEnter lock(mMon); + NS_ASSERTION(aLength, "null ptr"); if (Closed()) { @@ -237,6 +257,8 @@ NS_IMETHODIMP nsStringInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount, uint32_t* aResult) { + ReentrantMonitorAutoEnter lock(mMon); + NS_ASSERTION(aResult, "null ptr"); NS_ASSERTION(Length() >= mOffset, "bad stream state"); @@ -280,6 +302,8 @@ nsStringInputStream::IsNonBlocking(bool* aNonBlocking) NS_IMETHODIMP nsStringInputStream::Seek(int32_t aWhence, int64_t aOffset) { + ReentrantMonitorAutoEnter lock(mMon); + if (Closed()) { return NS_BASE_STREAM_CLOSED; } @@ -312,6 +336,8 @@ nsStringInputStream::Seek(int32_t aWhence, int64_t aOffset) NS_IMETHODIMP nsStringInputStream::Tell(int64_t* aOutWhere) { + ReentrantMonitorAutoEnter lock(mMon); + if (Closed()) { return NS_BASE_STREAM_CLOSED; } @@ -323,6 +349,8 @@ nsStringInputStream::Tell(int64_t* aOutWhere) NS_IMETHODIMP nsStringInputStream::SetEOF() { + ReentrantMonitorAutoEnter lock(mMon); + if (Closed()) { return NS_BASE_STREAM_CLOSED; } @@ -339,6 +367,8 @@ void nsStringInputStream::Serialize(InputStreamParams& aParams, FileDescriptorArray& /* aFDs */) { + ReentrantMonitorAutoEnter lock(mMon); + StringInputStreamParams params; params.data() = PromiseFlatCString(mData); aParams = params; @@ -367,6 +397,8 @@ nsStringInputStream::Deserialize(const InputStreamParams& aParams, Maybe nsStringInputStream::ExpectedSerializedLength() { + ReentrantMonitorAutoEnter lock(mMon); + return Some(static_cast(Length())); } @@ -384,6 +416,8 @@ nsStringInputStream::GetCloneable(bool* aCloneableOut) NS_IMETHODIMP nsStringInputStream::Clone(nsIInputStream** aCloneOut) { + ReentrantMonitorAutoEnter lock(mMon); + RefPtr ref = new nsStringInputStream(*this); ref.forget(aCloneOut); return NS_OK; From df7640136e9b192ffe574df0054a820aebfaf333 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Fri, 22 Mar 2019 14:06:07 +0100 Subject: [PATCH 12/16] Revert "Guard against re-entrancy in nsStringStream." This reverts commit 411919cca7a3795d08ec3cd24efa0167683a80fb. --- xpcom/io/nsStringStream.cpp | 34 ---------------------------------- 1 file changed, 34 deletions(-) diff --git a/xpcom/io/nsStringStream.cpp b/xpcom/io/nsStringStream.cpp index 60da385cc9..b65242c143 100644 --- a/xpcom/io/nsStringStream.cpp +++ b/xpcom/io/nsStringStream.cpp @@ -22,7 +22,6 @@ #include "nsIClassInfoImpl.h" #include "mozilla/Attributes.h" #include "mozilla/ipc/InputStreamUtils.h" -#include "mozilla/ReentrantMonitor.h" #include "nsIIPCSerializableInputStream.h" using namespace mozilla::ipc; @@ -51,7 +50,6 @@ public: NS_DECL_NSICLONEABLEINPUTSTREAM nsStringInputStream() - : mMon("nsStringInputStream") { Clear(); } @@ -91,8 +89,6 @@ private: nsDependentCSubstring mData; uint32_t mOffset; - - mozilla::ReentrantMonitor mMon; }; // This class needs to support threadsafe refcounting since people often @@ -130,8 +126,6 @@ nsStringInputStream::GetType(uint16_t* aType) NS_IMETHODIMP nsStringInputStream::GetData(nsACString& data) { - ReentrantMonitorAutoEnter lock(mMon); - // The stream doesn't have any data when it is closed. We could fake it // and return an empty string here, but it seems better to keep this return // value consistent with the behavior of the other 'getter' methods. @@ -146,8 +140,6 @@ nsStringInputStream::GetData(nsACString& data) NS_IMETHODIMP nsStringInputStream::SetData(const nsACString& aData) { - ReentrantMonitorAutoEnter lock(mMon); - mData.Assign(aData); mOffset = 0; return NS_OK; @@ -167,8 +159,6 @@ nsStringInputStream::ToString(char** aResult) NS_IMETHODIMP nsStringInputStream::SetData(const char* aData, int32_t aDataLen) { - ReentrantMonitorAutoEnter lock(mMon); - if (NS_WARN_IF(!aData)) { return NS_ERROR_INVALID_ARG; } @@ -180,8 +170,6 @@ nsStringInputStream::SetData(const char* aData, int32_t aDataLen) NS_IMETHODIMP nsStringInputStream::AdoptData(char* aData, int32_t aDataLen) { - ReentrantMonitorAutoEnter lock(mMon); - if (NS_WARN_IF(!aData)) { return NS_ERROR_INVALID_ARG; } @@ -193,8 +181,6 @@ nsStringInputStream::AdoptData(char* aData, int32_t aDataLen) NS_IMETHODIMP nsStringInputStream::ShareData(const char* aData, int32_t aDataLen) { - ReentrantMonitorAutoEnter lock(mMon); - if (NS_WARN_IF(!aData)) { return NS_ERROR_INVALID_ARG; } @@ -211,8 +197,6 @@ nsStringInputStream::ShareData(const char* aData, int32_t aDataLen) NS_IMETHODIMP_(size_t) nsStringInputStream::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) { - ReentrantMonitorAutoEnter lock(mMon); - size_t n = aMallocSizeOf(this); n += mData.SizeOfExcludingThisIfUnshared(aMallocSizeOf); return n; @@ -225,8 +209,6 @@ nsStringInputStream::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) NS_IMETHODIMP nsStringInputStream::Close() { - ReentrantMonitorAutoEnter lock(mMon); - Clear(); return NS_OK; } @@ -234,8 +216,6 @@ nsStringInputStream::Close() NS_IMETHODIMP nsStringInputStream::Available(uint64_t* aLength) { - ReentrantMonitorAutoEnter lock(mMon); - NS_ASSERTION(aLength, "null ptr"); if (Closed()) { @@ -257,8 +237,6 @@ NS_IMETHODIMP nsStringInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure, uint32_t aCount, uint32_t* aResult) { - ReentrantMonitorAutoEnter lock(mMon); - NS_ASSERTION(aResult, "null ptr"); NS_ASSERTION(Length() >= mOffset, "bad stream state"); @@ -302,8 +280,6 @@ nsStringInputStream::IsNonBlocking(bool* aNonBlocking) NS_IMETHODIMP nsStringInputStream::Seek(int32_t aWhence, int64_t aOffset) { - ReentrantMonitorAutoEnter lock(mMon); - if (Closed()) { return NS_BASE_STREAM_CLOSED; } @@ -336,8 +312,6 @@ nsStringInputStream::Seek(int32_t aWhence, int64_t aOffset) NS_IMETHODIMP nsStringInputStream::Tell(int64_t* aOutWhere) { - ReentrantMonitorAutoEnter lock(mMon); - if (Closed()) { return NS_BASE_STREAM_CLOSED; } @@ -349,8 +323,6 @@ nsStringInputStream::Tell(int64_t* aOutWhere) NS_IMETHODIMP nsStringInputStream::SetEOF() { - ReentrantMonitorAutoEnter lock(mMon); - if (Closed()) { return NS_BASE_STREAM_CLOSED; } @@ -367,8 +339,6 @@ void nsStringInputStream::Serialize(InputStreamParams& aParams, FileDescriptorArray& /* aFDs */) { - ReentrantMonitorAutoEnter lock(mMon); - StringInputStreamParams params; params.data() = PromiseFlatCString(mData); aParams = params; @@ -397,8 +367,6 @@ nsStringInputStream::Deserialize(const InputStreamParams& aParams, Maybe nsStringInputStream::ExpectedSerializedLength() { - ReentrantMonitorAutoEnter lock(mMon); - return Some(static_cast(Length())); } @@ -416,8 +384,6 @@ nsStringInputStream::GetCloneable(bool* aCloneableOut) NS_IMETHODIMP nsStringInputStream::Clone(nsIInputStream** aCloneOut) { - ReentrantMonitorAutoEnter lock(mMon); - RefPtr ref = new nsStringInputStream(*this); ref.forget(aCloneOut); return NS_OK; From ad188bf3c079ac2534cdc6eca6d25669b7c0440b Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Fri, 22 Mar 2019 18:41:22 +0100 Subject: [PATCH 13/16] Close the transaction if PR_Read/PR_Write failed. When PR_Read/PR_White returns -1, we have to use ErrorAccordingToNSPR to get the error code. We need to close the transaction if a real error happens. --- netwerk/protocol/http/TunnelUtils.cpp | 44 ++++++++++++++++++---- netwerk/protocol/http/TunnelUtils.h | 4 +- netwerk/protocol/http/nsHttpConnection.cpp | 15 +++++--- netwerk/protocol/http/nsHttpConnection.h | 3 +- 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/netwerk/protocol/http/TunnelUtils.cpp b/netwerk/protocol/http/TunnelUtils.cpp index 4cc24a07fd..71adef9d78 100644 --- a/netwerk/protocol/http/TunnelUtils.cpp +++ b/netwerk/protocol/http/TunnelUtils.cpp @@ -23,6 +23,7 @@ #include "nsNetCID.h" #include "nsServiceManagerUtils.h" #include "nsComponentManagerUtils.h" +#include "nsSocketTransport2.h" namespace mozilla { namespace net { @@ -130,6 +131,19 @@ TLSFilterTransaction::Close(nsresult aReason) } mTransaction->Close(aReason); mTransaction = nullptr; + + RefPtr baseTrans(do_QueryReferent(mWeakTrans)); + SpdyConnectTransaction *trans = baseTrans + ? baseTrans->QuerySpdyConnectTransaction() + : nullptr; + + LOG(("TLSFilterTransaction::Close %p aReason=%" PRIx32 " trans=%p\n", + this, static_cast(aReason), trans)); + + if (trans) { + trans->Close(aReason); + trans = nullptr; + } } nsresult @@ -190,8 +204,15 @@ TLSFilterTransaction::OnReadSegment(const char *aData, // mTransaction ReadSegments actually obscures this code, so // keep it in a member var for this::ReadSegments to insepct. Similar // to nsHttpConnection::mSocketOutCondition - mReadSegmentBlocked = (PR_GetError() == PR_WOULD_BLOCK_ERROR); - return mReadSegmentBlocked ? NS_BASE_STREAM_WOULD_BLOCK : NS_ERROR_FAILURE; + PRErrorCode code = PR_GetError(); + mReadSegmentBlocked = (code == PR_WOULD_BLOCK_ERROR); + if (mReadSegmentBlocked) { + return NS_BASE_STREAM_WOULD_BLOCK; + } + + nsresult rv = ErrorAccordingToNSPR(code); + Close(rv); + return rv; } aCount -= written; aData += written; @@ -273,10 +294,13 @@ TLSFilterTransaction::OnWriteSegment(char *aData, mFilterReadCode = NS_OK; int32_t bytesRead = PR_Read(mFD, aData, aCount); if (bytesRead == -1) { - if (PR_GetError() == PR_WOULD_BLOCK_ERROR) { + PRErrorCode code = PR_GetError(); + if (code == PR_WOULD_BLOCK_ERROR) { return NS_BASE_STREAM_WOULD_BLOCK; } - return NS_ERROR_FAILURE; + nsresult rv = ErrorAccordingToNSPR(code); + Close(rv); + return rv; } *outCountRead = bytesRead; @@ -675,10 +699,12 @@ TLSFilterTransaction::TakeSubTransactions( } nsresult -TLSFilterTransaction::SetProxiedTransaction(nsAHttpTransaction *aTrans) +TLSFilterTransaction::SetProxiedTransaction(nsAHttpTransaction *aTrans, + nsAHttpTransaction *aSpdyConnectTransaction) { - LOG(("TLSFilterTransaction::SetProxiedTransaction [this=%p] aTrans=%p\n", - this, aTrans)); + LOG(("TLSFilterTransaction::SetProxiedTransaction [this=%p] aTrans=%p, " + "aSpdyConnectTransaction=%p\n", + this, aTrans, aSpdyConnectTransaction)); mTransaction = aTrans; nsCOMPtr callbacks; @@ -688,6 +714,8 @@ TLSFilterTransaction::SetProxiedTransaction(nsAHttpTransaction *aTrans) secCtrl->SetNotificationCallbacks(callbacks); } + mWeakTrans = do_GetWeakReference(aSpdyConnectTransaction); + return NS_OK; } @@ -1075,7 +1103,7 @@ SpdyConnectTransaction::MapStreamToHttpConnection(nsISocketTransport *aTransport if (mForcePlainText) { mTunneledConn->ForcePlainText(); } else { - mTunneledConn->SetupSecondaryTLS(); + mTunneledConn->SetupSecondaryTLS(this); mTunneledConn->SetInSpdyTunnel(true); } diff --git a/netwerk/protocol/http/TunnelUtils.h b/netwerk/protocol/http/TunnelUtils.h index 20cfaf7ee9..7e491a0d78 100644 --- a/netwerk/protocol/http/TunnelUtils.h +++ b/netwerk/protocol/http/TunnelUtils.h @@ -121,7 +121,8 @@ public: nsresult CommitToSegmentSize(uint32_t size, bool forceCommitment) override; nsresult GetTransactionSecurityInfo(nsISupports **) override; nsresult NudgeTunnel(NudgeTunnelCallback *callback); - nsresult SetProxiedTransaction(nsAHttpTransaction *aTrans); + MOZ_MUST_USE nsresult SetProxiedTransaction(nsAHttpTransaction *aTrans, + nsAHttpTransaction *aSpdyConnectTransaction = nullptr); void newIODriver(nsIAsyncInputStream *aSocketIn, nsIAsyncOutputStream *aSocketOut, nsIAsyncInputStream **outSocketIn, @@ -153,6 +154,7 @@ private: private: RefPtr mTransaction; + nsWeakPtr mWeakTrans; // SpdyConnectTransaction * nsCOMPtr mSecInfo; nsCOMPtr mTimer; RefPtr mNudgeCallback; diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp index 8ccba76e2c..71a08e1774 100644 --- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -639,7 +639,9 @@ nsHttpConnection::Activate(nsAHttpTransaction *trans, uint32_t caps, int32_t pri } if (mTLSFilter) { - mTLSFilter->SetProxiedTransaction(trans); + RefPtr baseTrans(do_QueryReferent(mWeakTrans)); + rv = mTLSFilter->SetProxiedTransaction(trans, baseTrans); + NS_ENSURE_SUCCESS(rv, rv); mTransaction = mTLSFilter; } @@ -1979,7 +1981,7 @@ nsHttpConnection::OnSocketReadable() // negotiation are known (which is determined from the write path). // If the server speaks SPDY it is likely the readable data here is // a spdy settings frame and without NPN it would be misinterpreted - // as HTTP/* + // as HTTP LOG(("nsHttpConnection::OnSocketReadable %p return due to inactive " "tunnel setup but incomplete NPN state\n", this)); @@ -2019,12 +2021,14 @@ nsHttpConnection::OnSocketReadable() } void -nsHttpConnection::SetupSecondaryTLS() +nsHttpConnection::SetupSecondaryTLS(nsAHttpTransaction *aSpdyConnectTransaction) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); MOZ_ASSERT(!mTLSFilter); - LOG(("nsHttpConnection %p SetupSecondaryTLS %s %d\n", - this, mConnInfo->Origin(), mConnInfo->OriginPort())); + LOG(("nsHttpConnection %p SetupSecondaryTLS %s %d " + "aSpdyConnectTransaction=%p\n", + this, mConnInfo->Origin(), mConnInfo->OriginPort(), + aSpdyConnectTransaction)); nsHttpConnectionInfo *ci = nullptr; if (mTransaction) { @@ -2041,6 +2045,7 @@ nsHttpConnection::SetupSecondaryTLS() if (mTransaction) { mTransaction = mTLSFilter; } + mWeakTrans = do_GetWeakReference(aSpdyConnectTransaction); } void diff --git a/netwerk/protocol/http/nsHttpConnection.h b/netwerk/protocol/http/nsHttpConnection.h index 08eea1de28..ce7523eb53 100644 --- a/netwerk/protocol/http/nsHttpConnection.h +++ b/netwerk/protocol/http/nsHttpConnection.h @@ -202,7 +202,7 @@ public: static nsresult MakeConnectString(nsAHttpTransaction *trans, nsHttpRequestHead *request, nsACString &result); - void SetupSecondaryTLS(); + void SetupSecondaryTLS(nsAHttpTransaction *aSpdyConnectTransaction = nullptr); void SetInSpdyTunnel(bool arg); // Check active connections for traffic (or not). SPDY connections send a @@ -281,6 +281,7 @@ private: // transaction is open, otherwise it is null. RefPtr mTransaction; RefPtr mTLSFilter; + nsWeakPtr mWeakTrans; // SpdyConnectTransaction * RefPtr mHttpHandler; // keep gHttpHandler alive From d93b231bab6a5124d2829a1ab540f9c8f2698a54 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Fri, 22 Mar 2019 19:21:52 +0100 Subject: [PATCH 14/16] Add SSUAO for polyfill.io Financial Times' polyfill.io service horribly breaks when it finds anything but a short list of predefined UA strings. We have to send them a strict Firefox UA or other sites relying on it will break too (including PayPal!). An issue has been raised on their repo. --- application/palemoon/branding/shared/pref/uaoverrides.inc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/application/palemoon/branding/shared/pref/uaoverrides.inc b/application/palemoon/branding/shared/pref/uaoverrides.inc index ad4c3f0195..98367e2bb5 100644 --- a/application/palemoon/branding/shared/pref/uaoverrides.inc +++ b/application/palemoon/branding/shared/pref/uaoverrides.inc @@ -57,6 +57,9 @@ pref("@GUAO_PREF@.www.amazon.com","Mozilla/5.0 (@OS_SLICE@ rv:45.9) @GK_SLICE@ F pref("@GUAO_PREF@.soundcloud.com","Mozilla/5.0 (@OS_SLICE@ rv:@GRE_VERSION@) @GRE_DATE_SLICE@ @PM_SLICE@"); // Daily motion only likes strict Firefox UAs pref("@GUAO_PREF@.dailymotion.com","Mozilla/5.0 (@OS_SLICE@ rv:52.0) @GK_SLICE@ Firefox/52.0"); +// Financial Times' polyfill.io breaks horribly on a Pale Moon UA. Send a strict Firefox UA instead. +pref("@GUAO_PREF@.polyfill.io","Mozilla/5.0 (@OS_SLICE@ rv:60.9) @GK_SLICE@ Firefox/60.9"); + // The following requires native mode. Or it blocks.. "too old firefox", breakage, etc. pref("@GUAO_PREF@.deviantart.com","Mozilla/5.0 (@OS_SLICE@ rv:@GRE_VERSION@) @GRE_DATE_SLICE@ @PM_SLICE@"); From 0363b2d35896cc447b5c777b3d0083bd0b2da161 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Fri, 22 Mar 2019 20:11:09 +0100 Subject: [PATCH 15/16] Return proper error if the nss layer encounters an error on the http tunnel. --- netwerk/protocol/http/TunnelUtils.cpp | 43 ++++++++++++---------- netwerk/protocol/http/TunnelUtils.h | 7 ++-- netwerk/protocol/http/nsHttpConnection.cpp | 6 +-- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/netwerk/protocol/http/TunnelUtils.cpp b/netwerk/protocol/http/TunnelUtils.cpp index 71adef9d78..6880e01872 100644 --- a/netwerk/protocol/http/TunnelUtils.cpp +++ b/netwerk/protocol/http/TunnelUtils.cpp @@ -43,6 +43,7 @@ TLSFilterTransaction::TLSFilterTransaction(nsAHttpTransaction *aWrapped, , mSegmentReader(aReader) , mSegmentWriter(aWriter) , mForce(false) + , mReadSegmentReturnValue(NS_OK) , mNudgeCounter(0) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); @@ -154,7 +155,7 @@ TLSFilterTransaction::OnReadSegment(const char *aData, LOG(("TLSFilterTransaction %p OnReadSegment %d (buffered %d)\n", this, aCount, mEncryptedTextUsed)); - mReadSegmentBlocked = false; + mReadSegmentReturnValue = NS_OK; MOZ_ASSERT(mSegmentReader); if (!mSecInfo) { return NS_ERROR_FAILURE; @@ -202,17 +203,12 @@ TLSFilterTransaction::OnReadSegment(const char *aData, return NS_OK; } // mTransaction ReadSegments actually obscures this code, so - // keep it in a member var for this::ReadSegments to insepct. Similar + // keep it in a member var for this::ReadSegments to inspect. Similar // to nsHttpConnection::mSocketOutCondition PRErrorCode code = PR_GetError(); - mReadSegmentBlocked = (code == PR_WOULD_BLOCK_ERROR); - if (mReadSegmentBlocked) { - return NS_BASE_STREAM_WOULD_BLOCK; - } + mReadSegmentReturnValue = ErrorAccordingToNSPR(code); - nsresult rv = ErrorAccordingToNSPR(code); - Close(rv); - return rv; + return mReadSegmentReturnValue; } aCount -= written; aData += written; @@ -298,9 +294,14 @@ TLSFilterTransaction::OnWriteSegment(char *aData, if (code == PR_WOULD_BLOCK_ERROR) { return NS_BASE_STREAM_WOULD_BLOCK; } - nsresult rv = ErrorAccordingToNSPR(code); - Close(rv); - return rv; + // If reading from the socket succeeded (NS_SUCCEEDED(mFilterReadCode)), + // but the nss layer encountered an error remember the error. + if (NS_SUCCEEDED(mFilterReadCode)) { + mFilterReadCode = ErrorAccordingToNSPR(code); + LOG(("TLSFilterTransaction::OnWriteSegment %p nss error %" PRIx32 ".\n", + this, static_cast(mFilterReadCode))); + } + return mFilterReadCode; } *outCountRead = bytesRead; @@ -327,7 +328,7 @@ TLSFilterTransaction::FilterInput(char *aBuf, int32_t aAmount) if (NS_SUCCEEDED(mFilterReadCode) && outCountRead) { LOG(("TLSFilterTransaction::FilterInput rv=%x read=%d input from net " "1 layer stripped, 1 still on\n", mFilterReadCode, outCountRead)); - if (mReadSegmentBlocked) { + if (mReadSegmentReturnValue == NS_BASE_STREAM_WOULD_BLOCK) { mNudgeCounter = 0; } } @@ -349,19 +350,18 @@ TLSFilterTransaction::ReadSegments(nsAHttpSegmentReader *aReader, return NS_ERROR_UNEXPECTED; } - mReadSegmentBlocked = false; + mReadSegmentReturnValue = NS_OK; mSegmentReader = aReader; nsresult rv = mTransaction->ReadSegments(this, aCount, outCountRead); LOG(("TLSFilterTransaction %p called trans->ReadSegments rv=%x %d\n", this, rv, *outCountRead)); - if (NS_SUCCEEDED(rv) && mReadSegmentBlocked) { - rv = NS_BASE_STREAM_WOULD_BLOCK; + if (NS_SUCCEEDED(rv) && (mReadSegmentReturnValue == NS_BASE_STREAM_WOULD_BLOCK)) { LOG(("TLSFilterTransaction %p read segment blocked found rv=%x\n", - this, rv)); + this, static_cast(rv))); Connection()->ForceSend(); } - return rv; + return NS_SUCCEEDED(rv) ? mReadSegmentReturnValue : rv; } nsresult @@ -466,7 +466,10 @@ TLSFilterTransaction::Notify(nsITimer *timer) if (timer != mTimer) { return NS_ERROR_UNEXPECTED; } - StartTimerCallback(); + nsresult rv = StartTimerCallback(); + if (NS_FAILED(rv)) { + Close(rv); + } return NS_OK; } @@ -480,7 +483,7 @@ TLSFilterTransaction::StartTimerCallback() // This class can be called re-entrantly, so cleanup m* before ->on() RefPtr cb(mNudgeCallback); mNudgeCallback = nullptr; - cb->OnTunnelNudged(this); + return cb->OnTunnelNudged(this); } return NS_OK; } diff --git a/netwerk/protocol/http/TunnelUtils.h b/netwerk/protocol/http/TunnelUtils.h index 7e491a0d78..4a003082ec 100644 --- a/netwerk/protocol/http/TunnelUtils.h +++ b/netwerk/protocol/http/TunnelUtils.h @@ -93,10 +93,11 @@ class TLSFilterTransaction; class NudgeTunnelCallback : public nsISupports { public: - virtual void OnTunnelNudged(TLSFilterTransaction *) = 0; + virtual nsresult OnTunnelNudged(TLSFilterTransaction *) = 0; }; -#define NS_DECL_NUDGETUNNELCALLBACK void OnTunnelNudged(TLSFilterTransaction *) override; +#define NS_DECL_NUDGETUNNELCALLBACK \ + nsresult OnTunnelNudged(TLSFilterTransaction *) override; class TLSFilterTransaction final : public nsAHttpTransaction @@ -170,7 +171,7 @@ private: nsresult mFilterReadCode; bool mForce; - bool mReadSegmentBlocked; + nsresult mReadSegmentReturnValue; uint32_t mNudgeCounter; }; diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp index 71a08e1774..505d849c0b 100644 --- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -535,16 +535,16 @@ npnComplete: return true; } -void +nsresult nsHttpConnection::OnTunnelNudged(TLSFilterTransaction *trans) { MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); LOG(("nsHttpConnection::OnTunnelNudged %p\n", this)); if (trans != mTLSFilter) { - return; + return NS_OK; } LOG(("nsHttpConnection::OnTunnelNudged %p Calling OnSocketWritable\n", this)); - OnSocketWritable(); + return OnSocketWritable(); } // called on the socket thread From a4dd5cc08835eddf1dd2e3c8795539ff350a9745 Mon Sep 17 00:00:00 2001 From: wolfbeast Date: Fri, 22 Mar 2019 21:16:09 +0100 Subject: [PATCH 16/16] Use ptrdiff_t in RangedPtr. --- mfbt/RangedPtr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mfbt/RangedPtr.h b/mfbt/RangedPtr.h index a07c1f4f85..a3d4ec1032 100644 --- a/mfbt/RangedPtr.h +++ b/mfbt/RangedPtr.h @@ -212,7 +212,7 @@ public: return *this; } - T& operator[](int aIndex) const + T& operator[](ptrdiff_t aIndex) const { MOZ_ASSERT(size_t(aIndex > 0 ? aIndex : -aIndex) <= size_t(-1) / sizeof(T)); return *create(mPtr + aIndex);