From de24cec63620aaf2a176a27b35aede586cfeb062 Mon Sep 17 00:00:00 2001 From: Roy Tam Date: Sat, 16 Jun 2018 22:56:47 +0800 Subject: [PATCH] cherry-picked mozilla upstream changes: bug1335829, bug1336216, bug1319771, bug1329179, bug1330823, bug1334085, bug1312049, bug1335070, bug1336018 --- application/basilisk/modules/ExtensionsUI.jsm | 7 ++- .../shared/customizableui/panelUI.inc.css | 1 + chrome/nsChromeRegistry.cpp | 10 +++++ chrome/nsIChromeRegistry.idl | 3 +- ...rowser_inspector_breadcrumbs_visibility.js | 4 +- dom/audiochannel/AudioChannelAgent.cpp | 6 +++ dom/audiochannel/AudioChannelService.cpp | 33 +++++++++++++- dom/audiochannel/AudioChannelService.h | 4 ++ dom/base/nsDocument.cpp | 5 +-- dom/base/nsGlobalWindow.cpp | 39 ++++++++++++++++ dom/base/nsPIDOMWindow.h | 3 ++ .../test/test_exception_messages.html | 4 +- dom/url/URL.cpp | 33 +++++--------- dom/url/URL.h | 8 +--- dom/webidl/AddonManager.webidl | 3 ++ dom/webidl/URL.webidl | 11 ++--- dom/xul/XULDocument.cpp | 4 +- gfx/layers/apz/util/APZCCallbackHelper.cpp | 2 +- js/src/jit/JitSpewer.cpp | 6 +-- layout/base/PresShell.cpp | 9 +--- layout/base/PresShell.h | 4 +- layout/base/nsIPresShell.h | 4 +- toolkit/components/extensions/Extension.jsm | 14 ++++++ .../test/mochitest/test_ext_i18n_css.html | 10 +++-- .../content/tests/chrome/test_bug437844.xul | 4 +- .../content/tests/chrome/test_righttoleft.xul | 24 ++++------ toolkit/mozapps/extensions/AddonManager.jsm | 30 +++---------- toolkit/mozapps/extensions/amWebAPI.js | 7 +++ .../mozapps/extensions/content/extensions.js | 45 +++++++++++++++++++ .../extensions/test/browser/browser_webapi.js | 16 +++++++ 30 files changed, 242 insertions(+), 111 deletions(-) diff --git a/application/basilisk/modules/ExtensionsUI.jsm b/application/basilisk/modules/ExtensionsUI.jsm index 9b06787ca..3f241dca7 100644 --- a/application/basilisk/modules/ExtensionsUI.jsm +++ b/application/basilisk/modules/ExtensionsUI.jsm @@ -128,8 +128,11 @@ this.ExtensionsUI = { } let reply = answer => { - Services.obs.notifyObservers(subject, "webextension-permission-response", - JSON.stringify(answer)); + if (answer) { + info.resolve(); + } else { + info.reject(); + } }; let perms = info.addon.userPermissions; diff --git a/application/basilisk/themes/shared/customizableui/panelUI.inc.css b/application/basilisk/themes/shared/customizableui/panelUI.inc.css index 9eb44a65d..f37f0ae40 100644 --- a/application/basilisk/themes/shared/customizableui/panelUI.inc.css +++ b/application/basilisk/themes/shared/customizableui/panelUI.inc.css @@ -616,6 +616,7 @@ toolbarpaletteitem[place="palette"] > toolbaritem > toolbarbutton { #PanelUI-update-status > .toolbarbutton-text, #PanelUI-fxa-label > .toolbarbutton-text, +#PanelUI-footer-addons > toolbarbutton > .toolbarbutton-text, #PanelUI-customize > .toolbarbutton-text { margin: 0; padding: 0 6px; diff --git a/chrome/nsChromeRegistry.cpp b/chrome/nsChromeRegistry.cpp index b34556647..2fa014505 100644 --- a/chrome/nsChromeRegistry.cpp +++ b/chrome/nsChromeRegistry.cpp @@ -653,6 +653,15 @@ nsChromeRegistry::MustLoadURLRemotely(nsIURI *aURI, bool *aResult) bool nsChromeRegistry::GetDirectionForLocale(const nsACString& aLocale) { +#ifdef ENABLE_INTL_API + int pref = mozilla::Preferences::GetInt("intl.uidirection", -1); + if (pref >= 0) { + return (pref > 0); + } + nsAutoCString locale(aLocale); + SanitizeForBCP47(locale); + return uloc_isRightToLeft(locale.get()); +#else // first check the intl.uidirection. preference, and if that is not // set, check the same preference but with just the first two characters of // the locale. If that isn't set, default to left-to-right. @@ -673,6 +682,7 @@ nsChromeRegistry::GetDirectionForLocale(const nsACString& aLocale) } return dir.EqualsLiteral("rtl"); +#endif } NS_IMETHODIMP_(bool) diff --git a/chrome/nsIChromeRegistry.idl b/chrome/nsIChromeRegistry.idl index 8df3a8bdf..8d67c6a50 100644 --- a/chrome/nsIChromeRegistry.idl +++ b/chrome/nsIChromeRegistry.idl @@ -58,7 +58,8 @@ interface nsIXULChromeRegistry : nsIChromeRegistry ACString getSelectedLocale(in ACString packageName, [optional] in boolean asBCP47); - // Get the direction of the locale via the intl.uidirection. pref + // Get whether the default writing direction of the locale is RTL + // (or may be overridden by intl.uidirection pref) boolean isLocaleRTL(in ACString package); /* Should be called when skins change. Reloads only stylesheets. */ diff --git a/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js b/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js index caee745c9..b07f7f8db 100644 --- a/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js +++ b/devtools/client/inspector/test/browser_inspector_breadcrumbs_visibility.js @@ -49,11 +49,11 @@ add_task(function* () { hostWindow.resizeTo(640, 300); info("Testing transitions ltr"); - yield pushPref("intl.uidirection.en-US", "ltr"); + yield pushPref("intl.uidirection", 0); yield testBreadcrumbTransitions(hostWindow, inspector); info("Testing transitions rtl"); - yield pushPref("intl.uidirection.en-US", "rtl"); + yield pushPref("intl.uidirection", 1); yield testBreadcrumbTransitions(hostWindow, inspector); hostWindow.resizeTo(originalWidth, originalHeight); diff --git a/dom/audiochannel/AudioChannelAgent.cpp b/dom/audiochannel/AudioChannelAgent.cpp index 700ecc378..bab1b4085 100644 --- a/dom/audiochannel/AudioChannelAgent.cpp +++ b/dom/audiochannel/AudioChannelAgent.cpp @@ -41,6 +41,9 @@ AudioChannelAgent::AudioChannelAgent() , mInnerWindowID(0) , mIsRegToService(false) { + // Init service in the begining, it can help us to know whether there is any + // created media component via AudioChannelService::IsServiceStarted(). + RefPtr service = AudioChannelService::GetOrCreate(); } AudioChannelAgent::~AudioChannelAgent() @@ -181,6 +184,9 @@ AudioChannelAgent::InitInternal(nsPIDOMWindowInner* aWindow, mCallback = aCallback; } + RefPtr service = AudioChannelService::GetOrCreate(); + service->NotifyCreatedNewAgent(this); + MOZ_LOG(AudioChannelService::GetAudioChannelLog(), LogLevel::Debug, ("AudioChannelAgent, InitInternal, this = %p, type = %d, " "owner = %p, hasCallback = %d\n", this, mAudioChannelType, diff --git a/dom/audiochannel/AudioChannelService.cpp b/dom/audiochannel/AudioChannelService.cpp index 4a79f7988..0d9674510 100644 --- a/dom/audiochannel/AudioChannelService.cpp +++ b/dom/audiochannel/AudioChannelService.cpp @@ -202,6 +202,13 @@ AudioChannelService::CreateServiceIfNeeded() } } +/* static */ bool +AudioChannelService::IsServiceStarted() +{ + // The service would start when the first AudioChannelAgent is created. + return !!gAudioChannelService; +} + /* static */ already_AddRefed AudioChannelService::GetOrCreate() { @@ -300,6 +307,19 @@ AudioChannelService::~AudioChannelService() { } +void +AudioChannelService::NotifyCreatedNewAgent(AudioChannelAgent* aAgent) +{ + MOZ_ASSERT(aAgent); + + nsCOMPtr window = aAgent->Window(); + if (!window) { + return; + } + + window->NotifyCreatedNewMediaComponent(); +} + void AudioChannelService::RegisterAudioChannelAgent(AudioChannelAgent* aAgent, AudibleState aAudible) @@ -1433,7 +1453,18 @@ AudioChannelService::AudioChannelWindow::MaybeNotifyMediaBlocked(AudioChannelAge } MOZ_ASSERT(window->IsOuterWindow()); - if (window->GetMediaSuspend() != nsISuspendedTypes::SUSPENDED_BLOCK) { + nsCOMPtr inner = window->GetCurrentInnerWindow(); + if (!inner) { + return; + } + + nsCOMPtr doc = inner->GetExtantDoc(); + if (!doc) { + return; + } + + if (window->GetMediaSuspend() != nsISuspendedTypes::SUSPENDED_BLOCK || + !doc->Hidden()) { return; } diff --git a/dom/audiochannel/AudioChannelService.h b/dom/audiochannel/AudioChannelService.h index 7034470fd..736a9707f 100644 --- a/dom/audiochannel/AudioChannelService.h +++ b/dom/audiochannel/AudioChannelService.h @@ -106,6 +106,8 @@ public: static bool IsEnableAudioCompeting(); + static bool IsServiceStarted(); + /** * Any audio channel agent that starts playing should register itself to * this service, sharing the AudioChannel. @@ -205,6 +207,8 @@ public: void ChildStatusReceived(uint64_t aChildID, bool aTelephonyChannel, bool aContentOrNormalChannel, bool aAnyChannel); + void NotifyCreatedNewAgent(AudioChannelAgent* aAgent); + private: AudioChannelService(); ~AudioChannelService(); diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 154034a14..c8ed26af9 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -8,6 +8,7 @@ * Base class for all our document implementations. */ +#include "AudioChannelService.h" #include "nsDocument.h" #include "nsIDocumentInlines.h" #include "mozilla/AnimationComparator.h" @@ -12016,9 +12017,7 @@ nsDocument::MaybeActiveMediaComponents() } mEverInForeground = true; - if (GetWindow()->GetMediaSuspend() == nsISuspendedTypes::SUSPENDED_BLOCK) { - GetWindow()->SetMediaSuspend(nsISuspendedTypes::NONE_SUSPENDED); - } + GetWindow()->MaybeActiveMediaComponents(); } NS_IMETHODIMP diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 5eec7e163..8832500ef 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -4189,6 +4189,45 @@ nsPIDOMWindowInner::IsRunningTimeout() return TimeoutManager().IsRunningTimeout(); } +void +nsPIDOMWindowOuter::NotifyCreatedNewMediaComponent() +{ + if (mMediaSuspend != nsISuspendedTypes::SUSPENDED_BLOCK) { + return; + } + + // If the document is already on the foreground but the suspend state is still + // suspend-block, that means the media component was created after calling + // MaybeActiveMediaComponents, so the window's suspend state doesn't be + // changed yet. Therefore, we need to call it again, because the state is only + // changed after there exists alive media within the window. + MaybeActiveMediaComponents(); +} + +void +nsPIDOMWindowOuter::MaybeActiveMediaComponents() +{ + if (IsInnerWindow()) { + return mOuterWindow->MaybeActiveMediaComponents(); + } + + nsCOMPtr inner = GetCurrentInnerWindow(); + if (!inner) { + return; + } + + nsCOMPtr doc = inner->GetExtantDoc(); + if (!doc) { + return; + } + + if (!doc->Hidden() && + mMediaSuspend == nsISuspendedTypes::SUSPENDED_BLOCK && + AudioChannelService::IsServiceStarted()) { + SetMediaSuspend(nsISuspendedTypes::NONE_SUSPENDED); + } +} + SuspendTypes nsPIDOMWindowOuter::GetMediaSuspend() const { diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index 86ed0232d..d2eb1e51f 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -945,6 +945,9 @@ public: float GetAudioVolume() const; nsresult SetAudioVolume(float aVolume); + void NotifyCreatedNewMediaComponent(); + void MaybeActiveMediaComponents(); + void SetServiceWorkersTestingEnabled(bool aEnabled); bool GetServiceWorkersTestingEnabled(); diff --git a/dom/bindings/test/test_exception_messages.html b/dom/bindings/test/test_exception_messages.html index 9d5378f23..50a48d79b 100644 --- a/dom/bindings/test/test_exception_messages.html +++ b/dom/bindings/test/test_exception_messages.html @@ -47,8 +47,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=882653 [ '(new TextDecoder).decode(new Uint8Array(), 5)', "Argument 2 of TextDecoder.decode can't be converted to a dictionary.", "primitive passed for a dictionary" ], - [ 'URL.createObjectURL(null, null)', - "Argument 1 is not valid for any of the 2-argument overloads of URL.createObjectURL.", + [ 'URL.createObjectURL(null)', + "Argument 1 is not valid for any of the 1-argument overloads of URL.createObjectURL.", "overload resolution failure" ], [ 'document.createElement("select").add({})', "Argument 1 of HTMLSelectElement.add could not be converted to any of: HTMLOptionElement, HTMLOptGroupElement.", diff --git a/dom/url/URL.cpp b/dom/url/URL.cpp index 04f5ec137..3717d46b5 100644 --- a/dom/url/URL.cpp +++ b/dom/url/URL.cpp @@ -80,8 +80,7 @@ public: static void CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob, - const objectURLOptions& aOptions, nsAString& aResult, - ErrorResult& aRv) + nsAString& aResult, ErrorResult& aRv) { MOZ_ASSERT(NS_IsMainThread()); CreateObjectURLInternal(aGlobal, aBlob.Impl(), aResult, aRv); @@ -89,8 +88,7 @@ public: static void CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream, - const objectURLOptions& aOptions, nsAString& aResult, - ErrorResult& aRv) + nsAString& aResult, ErrorResult& aRv) { MOZ_ASSERT(NS_IsMainThread()); CreateObjectURLInternal(aGlobal, &aStream, aResult, aRv); @@ -98,8 +96,7 @@ public: static void CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource, - const objectURLOptions& aOptions, nsAString& aResult, - ErrorResult& aRv); + nsAString& aResult, ErrorResult& aRv); static void RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aURL, @@ -257,7 +254,6 @@ URLMainThread::Constructor(nsISupports* aParent, const nsAString& aURL, /* static */ void URLMainThread::CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource, - const objectURLOptions& aOptions, nsAString& aResult, ErrorResult& aRv) { MOZ_ASSERT(NS_IsMainThread()); @@ -654,7 +650,6 @@ public: static void CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob, - const mozilla::dom::objectURLOptions& aOptions, nsAString& aResult, mozilla::ErrorResult& aRv); static void @@ -755,7 +750,6 @@ private: public: CreateURLRunnable(WorkerPrivate* aWorkerPrivate, BlobImpl* aBlobImpl, - const objectURLOptions& aOptions, nsAString& aURL) : WorkerMainThreadRunnable(aWorkerPrivate, NS_LITERAL_CSTRING("URL :: CreateURL")) @@ -1297,7 +1291,6 @@ URLWorker::Constructor(const GlobalObject& aGlobal, const nsAString& aURL, /* static */ void URLWorker::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob, - const mozilla::dom::objectURLOptions& aOptions, nsAString& aResult, mozilla::ErrorResult& aRv) { JSContext* cx = aGlobal.Context(); @@ -1312,7 +1305,7 @@ URLWorker::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob, } RefPtr runnable = - new CreateURLRunnable(workerPrivate, blobImpl, aOptions, aResult); + new CreateURLRunnable(workerPrivate, blobImpl, aResult); runnable->Dispatch(Terminating, aRv); if (NS_WARN_IF(aRv.Failed())) { @@ -1720,33 +1713,29 @@ URL::WorkerConstructor(const GlobalObject& aGlobal, const nsAString& aURL, void URL::CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob, - const objectURLOptions& aOptions, nsAString& aResult, - ErrorResult& aRv) + nsAString& aResult, ErrorResult& aRv) { if (NS_IsMainThread()) { - URLMainThread::CreateObjectURL(aGlobal, aBlob, aOptions, aResult, aRv); + URLMainThread::CreateObjectURL(aGlobal, aBlob, aResult, aRv); } else { - URLWorker::CreateObjectURL(aGlobal, aBlob, aOptions, aResult, aRv); + URLWorker::CreateObjectURL(aGlobal, aBlob, aResult, aRv); } } void URL::CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream, - const objectURLOptions& aOptions, nsAString& aResult, - ErrorResult& aRv) + nsAString& aResult, ErrorResult& aRv) { MOZ_ASSERT(NS_IsMainThread()); - URLMainThread::CreateObjectURL(aGlobal, aStream, aOptions, aResult, aRv); + URLMainThread::CreateObjectURL(aGlobal, aStream, aResult, aRv); } void URL::CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource, - const objectURLOptions& aOptions, - nsAString& aResult, - ErrorResult& aRv) + nsAString& aResult, ErrorResult& aRv) { MOZ_ASSERT(NS_IsMainThread()); - URLMainThread::CreateObjectURL(aGlobal, aSource, aOptions, aResult, aRv); + URLMainThread::CreateObjectURL(aGlobal, aSource, aResult, aRv); } void diff --git a/dom/url/URL.h b/dom/url/URL.h index 45e4dd289..9080bca79 100644 --- a/dom/url/URL.h +++ b/dom/url/URL.h @@ -26,7 +26,6 @@ namespace dom { class Blob; class MediaSource; class GlobalObject; -struct objectURLOptions; class URL : public URLSearchParamsObserver , public nsWrapperCache @@ -64,18 +63,15 @@ public: static void CreateObjectURL(const GlobalObject& aGlobal, Blob& aBlob, - const objectURLOptions& aOptions, nsAString& aResult, ErrorResult& aRv); static void CreateObjectURL(const GlobalObject& aGlobal, DOMMediaStream& aStream, - const objectURLOptions& aOptions, nsAString& aResult, - ErrorResult& aRv); + nsAString& aResult, ErrorResult& aRv); static void CreateObjectURL(const GlobalObject& aGlobal, MediaSource& aSource, - const objectURLOptions& aOptions, nsAString& aResult, - ErrorResult& aRv); + nsAString& aResult, ErrorResult& aRv); static void RevokeObjectURL(const GlobalObject& aGlobal, const nsAString& aURL, diff --git a/dom/webidl/AddonManager.webidl b/dom/webidl/AddonManager.webidl index 02c7953e6..c6f6d1668 100644 --- a/dom/webidl/AddonManager.webidl +++ b/dom/webidl/AddonManager.webidl @@ -77,6 +77,9 @@ interface AddonManager : EventTarget { */ Promise createInstall(optional addonInstallOptions options); + // Indicator to content whether permissions prompts are enabled + readonly attribute boolean permissionPromptsEnabled; + /* Hooks for managing event listeners */ [ChromeOnly] void eventListenerWasAdded(DOMString type); diff --git a/dom/webidl/URL.webidl b/dom/webidl/URL.webidl index 4d491e1b3..bab0864df 100644 --- a/dom/webidl/URL.webidl +++ b/dom/webidl/URL.webidl @@ -54,22 +54,17 @@ interface URL { partial interface URL { [Throws] - static DOMString createObjectURL(Blob blob, optional objectURLOptions options); + static DOMString createObjectURL(Blob blob); [Throws] - static DOMString createObjectURL(MediaStream stream, optional objectURLOptions options); + static DOMString createObjectURL(MediaStream stream); [Throws] static void revokeObjectURL(DOMString url); [ChromeOnly, Throws] static boolean isValidURL(DOMString url); }; -dictionary objectURLOptions -{ -/* boolean autoRevoke = true; */ /* not supported yet */ -}; - // https://dvcs.w3.org/hg/html-media/raw-file/default/media-source/media-source.html partial interface URL { [Throws] - static DOMString? createObjectURL(MediaSource source, optional objectURLOptions options); + static DOMString? createObjectURL(MediaSource source); }; diff --git a/dom/xul/XULDocument.cpp b/dom/xul/XULDocument.cpp index a0f05d7ec..efd8d72db 100644 --- a/dom/xul/XULDocument.cpp +++ b/dom/xul/XULDocument.cpp @@ -226,7 +226,7 @@ XULDocument::~XULDocument() delete mTemplateBuilderTable; Preferences::UnregisterCallback(XULDocument::DirectionChanged, - "intl.uidirection.", this); + "intl.uidirection", this); if (mOffThreadCompileStringBuf) { js_free(mOffThreadCompileStringBuf); @@ -1885,7 +1885,7 @@ XULDocument::Init() } Preferences::RegisterCallback(XULDocument::DirectionChanged, - "intl.uidirection.", this); + "intl.uidirection", this); return NS_OK; } diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 5fef12a6b..5e6fe0e12 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -589,7 +589,7 @@ UpdateRootFrameForTouchTargetDocument(nsIFrame* aRootFrame) // Re-target so that the hit test is performed relative to the frame for the // Root Content Document instead of the Root Document which are different in // Android. See bug 1229752 comment 16 for an explanation of why this is necessary. - if (nsIDocument* doc = aRootFrame->PresContext()->PresShell()->GetTouchEventTargetDocument()) { + if (nsIDocument* doc = aRootFrame->PresContext()->PresShell()->GetPrimaryContentDocument()) { if (nsIPresShell* shell = doc->GetShell()) { if (nsIFrame* frame = shell->GetRootFrame()) { return frame; diff --git a/js/src/jit/JitSpewer.cpp b/js/src/jit/JitSpewer.cpp index 865c78a3c..006744eb1 100644 --- a/js/src/jit/JitSpewer.cpp +++ b/js/src/jit/JitSpewer.cpp @@ -31,11 +31,11 @@ #ifndef JIT_SPEW_DIR # if defined(_WIN32) -# define JIT_SPEW_DIR "" +# define JIT_SPEW_DIR "." # elif defined(__ANDROID__) -# define JIT_SPEW_DIR "/data/local/tmp/" +# define JIT_SPEW_DIR "/data/local/tmp" # else -# define JIT_SPEW_DIR "/tmp/" +# define JIT_SPEW_DIR "/tmp" # endif #endif diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp index 9a61debfb..7173948bf 100644 --- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -198,10 +198,7 @@ #include "mozilla/StyleSheet.h" #include "mozilla/StyleSheetInlines.h" #include "mozilla/dom/ImageTracker.h" - -#ifdef ANDROID #include "nsIDocShellTreeOwner.h" -#endif #ifdef MOZ_TASK_TRACER #include "GoannaTaskTracer.h" @@ -7213,7 +7210,7 @@ PresShell::HandleEvent(nsIFrame* aFrame, } else if ((aEvent->mClass == eTouchEventClass) || (aEvent->mClass == eMouseEventClass) || (aEvent->mClass == eWheelEventClass)) { - retargetEventDoc = GetTouchEventTargetDocument(); + retargetEventDoc = GetPrimaryContentDocument(); #endif } @@ -7774,9 +7771,8 @@ PresShell::HandleEvent(nsIFrame* aFrame, return rv; } -#ifdef ANDROID nsIDocument* -PresShell::GetTouchEventTargetDocument() +PresShell::GetPrimaryContentDocument() { nsPresContext* context = GetPresContext(); if (!context || !context->IsRoot()) { @@ -7804,7 +7800,6 @@ PresShell::GetTouchEventTargetDocument() return childDocShell->GetDocument(); } -#endif #ifdef DEBUG void diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h index 0e7adfeee..80bfb6cc6 100644 --- a/layout/base/PresShell.h +++ b/layout/base/PresShell.h @@ -743,9 +743,7 @@ protected: virtual void SysColorChanged() override { mPresContext->SysColorChanged(); } virtual void ThemeChanged() override { mPresContext->ThemeChanged(); } virtual void BackingScaleFactorChanged() override { mPresContext->UIResolutionChanged(); } -#ifdef ANDROID - virtual nsIDocument* GetTouchEventTargetDocument() override; -#endif + virtual nsIDocument* GetPrimaryContentDocument() override; virtual void PausePainting() override; virtual void ResumePainting() override; diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 1c1e2cd12..3cb7d579f 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -1705,9 +1705,7 @@ public: void SyncWindowProperties(nsView* aView); -#ifdef ANDROID - virtual nsIDocument* GetTouchEventTargetDocument() = 0; -#endif + virtual nsIDocument* GetPrimaryContentDocument() = 0; protected: friend class nsRefreshDriver; diff --git a/toolkit/components/extensions/Extension.jsm b/toolkit/components/extensions/Extension.jsm index 1a8adf738..b2fbee147 100644 --- a/toolkit/components/extensions/Extension.jsm +++ b/toolkit/components/extensions/Extension.jsm @@ -389,6 +389,20 @@ this.ExtensionData = class { return result; } + // Compute the difference between two sets of permissions, suitable + // for presenting to the user. + static comparePermissions(oldPermissions, newPermissions) { + // See bug 1331769: should we do something more complicated to + // compare host permissions? + // e.g., if we go from to a specific host or from + // a *.domain.com to specific-host.domain.com that's actually a + // drop in permissions but the simple test below will cause a prompt. + return { + hosts: newPermissions.hosts.filter(perm => !oldPermissions.hosts.includes(perm)), + permissions: newPermissions.permissions.filter(perm => !oldPermissions.permissions.includes(perm)), + }; + } + // Reads the extension's |manifest.json| file, and stores its // parsed contents in |this.manifest|. readManifest() { diff --git a/toolkit/components/extensions/test/mochitest/test_ext_i18n_css.html b/toolkit/components/extensions/test/mochitest/test_ext_i18n_css.html index 7c6a8eeaa..4e2dbab4d 100644 --- a/toolkit/components/extensions/test/mochitest/test_ext_i18n_css.html +++ b/toolkit/components/extensions/test/mochitest/test_ext_i18n_css.html @@ -94,18 +94,22 @@ add_task(function* test_i18n_css() { is(css, '* { content: "en_US ltr rtl left right" }', "CSS file localized in mochitest scope"); const LOCALE = "general.useragent.locale"; - const DIR = "intl.uidirection.en"; + const DIR = "intl.uidirection"; + const DIR_LEGACY = "intl.uidirection.en"; // Needed for Android until bug 1215247 is resolved // We don't wind up actually switching the chrome registry locale, since we - // don't have a chrome package for Hebrew. So just override it. + // don't have a chrome package for Hebrew. So just override it, and force + // RTL directionality. SpecialPowers.setCharPref(LOCALE, "he"); - SpecialPowers.setCharPref(DIR, "rtl"); + SpecialPowers.setIntPref(DIR, 1); + SpecialPowers.setCharPref(DIR_LEGACY, "rtl"); css = yield fetch(cssURL); is(css, '* { content: "he rtl ltr right left" }', "CSS file localized in mochitest scope"); SpecialPowers.clearUserPref(LOCALE); SpecialPowers.clearUserPref(DIR); + SpecialPowers.clearUserPref(DIR_LEGACY); yield extension.awaitFinish("i18n-css"); yield extension.unload(); diff --git a/toolkit/content/tests/chrome/test_bug437844.xul b/toolkit/content/tests/chrome/test_bug437844.xul index b194b3041..89aab4af4 100644 --- a/toolkit/content/tests/chrome/test_bug437844.xul +++ b/toolkit/content/tests/chrome/test_bug437844.xul @@ -44,7 +44,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=348233 let prefs = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); - prefs.setCharPref("intl.uidirection.en-US", "rtl"); + prefs.setIntPref("intl.uidirection", 1); let rootDir = getRootDirectory(window.location.href); let manifest = rootDir + "rtlchrome/rtl.manifest"; @@ -82,7 +82,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=348233 is(frame.contentDocument.body.dir, "rtl", "file:// listings should be RTL in RTL locales"); cleanupFunc(); - prefs.clearUserPref("intl.uidirection.en-US"); + prefs.clearUserPref("intl.uidirection"); SimpleTest.finish(); }, false); document.documentElement.appendChild(frame); diff --git a/toolkit/content/tests/chrome/test_righttoleft.xul b/toolkit/content/tests/chrome/test_righttoleft.xul index 64b1419da..eaee4364e 100644 --- a/toolkit/content/tests/chrome/test_righttoleft.xul +++ b/toolkit/content/tests/chrome/test_righttoleft.xul @@ -32,8 +32,8 @@ let prefs = Cc["@mozilla.org/preferences-service;1"]. getService(Ci.nsIPrefBranch); - const UI_DIRECTION_PREF = "intl.uidirection.ar"; - prefs.setCharPref(UI_DIRECTION_PREF, "rtl"); + const UI_DIRECTION_PREF = "intl.uidirection"; + prefs.setIntPref(UI_DIRECTION_PREF, -1); let rootDir = getRootDirectory(window.location.href); registerManifestPermanently(rootDir + "rtltest/righttoleft.manifest"); @@ -98,21 +98,15 @@ subdoc.documentElement.removeAttribute("localedir"); - prefs.setCharPref(UI_DIRECTION_PREF, ""); - is(subwin.getComputedStyle(subdoc.documentElement, "").direction, "ltr", - "left to right direction with no preference set"); - prefs.setCharPref(UI_DIRECTION_PREF + "-QA", "rtl"); + prefs.setIntPref(UI_DIRECTION_PREF, -1); is(subwin.getComputedStyle(subdoc.documentElement, "").direction, "rtl", - "right to left direction with more specific preference set"); - prefs.setCharPref(UI_DIRECTION_PREF, "ltr"); - is(subwin.getComputedStyle(subdoc.documentElement, "").direction, "rtl", - "right to left direction with less specific and more specific preference set"); - prefs.setCharPref(UI_DIRECTION_PREF, "rtl"); - prefs.setCharPref(UI_DIRECTION_PREF + "-QA", "ltr"); + "right to left direction with default uidirection preference"); + prefs.setIntPref(UI_DIRECTION_PREF, 0); is(subwin.getComputedStyle(subdoc.documentElement, "").direction, "ltr", - "left to right direction specific preference overrides"); - if (prefs.prefHasUserValue(UI_DIRECTION_PREF + "-QA")) - prefs.clearUserPref(UI_DIRECTION_PREF + "-QA"); + "right to left direction overridden by uidirection preference = 0"); + prefs.setIntPref(UI_DIRECTION_PREF, 1); + is(subwin.getComputedStyle(subdoc.documentElement).direction, "rtl", + "right to left direction overridden by uidirection preference = 1"); if (prefs.prefHasUserValue(UI_DIRECTION_PREF)) prefs.clearUserPref(UI_DIRECTION_PREF); diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm index 94619f86e..5e257377c 100644 --- a/toolkit/mozapps/extensions/AddonManager.jsm +++ b/toolkit/mozapps/extensions/AddonManager.jsm @@ -1360,15 +1360,7 @@ var AddonManagerInternal = { let oldPerms = info.existingAddon.userPermissions || {hosts: [], permissions: []}; let newPerms = info.addon.userPermissions; - // See bug 1331769: should we do something more complicated to - // compare host permissions? - // e.g., if we go from to a specific host or from - // a *.domain.com to specific-host.domain.com that's actually a - // drop in permissions but the simple test below will cause a prompt. - let difference = { - hosts: newPerms.hosts.filter(perm => !oldPerms.hosts.includes(perm)), - permissions: newPerms.permissions.filter(perm => !oldPerms.permissions.includes(perm)), - }; + let difference = Extension.comparePermissions(oldPerms, newPerms); // If there are no new permissions, just go ahead with the update if (difference.hosts.length == 0 && difference.permissions.length == 0) { @@ -2729,24 +2721,12 @@ var AddonManagerInternal = { // "addon-install-confirmation" notification. If the application // does not implement its own prompt, use the built-in xul dialog. if (info.addon.userPermissions && WEBEXT_PERMISSION_PROMPTS) { - const observer = { - observe(subject, topic, data) { - if (topic == "webextension-permission-response" - && subject.wrappedJSObject.info.addon == info.addon) { - let answer = JSON.parse(data); - Services.obs.removeObserver(observer, "webextension-permission-response"); - if (answer) { - resolve(); - } else { - reject(); - } - } + let subject = { + wrappedJSObject: { + target: browser, + info: Object.assign({resolve, reject}, info), } }; - - Services.obs.addObserver(observer, "webextension-permission-response", false); - - let subject = {wrappedJSObject: {target: browser, info}}; Services.obs.notifyObservers(subject, "webextension-permission-prompt", null); } else if (requireConfirm) { // The methods below all want to call the install() or cancel() diff --git a/toolkit/mozapps/extensions/amWebAPI.js b/toolkit/mozapps/extensions/amWebAPI.js index 5ad0d23f1..ab46d270d 100644 --- a/toolkit/mozapps/extensions/amWebAPI.js +++ b/toolkit/mozapps/extensions/amWebAPI.js @@ -10,6 +10,9 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Task.jsm"); +XPCOMUtils.defineLazyPreferenceGetter(this, "WEBEXT_PERMISSION_PROMPTS", + "extensions.webextPermissionPrompts", false); + const MSG_PROMISE_REQUEST = "WebAPIPromiseRequest"; const MSG_PROMISE_RESULT = "WebAPIPromiseResult"; const MSG_INSTALL_EVENT = "WebAPIInstallEvent"; @@ -239,6 +242,10 @@ class WebAPI extends APIObject { }); } + get permissionPromptsEnabled() { + return WEBEXT_PERMISSION_PROMPTS; + } + eventListenerWasAdded(type) { if (this.listenerCount == 0) { this.broker.setAddonListener(data => { diff --git a/toolkit/mozapps/extensions/content/extensions.js b/toolkit/mozapps/extensions/content/extensions.js index 49563ad64..2c1bfb0dd 100644 --- a/toolkit/mozapps/extensions/content/extensions.js +++ b/toolkit/mozapps/extensions/content/extensions.js @@ -21,6 +21,8 @@ Cu.import("resource://gre/modules/AddonManager.jsm"); Cu.import("resource://gre/modules/addons/AddonRepository.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "E10SUtils", "resource:///modules/E10SUtils.jsm"); +XPCOMUtils.defineLazyModuleGetter(this, "Extension", + "resource://gre/modules/Extension.jsm"); XPCOMUtils.defineLazyModuleGetter(this, "ExtensionParent", "resource://gre/modules/ExtensionParent.jsm"); @@ -38,6 +40,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "Preferences", XPCOMUtils.defineLazyModuleGetter(this, "Experiments", "resource:///modules/experiments/Experiments.jsm"); +XPCOMUtils.defineLazyPreferenceGetter(this, "WEBEXT_PERMISSION_PROMPTS", + "extensions.webextPermissionPrompts", false); + const PREF_DISCOVERURL = "extensions.webservice.discoverURL"; const PREF_DISCOVER_ENABLED = "extensions.getAddons.showPane"; const PREF_XPI_ENABLED = "xpinstall.enabled"; @@ -694,6 +699,40 @@ var gEventManager = { } }; +function attachUpdateHandler(install) { + if (!WEBEXT_PERMISSION_PROMPTS) { + return; + } + + install.promptHandler = (info) => { + let oldPerms = info.existingAddon.userPermissions || {hosts: [], permissions: []}; + let newPerms = info.addon.userPermissions; + + let difference = Extension.comparePermissions(oldPerms, newPerms); + + // If there are no new permissions, just proceed + if (difference.hosts.length == 0 && difference.permissions.length == 0) { + return Promise.resolve(); + } + + return new Promise((resolve, reject) => { + let subject = { + wrappedJSObject: { + target: getBrowserElement(), + info: { + type: "update", + addon: info.addon, + icon: info.addon.icon, + permissions: difference, + resolve, + reject, + }, + }, + }; + Services.obs.notifyObservers(subject, "webextension-permission-prompt", null); + }); + }; +} var gViewController = { viewPort: null, @@ -1081,6 +1120,10 @@ var gViewController = { pendingChecks--; updateStatus(); }, + onInstallCancelled() { + pendingChecks--; + updateStatus(); + }, onInstallFailed() { pendingChecks--; updateStatus(); @@ -1098,6 +1141,7 @@ var gViewController = { onUpdateAvailable(aAddon, aInstall) { gEventManager.delegateAddonEvent("onUpdateAvailable", [aAddon, aInstall]); + attachUpdateHandler(aInstall); if (AddonManager.shouldAutoUpdate(aAddon)) { aInstall.addListener(updateInstallListener); aInstall.install(); @@ -1143,6 +1187,7 @@ var gViewController = { onUpdateAvailable(aAddon, aInstall) { gEventManager.delegateAddonEvent("onUpdateAvailable", [aAddon, aInstall]); + attachUpdateHandler(aInstall); if (AddonManager.shouldAutoUpdate(aAddon)) aInstall.install(); }, diff --git a/toolkit/mozapps/extensions/test/browser/browser_webapi.js b/toolkit/mozapps/extensions/test/browser/browser_webapi.js index ca8e41aad..823f1c907 100644 --- a/toolkit/mozapps/extensions/test/browser/browser_webapi.js +++ b/toolkit/mozapps/extensions/test/browser/browser_webapi.js @@ -104,3 +104,19 @@ add_task(testWithAPI(function*(browser) { compareObjects(w2, a2); compareObjects(w3, a3); })); + +add_task(testWithAPI(function*(browser) { + function* check(value, message) { + let enabled = yield ContentTask.spawn(browser, null, function*() { + return content.navigator.mozAddonManager.permissionPromptsEnabled; + }); + is(enabled, value, message); + } + + const PERM = "extensions.webextPermissionPrompts"; + yield SpecialPowers.pushPrefEnv({clear: [[PERM]]}); + yield check(false, `mozAddonManager.permissionPromptsEnabled is false when ${PERM} is unset`); + + yield SpecialPowers.pushPrefEnv({set: [[PERM, true]]}); + yield check(true, `mozAddonManager.permissionPromptsEnabled is true when ${PERM} is set`); +}));