author | Carsten "Tomcat" Book <cbook@mozilla.com> |
Thu, 06 Jul 2017 11:18:05 +0200 | |
changeset 367593 | 018b3829d0a7f6944a5ae1489f3a64c9e2893909 |
parent 367528 | 6cab68456fae75270cb6e014f32ce99c394d6d54 (current diff) |
parent 367592 | 16fb069369c932c5fef1d13020283a1eb0fd0ae2 (diff) |
child 367594 | 4bd7db49d22847111dff9c1dd63ed573903faa5b |
child 367625 | e3d06ac5d1d7a64f213c59b4c93723bee3dddbda |
child 367659 | 530b9cd1f9635702612eb16db37b79338a826bdd |
push id | 32137 |
push user | cbook@mozilla.com |
push date | Thu, 06 Jul 2017 09:18:21 +0000 |
treeherder | mozilla-central@018b3829d0a7 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 56.0a1 |
first release with | nightly win32
018b3829d0a7
/
56.0a1
/
20170706030206
/
files
nightly win64
018b3829d0a7
/
56.0a1
/
20170706030206
/
files
nightly linux32
nightly linux64
nightly mac
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly win32
56.0a1
/
20170706030206
/
pushlog to previous
nightly win64
56.0a1
/
20170706030206
/
pushlog to previous
|
dom/ipc/ContentChild.cpp | file | annotate | diff | comparison | revisions | |
dom/ipc/TabChild.cpp | file | annotate | diff | comparison | revisions | |
dom/plugins/ipc/PluginAsyncSurrogate.cpp | file | annotate | diff | comparison | revisions | |
dom/plugins/ipc/PluginAsyncSurrogate.h | file | annotate | diff | comparison | revisions | |
dom/plugins/ipc/PluginDataResolver.h | file | annotate | diff | comparison | revisions | |
toolkit/components/telemetry/TelemetrySession.jsm | file | annotate | diff | comparison | revisions |
--- a/accessible/generic/Accessible.cpp +++ b/accessible/generic/Accessible.cpp @@ -1409,16 +1409,32 @@ Accessible::SetCurValue(double aValue) return NS_SUCCEEDED( mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::aria_valuenow, strValue, true)); } role Accessible::ARIATransformRole(role aRole) { + // Beginning with ARIA 1.1, user agents are expected to use the native host + // language role of the element when the region role is used without a name. + // https://rawgit.com/w3c/aria/master/core-aam/core-aam.html#role-map-region + // + // XXX: While the name computation algorithm can be non-trivial in the general + // case, it should not be especially bad here: If the author hasn't used the + // region role, this calculation won't occur. And the region role's name + // calculation rule excludes name from content. That said, this use case is + // another example of why we should consider caching the accessible name. See: + // https://bugzilla.mozilla.org/show_bug.cgi?id=1378235. + if (aRole == roles::REGION) { + nsAutoString name; + Name(name); + return name.IsEmpty() ? NativeRole() : aRole; + } + // XXX: these unfortunate exceptions don't fit into the ARIA table. This is // where the accessible role depends on both the role and ARIA state. if (aRole == roles::PUSHBUTTON) { if (nsAccUtils::HasDefinedARIAToken(mContent, nsGkAtoms::aria_pressed)) { // For simplicity, any existing pressed attribute except "" or "undefined" // indicates a toggle. return roles::TOGGLE_BUTTON; }
--- a/accessible/ipc/win/PlatformChild.cpp +++ b/accessible/ipc/win/PlatformChild.cpp @@ -1,18 +1,18 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "mozilla/a11y/Compatibility.h" #include "mozilla/a11y/PlatformChild.h" #include "mozilla/mscom/EnsureMTA.h" #include "mozilla/mscom/InterceptorLog.h" -#include "mozilla/WindowsVersion.h" #include "Accessible2.h" #include "Accessible2_2.h" #include "AccessibleHypertext2.h" #include "AccessibleTableCell.h" #include "AccessibleHypertext2_i.c" @@ -44,30 +44,17 @@ static const mozilla::mscom::ArrayData s // we intend to instantiate them. Therefore RegisterProxy() must be called // via EnsureMTA. PlatformChild::PlatformChild() : mAccTypelib(mozilla::mscom::RegisterTypelib(L"oleacc.dll", mozilla::mscom::RegistrationFlags::eUseSystemDirectory)) , mMiscTypelib(mozilla::mscom::RegisterTypelib(L"Accessible.tlb")) , mSdnTypelib(mozilla::mscom::RegisterTypelib(L"AccessibleMarshal.dll")) { - // The manifest for 32-bit Windows is embedded with resource ID 32. - // The manifest for 64-bit Windows is embedded with resource ID 64. - // Beginning with Windows 10 Creators Update, 32-bit builds use the 64-bit - // manifest. - WORD actCtxResourceId; -#if defined(HAVE_64BIT_BUILD) - actCtxResourceId = 64; -#else - if (IsWin10CreatorsUpdateOrLater()) { - actCtxResourceId = 64; - } else { - actCtxResourceId = 32; - } -#endif + WORD actCtxResourceId = Compatibility::GetActCtxResourceId(); mozilla::mscom::MTADeletePtr<mozilla::mscom::ActivationContextRegion> tmpActCtxMTA; mozilla::mscom::EnsureMTA([actCtxResourceId, &tmpActCtxMTA]() -> void { tmpActCtxMTA.reset(new mozilla::mscom::ActivationContextRegion(actCtxResourceId)); }); mActCtxMTA = Move(tmpActCtxMTA); mozilla::mscom::InterceptorLog::Init();
--- a/accessible/ipc/win/handler/AccessibleHandler.cpp +++ b/accessible/ipc/win/handler/AccessibleHandler.cpp @@ -217,27 +217,22 @@ AccessibleHandler::ReadHandlerPayload(IS if (!deserializer.Read(&mCachedData, &IA2Payload_Decode)) { return E_FAIL; } if (!mCachedData.mGeckoBackChannel) { return S_OK; } - long pid = static_cast<long>(::GetCurrentProcessId()); - - RefPtr<IHandlerControl> ctl; - HRESULT hr = gControlFactory.CreateInstance(nullptr, IID_IHandlerControl, - getter_AddRefs(ctl)); - if (SUCCEEDED(hr)) { - hr = mCachedData.mGeckoBackChannel->put_HandlerControl(pid, ctl); - MOZ_ASSERT(SUCCEEDED(hr)); + RefPtr<AccessibleHandlerControl> ctl(gControlFactory.GetOrCreateSingleton()); + if (!ctl) { + return E_OUTOFMEMORY; } - return hr; + return ctl->Register(WrapNotNull(mCachedData.mGeckoBackChannel)); } REFIID AccessibleHandler::MarshalAs(REFIID aIid) { static_assert(&NEWEST_IA2_IID == &IID_IAccessible2_3, "You have modified NEWEST_IA2_IID. This code needs updating."); if (aIid == IID_IAccessible2_3 || aIid == IID_IAccessible2_2 ||
--- a/accessible/ipc/win/handler/AccessibleHandlerControl.cpp +++ b/accessible/ipc/win/handler/AccessibleHandlerControl.cpp @@ -127,17 +127,18 @@ AccessibleHandlerControl::Create(Accessi } RefPtr<AccessibleHandlerControl> ctl(new AccessibleHandlerControl()); ctl.forget(aOutObject); return S_OK; } AccessibleHandlerControl::AccessibleHandlerControl() - : mCacheGen(0) + : mIsRegistered(false) + , mCacheGen(0) , mIA2Proxy(mscom::RegisterProxy(L"ia2marshal.dll")) , mHandlerProxy(mscom::RegisterProxy()) { MOZ_ASSERT(mIA2Proxy); } IMPL_IUNKNOWN1(AccessibleHandlerControl, IHandlerControl) @@ -184,10 +185,24 @@ AccessibleHandlerControl::GetHandlerType if (!mHandlerProxy) { return E_UNEXPECTED; } return mHandlerProxy->GetTypeInfoForGuid(CLSID_AccessibleHandler, aOutTypeInfo); } +HRESULT +AccessibleHandlerControl::Register(NotNull<IGeckoBackChannel*> aGecko) +{ + if (mIsRegistered) { + return S_OK; + } + + long pid = static_cast<long>(::GetCurrentProcessId()); + HRESULT hr = aGecko->put_HandlerControl(pid, this); + mIsRegistered = SUCCEEDED(hr); + MOZ_ASSERT(mIsRegistered); + return hr; +} + } // namespace a11y } // namespace mozilla
--- a/accessible/ipc/win/handler/AccessibleHandlerControl.h +++ b/accessible/ipc/win/handler/AccessibleHandlerControl.h @@ -66,20 +66,23 @@ public: return mCacheGen; } HRESULT GetNewText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutNewText); HRESULT GetOldText(long aIA2UniqueId, NotNull<IA2TextSegment*> aOutOldText); HRESULT GetHandlerTypeInfo(ITypeInfo** aOutTypeInfo); + HRESULT Register(NotNull<IGeckoBackChannel*> aGecko); + private: AccessibleHandlerControl(); ~AccessibleHandlerControl() = default; + bool mIsRegistered; uint32_t mCacheGen; detail::TextChange mTextChange; UniquePtr<mscom::RegisteredProxy> mIA2Proxy; UniquePtr<mscom::RegisteredProxy> mHandlerProxy; }; extern mscom::SingletonFactory<AccessibleHandlerControl> gControlFactory;
--- a/accessible/mac/mozAccessible.mm +++ b/accessible/mac/mozAccessible.mm @@ -793,17 +793,17 @@ ConvertToNSArray(nsTArray<ProxyAccessibl return @"AXApplicationLog"; if (roleAtom == nsGkAtoms::marquee) return @"AXApplicationMarquee"; if (roleAtom == nsGkAtoms::math) return @"AXDocumentMath"; if (roleAtom == nsGkAtoms::note_) return @"AXDocumentNote"; if (roleAtom == nsGkAtoms::region) - return @"AXLandmarkRegion"; + return mRole == roles::REGION ? @"AXLandmarkRegion" : nil; if (roleAtom == nsGkAtoms::status) return @"AXApplicationStatus"; if (roleAtom == nsGkAtoms::tabpanel) return @"AXTabPanel"; if (roleAtom == nsGkAtoms::timer) return @"AXApplicationTimer"; if (roleAtom == nsGkAtoms::tooltip) return @"AXUserInterfaceTooltip";
--- a/accessible/tests/mochitest/role/test_aria.html +++ b/accessible/tests/mochitest/role/test_aria.html @@ -49,17 +49,21 @@ testRole("aria_menuitem", ROLE_MENUITEM); testRole("aria_menuitemcheckbox", ROLE_CHECK_MENU_ITEM); testRole("aria_menuitemradio", ROLE_RADIO_MENU_ITEM); testRole("aria_note", ROLE_NOTE); testRole("aria_presentation", ROLE_TEXT); // weak role testRole("aria_progressbar", ROLE_PROGRESSBAR); testRole("aria_radio", ROLE_RADIOBUTTON); testRole("aria_radiogroup", ROLE_RADIO_GROUP); - testRole("aria_region", ROLE_REGION); + testRole("aria_region_no_name", ROLE_TEXT); + testRole("aria_region_has_label", ROLE_REGION); + testRole("aria_region_has_labelledby", ROLE_REGION); + testRole("aria_region_has_title", ROLE_REGION); + testRole("aria_region_empty_name", ROLE_TEXT); testRole("aria_row", ROLE_ROW); testRole("aria_rowheader", ROLE_ROWHEADER); testRole("aria_scrollbar", ROLE_SCROLLBAR); testRole("aria_searchbox", ROLE_ENTRY); testRole("aria_separator", ROLE_SEPARATOR); testRole("aria_slider", ROLE_SLIDER); testRole("aria_spinbutton", ROLE_SPINBUTTON); testRole("aria_status", ROLE_STATUSBAR); @@ -233,17 +237,21 @@ <span id="aria_menuitem" role="menuitem"/> <span id="aria_menuitemcheckbox" role="menuitemcheckbox"/> <span id="aria_menuitemradio" role="menuitemradio"/> <span id="aria_note" role="note"/> <span id="aria_presentation" role="presentation" tabindex="0"/> <span id="aria_progressbar" role="progressbar"/> <span id="aria_radio" role="radio"/> <span id="aria_radiogroup" role="radiogroup"/> - <span id="aria_region" role="region"/> + <span id="aria_region_no_name" role="region"/> + <span id="aria_region_has_label" role="region" aria-label="label"/> + <span id="aria_region_has_labelledby" role="region" aria-labelledby="label"/><span id="label" aria-label="label"> + <span id="aria_region_has_title" role="region" title="title"/> + <span id="aria_region_empty_name" role="region" aria-label="" title="" aria-labelledby="empty"/><span id="empty"/> <span id="aria_row" role="row"/> <span id="aria_rowheader" role="rowheader"/> <span id="aria_scrollbar" role="scrollbar"/> <span id="aria_searchbox" role="textbox"/> <span id="aria_separator" role="separator"/> <span id="aria_slider" role="slider"/> <span id="aria_spinbutton" role="spinbutton"/> <span id="aria_status" role="status"/>
--- a/accessible/windows/msaa/Compatibility.cpp +++ b/accessible/windows/msaa/Compatibility.cpp @@ -1,22 +1,27 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "Compatibility.h" +#include "mozilla/WindowsVersion.h" +#include "nsExceptionHandler.h" +#include "nsUnicharUtils.h" #include "nsWindowsDllInterceptor.h" #include "nsWinUtils.h" #include "Statistics.h" #include "mozilla/Preferences.h" +#include <shlobj.h> + using namespace mozilla; using namespace mozilla::a11y; /** * Return true if module version is lesser than the given version. */ bool IsModuleVersionLessThan(HMODULE aModuleHandle, DWORD aMajor, DWORD aMinor) @@ -198,8 +203,183 @@ Compatibility::Init() // SEH handlers. if (!sVectoredExceptionHandler) { sVectoredExceptionHandler = AddVectoredExceptionHandler(TRUE, &DetectInSendMessageExCompat); } } } +#if !defined(HAVE_64BIT_BUILD) + +static bool +ReadCOMRegDefaultString(const nsString& aRegPath, nsAString& aOutBuf) +{ + aOutBuf.Truncate(); + + // Get the required size and type of the registry value. + // We expect either REG_SZ or REG_EXPAND_SZ. + DWORD type; + DWORD bufLen = 0; + LONG result = ::RegGetValue(HKEY_CLASSES_ROOT, aRegPath.get(), + nullptr, RRF_RT_ANY, &type, nullptr, &bufLen); + if (result != ERROR_SUCCESS || (type != REG_SZ && type != REG_EXPAND_SZ)) { + return false; + } + + // Now obtain the value + DWORD flags = type == REG_SZ ? RRF_RT_REG_SZ : RRF_RT_REG_EXPAND_SZ; + + aOutBuf.SetLength((bufLen + 1) / sizeof(char16_t)); + + result = ::RegGetValue(HKEY_CLASSES_ROOT, aRegPath.get(), nullptr, + flags, nullptr, aOutBuf.BeginWriting(), &bufLen); + if (result != ERROR_SUCCESS) { + aOutBuf.Truncate(); + return false; + } + + // Truncate terminator + aOutBuf.Truncate((bufLen + 1) / sizeof(char16_t) - 1); + return true; +} + +static bool +IsSystemOleAcc(nsCOMPtr<nsIFile>& aFile) +{ + // Use FOLDERID_SystemX86 so that Windows doesn't give us a redirected + // system32 if we're a 32-bit process running on a 64-bit OS. This is + // necessary because the values that we are reading from the registry + // are not redirected; they reference SysWOW64 directly. + PWSTR systemPath = nullptr; + HRESULT hr = ::SHGetKnownFolderPath(FOLDERID_SystemX86, 0, nullptr, + &systemPath); + if (FAILED(hr)) { + return false; + } + + nsCOMPtr<nsIFile> oleAcc; + nsresult rv = NS_NewLocalFile(nsDependentString(systemPath), false, + getter_AddRefs(oleAcc)); + + ::CoTaskMemFree(systemPath); + systemPath = nullptr; + + if (NS_FAILED(rv)) { + return false; + } + + rv = oleAcc->Append(NS_LITERAL_STRING("oleacc.dll")); + if (NS_FAILED(rv)) { + return false; + } + + bool isEqual; + rv = oleAcc->Equals(aFile, &isEqual); + return NS_SUCCEEDED(rv) && isEqual; +} + +static bool +IsTypelibPreferred() +{ + // If IAccessible's Proxy/Stub CLSID is kUniversalMarshalerClsid, then any + // external a11y clients are expecting to use a typelib. + NS_NAMED_LITERAL_STRING(kUniversalMarshalerClsid, + "{00020424-0000-0000-C000-000000000046}"); + + NS_NAMED_LITERAL_STRING(kIAccessiblePSClsidPath, + "Interface\\{618736E0-3C3D-11CF-810C-00AA00389B71}\\ProxyStubClsid32"); + + nsAutoString psClsid; + if (!ReadCOMRegDefaultString(kIAccessiblePSClsidPath, psClsid)) { + return false; + } + + return psClsid.Equals(kUniversalMarshalerClsid, + nsCaseInsensitiveStringComparator()); +} + +static bool +IsIAccessibleTypelibRegistered() +{ + // The system default IAccessible typelib is always registered with version + // 1.1, under the neutral locale (LCID 0). + NS_NAMED_LITERAL_STRING(kIAccessibleTypelibRegPath, + "TypeLib\\{1EA4DBF0-3C3B-11CF-810C-00AA00389B71}\\1.1\\0\\win32"); + + nsAutoString typelibPath; + if (!ReadCOMRegDefaultString(kIAccessibleTypelibRegPath, typelibPath)) { + return false; + } + + nsCOMPtr<nsIFile> libTestFile; + nsresult rv = NS_NewLocalFile(typelibPath, false, getter_AddRefs(libTestFile)); + if (NS_FAILED(rv)) { + return false; + } + + return IsSystemOleAcc(libTestFile); +} + +static bool +IsIAccessiblePSRegistered() +{ + NS_NAMED_LITERAL_STRING(kIAccessiblePSRegPath, + "CLSID\\{03022430-ABC4-11D0-BDE2-00AA001A1953}\\InProcServer32"); + + nsAutoString proxyStubPath; + if (!ReadCOMRegDefaultString(kIAccessiblePSRegPath, proxyStubPath)) { + return false; + } + + nsCOMPtr<nsIFile> libTestFile; + nsresult rv = NS_NewLocalFile(proxyStubPath, false, getter_AddRefs(libTestFile)); + if (NS_FAILED(rv)) { + return false; + } + + return IsSystemOleAcc(libTestFile); +} + +static bool +UseIAccessibleProxyStub() +{ + // If a typelib is preferred then external clients are expecting to use + // typelib marshaling, so we should use that whenever available. + if (IsTypelibPreferred() && IsIAccessibleTypelibRegistered()) { + return false; + } + + // Otherwise we try the proxy/stub + if (IsIAccessiblePSRegistered()) { + return true; + } + + // If we reach this point then something is seriously wrong with the + // IAccessible configuration in the computer's registry. Let's annotate this + // so that we can easily determine this condition during crash analysis. + CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("IAccessibleConfig"), + NS_LITERAL_CSTRING("NoSystemTypeLibOrPS")); + return false; +} + +#endif // !defined(HAVE_64BIT_BUILD) + +uint16_t +Compatibility::GetActCtxResourceId() +{ +#if defined(HAVE_64BIT_BUILD) + // The manifest for 64-bit Windows is embedded with resource ID 64. + return 64; +#else + // The manifest for 32-bit Windows is embedded with resource ID 32. + // Beginning with Windows 10 Creators Update, 32-bit builds always use the + // 64-bit manifest. Older builds of Windows may or may not require the 64-bit + // manifest: UseIAccessibleProxyStub() determines the course of action. + if (mozilla::IsWin10CreatorsUpdateOrLater() || + UseIAccessibleProxyStub()) { + return 64; + } + + return 32; +#endif // defined(HAVE_64BIT_BUILD) +} +
--- a/accessible/windows/msaa/Compatibility.h +++ b/accessible/windows/msaa/Compatibility.h @@ -34,16 +34,22 @@ public: */ static bool IsWE() { return !!(sConsumers & WE); } /** * Return true if Dolphin mode is enabled. */ static bool IsDolphin() { return !!(sConsumers & DOLPHIN); } + /** + * @return ID of a11y manifest resource to be passed to + * mscom::ActivationContext + */ + static uint16_t GetActCtxResourceId(); + private: Compatibility(); Compatibility(const Compatibility&); Compatibility& operator = (const Compatibility&); /** * Initialize compatibility mode. Called by platform (see Platform.h) during * accessibility initialization.
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -5117,17 +5117,17 @@ nsBrowserAccess.prototype = { let browser = win.gBrowser.getBrowserForTab(tab); if (needToFocusWin || (!loadInBackground && aIsExternal)) win.focus(); return browser; }, - openURI(aURI, aOpener, aWhere, aFlags) { + openURI(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) { // This function should only ever be called if we're opening a URI // from a non-remote browser window (via nsContentTreeOwner). if (aOpener && Cu.isCrossProcessWrapper(aOpener)) { Cu.reportError("nsBrowserAccess.openURI was passed a CPOW for aOpener. " + "openURI should only ever be called from non-remote browsers."); throw Cr.NS_ERROR_FAILURE; } @@ -5149,21 +5149,19 @@ nsBrowserAccess.prototype = { if (isExternal && gPrefService.prefHasUserValue("browser.link.open_newwindow.override.external")) aWhere = gPrefService.getIntPref("browser.link.open_newwindow.override.external"); else aWhere = gPrefService.getIntPref("browser.link.open_newwindow"); } let referrer = aOpener ? makeURI(aOpener.location.href) : null; - let triggeringPrincipal = null; let referrerPolicy = Ci.nsIHttpChannel.REFERRER_POLICY_UNSET; if (aOpener && aOpener.document) { referrerPolicy = aOpener.document.referrerPolicy; - triggeringPrincipal = aOpener.document.nodePrincipal; } let isPrivate = aOpener ? PrivateBrowsingUtils.isContentWindowPrivate(aOpener) : PrivateBrowsingUtils.isWindowPrivate(window); switch (aWhere) { case Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW : // FIXME: Bug 408379. So how come this doesn't send the @@ -5187,28 +5185,28 @@ nsBrowserAccess.prototype = { let forceNotRemote = !!aOpener; let userContextId = aOpener && aOpener.document ? aOpener.document.nodePrincipal.originAttributes.userContextId : Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID; let openerWindow = (aFlags & Ci.nsIBrowserDOMWindow.OPEN_NO_OPENER) ? null : aOpener; let browser = this._openURIInNewTab(aURI, referrer, referrerPolicy, isPrivate, isExternal, forceNotRemote, userContextId, - openerWindow, triggeringPrincipal); + openerWindow, aTriggeringPrincipal); if (browser) newWindow = browser.contentWindow; break; default : // OPEN_CURRENTWINDOW or an illegal value newWindow = window.content; if (aURI) { let loadflags = isExternal ? Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL : Ci.nsIWebNavigation.LOAD_FLAGS_NONE; gBrowser.loadURIWithFlags(aURI.spec, { - triggeringPrincipal, + aTriggeringPrincipal, flags: loadflags, referrerURI: referrer, referrerPolicy, }); } if (!gPrefService.getBoolPref("browser.tabs.loadDivertedInBackground")) window.focus(); }
--- a/browser/base/content/test/general/browser_bug520538.js +++ b/browser/base/content/test/general/browser_bug520538.js @@ -1,15 +1,16 @@ function test() { var tabCount = gBrowser.tabs.length; gBrowser.selectedBrowser.focus(); window.browserDOMWindow.openURI(makeURI("about:blank"), null, Ci.nsIBrowserDOMWindow.OPEN_NEWTAB, - Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL); + Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL, + Services.scriptSecurityManager.getSystemPrincipal()); is(gBrowser.tabs.length, tabCount + 1, "'--new-tab about:blank' opens a new tab"); is(gBrowser.selectedTab, gBrowser.tabs[tabCount], "'--new-tab about:blank' selects the new tab"); is(document.activeElement, gURLBar.inputField, "'--new-tab about:blank' focuses the location bar"); gBrowser.removeCurrentTab(); }
--- a/browser/base/content/test/general/browser_bug537474.js +++ b/browser/base/content/test/general/browser_bug537474.js @@ -1,7 +1,8 @@ add_task(async function() { let browserLoadedPromise = BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser); window.browserDOMWindow.openURI(makeURI("about:"), null, - Ci.nsIBrowserDOMWindow.OPEN_CURRENTWINDOW, null) + Ci.nsIBrowserDOMWindow.OPEN_CURRENTWINDOW, null, + Services.scriptSecurityManager.getSystemPrincipal()) await browserLoadedPromise; is(gBrowser.currentURI.spec, "about:", "page loads in the current content window"); });
--- a/browser/base/content/test/urlbar/browser_bug562649.js +++ b/browser/base/content/test/urlbar/browser_bug562649.js @@ -1,14 +1,15 @@ function test() { const URI = "data:text/plain,bug562649"; window.browserDOMWindow.openURI(makeURI(URI), null, Ci.nsIBrowserDOMWindow.OPEN_NEWTAB, - Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL); + Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL, + Services.scriptSecurityManager.getSystemPrincipal()); is(gBrowser.userTypedValue, URI, "userTypedValue matches test URI"); is(gURLBar.value, URI, "location bar value matches test URI"); gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser); gBrowser.removeCurrentTab({ skipPermitUnload: true }); is(gBrowser.userTypedValue, URI, "userTypedValue matches test URI after switching tabs"); is(gURLBar.value, URI, "location bar value matches test URI after switching tabs");
--- a/browser/components/nsBrowserContentHandler.js +++ b/browser/components/nsBrowserContentHandler.js @@ -338,17 +338,18 @@ nsBrowserContentHandler.prototype = { } } catch (e) { Components.utils.reportError(e); } try { while ((uriparam = cmdLine.handleFlagWithParam("new-tab", false))) { let uri = resolveURIInternal(cmdLine, uriparam); - handURIToExistingBrowser(uri, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine); + handURIToExistingBrowser(uri, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine, false, + Services.scriptSecurityManager.getSystemPrincipal()); cmdLine.preventDefault = true; } } catch (e) { Components.utils.reportError(e); } var chromeParam = cmdLine.handleFlagWithParam("chrome", false); if (chromeParam) { @@ -386,17 +387,18 @@ nsBrowserContentHandler.prototype = { } if (cmdLine.handleFlag("silent", false)) cmdLine.preventDefault = true; try { var privateWindowParam = cmdLine.handleFlagWithParam("private-window", false); if (privateWindowParam) { let resolvedURI = resolveURIInternal(cmdLine, privateWindowParam); - handURIToExistingBrowser(resolvedURI, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine, true); + handURIToExistingBrowser(resolvedURI, nsIBrowserDOMWindow.OPEN_NEWTAB, cmdLine, true, + Services.scriptSecurityManager.getSystemPrincipal()); cmdLine.preventDefault = true; } } catch (e) { if (e.result != Components.results.NS_ERROR_INVALID_ARG) { throw e; } // NS_ERROR_INVALID_ARG is thrown when flag exists, but has no param. if (cmdLine.handleFlag("private-window", false)) { @@ -602,18 +604,18 @@ nsBrowserContentHandler.prototype = { if (!webNavInfo.isTypeSupported(contentType, null)) { throw NS_ERROR_WONT_HANDLE_CONTENT; } } catch (e) { throw NS_ERROR_WONT_HANDLE_CONTENT; } request.QueryInterface(nsIChannel); - handURIToExistingBrowser(request.URI, - nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, null); + handURIToExistingBrowser(request.URI, nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, null, false, + request.loadInfo.triggeringPrincipal); request.cancel(NS_BINDING_ABORTED); }, /* nsICommandLineValidator */ validate: function bch_validate(cmdLine) { // Other handlers may use osint so only handle the osint flag if the url // flag is also present and the command line is valid. var osintFlagIdx = cmdLine.findFlag("osint", false); @@ -637,17 +639,17 @@ nsBrowserContentHandler.prototype = { throw NS_ERROR_ABORT; } cmdLine.handleFlag("osint", false) } }, }; var gBrowserContentHandler = new nsBrowserContentHandler(); -function handURIToExistingBrowser(uri, location, cmdLine, forcePrivate) { +function handURIToExistingBrowser(uri, location, cmdLine, forcePrivate, triggeringPrincipal) { if (!shouldLoadURI(uri)) return; // Unless using a private window is forced, open external links in private // windows only if we're in perma-private mode. var allowPrivate = forcePrivate || PrivateBrowsingUtils.permanentPrivateBrowsing; var navWin = RecentWindow.getMostRecentBrowserWindow({private: allowPrivate}); if (!navWin) { @@ -662,17 +664,17 @@ function handURIToExistingBrowser(uri, l var navNav = navWin.QueryInterface(nsIInterfaceRequestor) .getInterface(nsIWebNavigation); var rootItem = navNav.QueryInterface(nsIDocShellTreeItem).rootTreeItem; var rootWin = rootItem.QueryInterface(nsIInterfaceRequestor) .getInterface(nsIDOMWindow); var bwin = rootWin.QueryInterface(nsIDOMChromeWindow).browserDOMWindow; bwin.openURI(uri, null, location, - nsIBrowserDOMWindow.OPEN_EXTERNAL); + nsIBrowserDOMWindow.OPEN_EXTERNAL, triggeringPrincipal); } function nsDefaultCommandLineHandler() { } nsDefaultCommandLineHandler.prototype = { classID: Components.ID("{47cd0651-b1be-4a0f-b5c4-10e5a573ef71}"), @@ -737,17 +739,18 @@ nsDefaultCommandLineHandler.prototype = } if (urilist.length) { if (cmdLine.state != nsICommandLine.STATE_INITIAL_LAUNCH && urilist.length == 1) { // Try to find an existing window and load our URI into the // current tab, new tab, or new window as prefs determine. try { - handURIToExistingBrowser(urilist[0], nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, cmdLine); + handURIToExistingBrowser(urilist[0], nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, cmdLine, false, + Services.scriptSecurityManager.getSystemPrincipal()); return; } catch (e) { } } var URLlist = urilist.filter(shouldLoadURI).map(u => u.spec); if (URLlist.length) { openWindow(null, gBrowserContentHandler.chromeURL, "_blank",
--- a/devtools/client/responsive.html/browser/tunnel.js +++ b/devtools/client/responsive.html/browser/tunnel.js @@ -236,23 +236,28 @@ function tunnelToInnerBrowser(outer, inn // * Specific target names (everything treated as _blank) // * Window features // * window.opener // These things are deferred for now, since content which does depend on them seems // outside the main focus of RDM. let { detail } = event; event.preventDefault(); let uri = Services.io.newURI(detail.url); + let sourceNode = event.dataTransfer.mozSourceNode; + let triggeringPrincipal = sourceNode + ? sourceNode.nodePrincipal + : Services.scriptSecurityManager.getSystemPrincipal(); // This API is used mainly because it's near the path used for <a target/> with // regular browser tabs (which calls `openURIInFrame`). The more elaborate APIs // that support openers, window features, etc. didn't seem callable from JS and / or // this event doesn't give enough info to use them. browserWindow.browserDOMWindow .openURI(uri, null, Ci.nsIBrowserDOMWindow.OPEN_NEWTAB, - Ci.nsIBrowserDOMWindow.OPEN_NEW); + Ci.nsIBrowserDOMWindow.OPEN_NEW, + triggeringPrincipal); }, stop() { let tab = gBrowser.getTabForBrowser(outer); let filteredProgressListener = gBrowser._tabFilters.get(tab); // The browser's state has changed over time while the tunnel was active. Push the // the current state down to the inner browser, so that it follows the content in
--- a/dom/base/nsOpenURIInFrameParams.cpp +++ b/dom/base/nsOpenURIInFrameParams.cpp @@ -36,15 +36,30 @@ NS_IMETHODIMP nsOpenURIInFrameParams::GetIsPrivate(bool* aIsPrivate) { NS_ENSURE_ARG_POINTER(aIsPrivate); *aIsPrivate = mOpenerOriginAttributes.mPrivateBrowsingId > 0; return NS_OK; } NS_IMETHODIMP +nsOpenURIInFrameParams::GetTriggeringPrincipal(nsIPrincipal** aTriggeringPrincipal) +{ + NS_ADDREF(*aTriggeringPrincipal = mTriggeringPrincipal); + return NS_OK; +} + +NS_IMETHODIMP +nsOpenURIInFrameParams::SetTriggeringPrincipal(nsIPrincipal* aTriggeringPrincipal) +{ + NS_ENSURE_TRUE(aTriggeringPrincipal, NS_ERROR_INVALID_ARG); + mTriggeringPrincipal = aTriggeringPrincipal; + return NS_OK; +} + +NS_IMETHODIMP nsOpenURIInFrameParams::GetOpenerOriginAttributes(JSContext* aCx, JS::MutableHandle<JS::Value> aValue) { bool ok = ToJSValue(aCx, mOpenerOriginAttributes, aValue); NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE); return NS_OK; }
--- a/dom/base/nsOpenURIInFrameParams.h +++ b/dom/base/nsOpenURIInFrameParams.h @@ -20,9 +20,10 @@ public: explicit nsOpenURIInFrameParams(const mozilla::OriginAttributes& aOriginAttributes); private: ~nsOpenURIInFrameParams(); mozilla::OriginAttributes mOpenerOriginAttributes; nsString mReferrer; + nsCOMPtr<nsIPrincipal> mTriggeringPrincipal; };
--- a/dom/interfaces/base/nsIBrowserDOMWindow.idl +++ b/dom/interfaces/base/nsIBrowserDOMWindow.idl @@ -4,22 +4,24 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsISupports.idl" interface mozIDOMWindowProxy; interface nsIDOMWindow; interface nsIURI; interface nsIFrameLoaderOwner; +interface nsIPrincipal; [scriptable, uuid(e774db14-79ac-4156-a7a3-aa3fd0a22c10)] interface nsIOpenURIInFrameParams : nsISupports { attribute DOMString referrer; readonly attribute boolean isPrivate; + attribute nsIPrincipal triggeringPrincipal; [implicit_jscontext] readonly attribute jsval openerOriginAttributes; }; [scriptable, uuid(9d17f3dd-672b-451e-afd2-b1115df780d5)] /** @@ -92,21 +94,22 @@ interface nsIBrowserDOMWindow : nsISuppo * @param aURI the URI to open. null is allowed. If null is passed in, no * load will be done, though the window the load would have * happened in will be returned. * @param aWhere see possible values described above. * @param aOpener window requesting the open (can be null). * @param aFlags flags which control the behavior of the load. The * OPEN_EXTERNAL/OPEN_NEW flag is only used when * aWhere == OPEN_DEFAULTWINDOW. + * @param aTriggeringPrincipal the principal that triggered the load of aURI * @return the window into which the URI was opened. */ mozIDOMWindowProxy openURI(in nsIURI aURI, in mozIDOMWindowProxy aOpener, - in short aWhere, in long aFlags); + in short aWhere, in long aFlags, in nsIPrincipal aTriggeringPrincipal); /** * As above, but return the nsIFrameLoaderOwner for the new window. * * Additional Parameters: * @param aNextTabParentId The TabParent to associate the window with * @param aName The name to give the window opened in the new tab. * @return The nsIFrameLoaderOwner for the newly opened window.
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -67,16 +67,17 @@ #include "mozilla/widget/ScreenManager.h" #include "mozilla/widget/WidgetMessageUtils.h" #include "nsBaseDragService.h" #include "mozilla/media/MediaChild.h" #include "mozilla/BasePrincipal.h" #include "mozilla/WebBrowserPersistDocumentChild.h" #include "imgLoader.h" #include "GMPServiceChild.h" +#include "NullPrincipal.h" #ifdef MOZ_GECKO_PROFILER #include "ChildProfilerController.h" #endif #if defined(MOZ_CONTENT_SANDBOX) #include "mozilla/SandboxSettings.h" #if defined(XP_WIN) @@ -685,25 +686,29 @@ ContentChild::ProvideWindow(mozIDOMWindo return ProvideWindowCommon(nullptr, aParent, false, aChromeFlags, aCalledFromJS, aPositionSpecified, aSizeSpecified, aURI, aName, aFeatures, aForceNoOpener, aWindowIsNew, aReturn); } static nsresult GetWindowParamsFromParent(mozIDOMWindowProxy* aParent, - nsACString& aBaseURIString, float* aFullZoom) + nsACString& aBaseURIString, float* aFullZoom, + nsIPrincipal** aTriggeringPrincipal) { *aFullZoom = 1.0f; auto* opener = nsPIDOMWindowOuter::From(aParent); if (!opener) { + nsCOMPtr<nsIPrincipal> nullPrincipal = NullPrincipal::Create(); + NS_ADDREF(*aTriggeringPrincipal = nullPrincipal); return NS_OK; } nsCOMPtr<nsIDocument> doc = opener->GetDoc(); + NS_ADDREF(*aTriggeringPrincipal = doc->NodePrincipal()); nsCOMPtr<nsIURI> baseURI = doc->GetDocBaseURI(); if (!baseURI) { NS_ERROR("nsIDocument didn't return a base URI"); return NS_ERROR_FAILURE; } baseURI->GetSpec(aBaseURIString); @@ -773,33 +778,36 @@ ContentChild::ProvideWindowCommon(TabChi } } // If we're in a content process and we have noopener set, there's no reason // to load in our process, so let's load it elsewhere! if (loadInDifferentProcess) { nsAutoCString baseURIString; float fullZoom; - rv = GetWindowParamsFromParent(aParent, baseURIString, &fullZoom); + nsCOMPtr<nsIPrincipal> triggeringPrincipal; + rv = GetWindowParamsFromParent(aParent, baseURIString, &fullZoom, + getter_AddRefs(triggeringPrincipal)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } URIParams uriToLoad; SerializeURI(aURI, uriToLoad); Unused << SendCreateWindowInDifferentProcess(aTabOpener, aChromeFlags, aCalledFromJS, aPositionSpecified, aSizeSpecified, uriToLoad, features, baseURIString, fullZoom, - name); + name, + Principal(triggeringPrincipal)); // We return NS_ERROR_ABORT, so that the caller knows that we've abandoned // the window open as far as it is concerned. return NS_ERROR_ABORT; } if (aTabOpener) { PopupIPCTabContext context; @@ -885,28 +893,31 @@ ContentChild::ProvideWindowCommon(TabChi // NOTE: BrowserFrameOpenWindowPromise is the same type as // CreateWindowPromise, and this code depends on that fact. windowCreated = newChild->SendBrowserFrameOpenWindow(aTabOpener, renderFrame, NS_ConvertUTF8toUTF16(url), name, NS_ConvertUTF8toUTF16(features)); } else { nsAutoCString baseURIString; float fullZoom; - rv = GetWindowParamsFromParent(aParent, baseURIString, &fullZoom); + nsCOMPtr<nsIPrincipal> triggeringPrincipal; + rv = GetWindowParamsFromParent(aParent, baseURIString, &fullZoom, + getter_AddRefs(triggeringPrincipal)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } windowCreated = SendCreateWindow(aTabOpener, newChild, renderFrame, aChromeFlags, aCalledFromJS, aPositionSpecified, aSizeSpecified, features, baseURIString, - fullZoom); + fullZoom, + Principal(triggeringPrincipal)); } // Await the promise being resolved. When the promise is resolved, we'll set // the `ready` local variable, which will cause us to exit our nested event // loop. // // NOTE: We need to run this callback on the StableStateEventTarget because we // need to resolve our runnable and exit from the nested event loop before @@ -2744,39 +2755,16 @@ ContentChild::DeallocPOfflineCacheUpdate { OfflineCacheUpdateChild* offlineCacheUpdate = static_cast<OfflineCacheUpdateChild*>(actor); NS_RELEASE(offlineCacheUpdate); return true; } mozilla::ipc::IPCResult -ContentChild::RecvLoadPluginResult(const uint32_t& aPluginId, - const bool& aResult) -{ - nsresult rv; - Endpoint<PPluginModuleParent> endpoint; - bool finalResult = aResult && - SendConnectPluginBridge(aPluginId, &rv, &endpoint) && - NS_SUCCEEDED(rv); - plugins::PluginModuleContentParent::OnLoadPluginResult(aPluginId, - finalResult, - Move(endpoint)); - return IPC_OK(); -} - -mozilla::ipc::IPCResult -ContentChild::RecvAssociatePluginId(const uint32_t& aPluginId, - const base::ProcessId& aProcessId) -{ - plugins::PluginModuleContentParent::AssociatePluginId(aPluginId, aProcessId); - return IPC_OK(); -} - -mozilla::ipc::IPCResult ContentChild::RecvDomainSetChanged(const uint32_t& aSetType, const uint32_t& aChangeType, const OptionalURIParams& aDomain) { if (aChangeType == ACTIVATE_POLICY) { if (mPolicy) { return IPC_OK(); }
--- a/dom/ipc/ContentChild.h +++ b/dom/ipc/ContentChild.h @@ -433,22 +433,16 @@ public: void AddIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS); void RemoveIdleObserver(nsIObserver* aObserver, uint32_t aIdleTimeInS); virtual mozilla::ipc::IPCResult RecvNotifyIdleObserver(const uint64_t& aObserver, const nsCString& aTopic, const nsString& aData) override; - virtual mozilla::ipc::IPCResult RecvAssociatePluginId(const uint32_t& aPluginId, - const base::ProcessId& aProcessId) override; - - virtual mozilla::ipc::IPCResult RecvLoadPluginResult(const uint32_t& aPluginId, - const bool& aResult) override; - virtual mozilla::ipc::IPCResult RecvUpdateWindow(const uintptr_t& aChildId) override; virtual mozilla::ipc::IPCResult RecvDomainSetChanged(const uint32_t& aSetType, const uint32_t& aChangeType, const OptionalURIParams& aDomain) override; virtual mozilla::ipc::IPCResult RecvShutdown() override;
--- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -1099,18 +1099,17 @@ ContentParent::RecvCreateGMPService() mozilla::ipc::IPCResult ContentParent::RecvLoadPlugin(const uint32_t& aPluginId, nsresult* aRv, uint32_t* aRunID, Endpoint<PPluginModuleParent>* aEndpoint) { *aRv = NS_OK; - if (!mozilla::plugins::SetupBridge(aPluginId, this, false, aRv, aRunID, - aEndpoint)) { + if (!mozilla::plugins::SetupBridge(aPluginId, this, aRv, aRunID, aEndpoint)) { return IPC_FAIL_NO_REASON(this); } return IPC_OK(); } mozilla::ipc::IPCResult ContentParent::RecvUngrabPointer(const uint32_t& aTime) { @@ -1136,17 +1135,17 @@ ContentParent::RecvConnectPluginBridge(c nsresult* aRv, Endpoint<PPluginModuleParent>* aEndpoint) { *aRv = NS_OK; // We don't need to get the run ID for the plugin, since we already got it // in the first call to SetupBridge in RecvLoadPlugin, so we pass in a dummy // pointer and just throw it away. uint32_t dummy = 0; - if (!mozilla::plugins::SetupBridge(aPluginId, this, true, aRv, &dummy, aEndpoint)) { + if (!mozilla::plugins::SetupBridge(aPluginId, this, aRv, &dummy, aEndpoint)) { return IPC_FAIL(this, "SetupBridge failed"); } return IPC_OK(); } mozilla::ipc::IPCResult ContentParent::RecvGetBlocklistState(const uint32_t& aPluginId, uint32_t* aState) @@ -4499,17 +4498,18 @@ ContentParent::CommonCreateWindow(PBrows nsIURI* aURIToLoad, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, uint64_t aNextTabParentId, const nsString& aName, nsresult& aResult, nsCOMPtr<nsITabParent>& aNewTabParent, - bool* aWindowIsNew) + bool* aWindowIsNew, + nsIPrincipal* aTriggeringPrincipal) { // The content process should never be in charge of computing whether or // not a window should be private or remote - the parent will do that. const uint32_t badFlags = nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW | nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW | nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME | nsIWebBrowserChrome::CHROME_REMOTE_WINDOW; @@ -4577,16 +4577,18 @@ ContentParent::CommonCreateWindow(PBrows if (NS_WARN_IF(!browserDOMWin)) { aResult = NS_ERROR_ABORT; return IPC_OK(); } nsCOMPtr<nsIOpenURIInFrameParams> params = new nsOpenURIInFrameParams(openerOriginAttributes); params->SetReferrer(NS_ConvertUTF8toUTF16(aBaseURI)); + MOZ_ASSERT(aTriggeringPrincipal, "need a valid triggeringPrincipal"); + params->SetTriggeringPrincipal(aTriggeringPrincipal); nsCOMPtr<nsIFrameLoaderOwner> frameLoaderOwner; aResult = browserDOMWin->OpenURIInFrame(aURIToLoad, params, openLocation, nsIBrowserDOMWindow::OPEN_NEW, aNextTabParentId, aName, getter_AddRefs(frameLoaderOwner)); if (NS_SUCCEEDED(aResult) && frameLoaderOwner) { RefPtr<nsFrameLoader> frameLoader = frameLoaderOwner->GetFrameLoader(); @@ -4642,16 +4644,17 @@ ContentParent::CommonCreateWindow(PBrows if (NS_WARN_IF(!newBrowserDOMWin)) { aResult = NS_ERROR_ABORT; return IPC_OK(); } nsCOMPtr<mozIDOMWindowProxy> win; aResult = newBrowserDOMWin->OpenURI(aURIToLoad, openerWindow, nsIBrowserDOMWindow::OPEN_CURRENTWINDOW, nsIBrowserDOMWindow::OPEN_NEW, + aTriggeringPrincipal, getter_AddRefs(win)); } return IPC_OK(); } mozilla::ipc::IPCResult ContentParent::RecvCreateWindow(PBrowserParent* aThisTab, @@ -4659,16 +4662,17 @@ ContentParent::RecvCreateWindow(PBrowser PRenderFrameParent* aRenderFrame, const uint32_t& aChromeFlags, const bool& aCalledFromJS, const bool& aPositionSpecified, const bool& aSizeSpecified, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, + const IPC::Principal& aTriggeringPrincipal, CreateWindowResolver&& aResolve) { nsresult rv = NS_OK; CreatedWindowInfo cwi; // We always expect to open a new window here. If we don't, it's an error. cwi.windowOpened() = true; cwi.layersId() = 0; @@ -4703,17 +4707,18 @@ ContentParent::RecvCreateWindow(PBrowser sNextTabParents.Put(nextTabParentId, newTab); nsCOMPtr<nsITabParent> newRemoteTab; mozilla::ipc::IPCResult ipcResult = CommonCreateWindow(aThisTab, /* aSetOpener = */ true, aChromeFlags, aCalledFromJS, aPositionSpecified, aSizeSpecified, nullptr, aFeatures, aBaseURI, aFullZoom, nextTabParentId, NullString(), rv, - newRemoteTab, &cwi.windowOpened()); + newRemoteTab, &cwi.windowOpened(), + aTriggeringPrincipal); if (!ipcResult) { return ipcResult; } if (NS_WARN_IF(NS_FAILED(rv))) { return IPC_OK(); } @@ -4746,28 +4751,29 @@ ContentParent::RecvCreateWindowInDiffere const uint32_t& aChromeFlags, const bool& aCalledFromJS, const bool& aPositionSpecified, const bool& aSizeSpecified, const URIParams& aURIToLoad, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, - const nsString& aName) + const nsString& aName, + const IPC::Principal& aTriggeringPrincipal) { nsCOMPtr<nsITabParent> newRemoteTab; bool windowIsNew; nsCOMPtr<nsIURI> uriToLoad = DeserializeURI(aURIToLoad); nsresult rv; mozilla::ipc::IPCResult ipcResult = CommonCreateWindow(aThisTab, /* aSetOpener = */ false, aChromeFlags, aCalledFromJS, aPositionSpecified, aSizeSpecified, uriToLoad, aFeatures, aBaseURI, aFullZoom, /* aNextTabParentId = */ 0, aName, rv, - newRemoteTab, &windowIsNew); + newRemoteTab, &windowIsNew, aTriggeringPrincipal); if (!ipcResult) { return ipcResult; } if (NS_FAILED(rv)) { NS_WARNING("Call to CommonCreateWindow failed."); }
--- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -531,29 +531,31 @@ public: layout::PRenderFrameParent* aRenderFrame, const uint32_t& aChromeFlags, const bool& aCalledFromJS, const bool& aPositionSpecified, const bool& aSizeSpecified, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, + const IPC::Principal& aTriggeringPrincipal, CreateWindowResolver&& aResolve) override; virtual mozilla::ipc::IPCResult RecvCreateWindowInDifferentProcess( PBrowserParent* aThisTab, const uint32_t& aChromeFlags, const bool& aCalledFromJS, const bool& aPositionSpecified, const bool& aSizeSpecified, const URIParams& aURIToLoad, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, - const nsString& aName) override; + const nsString& aName, + const IPC::Principal& aTriggeringPrincipal) override; static bool AllocateLayerTreeId(TabParent* aTabParent, uint64_t* aId); static void BroadcastBlobURLRegistration(const nsACString& aURI, BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal, ContentParent* aIgnoreThisCP = nullptr); @@ -704,17 +706,18 @@ private: nsIURI* aURIToLoad, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, uint64_t aNextTabParentId, const nsString& aName, nsresult& aResult, nsCOMPtr<nsITabParent>& aNewTabParent, - bool* aWindowIsNew); + bool* aWindowIsNew, + nsIPrincipal* aTriggeringPrincipal); FORWARD_SHMEM_ALLOCATOR_TO(PContentParent) explicit ContentParent(int32_t aPluginID) : ContentParent(nullptr, EmptyString(), aPluginID) {} ContentParent(ContentParent* aOpener, const nsAString& aRemoteType)
--- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -484,29 +484,16 @@ child: async LoadAndRegisterSheet(URIParams uri, uint32_t type); async UnregisterSheet(URIParams uri, uint32_t type); /** * Notify idle observers in the child */ async NotifyIdleObserver(uint64_t observerId, nsCString topic, nsString str); - /** - * Called during plugin initialization to map a plugin id to a child process - * id. - */ - async AssociatePluginId(uint32_t aPluginId, ProcessId aProcessId); - - /** - * This call is used by async plugin initialization to notify the - * PluginModuleContentParent that the PluginModuleChromeParent's async - * init has completed. - */ - async LoadPluginResult(uint32_t aPluginId, bool aResult); - async InvokeDragSession(IPCDataTransfer[] transfers, uint32_t action); async EndDragSession(bool aDoneDrag, bool aUserCancelled, LayoutDeviceIntPoint aDragEndPoint, uint32_t aKeyModifiers); async DomainSetChanged(uint32_t aSetType, uint32_t aChangeType, OptionalURIParams aDomain); @@ -986,30 +973,32 @@ parent: PBrowser aNewTab, PRenderFrame aRenderFrame, uint32_t aChromeFlags, bool aCalledFromJS, bool aPositionSpecified, bool aSizeSpecified, nsCString aFeatures, nsCString aBaseURI, - float aFullZoom) + float aFullZoom, + Principal aTriggeringPrincipal) returns (CreatedWindowInfo window); async CreateWindowInDifferentProcess( PBrowser aThisTab, uint32_t aChromeFlags, bool aCalledFromJS, bool aPositionSpecified, bool aSizeSpecified, URIParams aURIToLoad, nsCString aFeatures, nsCString aBaseURI, float aFullZoom, - nsString aName); + nsString aName, + Principal aTriggeringPrincipal); sync GetAndroidSystemInfo() returns (AndroidSystemInfo info); /** * Tells the parent to ungrab the pointer on the default display. * * This is for GTK platforms where we have to ensure the pointer ungrab happens in the
--- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -3439,17 +3439,17 @@ TabChildSHistoryListener::OnRequestCross if (!tabChild) { return NS_ERROR_FAILURE; } return tabChild->SendRequestCrossBrowserNavigation(aIndex) ? NS_OK : NS_ERROR_FAILURE; } -TabChildGlobal::TabChildGlobal(TabChildBase* aTabChild) +TabChildGlobal::TabChildGlobal(TabChild* aTabChild) : mTabChild(aTabChild) { SetIsNotDOMBinding(); } TabChildGlobal::~TabChildGlobal() { } @@ -3541,8 +3541,37 @@ TabChildGlobal::GetPrincipal() } JSObject* TabChildGlobal::GetGlobalJSObject() { NS_ENSURE_TRUE(mTabChild, nullptr); return mTabChild->GetGlobal(); } + +nsresult +TabChildGlobal::Dispatch(const char* aName, + TaskCategory aCategory, + already_AddRefed<nsIRunnable>&& aRunnable) +{ + if (mTabChild && mTabChild->TabGroup()) { + return mTabChild->TabGroup()->Dispatch(aName, aCategory, Move(aRunnable)); + } + return DispatcherTrait::Dispatch(aName, aCategory, Move(aRunnable)); +} + +nsISerialEventTarget* +TabChildGlobal::EventTargetFor(TaskCategory aCategory) const +{ + if (mTabChild && mTabChild->TabGroup()) { + return mTabChild->TabGroup()->EventTargetFor(aCategory); + } + return DispatcherTrait::EventTargetFor(aCategory); +} + +AbstractThread* +TabChildGlobal::AbstractMainThreadFor(TaskCategory aCategory) +{ + if (mTabChild && mTabChild->TabGroup()) { + return mTabChild->TabGroup()->AbstractMainThreadFor(aCategory); + } + return DispatcherTrait::AbstractMainThreadFor(aCategory); +}
--- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -40,18 +40,20 @@ #include "AudioChannelService.h" #include "PuppetWidget.h" #include "mozilla/layers/GeckoContentController.h" #include "nsISHistoryListener.h" #include "nsIPartialSHistoryListener.h" class nsIDOMWindowUtils; class nsIHttpChannel; +class nsISerialEventTarget; namespace mozilla { +class AbstractThread; namespace layout { class RenderFrameChild; } // namespace layout namespace layers { class APZChild; class APZEventState; class AsyncDragMetrics; @@ -64,26 +66,25 @@ struct AutoCacheNativeKeyCommands; } // namespace widget namespace dom { class TabChild; class TabGroup; class ClonedMessageData; class CoalescedWheelData; -class TabChildBase; class TabChildGlobal : public DOMEventTargetHelper, public nsIContentFrameMessageManager, public nsIScriptObjectPrincipal, public nsIGlobalObject, public nsSupportsWeakReference { public: - explicit TabChildGlobal(TabChildBase* aTabChild); + explicit TabChildGlobal(TabChild* aTabChild); void Init(); NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(TabChildGlobal, DOMEventTargetHelper) NS_FORWARD_SAFE_NSIMESSAGELISTENERMANAGER(mMessageManager) NS_FORWARD_SAFE_NSIMESSAGESENDER(mMessageManager) NS_FORWARD_SAFE_NSIMESSAGEMANAGERGLOBAL(mMessageManager) NS_IMETHOD SendSyncMessage(const nsAString& aMessageName, JS::Handle<JS::Value> aObject, @@ -144,18 +145,29 @@ public: virtual nsIPrincipal* GetPrincipal() override; virtual JSObject* GetGlobalJSObject() override; virtual JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) override { MOZ_CRASH("TabChildGlobal doesn't use DOM bindings!"); } + // Dispatch a runnable related to the global. + virtual nsresult Dispatch(const char* aName, + mozilla::TaskCategory aCategory, + already_AddRefed<nsIRunnable>&& aRunnable) override; + + virtual nsISerialEventTarget* + EventTargetFor(mozilla::TaskCategory aCategory) const override; + + virtual AbstractThread* + AbstractMainThreadFor(mozilla::TaskCategory aCategory) override; + nsCOMPtr<nsIContentFrameMessageManager> mMessageManager; - RefPtr<TabChildBase> mTabChild; + RefPtr<TabChild> mTabChild; protected: ~TabChildGlobal(); }; class ContentListener final : public nsIDOMEventListener { public:
--- a/dom/media/eme/mediadrm/MediaDrmCDMProxy.h +++ b/dom/media/eme/mediadrm/MediaDrmCDMProxy.h @@ -23,17 +23,17 @@ using namespace mozilla::java; namespace mozilla { class MediaDrmCDMCallbackProxy; class MediaDrmCDMProxy : public CDMProxy { public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDrmCDMProxy) + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDrmCDMProxy, override) MediaDrmCDMProxy(dom::MediaKeys* aKeys, const nsAString& aKeySystem, bool aDistinctiveIdentifierRequired, bool aPersistentStateRequired, nsIEventTarget* aMainThread); void Init(PromiseId aPromiseId,
--- a/dom/payments/PaymentRequest.cpp +++ b/dom/payments/PaymentRequest.cpp @@ -585,34 +585,46 @@ PaymentRequest::UpdateShippingAddress(co aPostalCode, aSortingCode, aLanguageCode, aOrganization, aRecipient, aPhone); // Fire shippingaddresschange event return DispatchUpdateEvent(NS_LITERAL_STRING("shippingaddresschange")); } void +PaymentRequest::SetShippingOption(const nsAString& aShippingOption) +{ + mShippingOption = aShippingOption; +} + +void PaymentRequest::GetShippingOption(nsAString& aRetVal) const { aRetVal = mShippingOption; } nsresult PaymentRequest::UpdateShippingOption(const nsAString& aShippingOption) { mShippingOption = aShippingOption; // Fire shippingaddresschange event return DispatchUpdateEvent(NS_LITERAL_STRING("shippingoptionchange")); } +void +PaymentRequest::SetShippingType(const Nullable<PaymentShippingType>& aShippingType) +{ + mShippingType = aShippingType; +} + Nullable<PaymentShippingType> PaymentRequest::GetShippingType() const { - return nullptr; + return mShippingType; } PaymentRequest::~PaymentRequest() { } JSObject* PaymentRequest::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
--- a/dom/payments/PaymentRequest.h +++ b/dom/payments/PaymentRequest.h @@ -101,22 +101,25 @@ public: const nsAString& aDependentLocality, const nsAString& aPostalCode, const nsAString& aSortingCode, const nsAString& aLanguageCode, const nsAString& aOrganization, const nsAString& aRecipient, const nsAString& aPhone); + + void SetShippingOption(const nsAString& aShippingOption); void GetShippingOption(nsAString& aRetVal) const; nsresult UpdateShippingOption(const nsAString& aShippingOption); nsresult UpdatePayment(const PaymentDetailsUpdate& aDetails); void AbortUpdate(nsresult aRv); + void SetShippingType(const Nullable<PaymentShippingType>& aShippingType); Nullable<PaymentShippingType> GetShippingType() const; IMPL_EVENT_HANDLER(shippingaddresschange); IMPL_EVENT_HANDLER(shippingoptionchange); protected: ~PaymentRequest(); @@ -138,16 +141,18 @@ protected: RefPtr<Promise> mAbortPromise; // Resolve mAcceptPromise with mResponse if user accepts the request. RefPtr<PaymentResponse> mResponse; // It is populated when the user provides a shipping address. RefPtr<PaymentAddress> mShippingAddress; // It is populated when the user chooses a shipping option. nsString mShippingOption; + Nullable<PaymentShippingType> mShippingType; + // "true" when there is a pending updateWith() call to update the payment request // and "false" otherwise. bool mUpdating; // The error is set in AbortUpdate(). The value is NS_OK by default. nsresult mUpdateError; enum { eUnknown,
--- a/dom/payments/PaymentRequestManager.cpp +++ b/dom/payments/PaymentRequestManager.cpp @@ -98,26 +98,27 @@ ConvertShippingOption(const PaymentShipp ConvertCurrencyAmount(aOption.mAmount, amount); aIPCOption = IPCPaymentShippingOption(aOption.mId, aOption.mLabel, amount, aOption.mSelected); } nsresult ConvertDetailsBase(const PaymentDetailsBase& aDetails, nsTArray<IPCPaymentItem>& aDisplayItems, nsTArray<IPCPaymentShippingOption>& aShippingOptions, - nsTArray<IPCPaymentDetailsModifier>& aModifiers) + nsTArray<IPCPaymentDetailsModifier>& aModifiers, + bool aResetShippingOptions) { if (aDetails.mDisplayItems.WasPassed()) { for (const PaymentItem& item : aDetails.mDisplayItems.Value()) { IPCPaymentItem displayItem; ConvertItem(item, displayItem); aDisplayItems.AppendElement(displayItem); } } - if (aDetails.mShippingOptions.WasPassed()) { + if (aDetails.mShippingOptions.WasPassed() && !aResetShippingOptions) { for (const PaymentShippingOption& option : aDetails.mShippingOptions.Value()) { IPCPaymentShippingOption shippingOption; ConvertShippingOption(option, shippingOption); aShippingOptions.AppendElement(shippingOption); } } if (aDetails.mModifiers.WasPassed()) { for (const PaymentDetailsModifier& modifier : aDetails.mModifiers.Value()) { @@ -129,23 +130,24 @@ ConvertDetailsBase(const PaymentDetailsB aModifiers.AppendElement(detailsModifier); } } return NS_OK; } nsresult ConvertDetailsInit(const PaymentDetailsInit& aDetails, - IPCPaymentDetails& aIPCDetails) + IPCPaymentDetails& aIPCDetails, + bool aResetShippingOptions) { // Convert PaymentDetailsBase members nsTArray<IPCPaymentItem> displayItems; nsTArray<IPCPaymentShippingOption> shippingOptions; nsTArray<IPCPaymentDetailsModifier> modifiers; - nsresult rv = ConvertDetailsBase(aDetails, displayItems, shippingOptions, modifiers); + nsresult rv = ConvertDetailsBase(aDetails, displayItems, shippingOptions, modifiers, aResetShippingOptions); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } // Convert |id| nsString id(EmptyString()); if (aDetails.mId.WasPassed()) { id = aDetails.mId.Value(); @@ -170,17 +172,20 @@ ConvertDetailsInit(const PaymentDetailsI nsresult ConvertDetailsUpdate(const PaymentDetailsUpdate& aDetails, IPCPaymentDetails& aIPCDetails) { // Convert PaymentDetailsBase members nsTArray<IPCPaymentItem> displayItems; nsTArray<IPCPaymentShippingOption> shippingOptions; nsTArray<IPCPaymentDetailsModifier> modifiers; - nsresult rv = ConvertDetailsBase(aDetails, displayItems, shippingOptions, modifiers); + // [TODO] Populate a boolean flag as aResetShippingOptions based on the + // result of processing details.shippingOptions in UpdatePayment method. + nsresult rv = ConvertDetailsBase( + aDetails, displayItems, shippingOptions, modifiers, false); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } // Convert required |total| IPCPaymentItem total; ConvertItem(aDetails.mTotal, total); @@ -347,46 +352,58 @@ PaymentRequestManager::GetPaymentRequest if (request->Equals(aRequestId)) { RefPtr<PaymentRequest> paymentRequest = request; return paymentRequest.forget(); } } return nullptr; } +void +GetSelectedShippingOption(const PaymentDetailsInit& aDetails, + nsAString& aOption, + bool* aResetOptions) +{ + SetDOMStringToNull(aOption); + if (!aDetails.mShippingOptions.WasPassed()) { + return; + } + + nsTArray<nsString> seenIDs; + const Sequence<PaymentShippingOption>& shippingOptions = + aDetails.mShippingOptions.Value(); + for (const PaymentShippingOption& shippingOption : shippingOptions) { + // If there are duplicate IDs present in the shippingOptions, reset aOption + // to null and set resetOptions flag to reset details.shippingOptions later + // when converting to IPC structure. + if (seenIDs.Contains(shippingOption.mId)) { + SetDOMStringToNull(aOption); + *aResetOptions = true; + return; + } + seenIDs.AppendElement(shippingOption.mId); + + // set aOption to last selected option's ID + if (shippingOption.mSelected) { + aOption = shippingOption.mId; + } + } +} + nsresult PaymentRequestManager::CreatePayment(nsPIDOMWindowInner* aWindow, const Sequence<PaymentMethodData>& aMethodData, const PaymentDetailsInit& aDetails, const PaymentOptions& aOptions, PaymentRequest** aRequest) { MOZ_ASSERT(NS_IsMainThread()); NS_ENSURE_ARG_POINTER(aRequest); *aRequest = nullptr; - nsresult rv; - nsTArray<IPCPaymentMethodData> methodData; - for (const PaymentMethodData& data : aMethodData) { - IPCPaymentMethodData ipcMethodData; - rv = ConvertMethodData(data, ipcMethodData); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - methodData.AppendElement(ipcMethodData); - } - - IPCPaymentDetails details; - rv = ConvertDetailsInit(aDetails, details); - if (NS_WARN_IF(NS_FAILED(rv))) { - return rv; - } - - IPCPaymentOptions options; - ConvertOptions(aOptions, options); RefPtr<PaymentRequest> request = PaymentRequest::CreatePaymentRequest(aWindow, rv); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } /* * Set request's |mId| to details.id if details.id exists. @@ -395,18 +412,58 @@ PaymentRequestManager::CreatePayment(nsP nsAutoString requestId; if (aDetails.mId.WasPassed() && !aDetails.mId.Value().IsEmpty()) { requestId = aDetails.mId.Value(); } else { request->GetInternalId(requestId); } request->SetId(requestId); + /* + * Set request's mShippingOption to last selected option's ID if + * details.shippingOptions exists and IDs of all options are unique. + * Otherwise, set mShippingOption to null and set the resetShippingOptions + * flag to reset details.shippingOptions to an empty array later when + * converting details to IPC structure. + */ + nsAutoString shippingOption; + bool resetShippingOptions = false; + GetSelectedShippingOption(aDetails, shippingOption, &resetShippingOptions); + request->SetShippingOption(shippingOption); + + /* + * Set request's |mShippingType| if shipping is required. + */ + if (aOptions.mRequestShipping) { + request->SetShippingType( + Nullable<PaymentShippingType>(aOptions.mShippingType)); + } + nsAutoString internalId; request->GetInternalId(internalId); + + nsTArray<IPCPaymentMethodData> methodData; + for (const PaymentMethodData& data : aMethodData) { + IPCPaymentMethodData ipcMethodData; + rv = ConvertMethodData(data, ipcMethodData); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + methodData.AppendElement(ipcMethodData); + } + + IPCPaymentDetails details; + rv = ConvertDetailsInit(aDetails, details, resetShippingOptions); + if (NS_WARN_IF(NS_FAILED(rv))) { + return rv; + } + + IPCPaymentOptions options; + ConvertOptions(aOptions, options); + IPCPaymentCreateActionRequest action(internalId, methodData, details, options); rv = SendRequestPayment(request, action, true); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; @@ -484,16 +541,22 @@ nsresult PaymentRequestManager::UpdatePayment(const nsAString& aRequestId, const PaymentDetailsUpdate& aDetails) { RefPtr<PaymentRequest> request = GetPaymentRequestById(aRequestId); if (!request) { return NS_ERROR_UNEXPECTED; } + // [TODO] Process details.shippingOptions if presented. + // 1) Check if there are duplicate IDs in details.shippingOptions, + // if so, reset details.shippingOptions to an empty sequence. + // 2) Set request's selectedShippingOption to the ID of last selected + // option. + IPCPaymentDetails details; nsresult rv = ConvertDetailsUpdate(aDetails, details); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsAutoString requestId(aRequestId); IPCPaymentUpdateActionRequest action(requestId, details);
--- a/dom/payments/test/ConstructorChromeScript.js +++ b/dom/payments/test/ConstructorChromeScript.js @@ -222,16 +222,77 @@ function checkComplexRequest(payRequest) if (!paymentOptions.requestShipping) { emitTestFail("requestShipping option should be true."); } if (paymentOptions.shippingType != "shipping") { emitTestFail("shippingType option should be 'shipping'.") } } +function checkDuplicateShippingOptionsRequest(payRequest) { + if (payRequest.paymentMethods.length != 1) { + emitTestFail("paymentMethods' length should be 1."); + } + + const methodData = payRequest.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData); + if (!methodData) { + emitTestFail("Fail to get payment methodData."); + } + let supportedMethod = methodData.supportedMethods; + if (supportedMethod != "basic-card") { + emitTestFail("supported method should be 'basic-card'."); + } + // checking the passed PaymentDetails parameter + const details = payRequest.paymentDetails; + if (details.id != "duplicate shipping options details" ) { + emitTestFail("details.id should be 'duplicate shipping options details'."); + } + if (details.totalItem.label != "Total") { + emitTestFail("total item's label should be 'Total'."); + } + if (details.totalItem.amount.currency != "USD") { + emitTestFail("total item's currency should be 'USD'."); + } + if (details.totalItem.amount.value != "1.00") { + emitTestFail("total item's value should be '1.00'."); + } + + if (details.displayItems) { + emitTestFail("details.displayItems should be undefined."); + } + if (details.modifiers) { + emitTestFail("details.displayItems should be undefined."); + } + const shippingOptions = details.shippingOptions; + if (!shippingOptions) { + emitTestFail("details.shippingOptions should not be undefined."); + } + if (shippingOptions.length != 0) { + emitTestFail("shippingOptions' length should be 0."); + } + + // checking the default generated PaymentOptions parameter + const paymentOptions = payRequest.paymentOptions; + if (paymentOptions.requestPayerName) { + emitTestFail("requestPayerName option should be false."); + } + if (paymentOptions.requestPayerEmail) { + emitTestFail("requestPayerEmail option should be false."); + } + if (paymentOptions.requestPayerPhone) { + emitTestFail("requestPayerPhone option should be false."); + } + if (paymentOptions.requestShipping) { + emitTestFail("requestShipping option should be false."); + } + if (paymentOptions.shippingType != "shipping") { + emitTestFail("shippingType option should be 'shipping'.") + } +} + function checkSimplestRequestHandler() { const paymentEnum = paymentSrv.enumerate(); if (!paymentEnum.hasMoreElements()) { emitTestFail("PaymentRequestService should have at least one payment request."); } while (paymentEnum.hasMoreElements()) { let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest); if (!payRequest) { @@ -256,37 +317,57 @@ function checkComplexRequestHandler() { break; } checkComplexRequest(payRequest); } paymentSrv.cleanup(); sendAsyncMessage("check-complete"); } +function checkDuplicateShippingOptionsRequestHandler() { + const paymentEnum = paymentSrv.enumerate(); + if (!paymentEnum.hasMoreElements()) { + emitTestFail("PaymentRequestService should have at least one payment request."); + } + while (paymentEnum.hasMoreElements()) { + let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest); + if (!payRequest) { + emitTestFail("Fail to get existing payment request."); + break; + } + checkDuplicateShippingOptionsRequest(payRequest); + } + paymentSrv.cleanup(); + sendAsyncMessage("check-complete"); +} + function checkMultipleRequestsHandler () { const paymentEnum = paymentSrv.enumerate(); if (!paymentEnum.hasMoreElements()) { emitTestFail("PaymentRequestService should have at least one payment request."); } while (paymentEnum.hasMoreElements()) { let payRequest = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest); if (!payRequest) { emitTestFail("Fail to get existing payment request."); break; } - if (payRequest.paymentDetails.id != "payment details") { + if (payRequest.paymentDetails.id == "payment details") { + checkComplexRequest(payRequest); + } else if (payRequest.paymentDetails.id == "duplicate shipping options details") { + checkDuplicateShippingOptionsRequest(payRequest); + } else { checkSimplestRequest(payRequest); - } else { - checkComplexRequest(payRequest); } } paymentSrv.cleanup(); sendAsyncMessage("check-complete"); } addMessageListener("check-simplest-request", checkSimplestRequestHandler); addMessageListener("check-complex-request", checkComplexRequestHandler); +addMessageListener("check-duplicate-shipping-options-request", checkDuplicateShippingOptionsRequestHandler); addMessageListener("check-multiple-requests", checkMultipleRequestsHandler); addMessageListener("teardown", function() { paymentSrv.cleanup(); sendAsyncMessage("teardown-complete"); });
--- a/dom/payments/test/browser_multiple_construction.js +++ b/dom/payments/test/browser_multiple_construction.js @@ -17,16 +17,18 @@ add_task(async function() { ok(paymentEnum.hasMoreElements(), "PaymentRequestService should have at least one payment request."); while (paymentEnum.hasMoreElements()) { let payment = paymentEnum.getNext().QueryInterface(Ci.nsIPaymentRequest); ok(payment, "Fail to get existing payment request."); if (payment.paymentDetails.id == "complex details") { checkComplexPayment(payment); } else if (payment.paymentDetails.id == "simple details") { checkSimplePayment(payment); + } else if (payment.paymentDetails.id == "duplicate shipping options details") { + checkDupShippingOptionsPayment(payment); } else { ok(false, "Unknown payment."); } } Services.prefs.setBoolPref("dom.payments.request.enabled", false); } ); });
--- a/dom/payments/test/head.js +++ b/dom/payments/test/head.js @@ -96,14 +96,42 @@ function checkComplexPayment(aPayment) { const paymentOptions = aPayment.paymentOptions; ok(paymentOptions.requestPayerName, "payerName option should be true"); ok(paymentOptions.requestPayerEmail, "payerEmail option should be true"); ok(paymentOptions.requestPayerPhone, "payerPhone option should be true"); ok(paymentOptions.requestShipping, "requestShipping option should be true"); is(paymentOptions.shippingType, "shipping", "shippingType option should be 'shipping'"); } +function checkDupShippingOptionsPayment(aPayment) { + // checking the passed PaymentMethods parameter + is(aPayment.paymentMethods.length, 1, "paymentMethods' length should be 1."); + + const methodData = aPayment.paymentMethods.queryElementAt(0, Ci.nsIPaymentMethodData); + ok(methodData, "Fail to get payment methodData."); + is(methodData.supportedMethods, "MyPay", "modifier's supported method name should be 'MyPay'."); + is(methodData.data, "", "method data should be empty"); + + // checking the passed PaymentDetails parameter + const details = aPayment.paymentDetails; + is(details.id, "duplicate shipping options details", "details.id should be 'duplicate shipping options details'."); + is(details.totalItem.label, "Donation", "total item's label should be 'Donation'."); + is(details.totalItem.amount.currency, "USD", "total item's currency should be 'USD'."); + is(details.totalItem.amount.value, "55.00", "total item's value should be '55.00'."); + + const shippingOptions = details.shippingOptions; + is(shippingOptions.length, 0, "shippingOptions' length should be 0."); + + // checking the passed PaymentOptions parameter + const paymentOptions = aPayment.paymentOptions; + ok(paymentOptions.requestPayerName, "payerName option should be true"); + ok(paymentOptions.requestPayerEmail, "payerEmail option should be true"); + ok(paymentOptions.requestPayerPhone, "payerPhone option should be true"); + ok(paymentOptions.requestShipping, "requestShipping option should be true"); + is(paymentOptions.shippingType, "shipping", "shippingType option should be 'shipping'"); +} + function cleanup() { const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"].getService(Ci.nsIPaymentRequestService); if (paymentSrv) { paymentSrv.cleanup(); } }
--- a/dom/payments/test/multiple_payment_request.html +++ b/dom/payments/test/multiple_payment_request.html @@ -61,24 +61,49 @@ const simpleDetails = { id: "simple details", total: { label: "Donation", amount: { currency: "USD", value: "55.00" } }, }; + const dupShippingOptionsDetails = { + id: "duplicate shipping options details", + total: { + label: "Donation", + amount: { currency: "USD", value: "55.00" } + }, + shippingOptions: [ + { + id: "dupShipping", + label: "NormalShipping", + amount: { currency: "USD", value: "10.00", }, + selected: true, + }, + { + id: "dupShipping", + label: "FastShipping", + amount: { currency: "USD", value: "30.00", }, + selected: false, + }, + ], + }; + const options = { requestPayerName: true, requestPayerEmail: true, requestPayerPhone: true, requestShipping: true, shippingType: "shipping", }; const paymentRequest1 = new PaymentRequest(supportedInstruments, complexDetails, options); const paymentRequest2 = new PaymentRequest(supportedInstruments, simpleDetails); + const paymentRequest3 = new PaymentRequest(supportedInstruments, + dupShippingOptionsDetails, + options); </script> </body> </html>
--- a/dom/payments/test/test_constructor.html +++ b/dom/payments/test/test_constructor.html @@ -116,16 +116,47 @@ https://bugzilla.mozilla.org/show_bug.cg const complexOptions = { requestPayerName: true, requestPayerEmail: true, requestPayerPhone: true, requestShipping: true, shippingType: "shipping" }; + const duplicateShippingOptionsDetails = { + id: "duplicate shipping options details", + total: { + label: "Total", + amount: { + currency: "USD", + value: "1.00" + } + }, + shippingOptions: [ + { + id: "dupShipping", + label: "NormalShipping", + amount: { + currency: "USD", + value: "10.00" + }, + selected: true, + }, + { + id: "dupShipping", + label: "FastShipping", + amount: { + currency: "USD", + value: "30.00" + }, + selected: false, + }, + ], + }; + function testWithSimplestParameters() { return new Promise((resolve, reject) => { const payRequest = new PaymentRequest(simplestMethods, simplestDetails); ok(payRequest, "PaymentRequest should be created"); gScript.addMessageListener("check-complete", function checkCompleteHandler() { gScript.removeMessageListener("check-complete", checkCompleteHandler); resolve(); @@ -141,22 +172,36 @@ https://bugzilla.mozilla.org/show_bug.cg gScript.addMessageListener("check-complete", function checkCompleteHandler() { gScript.removeMessageListener("check-complete", checkCompleteHandler); resolve(); }); gScript.sendAsyncMessage("check-complex-request"); }); } + function testWithDuplicateShippingOptionsParameters() { + return new Promise((resolve, reject) => { + const payRequest = new PaymentRequest(simplestMethods, duplicateShippingOptionsDetails); + ok(payRequest, "PaymentRequest should be created"); + gScript.addMessageListener("check-complete", function checkCompleteHandler() { + gScript.removeMessageListener("check-complete", checkCompleteHandler); + resolve(); + }); + gScript.sendAsyncMessage("check-duplicate-shipping-options-request"); + }); + } + function testMultipleRequests() { return new Promise((resolve, reject) => { const payRequest1 = new PaymentRequest(complexMethods, complexDetails, complexOptions); const payRequest2 = new PaymentRequest(simplestMethods, simplestDetails); + const payRequest3 = new PaymentRequest(simplestMethods, duplicateShippingOptionsDetails); ok(payRequest1, "PaymentRequest with complex parameters should be created"); ok(payRequest2, "PaymentRequest with simplest parameters should be created"); + ok(payRequest3, "PaymentRequest with duplicate shipping options parameters should be created"); gScript.addMessageListener("check-complete", function checkCompleteHandler() { gScript.removeMessageListener("check-complete", checkCompleteHandler); resolve(); }); gScript.sendAsyncMessage("check-multiple-requests"); }); } @@ -168,16 +213,17 @@ https://bugzilla.mozilla.org/show_bug.cg SimpleTest.finish(); }); gScript.sendAsyncMessage("teardown"); } function runTests() { testWithSimplestParameters() .then(testWithComplexParameters) + .then(testWithDuplicateShippingOptionsParameters) .then(testMultipleRequests) .then(teardown) .catch( e => { ok(false, "Unexpected error: " + e.name); SimpleTest.finish(); }); }
--- a/dom/plugins/base/nsJSNPRuntime.cpp +++ b/dom/plugins/base/nsJSNPRuntime.cpp @@ -1,9 +1,10 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "base/basictypes.h" #include "jsfriendapi.h" #include "jswrapper.h" @@ -24,20 +25,16 @@ #include "nsIDOMElement.h" #include "nsIContent.h" #include "nsPluginInstanceOwner.h" #include "nsWrapperCacheInlines.h" #include "js/GCHashTable.h" #include "js/TracingAPI.h" #include "mozilla/HashFunctions.h" #include "mozilla/dom/ScriptSettings.h" -#include "mozilla/plugins/PluginAsyncSurrogate.h" - -using mozilla::plugins::AsyncNPObject; -using mozilla::plugins::PluginAsyncSurrogate; #define NPRUNTIME_JSCLASS_NAME "NPObject JS wrapper class" using namespace mozilla::plugins::parent; using namespace mozilla; #include "mozilla/plugins/PluginScriptableObjectParent.h" using mozilla::plugins::PluginScriptableObjectParent; @@ -104,34 +101,20 @@ static PLDHashTable* sNPObjWrappers; static int32_t sWrapperCount; static bool sCallbackIsRegistered = false; static nsTArray<NPObject*>* sDelayedReleases; namespace { -inline void -CastNPObject(NPObject *aObj, PluginScriptableObjectParent*& aActor, - PluginAsyncSurrogate*& aSurrogate) -{ - aActor = nullptr; - aSurrogate = nullptr; - if (aObj->_class == PluginScriptableObjectParent::GetClass()) { - aActor = static_cast<ParentNPObject*>(aObj)->parent; - } else if (aObj->_class == PluginAsyncSurrogate::GetClass()) { - aSurrogate = static_cast<AsyncNPObject*>(aObj)->mSurrogate; - } -} - inline bool NPObjectIsOutOfProcessProxy(NPObject *obj) { - return obj->_class == PluginScriptableObjectParent::GetClass() || - obj->_class == PluginAsyncSurrogate::GetClass(); + return obj->_class == PluginScriptableObjectParent::GetClass(); } } // namespace // Helper class that suppresses any JS exceptions that were thrown while // the plugin executed JS, if the nsJSObjWrapper has a destroy pending. // Note that this class is the product (vestige?) of a long evolution in how // error reporting worked, and hence the mIsDestroyPending check, and hence this @@ -1092,27 +1075,16 @@ NPObject * nsJSObjWrapper::GetNewOrUsed(NPP npp, JS::Handle<JSObject*> obj) { if (!npp) { NS_ERROR("Null NPP passed to nsJSObjWrapper::GetNewOrUsed()!"); return nullptr; } - // If we're running out-of-process and initializing asynchronously, and if - // the plugin has been asked to destroy itself during initialization, - // don't return any new NPObjects. - nsNPAPIPluginInstance* inst = static_cast<nsNPAPIPluginInstance*>(npp->ndata); - if (inst->GetPlugin()->GetLibrary()->IsOOP()) { - PluginAsyncSurrogate* surrogate = PluginAsyncSurrogate::Cast(npp); - if (surrogate && surrogate->IsDestroyPending()) { - return nullptr; - } - } - // No need to enter the right compartment here as we only get the // class and private from the JSObject, neither of which cares about // compartments. if (nsNPObjWrapper::IsWrapper(obj)) { // obj is one of our own, its private data is the NPObject we're // looking for. @@ -1399,32 +1371,25 @@ NPObjWrapper_GetProperty(JSContext *cx, bool hasProperty, hasMethod; NPVariant npv; VOID_TO_NPVARIANT(npv); NPIdentifier identifier = JSIdToNPIdentifier(id); if (NPObjectIsOutOfProcessProxy(npobj)) { - PluginScriptableObjectParent* actor = nullptr; - PluginAsyncSurrogate* surrogate = nullptr; - CastNPObject(npobj, actor, surrogate); - - // actor and surrogate may be null if the plugin crashed. - if (!actor && !surrogate) + PluginScriptableObjectParent* actor = + static_cast<ParentNPObject*>(npobj)->parent; + + // actor may be null if the plugin crashed. + if (!actor) return false; - bool success = false; - if (surrogate) { - success = surrogate->GetPropertyHelper(npobj, identifier, &hasProperty, - &hasMethod, &npv); - } else if (actor) { - success = actor->GetPropertyHelper(identifier, &hasProperty, &hasMethod, - &npv); - } + bool success = actor->GetPropertyHelper(identifier, &hasProperty, + &hasMethod, &npv); if (!ReportExceptionIfPending(cx)) { if (success) _releasevariantvalue(&npv); return false; } if (success) {
--- a/dom/plugins/base/nsPluginHost.cpp +++ b/dom/plugins/base/nsPluginHost.cpp @@ -48,17 +48,16 @@ #include "nsIObjectLoadingContent.h" #include "nsIWritablePropertyBag2.h" #include "nsICategoryManager.h" #include "nsPluginStreamListenerPeer.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/FakePluginTagInitBinding.h" #include "mozilla/LoadInfo.h" -#include "mozilla/plugins/PluginAsyncSurrogate.h" #include "mozilla/plugins/PluginBridge.h" #include "mozilla/plugins/PluginTypes.h" #include "mozilla/Preferences.h" #include "mozilla/ipc/URIUtils.h" #include "nsEnumeratorUtils.h" #include "nsXPCOM.h" #include "nsXPCOMCID.h" @@ -114,17 +113,16 @@ #endif #include "npapi.h" using namespace mozilla; using mozilla::TimeStamp; using mozilla::plugins::FakePluginTag; using mozilla::plugins::PluginTag; -using mozilla::plugins::PluginAsyncSurrogate; using mozilla::dom::FakePluginTagInit; using mozilla::dom::FakePluginMimeEntry; // Null out a strong ref to a linked list iteratively to avoid // exhausting the stack (bug 486349). #define NS_ITERATIVE_UNREF_LIST(type_, list_, mNext_) \ { \ while (list_) { \ @@ -753,27 +751,25 @@ nsPluginHost::InstantiatePluginInstance( return NS_ERROR_FAILURE; } rv = SetUpPluginInstance(aMimeType, aURL, instanceOwner); if (NS_FAILED(rv)) { instanceOwner->Destroy(); return NS_ERROR_FAILURE; } - const bool isAsyncInit = (rv == NS_PLUGIN_INIT_PENDING); RefPtr<nsNPAPIPluginInstance> instance; rv = instanceOwner->GetInstance(getter_AddRefs(instance)); if (NS_FAILED(rv)) { instanceOwner->Destroy(); return rv; } - // Async init plugins will initiate their own widget creation. - if (!isAsyncInit && instance) { + if (instance) { CreateWidget(instanceOwner); } // At this point we consider instantiation to be successful. Do not return an error. instanceOwner.forget(aOwner); #ifdef PLUGIN_LOGGING nsAutoCString urlSpec2; @@ -2378,17 +2374,16 @@ nsPluginHost::SetPluginsInContent(uint32 tag.filename().get(), "", // aFullPath tag.version().get(), nsTArray<nsCString>(tag.mimeTypes()), nsTArray<nsCString>(tag.mimeDescriptions()), nsTArray<nsCString>(tag.extensions()), tag.isJavaPlugin(), tag.isFlashPlugin(), - tag.supportsAsyncInit(), tag.supportsAsyncRender(), tag.lastModifiedTime(), tag.isFromExtension(), tag.sandboxLevel()); AddPluginTag(pluginTag); } for (const auto& tag : aFakePlugins) { @@ -2619,17 +2614,16 @@ nsPluginHost::SendPluginsToContent() pluginTags.AppendElement(PluginTag(tag->mId, tag->Name(), tag->Description(), tag->MimeTypes(), tag->MimeDescriptions(), tag->Extensions(), tag->mIsJavaPlugin, tag->mIsFlashPlugin, - tag->mSupportsAsyncInit, tag->mSupportsAsyncRender, tag->FileName(), tag->Version(), tag->mLastModifiedTime, tag->IsFromExtension(), tag->mSandboxLevel)); } nsTArray<dom::ContentParent*> parents; @@ -4018,22 +4012,16 @@ mozilla::LinkedList<nsPluginDestroyRunna mozilla::LinkedList<PluginDestructionGuard> PluginDestructionGuard::sList; PluginDestructionGuard::PluginDestructionGuard(nsNPAPIPluginInstance *aInstance) : mInstance(aInstance) { Init(); } -PluginDestructionGuard::PluginDestructionGuard(PluginAsyncSurrogate *aSurrogate) - : mInstance(static_cast<nsNPAPIPluginInstance*>(aSurrogate->GetNPP()->ndata)) -{ - InitAsync(); -} - PluginDestructionGuard::PluginDestructionGuard(NPP npp) : mInstance(npp ? static_cast<nsNPAPIPluginInstance*>(npp->ndata) : nullptr) { Init(); } PluginDestructionGuard::~PluginDestructionGuard() {
--- a/dom/plugins/base/nsPluginHost.h +++ b/dom/plugins/base/nsPluginHost.h @@ -30,17 +30,16 @@ #ifdef XP_WIN #include <minwindef.h> #include "nsIWindowsRegKey.h" #endif namespace mozilla { namespace plugins { class FakePluginTag; -class PluginAsyncSurrogate; class PluginTag; } // namespace plugins } // namespace mozilla class nsNPAPIPlugin; class nsIFile; class nsIChannel; class nsPluginNativeWindow; @@ -420,43 +419,31 @@ private: // two different CIDs for some reason... static nsPluginHost* sInst; }; class PluginDestructionGuard : public mozilla::LinkedListElement<PluginDestructionGuard> { public: explicit PluginDestructionGuard(nsNPAPIPluginInstance *aInstance); - explicit PluginDestructionGuard(mozilla::plugins::PluginAsyncSurrogate *aSurrogate); explicit PluginDestructionGuard(NPP npp); ~PluginDestructionGuard(); static bool DelayDestroy(nsNPAPIPluginInstance *aInstance); protected: void Init() { NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread"); mDelayedDestroy = false; sList.insertBack(this); } - void InitAsync() - { - NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread"); - - mDelayedDestroy = false; - - // Instances with active surrogates must be inserted *in front of* sList so - // that they appear to be at the bottom of the stack - sList.insertFront(this); - } - RefPtr<nsNPAPIPluginInstance> mInstance; bool mDelayedDestroy; static mozilla::LinkedList<PluginDestructionGuard> sList; }; #endif // nsPluginHost_h_
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -1663,55 +1663,16 @@ void nsPluginInstanceOwner::ExitFullScre if (sFullScreenInstance && sFullScreenInstance->mInstance && env->IsSameObject(view, (jobject)sFullScreenInstance->mInstance->GetJavaSurface())) { sFullScreenInstance->ExitFullScreen(); } } #endif -void -nsPluginInstanceOwner::NotifyHostAsyncInitFailed() -{ - nsCOMPtr<nsIObjectLoadingContent> content = do_QueryReferent(mContent); - content->StopPluginInstance(); -} - -void -nsPluginInstanceOwner::NotifyHostCreateWidget() -{ - mPluginHost->CreateWidget(this); -#ifdef XP_MACOSX - FixUpPluginWindow(ePluginPaintEnable); -#else - if (mPluginFrame) { - mPluginFrame->InvalidateFrame(); - } else { - CallSetWindow(); - } -#endif -} - -void -nsPluginInstanceOwner::NotifyDestroyPending() -{ - if (!mInstance) { - return; - } - bool isOOP = false; - if (NS_FAILED(mInstance->GetIsOOP(&isOOP)) || !isOOP) { - return; - } - NPP npp = nullptr; - if (NS_FAILED(mInstance->GetNPP(&npp)) || !npp) { - return; - } - PluginAsyncSurrogate::NotifyDestroyPending(npp); -} - nsresult nsPluginInstanceOwner::DispatchFocusToPlugin(nsIDOMEvent* aFocusEvent) { #ifdef MOZ_WIDGET_ANDROID if (mInstance) { ANPEvent event; event.inSize = sizeof(ANPEvent); event.eventType = kLifecycle_ANPEventType;
--- a/dom/plugins/base/nsPluginInstanceOwner.h +++ b/dom/plugins/base/nsPluginInstanceOwner.h @@ -264,20 +264,16 @@ public: void RequestFullScreen(); void ExitFullScreen(); // Called from nsAppShell when we removed the fullscreen view. static void ExitFullScreen(jobject view); #endif - void NotifyHostAsyncInitFailed(); - void NotifyHostCreateWidget(); - void NotifyDestroyPending(); - bool GetCompositionString(uint32_t aIndex, nsTArray<uint8_t>* aString, int32_t* aLength); bool SetCandidateWindow( const mozilla::widget::CandidateWindowPosition& aPosition); bool RequestCommitOrCancel(bool aCommitted); // See nsIKeyEventInPluginCallback virtual void HandledWindowedPluginKeyEvent(
--- a/dom/plugins/base/nsPluginTags.cpp +++ b/dom/plugins/base/nsPluginTags.cpp @@ -228,17 +228,16 @@ nsPluginTag::nsPluginTag(nsPluginInfo* a : nsIInternalPluginTag(aPluginInfo->fName, aPluginInfo->fDescription, aPluginInfo->fFileName, aPluginInfo->fVersion), mId(sNextId++), mContentProcessRunningCount(0), mHadLocalInstance(false), mLibrary(nullptr), mIsJavaPlugin(false), mIsFlashPlugin(false), - mSupportsAsyncInit(false), mSupportsAsyncRender(false), mFullPath(aPluginInfo->fFullPath), mLastModifiedTime(aLastModifiedTime), mSandboxLevel(0), mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED), mCachedBlocklistStateValid(false), mIsFromExtension(fromExtension) { @@ -265,17 +264,16 @@ nsPluginTag::nsPluginTag(const char* aNa bool aArgsAreUTF8) : nsIInternalPluginTag(aName, aDescription, aFileName, aVersion), mId(sNextId++), mContentProcessRunningCount(0), mHadLocalInstance(false), mLibrary(nullptr), mIsJavaPlugin(false), mIsFlashPlugin(false), - mSupportsAsyncInit(false), mSupportsAsyncRender(false), mFullPath(aFullPath), mLastModifiedTime(aLastModifiedTime), mSandboxLevel(0), mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED), mCachedBlocklistStateValid(false), mIsFromExtension(fromExtension) { @@ -293,29 +291,27 @@ nsPluginTag::nsPluginTag(uint32_t aId, const char* aFileName, const char* aFullPath, const char* aVersion, nsTArray<nsCString> aMimeTypes, nsTArray<nsCString> aMimeDescriptions, nsTArray<nsCString> aExtensions, bool aIsJavaPlugin, bool aIsFlashPlugin, - bool aSupportsAsyncInit, bool aSupportsAsyncRender, int64_t aLastModifiedTime, bool aFromExtension, int32_t aSandboxLevel) : nsIInternalPluginTag(aName, aDescription, aFileName, aVersion, aMimeTypes, aMimeDescriptions, aExtensions), mId(aId), mContentProcessRunningCount(0), mLibrary(nullptr), mIsJavaPlugin(aIsJavaPlugin), mIsFlashPlugin(aIsFlashPlugin), - mSupportsAsyncInit(aSupportsAsyncInit), mSupportsAsyncRender(aSupportsAsyncRender), mLastModifiedTime(aLastModifiedTime), mSandboxLevel(aSandboxLevel), mNiceFileName(), mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED), mCachedBlocklistStateValid(false), mIsFromExtension(aFromExtension) { @@ -351,35 +347,27 @@ void nsPluginTag::InitMime(const char* c if (!nsPluginHost::IsTypeWhitelisted(mimeType.get())) { continue; } // Look for certain special plugins. switch (nsPluginHost::GetSpecialType(mimeType)) { case nsPluginHost::eSpecialType_Java: mIsJavaPlugin = true; - mSupportsAsyncInit = true; break; case nsPluginHost::eSpecialType_Flash: // VLC sometimes claims to implement the Flash MIME type, and we want // to allow users to control that separately from Adobe Flash. if (Name().EqualsLiteral("Shockwave Flash")) { mIsFlashPlugin = true; - mSupportsAsyncInit = true; } break; case nsPluginHost::eSpecialType_Test: - mSupportsAsyncInit = true; - break; case nsPluginHost::eSpecialType_None: default: -#ifndef RELEASE_OR_BETA - // Allow async init for all plugins on Nightly and Aurora - mSupportsAsyncInit = true; -#endif break; } // Fill in our MIME type array. mMimeTypes.AppendElement(mimeType); // Now fill in the MIME descriptions. if (aMimeDescriptions && aMimeDescriptions[i]) {
--- a/dom/plugins/base/nsPluginTags.h +++ b/dom/plugins/base/nsPluginTags.h @@ -127,17 +127,16 @@ public: const char* aFileName, const char* aFullPath, const char* aVersion, nsTArray<nsCString> aMimeTypes, nsTArray<nsCString> aMimeDescriptions, nsTArray<nsCString> aExtensions, bool aIsJavaPlugin, bool aIsFlashPlugin, - bool aSupportsAsyncInit, bool aSupportsAsyncRender, int64_t aLastModifiedTime, bool aFromExtension, int32_t aSandboxLevel); void TryUnloadPlugin(bool inShutdown); // plugin is enabled and not blocklisted @@ -164,17 +163,16 @@ public: // True if we've ever created an instance of this plugin in the current process. bool mHadLocalInstance; PRLibrary *mLibrary; RefPtr<nsNPAPIPlugin> mPlugin; bool mIsJavaPlugin; bool mIsFlashPlugin; - bool mSupportsAsyncInit; bool mSupportsAsyncRender; nsCString mFullPath; // UTF-8 int64_t mLastModifiedTime; nsCOMPtr<nsITimer> mUnloadTimer; int32_t mSandboxLevel; void InvalidateBlocklistState();
--- a/dom/plugins/ipc/BrowserStreamParent.cpp +++ b/dom/plugins/ipc/BrowserStreamParent.cpp @@ -1,16 +1,15 @@ /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "BrowserStreamParent.h" -#include "PluginAsyncSurrogate.h" #include "PluginInstanceParent.h" #include "nsNPAPIPlugin.h" #include "mozilla/UniquePtr.h" #include "mozilla/Unused.h" // How much data are we willing to send across the wire // in one chunk? @@ -18,17 +17,16 @@ static const int32_t kSendDataChunk = 0x namespace mozilla { namespace plugins { BrowserStreamParent::BrowserStreamParent(PluginInstanceParent* npp, NPStream* stream) : mNPP(npp) , mStream(stream) - , mDeferredDestroyReason(NPRES_DONE) , mState(INITIALIZING) { mStream->pdata = static_cast<AStream*>(this); nsNPAPIStreamWrapper* wrapper = reinterpret_cast<nsNPAPIStreamWrapper*>(mStream->ndata); if (wrapper) { mStreamListener = wrapper->GetStreamListener(); } @@ -41,51 +39,16 @@ BrowserStreamParent::~BrowserStreamParen void BrowserStreamParent::ActorDestroy(ActorDestroyReason aWhy) { // Implement me! Bug 1005159 } mozilla::ipc::IPCResult -BrowserStreamParent::RecvAsyncNPP_NewStreamResult(const NPError& rv, - const uint16_t& stype) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - PluginAsyncSurrogate* surrogate = mNPP->GetAsyncSurrogate(); - MOZ_ASSERT(surrogate); - surrogate->AsyncCallArriving(); - if (mState == DEFERRING_DESTROY) { - // We've been asked to destroy ourselves before init was complete. - mState = DYING; - Unused << SendNPP_DestroyStream(mDeferredDestroyReason); - return IPC_OK(); - } - - NPError error = rv; - if (error == NPERR_NO_ERROR) { - if (!mStreamListener) { - return IPC_FAIL_NO_REASON(this); - } - if (mStreamListener->SetStreamType(stype)) { - mState = ALIVE; - } else { - error = NPERR_GENERIC_ERROR; - } - } - - if (error != NPERR_NO_ERROR) { - surrogate->DestroyAsyncStream(mStream); - Unused << PBrowserStreamParent::Send__delete__(this); - } - - return IPC_OK(); -} - -mozilla::ipc::IPCResult BrowserStreamParent::AnswerNPN_RequestRead(const IPCByteRanges& ranges, NPError* result) { PLUGIN_LOG_DEBUG_FUNCTION; switch (mState) { case INITIALIZING: NS_ERROR("Requesting a read before initialization has completed"); @@ -144,17 +107,16 @@ BrowserStreamParent::RecvNPN_DestroyStre void BrowserStreamParent::NPP_DestroyStream(NPReason reason) { NS_ASSERTION(ALIVE == mState || INITIALIZING == mState, "NPP_DestroyStream called twice?"); bool stillInitializing = INITIALIZING == mState; if (stillInitializing) { mState = DEFERRING_DESTROY; - mDeferredDestroyReason = reason; } else { mState = DYING; Unused << SendNPP_DestroyStream(reason); } } mozilla::ipc::IPCResult BrowserStreamParent::RecvStreamDestroyed()
--- a/dom/plugins/ipc/BrowserStreamParent.h +++ b/dom/plugins/ipc/BrowserStreamParent.h @@ -25,20 +25,16 @@ public: BrowserStreamParent(PluginInstanceParent* npp, NPStream* stream); virtual ~BrowserStreamParent(); virtual bool IsBrowserStream() override { return true; } virtual void ActorDestroy(ActorDestroyReason aWhy) override; - virtual mozilla::ipc::IPCResult RecvAsyncNPP_NewStreamResult( - const NPError& rv, - const uint16_t& stype) override; - virtual mozilla::ipc::IPCResult AnswerNPN_RequestRead(const IPCByteRanges& ranges, NPError* result) override; virtual mozilla::ipc::IPCResult RecvNPN_DestroyStream(const NPReason& reason) override; virtual mozilla::ipc::IPCResult RecvStreamDestroyed() override; int32_t WriteReady(); @@ -56,17 +52,16 @@ public: private: using PBrowserStreamParent::SendNPP_DestroyStream; PluginInstanceParent* mNPP; NPStream* mStream; nsCOMPtr<nsISupports> mStreamPeer; RefPtr<nsNPAPIPluginStreamListener> mStreamListener; - NPReason mDeferredDestroyReason; enum { INITIALIZING, DEFERRING_DESTROY, ALIVE, DYING, DELETING } mState;
--- a/dom/plugins/ipc/PBrowserStream.ipdl +++ b/dom/plugins/ipc/PBrowserStream.ipdl @@ -31,17 +31,16 @@ child: /** * NPP_DestroyStream may race with other messages: the child acknowledges * the message with StreamDestroyed before this actor is deleted. */ async NPP_DestroyStream(NPReason reason); async __delete__(); parent: - async AsyncNPP_NewStreamResult(NPError rv, uint16_t stype); intr NPN_RequestRead(IPCByteRanges ranges) returns (NPError result); async NPN_DestroyStream(NPReason reason); async StreamDestroyed(); /* TODO: turn on state machine.
--- a/dom/plugins/ipc/PPluginInstance.ipdl +++ b/dom/plugins/ipc/PPluginInstance.ipdl @@ -249,19 +249,16 @@ parent: returns (NPError result); intr NPN_ConvertPoint(double sourceX, bool ignoreDestX, double sourceY, bool ignoreDestY, NPCoordinateSpace sourceSpace, NPCoordinateSpace destSpace) returns (double destX, double destY, bool result); async RedrawPlugin(); - // Notifies the parent of its NPP_New result code. - async AsyncNPP_NewResult(NPError aResult); - // Sends a native window to be adopted by the native window that would be // returned by NPN_GetValue_NPNVnetscapeWindow. Only used on Windows. async SetNetscapeWindowAsParent(NativeWindowHandle childWindow); sync GetCompositionString(uint32_t aType) returns (uint8_t[] aDist, int32_t aLength); // Set candidate window position. // @@ -288,19 +285,16 @@ child: nsCString headers); // Implements the legacy (synchronous) version of NPP_NewStream for when // async plugin init is preffed off. intr NPP_NewStream(PBrowserStream actor, nsCString mimeType, bool seekable) returns (NPError rv, uint16_t stype); - // Implements the async plugin init version of NPP_NewStream. - async AsyncNPP_NewStream(PBrowserStream actor, nsCString mimeType, bool seekable); - parent: /* NPN_NewStream */ intr PPluginStream(nsCString mimeType, nsCString target) returns (NPError result); parent: intr PluginFocusChange(bool gotFocus);
--- a/dom/plugins/ipc/PPluginModule.ipdl +++ b/dom/plugins/ipc/PPluginModule.ipdl @@ -57,30 +57,25 @@ child: // Forces the child process to update its plugin function table. intr NP_GetEntryPoints() returns (NPError rv); intr NP_Initialize(PluginSettings settings) returns (NPError rv); - async AsyncNP_Initialize(PluginSettings settings); - async PPluginInstance(nsCString aMimeType, nsCString[] aNames, nsCString[] aValues); // Implements the synchronous version of NPP_New for when async plugin init // is preffed off. intr SyncNPP_New(PPluginInstance aActor) returns (NPError rv); - // Implements the async plugin init version of NPP_New. - async AsyncNPP_New(PPluginInstance aActor); - intr NP_Shutdown() returns (NPError rv); intr OptionalFunctionsSupported() returns (bool aURLRedirectNotify, bool aClearSiteData, bool aGetSitesWithData); async NPP_ClearSiteData(nsCString site, uint64_t flags, uint64_t maxAge, uint64_t aCallbackId); @@ -99,18 +94,16 @@ child: async SettingChanged(PluginSettings settings); async NPP_SetValue_NPNVaudioDeviceChangeDetails(NPAudioDeviceChangeDetailsIPC changeDetails); async InitPluginModuleChild(Endpoint<PPluginModuleChild> endpoint); parent: - async NP_InitializeResult(NPError aError); - /** * This message is only used on X11 platforms. * * Send a dup of the plugin process's X socket to the parent * process. In theory, this scheme keeps the plugin's X resources * around until after both the plugin process shuts down *and* the * parent process closes the dup fd. This is used to prevent the * parent process from crashing on X errors if, e.g., the plugin
deleted file mode 100644 --- a/dom/plugins/ipc/PluginAsyncSurrogate.cpp +++ /dev/null @@ -1,996 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#include "PluginAsyncSurrogate.h" - -#include "base/message_loop.h" -#include "base/message_pump_default.h" -#include "mozilla/dom/ContentChild.h" -#include "mozilla/plugins/PluginInstanceParent.h" -#include "mozilla/plugins/PluginModuleParent.h" -#include "mozilla/plugins/PluginScriptableObjectParent.h" -#include "mozilla/Telemetry.h" -#include "nsJSNPRuntime.h" -#include "nsNPAPIPlugin.h" -#include "nsNPAPIPluginInstance.h" -#include "nsNPAPIPluginStreamListener.h" -#include "nsPluginInstanceOwner.h" -#include "nsPluginStreamListenerPeer.h" -#include "npruntime.h" -#include "nsThreadUtils.h" -#include "PluginMessageUtils.h" - -namespace mozilla { -namespace plugins { - -AsyncNPObject::AsyncNPObject(PluginAsyncSurrogate* aSurrogate) - : NPObject() - , mSurrogate(aSurrogate) - , mRealObject(nullptr) -{ -} - -AsyncNPObject::~AsyncNPObject() -{ - if (mRealObject) { - --mRealObject->asyncWrapperCount; - parent::_releaseobject(mRealObject); - mRealObject = nullptr; - } -} - -NPObject* -AsyncNPObject::GetRealObject() -{ - if (mRealObject) { - return mRealObject; - } - PluginInstanceParent* instance = PluginInstanceParent::Cast(mSurrogate->GetNPP()); - if (!instance) { - return nullptr; - } - NPObject* realObject = nullptr; - NPError err = instance->NPP_GetValue(NPPVpluginScriptableNPObject, - &realObject); - if (err != NPERR_NO_ERROR) { - return nullptr; - } - if (realObject->_class != PluginScriptableObjectParent::GetClass()) { - NS_ERROR("Don't know what kind of object this is!"); - parent::_releaseobject(realObject); - return nullptr; - } - mRealObject = static_cast<ParentNPObject*>(realObject); - ++mRealObject->asyncWrapperCount; - return mRealObject; -} - -class MOZ_STACK_CLASS RecursionGuard -{ -public: - RecursionGuard() - : mIsRecursive(sHasEntered) - { - if (!mIsRecursive) { - sHasEntered = true; - } - } - - ~RecursionGuard() - { - if (!mIsRecursive) { - sHasEntered = false; - } - } - - inline bool - IsRecursive() - { - return mIsRecursive; - } - -private: - bool mIsRecursive; - static bool sHasEntered; -}; - -bool RecursionGuard::sHasEntered = false; - -PluginAsyncSurrogate::PluginAsyncSurrogate(PluginModuleParent* aParent) - : mParent(aParent) - , mWindow(nullptr) - , mAcceptCalls(false) - , mInstantiated(false) - , mAsyncSetWindow(false) - , mInitCancelled(false) - , mDestroyPending(false) - , mAsyncCallsInFlight(0) -{ - MOZ_ASSERT(aParent); -} - -PluginAsyncSurrogate::~PluginAsyncSurrogate() -{ -} - -bool -PluginAsyncSurrogate::Init(NPMIMEType aPluginType, NPP aInstance, - int16_t aArgc, char* aArgn[], char* aArgv[]) -{ - mMimeType = aPluginType; - nsNPAPIPluginInstance* instance = - static_cast<nsNPAPIPluginInstance*>(aInstance->ndata); - MOZ_ASSERT(instance); - mInstance = instance; - for (int i = 0; i < aArgc; ++i) { - mNames.AppendElement(NullableString(aArgn[i])); - mValues.AppendElement(NullableString(aArgv[i])); - } - return true; -} - -/* static */ bool -PluginAsyncSurrogate::Create(PluginModuleParent* aParent, NPMIMEType aPluginType, - NPP aInstance, int16_t aArgc, - char* aArgn[], char* aArgv[]) -{ - RefPtr<PluginAsyncSurrogate> surrogate(new PluginAsyncSurrogate(aParent)); - if (!surrogate->Init(aPluginType, aInstance, aArgc, aArgn, aArgv)) { - return false; - } - PluginAsyncSurrogate* rawSurrogate = nullptr; - surrogate.forget(&rawSurrogate); - aInstance->pdata = static_cast<PluginDataResolver*>(rawSurrogate); - return true; -} - -/* static */ PluginAsyncSurrogate* -PluginAsyncSurrogate::Cast(NPP aInstance) -{ - MOZ_ASSERT(aInstance); - PluginDataResolver* resolver = - reinterpret_cast<PluginDataResolver*>(aInstance->pdata); - if (!resolver) { - return nullptr; - } - return resolver->GetAsyncSurrogate(); -} - -nsresult -PluginAsyncSurrogate::NPP_New(NPError* aError) -{ - if (!mInstance) { - return NS_ERROR_NULL_POINTER; - } - - nsresult rv = mParent->NPP_NewInternal(mMimeType.BeginWriting(), GetNPP(), - mNames, mValues, nullptr, - aError); - if (NS_FAILED(rv)) { - return rv; - } - return NS_OK; -} - -void -PluginAsyncSurrogate::NP_GetEntryPoints(NPPluginFuncs* aFuncs) -{ - aFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR; - aFuncs->destroy = &NPP_Destroy; - aFuncs->getvalue = &NPP_GetValue; - aFuncs->setvalue = &NPP_SetValue; - aFuncs->newstream = &NPP_NewStream; - aFuncs->setwindow = &NPP_SetWindow; - aFuncs->writeready = &NPP_WriteReady; - aFuncs->event = &NPP_HandleEvent; - aFuncs->destroystream = &NPP_DestroyStream; - // We need to set these so that content code doesn't make assumptions - // about these operations not being supported - aFuncs->write = &PluginModuleParent::NPP_Write; - aFuncs->asfile = &PluginModuleParent::NPP_StreamAsFile; -} - -/* static */ void -PluginAsyncSurrogate::NotifyDestroyPending(NPP aInstance) -{ - PluginAsyncSurrogate* surrogate = Cast(aInstance); - if (!surrogate) { - return; - } - surrogate->NotifyDestroyPending(); -} - -NPP -PluginAsyncSurrogate::GetNPP() -{ - MOZ_ASSERT(mInstance); - NPP npp; - DebugOnly<nsresult> rv = mInstance->GetNPP(&npp); - MOZ_ASSERT(NS_SUCCEEDED(rv)); - return npp; -} - -void -PluginAsyncSurrogate::NotifyDestroyPending() -{ - mDestroyPending = true; - nsJSNPRuntime::OnPluginDestroyPending(GetNPP()); -} - -NPError -PluginAsyncSurrogate::NPP_Destroy(NPSavedData** aSave) -{ - NotifyDestroyPending(); - if (!WaitForInit()) { - return NPERR_GENERIC_ERROR; - } - return PluginModuleParent::NPP_Destroy(GetNPP(), aSave); -} - -NPError -PluginAsyncSurrogate::NPP_GetValue(NPPVariable aVariable, void* aRetval) -{ - if (aVariable != NPPVpluginScriptableNPObject) { - if (!WaitForInit()) { - return NPERR_GENERIC_ERROR; - } - - PluginInstanceParent* instance = PluginInstanceParent::Cast(GetNPP()); - MOZ_ASSERT(instance); - return instance->NPP_GetValue(aVariable, aRetval); - } - - NPObject* npobject = parent::_createobject(GetNPP(), - const_cast<NPClass*>(GetClass())); - MOZ_ASSERT(npobject); - MOZ_ASSERT(npobject->_class == GetClass()); - MOZ_ASSERT(npobject->referenceCount == 1); - *(NPObject**)aRetval = npobject; - return npobject ? NPERR_NO_ERROR : NPERR_GENERIC_ERROR; -} - -NPError -PluginAsyncSurrogate::NPP_SetValue(NPNVariable aVariable, void* aValue) -{ - if (!WaitForInit()) { - return NPERR_GENERIC_ERROR; - } - return PluginModuleParent::NPP_SetValue(GetNPP(), aVariable, aValue); -} - -NPError -PluginAsyncSurrogate::NPP_NewStream(NPMIMEType aType, NPStream* aStream, - NPBool aSeekable, uint16_t* aStype) -{ - mPendingNewStreamCalls.AppendElement(PendingNewStreamCall(aType, aStream, - aSeekable)); - if (aStype) { - *aStype = nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN; - } - return NPERR_NO_ERROR; -} - -NPError -PluginAsyncSurrogate::NPP_SetWindow(NPWindow* aWindow) -{ - mWindow = aWindow; - mAsyncSetWindow = false; - return NPERR_NO_ERROR; -} - -nsresult -PluginAsyncSurrogate::AsyncSetWindow(NPWindow* aWindow) -{ - mWindow = aWindow; - mAsyncSetWindow = true; - return NS_OK; -} - -void -PluginAsyncSurrogate::NPP_Print(NPPrint* aPrintInfo) -{ - // Do nothing, we've got nothing to print right now -} - -int16_t -PluginAsyncSurrogate::NPP_HandleEvent(void* event) -{ - // Drop the event -- the plugin isn't around to handle it - return false; -} - -int32_t -PluginAsyncSurrogate::NPP_WriteReady(NPStream* aStream) -{ - // We'll tell the browser to retry in a bit. Eventually NPP_WriteReady - // will resolve to the plugin's NPP_WriteReady and this should all just work. - return 0; -} - -NPError -PluginAsyncSurrogate::NPP_DestroyStream(NPStream* aStream, NPReason aReason) -{ - for (uint32_t idx = 0, len = mPendingNewStreamCalls.Length(); idx < len; ++idx) { - PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[idx]; - if (curPendingCall.mStream == aStream) { - mPendingNewStreamCalls.RemoveElementAt(idx); - break; - } - } - return NPERR_NO_ERROR; -} - -/* static */ NPError -PluginAsyncSurrogate::NPP_Destroy(NPP aInstance, NPSavedData** aSave) -{ - PluginAsyncSurrogate* rawSurrogate = Cast(aInstance); - MOZ_ASSERT(rawSurrogate); - PluginModuleParent* module = rawSurrogate->GetParent(); - if (module && !module->IsInitialized()) { - // Take ownership of pdata's surrogate since we're going to release it - RefPtr<PluginAsyncSurrogate> surrogate(dont_AddRef(rawSurrogate)); - aInstance->pdata = nullptr; - // We haven't actually called NPP_New yet, so we should remove the - // surrogate for this instance. - bool removeOk = module->RemovePendingSurrogate(surrogate); - MOZ_ASSERT(removeOk); - if (!removeOk) { - return NPERR_GENERIC_ERROR; - } - surrogate->mInitCancelled = true; - return NPERR_NO_ERROR; - } - return rawSurrogate->NPP_Destroy(aSave); -} - -/* static */ NPError -PluginAsyncSurrogate::NPP_GetValue(NPP aInstance, NPPVariable aVariable, - void* aRetval) -{ - PluginAsyncSurrogate* surrogate = Cast(aInstance); - MOZ_ASSERT(surrogate); - return surrogate->NPP_GetValue(aVariable, aRetval); -} - -/* static */ NPError -PluginAsyncSurrogate::NPP_SetValue(NPP aInstance, NPNVariable aVariable, - void* aValue) -{ - PluginAsyncSurrogate* surrogate = Cast(aInstance); - MOZ_ASSERT(surrogate); - return surrogate->NPP_SetValue(aVariable, aValue); -} - -/* static */ NPError -PluginAsyncSurrogate::NPP_NewStream(NPP aInstance, NPMIMEType aType, - NPStream* aStream, NPBool aSeekable, - uint16_t* aStype) -{ - PluginAsyncSurrogate* surrogate = Cast(aInstance); - MOZ_ASSERT(surrogate); - return surrogate->NPP_NewStream(aType, aStream, aSeekable, aStype); -} - -/* static */ NPError -PluginAsyncSurrogate::NPP_SetWindow(NPP aInstance, NPWindow* aWindow) -{ - PluginAsyncSurrogate* surrogate = Cast(aInstance); - MOZ_ASSERT(surrogate); - return surrogate->NPP_SetWindow(aWindow); -} - -/* static */ void -PluginAsyncSurrogate::NPP_Print(NPP aInstance, NPPrint* aPrintInfo) -{ - PluginAsyncSurrogate* surrogate = Cast(aInstance); - MOZ_ASSERT(surrogate); - surrogate->NPP_Print(aPrintInfo); -} - -/* static */ int16_t -PluginAsyncSurrogate::NPP_HandleEvent(NPP aInstance, void* aEvent) -{ - PluginAsyncSurrogate* surrogate = Cast(aInstance); - MOZ_ASSERT(surrogate); - return surrogate->NPP_HandleEvent(aEvent); -} - -/* static */ int32_t -PluginAsyncSurrogate::NPP_WriteReady(NPP aInstance, NPStream* aStream) -{ - PluginAsyncSurrogate* surrogate = Cast(aInstance); - MOZ_ASSERT(surrogate); - return surrogate->NPP_WriteReady(aStream); -} - -/* static */ NPError -PluginAsyncSurrogate::NPP_DestroyStream(NPP aInstance, - NPStream* aStream, - NPReason aReason) -{ - PluginAsyncSurrogate* surrogate = Cast(aInstance); - MOZ_ASSERT(surrogate); - return surrogate->NPP_DestroyStream(aStream, aReason); -} - -PluginAsyncSurrogate::PendingNewStreamCall::PendingNewStreamCall( - NPMIMEType aType, NPStream* aStream, NPBool aSeekable) - : mType(NullableString(aType)) - , mStream(aStream) - , mSeekable(aSeekable) -{ -} - -/* static */ nsNPAPIPluginStreamListener* -PluginAsyncSurrogate::GetStreamListener(NPStream* aStream) -{ - nsNPAPIStreamWrapper* wrapper = - reinterpret_cast<nsNPAPIStreamWrapper*>(aStream->ndata); - if (!wrapper) { - return nullptr; - } - return wrapper->GetStreamListener(); -} - -void -PluginAsyncSurrogate::DestroyAsyncStream(NPStream* aStream) -{ - MOZ_ASSERT(aStream); - nsNPAPIPluginStreamListener* streamListener = GetStreamListener(aStream); - MOZ_ASSERT(streamListener); - // streamListener was suspended during async init. We must resume the stream - // request prior to calling _destroystream for cleanup to work correctly. - streamListener->ResumeRequest(); - if (!mInstance) { - return; - } - parent::_destroystream(GetNPP(), aStream, NPRES_DONE); -} - -/* static */ bool -PluginAsyncSurrogate::SetStreamType(NPStream* aStream, uint16_t aStreamType) -{ - nsNPAPIPluginStreamListener* streamListener = GetStreamListener(aStream); - if (!streamListener) { - return false; - } - return streamListener->SetStreamType(aStreamType); -} - -void -PluginAsyncSurrogate::OnInstanceCreated(PluginInstanceParent* aInstance) -{ - if (!mDestroyPending) { - // If NPP_Destroy has already been called then these streams have already - // been cleaned up on the browser side and are no longer valid. - for (uint32_t i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) { - PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[i]; - uint16_t streamType = NP_NORMAL; - NPError curError = aInstance->NPP_NewStream( - const_cast<char*>(NullableStringGet(curPendingCall.mType)), - curPendingCall.mStream, curPendingCall.mSeekable, - &streamType); - if (curError != NPERR_NO_ERROR) { - // If we failed here then the send failed and we need to clean up - DestroyAsyncStream(curPendingCall.mStream); - } - } - } - mPendingNewStreamCalls.Clear(); - mInstantiated = true; -} - -/** - * During asynchronous initialization it might be necessary to wait for the - * plugin to complete its initialization. This typically occurs when the result - * of a plugin call depends on the plugin being fully instantiated. For example, - * if some JS calls into the plugin, the call must be executed synchronously to - * preserve correctness. - * - * This function works by pumping the plugin's IPC channel for events until - * initialization has completed. - */ -bool -PluginAsyncSurrogate::WaitForInit() -{ - if (mInitCancelled) { - return false; - } - if (mAcceptCalls) { - return true; - } - Telemetry::AutoTimer<Telemetry::BLOCKED_ON_PLUGINASYNCSURROGATE_WAITFORINIT_MS> - timer(mParent->GetHistogramKey()); - bool result = false; - MOZ_ASSERT(mParent); - if (mParent->IsChrome()) { - PluginProcessParent* process = static_cast<PluginModuleChromeParent*>(mParent)->Process(); - MOZ_ASSERT(process); - process->SetCallRunnableImmediately(true); - if (!process->WaitUntilConnected()) { - return false; - } - } - if (!mParent->WaitForIPCConnection()) { - return false; - } - if (!mParent->IsChrome()) { - // For e10s content processes, we need to spin the content channel until the - // protocol bridging has occurred. - dom::ContentChild* cp = dom::ContentChild::GetSingleton(); - mozilla::ipc::MessageChannel* contentChannel = cp->GetIPCChannel(); - MOZ_ASSERT(contentChannel); - while (!mParent->mNPInitialized) { - if (mParent->mShutdown) { - // Since we are pumping the message channel for events, it may be - // possible for module initialization to fail during this loop. We must - // return false if this happens or else we'll be permanently stuck. - return false; - } - result = contentChannel->WaitForIncomingMessage(); - if (!result) { - return result; - } - } - } - mozilla::ipc::MessageChannel* channel = mParent->GetIPCChannel(); - MOZ_ASSERT(channel); - while (!mAcceptCalls) { - if (mInitCancelled) { - // Since we are pumping the message channel for events, it may be - // possible for plugin instantiation to fail during this loop. We must - // return false if this happens or else we'll be permanently stuck. - return false; - } - result = channel->WaitForIncomingMessage(); - if (!result) { - break; - } - } - return result; -} - -void -PluginAsyncSurrogate::AsyncCallDeparting() -{ - ++mAsyncCallsInFlight; - if (!mPluginDestructionGuard) { - mPluginDestructionGuard = MakeUnique<PluginDestructionGuard>(this); - } -} - -void -PluginAsyncSurrogate::AsyncCallArriving() -{ - MOZ_ASSERT(mAsyncCallsInFlight > 0); - if (--mAsyncCallsInFlight == 0) { - mPluginDestructionGuard.reset(nullptr); - } -} - -void -PluginAsyncSurrogate::NotifyAsyncInitFailed() -{ - if (!mDestroyPending) { - // Clean up any pending NewStream requests - for (uint32_t i = 0, len = mPendingNewStreamCalls.Length(); i < len; ++i) { - PendingNewStreamCall& curPendingCall = mPendingNewStreamCalls[i]; - DestroyAsyncStream(curPendingCall.mStream); - } - } - mPendingNewStreamCalls.Clear(); - - // Make sure that any WaitForInit calls on this surrogate will fail, or else - // we'll be perma-blocked - mInitCancelled = true; - - if (!mInstance) { - return; - } - nsPluginInstanceOwner* owner = mInstance->GetOwner(); - if (owner) { - owner->NotifyHostAsyncInitFailed(); - } -} - -// static -NPObject* -PluginAsyncSurrogate::ScriptableAllocate(NPP aInstance, NPClass* aClass) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - if (aClass != GetClass()) { - NS_ERROR("Huh?! Wrong class!"); - return nullptr; - } - - return new AsyncNPObject(Cast(aInstance)); -} - -// static -void -PluginAsyncSurrogate::ScriptableInvalidate(NPObject* aObject) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - if (aObject->_class != GetClass()) { - NS_ERROR("Don't know what kind of object this is!"); - return; - } - - AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject); - if (!object->mSurrogate->WaitForInit()) { - return; - } - NPObject* realObject = object->GetRealObject(); - if (!realObject) { - return; - } - realObject->_class->invalidate(realObject); -} - -// static -void -PluginAsyncSurrogate::ScriptableDeallocate(NPObject* aObject) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - if (aObject->_class != GetClass()) { - NS_ERROR("Don't know what kind of object this is!"); - return; - } - - AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject); - delete object; -} - -// static -bool -PluginAsyncSurrogate::ScriptableHasMethod(NPObject* aObject, - NPIdentifier aName) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - if (aObject->_class != GetClass()) { - NS_ERROR("Don't know what kind of object this is!"); - return false; - } - - RecursionGuard guard; - if (guard.IsRecursive()) { - return false; - } - - AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject); - MOZ_ASSERT(object); - bool checkPluginObject = !object->mSurrogate->mInstantiated && - !object->mSurrogate->mAcceptCalls; - - if (!object->mSurrogate->WaitForInit()) { - return false; - } - NPObject* realObject = object->GetRealObject(); - if (!realObject) { - return false; - } - bool result = realObject->_class->hasMethod(realObject, aName); - if (!result && checkPluginObject) { - // We may be calling into this object because properties in the WebIDL - // object hadn't been set yet. Now that we're further along in - // initialization, we should try again. - const NPNetscapeFuncs* npn = object->mSurrogate->mParent->GetNetscapeFuncs(); - NPObject* pluginObject = nullptr; - NPError nperror = npn->getvalue(object->mSurrogate->GetNPP(), - NPNVPluginElementNPObject, - (void*)&pluginObject); - if (nperror == NPERR_NO_ERROR) { - NPPAutoPusher nppPusher(object->mSurrogate->GetNPP()); - result = pluginObject->_class->hasMethod(pluginObject, aName); - npn->releaseobject(pluginObject); - NPUTF8* idstr = npn->utf8fromidentifier(aName); - npn->memfree(idstr); - } - } - return result; -} - -bool -PluginAsyncSurrogate::GetPropertyHelper(NPObject* aObject, NPIdentifier aName, - bool* aHasProperty, bool* aHasMethod, - NPVariant* aResult) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - - if (!aObject) { - return false; - } - - RecursionGuard guard; - if (guard.IsRecursive()) { - return false; - } - - if (!WaitForInit()) { - return false; - } - - AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject); - NPObject* realObject = object->GetRealObject(); - if (!realObject) { - return false; - } - if (realObject->_class != PluginScriptableObjectParent::GetClass()) { - NS_ERROR("Don't know what kind of object this is!"); - return false; - } - - PluginScriptableObjectParent* actor = - static_cast<ParentNPObject*>(realObject)->parent; - if (!actor) { - return false; - } - bool success = actor->GetPropertyHelper(aName, aHasProperty, aHasMethod, aResult); - if (!success) { - const NPNetscapeFuncs* npn = mParent->GetNetscapeFuncs(); - NPObject* pluginObject = nullptr; - NPError nperror = npn->getvalue(GetNPP(), NPNVPluginElementNPObject, - (void*)&pluginObject); - if (nperror == NPERR_NO_ERROR) { - NPPAutoPusher nppPusher(GetNPP()); - bool hasProperty = nsJSObjWrapper::HasOwnProperty(pluginObject, aName); - NPUTF8* idstr = npn->utf8fromidentifier(aName); - npn->memfree(idstr); - bool hasMethod = false; - if (hasProperty) { - hasMethod = pluginObject->_class->hasMethod(pluginObject, aName); - success = pluginObject->_class->getProperty(pluginObject, aName, aResult); - idstr = npn->utf8fromidentifier(aName); - npn->memfree(idstr); - } - *aHasProperty = hasProperty; - *aHasMethod = hasMethod; - npn->releaseobject(pluginObject); - } - } - return success; -} - -// static -bool -PluginAsyncSurrogate::ScriptableInvoke(NPObject* aObject, - NPIdentifier aName, - const NPVariant* aArgs, - uint32_t aArgCount, - NPVariant* aResult) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - if (aObject->_class != GetClass()) { - NS_ERROR("Don't know what kind of object this is!"); - return false; - } - - AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject); - if (!object->mSurrogate->WaitForInit()) { - return false; - } - NPObject* realObject = object->GetRealObject(); - if (!realObject) { - return false; - } - return realObject->_class->invoke(realObject, aName, aArgs, aArgCount, aResult); -} - -// static -bool -PluginAsyncSurrogate::ScriptableInvokeDefault(NPObject* aObject, - const NPVariant* aArgs, - uint32_t aArgCount, - NPVariant* aResult) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - if (aObject->_class != GetClass()) { - NS_ERROR("Don't know what kind of object this is!"); - return false; - } - - AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject); - if (!object->mSurrogate->WaitForInit()) { - return false; - } - NPObject* realObject = object->GetRealObject(); - if (!realObject) { - return false; - } - return realObject->_class->invokeDefault(realObject, aArgs, aArgCount, aResult); -} - -// static -bool -PluginAsyncSurrogate::ScriptableHasProperty(NPObject* aObject, - NPIdentifier aName) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - if (aObject->_class != GetClass()) { - NS_ERROR("Don't know what kind of object this is!"); - return false; - } - - RecursionGuard guard; - if (guard.IsRecursive()) { - return false; - } - - AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject); - MOZ_ASSERT(object); - bool checkPluginObject = !object->mSurrogate->mInstantiated && - !object->mSurrogate->mAcceptCalls; - - if (!object->mSurrogate->WaitForInit()) { - return false; - } - NPObject* realObject = object->GetRealObject(); - if (!realObject) { - return false; - } - bool result = realObject->_class->hasProperty(realObject, aName); - const NPNetscapeFuncs* npn = object->mSurrogate->mParent->GetNetscapeFuncs(); - NPUTF8* idstr = npn->utf8fromidentifier(aName); - npn->memfree(idstr); - if (!result && checkPluginObject) { - // We may be calling into this object because properties in the WebIDL - // object hadn't been set yet. Now that we're further along in - // initialization, we should try again. - NPObject* pluginObject = nullptr; - NPError nperror = npn->getvalue(object->mSurrogate->GetNPP(), - NPNVPluginElementNPObject, - (void*)&pluginObject); - if (nperror == NPERR_NO_ERROR) { - NPPAutoPusher nppPusher(object->mSurrogate->GetNPP()); - result = nsJSObjWrapper::HasOwnProperty(pluginObject, aName); - npn->releaseobject(pluginObject); - idstr = npn->utf8fromidentifier(aName); - npn->memfree(idstr); - } - } - return result; -} - -// static -bool -PluginAsyncSurrogate::ScriptableGetProperty(NPObject* aObject, - NPIdentifier aName, - NPVariant* aResult) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - // See GetPropertyHelper below. - NS_NOTREACHED("Shouldn't ever call this directly!"); - return false; -} - -// static -bool -PluginAsyncSurrogate::ScriptableSetProperty(NPObject* aObject, - NPIdentifier aName, - const NPVariant* aValue) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - if (aObject->_class != GetClass()) { - NS_ERROR("Don't know what kind of object this is!"); - return false; - } - - AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject); - if (!object->mSurrogate->WaitForInit()) { - return false; - } - NPObject* realObject = object->GetRealObject(); - if (!realObject) { - return false; - } - return realObject->_class->setProperty(realObject, aName, aValue); -} - -// static -bool -PluginAsyncSurrogate::ScriptableRemoveProperty(NPObject* aObject, - NPIdentifier aName) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - if (aObject->_class != GetClass()) { - NS_ERROR("Don't know what kind of object this is!"); - return false; - } - - AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject); - if (!object->mSurrogate->WaitForInit()) { - return false; - } - NPObject* realObject = object->GetRealObject(); - if (!realObject) { - return false; - } - return realObject->_class->removeProperty(realObject, aName); -} - -// static -bool -PluginAsyncSurrogate::ScriptableEnumerate(NPObject* aObject, - NPIdentifier** aIdentifiers, - uint32_t* aCount) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - if (aObject->_class != GetClass()) { - NS_ERROR("Don't know what kind of object this is!"); - return false; - } - - AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject); - if (!object->mSurrogate->WaitForInit()) { - return false; - } - NPObject* realObject = object->GetRealObject(); - if (!realObject) { - return false; - } - return realObject->_class->enumerate(realObject, aIdentifiers, aCount); -} - -// static -bool -PluginAsyncSurrogate::ScriptableConstruct(NPObject* aObject, - const NPVariant* aArgs, - uint32_t aArgCount, - NPVariant* aResult) -{ - PLUGIN_LOG_DEBUG_FUNCTION; - if (aObject->_class != GetClass()) { - NS_ERROR("Don't know what kind of object this is!"); - return false; - } - - AsyncNPObject* object = static_cast<AsyncNPObject*>(aObject); - if (!object->mSurrogate->WaitForInit()) { - return false; - } - NPObject* realObject = object->GetRealObject(); - if (!realObject) { - return false; - } - return realObject->_class->construct(realObject, aArgs, aArgCount, aResult); -} - -const NPClass PluginAsyncSurrogate::sNPClass = { - NP_CLASS_STRUCT_VERSION, - PluginAsyncSurrogate::ScriptableAllocate, - PluginAsyncSurrogate::ScriptableDeallocate, - PluginAsyncSurrogate::ScriptableInvalidate, - PluginAsyncSurrogate::ScriptableHasMethod, - PluginAsyncSurrogate::ScriptableInvoke, - PluginAsyncSurrogate::ScriptableInvokeDefault, - PluginAsyncSurrogate::ScriptableHasProperty, - PluginAsyncSurrogate::ScriptableGetProperty, - PluginAsyncSurrogate::ScriptableSetProperty, - PluginAsyncSurrogate::ScriptableRemoveProperty, - PluginAsyncSurrogate::ScriptableEnumerate, - PluginAsyncSurrogate::ScriptableConstruct -}; - -PushSurrogateAcceptCalls::PushSurrogateAcceptCalls(PluginInstanceParent* aInstance) - : mSurrogate(nullptr) - , mPrevAcceptCallsState(false) -{ - MOZ_ASSERT(aInstance); - mSurrogate = aInstance->GetAsyncSurrogate(); - if (mSurrogate) { - mPrevAcceptCallsState = mSurrogate->SetAcceptingCalls(true); - } -} - -PushSurrogateAcceptCalls::~PushSurrogateAcceptCalls() -{ - if (mSurrogate) { - mSurrogate->SetAcceptingCalls(mPrevAcceptCallsState); - } -} - -} // namespace plugins -} // namespace mozilla
deleted file mode 100644 --- a/dom/plugins/ipc/PluginAsyncSurrogate.h +++ /dev/null @@ -1,187 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef dom_plugins_ipc_PluginAsyncSurrogate_h -#define dom_plugins_ipc_PluginAsyncSurrogate_h - -#include "mozilla/UniquePtr.h" -#include "npapi.h" -#include "npfunctions.h" -#include "npruntime.h" -#include "nsISupportsImpl.h" -#include "nsPluginHost.h" -#include "nsString.h" -#include "nsTArray.h" -#include "PluginDataResolver.h" - -namespace mozilla { -namespace plugins { - -struct ParentNPObject; -class PluginInstanceParent; -class PluginModuleParent; - -class PluginAsyncSurrogate : public PluginDataResolver -{ -public: - NS_INLINE_DECL_REFCOUNTING(PluginAsyncSurrogate) - - bool Init(NPMIMEType aPluginType, NPP aInstance, - int16_t aArgc, char* aArgn[], char* aArgv[]); - nsresult NPP_New(NPError* aError); - NPError NPP_Destroy(NPSavedData** aSave); - NPError NPP_GetValue(NPPVariable aVariable, void* aRetval); - NPError NPP_SetValue(NPNVariable aVariable, void* aValue); - NPError NPP_NewStream(NPMIMEType aType, NPStream* aStream, NPBool aSeekable, - uint16_t* aStype); - NPError NPP_SetWindow(NPWindow* aWindow); - nsresult AsyncSetWindow(NPWindow* aWindow); - void NPP_Print(NPPrint* aPrintInfo); - int16_t NPP_HandleEvent(void* aEvent); - int32_t NPP_WriteReady(NPStream* aStream); - NPError NPP_DestroyStream(NPStream* aStream, NPReason aReason); - void OnInstanceCreated(PluginInstanceParent* aInstance); - static bool Create(PluginModuleParent* aParent, NPMIMEType aPluginType, - NPP aInstance, int16_t aArgc, - char* aArgn[], char* aArgv[]); - static const NPClass* GetClass() { return &sNPClass; } - static void NP_GetEntryPoints(NPPluginFuncs* aFuncs); - static PluginAsyncSurrogate* Cast(NPP aInstance); - static void NotifyDestroyPending(NPP aInstance); - void NotifyDestroyPending(); - - virtual PluginAsyncSurrogate* - GetAsyncSurrogate() { return this; } - - virtual PluginInstanceParent* - GetInstance() { return nullptr; } - - NPP GetNPP(); - - bool GetPropertyHelper(NPObject* aObject, NPIdentifier aName, - bool* aHasProperty, bool* aHasMethod, - NPVariant* aResult); - - PluginModuleParent* GetParent() { return mParent; } - - bool IsDestroyPending() const { return mDestroyPending; } - - bool SetAcceptingCalls(bool aAccept) - { - bool prevState = mAcceptCalls; - if (mInstantiated) { - aAccept = true; - } - mAcceptCalls = aAccept; - return prevState; - } - - void AsyncCallDeparting(); - void AsyncCallArriving(); - - void NotifyAsyncInitFailed(); - void DestroyAsyncStream(NPStream* aStream); - -private: - explicit PluginAsyncSurrogate(PluginModuleParent* aParent); - virtual ~PluginAsyncSurrogate(); - - bool WaitForInit(); - - static bool SetStreamType(NPStream* aStream, uint16_t aStreamType); - - static NPError NPP_Destroy(NPP aInstance, NPSavedData** aSave); - static NPError NPP_GetValue(NPP aInstance, NPPVariable aVariable, void* aRetval); - static NPError NPP_SetValue(NPP aInstance, NPNVariable aVariable, void* aValue); - static NPError NPP_NewStream(NPP aInstance, NPMIMEType aType, NPStream* aStream, - NPBool aSeekable, uint16_t* aStype); - static NPError NPP_SetWindow(NPP aInstance, NPWindow* aWindow); - static void NPP_Print(NPP aInstance, NPPrint* aPrintInfo); - static int16_t NPP_HandleEvent(NPP aInstance, void* aEvent); - static int32_t NPP_WriteReady(NPP aInstance, NPStream* aStream); - static NPError NPP_DestroyStream(NPP aInstance, NPStream* aStream, - NPReason aReason); - - static NPObject* ScriptableAllocate(NPP aInstance, NPClass* aClass); - static void ScriptableInvalidate(NPObject* aObject); - static void ScriptableDeallocate(NPObject* aObject); - static bool ScriptableHasMethod(NPObject* aObject, NPIdentifier aName); - static bool ScriptableInvoke(NPObject* aObject, NPIdentifier aName, - const NPVariant* aArgs, uint32_t aArgCount, - NPVariant* aResult); - static bool ScriptableInvokeDefault(NPObject* aObject, const NPVariant* aArgs, - uint32_t aArgCount, NPVariant* aResult); - static bool ScriptableHasProperty(NPObject* aObject, NPIdentifier aName); - static bool ScriptableGetProperty(NPObject* aObject, NPIdentifier aName, - NPVariant* aResult); - static bool ScriptableSetProperty(NPObject* aObject, NPIdentifier aName, - const NPVariant* aValue); - static bool ScriptableRemoveProperty(NPObject* aObject, NPIdentifier aName); - static bool ScriptableEnumerate(NPObject* aObject, NPIdentifier** aIdentifiers, - uint32_t* aCount); - static bool ScriptableConstruct(NPObject* aObject, const NPVariant* aArgs, - uint32_t aArgCount, NPVariant* aResult); - static nsNPAPIPluginStreamListener* GetStreamListener(NPStream* aStream); - -private: - struct PendingNewStreamCall - { - PendingNewStreamCall(NPMIMEType aType, NPStream* aStream, NPBool aSeekable); - ~PendingNewStreamCall() {} - nsCString mType; - NPStream* mStream; - NPBool mSeekable; - }; - -private: - PluginModuleParent* mParent; - // These values are used to construct the plugin instance - nsCString mMimeType; - mozilla::WeakPtr<nsNPAPIPluginInstance> mInstance; - InfallibleTArray<nsCString> mNames; - InfallibleTArray<nsCString> mValues; - // This is safe to store as a pointer because the spec says it will remain - // valid until destruction or a subsequent NPP_SetWindow call. - NPWindow* mWindow; - nsTArray<PendingNewStreamCall> mPendingNewStreamCalls; - UniquePtr<PluginDestructionGuard> mPluginDestructionGuard; - - bool mAcceptCalls; - bool mInstantiated; - bool mAsyncSetWindow; - bool mInitCancelled; - bool mDestroyPending; - int32_t mAsyncCallsInFlight; - - static const NPClass sNPClass; -}; - -struct AsyncNPObject : NPObject -{ - explicit AsyncNPObject(PluginAsyncSurrogate* aSurrogate); - ~AsyncNPObject(); - - NPObject* GetRealObject(); - - RefPtr<PluginAsyncSurrogate> mSurrogate; - ParentNPObject* mRealObject; -}; - -class MOZ_STACK_CLASS PushSurrogateAcceptCalls -{ -public: - explicit PushSurrogateAcceptCalls(PluginInstanceParent* aInstance); - ~PushSurrogateAcceptCalls(); - -private: - PluginAsyncSurrogate* mSurrogate; - bool mPrevAcceptCallsState; -}; - -} // namespace plugins -} // namespace mozilla - -#endif // dom_plugins_ipc_PluginAsyncSurrogate_h
--- a/dom/plugins/ipc/PluginBridge.h +++ b/dom/plugins/ipc/PluginBridge.h @@ -23,17 +23,17 @@ class Endpoint; } // namespace ipc namespace plugins { class PPluginModuleParent; bool SetupBridge(uint32_t aPluginId, dom::ContentParent* aContentParent, - bool aForceBridgeNow, nsresult* aResult, uint32_t* aRunID, + nsresult* aResult, uint32_t* aRunID, ipc::Endpoint<PPluginModuleParent>* aEndpoint); nsresult FindPluginsForContent(uint32_t aPluginEpoch, nsTArray<PluginTag>* aPlugins, nsTArray<FakePluginTag>* aFakePlugins, uint32_t* aNewPluginEpoch);
deleted file mode 100644 --- a/dom/plugins/ipc/PluginDataResolver.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -#ifndef dom_plugins_ipc_PluginDataResolver_h -#define dom_plugins_ipc_PluginDataResolver_h - -namespace mozilla { -namespace plugins { - -class PluginAsyncSurrogate; -class PluginInstanceParent; - -class PluginDataResolver -{ -public: - virtual PluginAsyncSurrogate* GetAsyncSurrogate() = 0; - virtual PluginInstanceParent* GetInstance() = 0; -}; - -} // namespace plugins -} // namespace mozilla - -#endif // dom_plugins_ipc_PluginDataResolver_h
--- a/dom/plugins/ipc/PluginInstanceChild.cpp +++ b/dom/plugins/ipc/PluginInstanceChild.cpp @@ -2503,62 +2503,16 @@ PluginInstanceChild::AnswerNPP_NewStream NPError* rv, uint16_t* stype) { *rv = DoNPP_NewStream(static_cast<BrowserStreamChild*>(actor), mimeType, seekable, stype); return IPC_OK(); } -class NewStreamAsyncCall : public ChildAsyncCall -{ -public: - NewStreamAsyncCall(PluginInstanceChild* aInstance, - BrowserStreamChild* aBrowserStreamChild, - const nsCString& aMimeType, - const bool aSeekable) - : ChildAsyncCall(aInstance, nullptr, nullptr) - , mBrowserStreamChild(aBrowserStreamChild) - , mMimeType(aMimeType) - , mSeekable(aSeekable) - { - } - - NS_IMETHOD Run() override - { - RemoveFromAsyncList(); - - uint16_t stype = NP_NORMAL; - NPError rv = mInstance->DoNPP_NewStream(mBrowserStreamChild, mMimeType, - mSeekable, &stype); - DebugOnly<bool> sendOk = - mBrowserStreamChild->SendAsyncNPP_NewStreamResult(rv, stype); - MOZ_ASSERT(sendOk); - return NS_OK; - } - -private: - BrowserStreamChild* mBrowserStreamChild; - const nsCString mMimeType; - const bool mSeekable; -}; - -mozilla::ipc::IPCResult -PluginInstanceChild::RecvAsyncNPP_NewStream(PBrowserStreamChild* actor, - const nsCString& mimeType, - const bool& seekable) -{ - // Reusing ChildAsyncCall so that the task is cancelled properly on Destroy - BrowserStreamChild* child = static_cast<BrowserStreamChild*>(actor); - RefPtr<NewStreamAsyncCall> task = - new NewStreamAsyncCall(this, child, mimeType, seekable); - PostChildAsyncCall(task.forget()); - return IPC_OK(); -} - PBrowserStreamChild* PluginInstanceChild::AllocPBrowserStreamChild(const nsCString& url, const uint32_t& length, const uint32_t& lastmodified, PStreamNotifyChild* notifyData, const nsCString& headers) { AssertPluginThread();
--- a/dom/plugins/ipc/PluginInstanceChild.h +++ b/dom/plugins/ipc/PluginInstanceChild.h @@ -160,22 +160,16 @@ protected: virtual mozilla::ipc::IPCResult AnswerNPP_NewStream( PBrowserStreamChild* actor, const nsCString& mimeType, const bool& seekable, NPError* rv, uint16_t* stype) override; - virtual mozilla::ipc::IPCResult - RecvAsyncNPP_NewStream( - PBrowserStreamChild* actor, - const nsCString& mimeType, - const bool& seekable) override; - virtual PBrowserStreamChild* AllocPBrowserStreamChild(const nsCString& url, const uint32_t& length, const uint32_t& lastmodified, PStreamNotifyChild* notifyData, const nsCString& headers) override; virtual bool
--- a/dom/plugins/ipc/PluginInstanceParent.cpp +++ b/dom/plugins/ipc/PluginInstanceParent.cpp @@ -7,17 +7,16 @@ #include "mozilla/DebugOnly.h" #include <stdint.h> // for intptr_t #include "mozilla/BasicEvents.h" #include "mozilla/Preferences.h" #include "mozilla/Telemetry.h" #include "PluginInstanceParent.h" #include "BrowserStreamParent.h" -#include "PluginAsyncSurrogate.h" #include "PluginBackgroundDestroyer.h" #include "PluginModuleParent.h" #include "PluginStreamParent.h" #include "StreamNotifyParent.h" #include "npfunctions.h" #include "nsAutoPtr.h" #include "gfxASurface.h" #include "gfxContext.h" @@ -110,18 +109,16 @@ PluginInstanceParent::LookupPluginInstan } #endif PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent, NPP npp, const nsCString& aMimeType, const NPNetscapeFuncs* npniface) : mParent(parent) - , mSurrogate(PluginAsyncSurrogate::Cast(npp)) - , mUseSurrogate(true) , mNPP(npp) , mNPNIface(npniface) , mWindowType(NPWindowTypeWindow) , mDrawingModel(kDefaultDrawingModel) , mLastRecordedDrawingModel(-1) , mFrameID(0) #if defined(OS_WIN) , mPluginHWND(nullptr) @@ -1218,22 +1215,16 @@ PluginInstanceParent::GetScrollCaptureCo RefPtr<ImageContainer> container = GetImageContainer(); container.forget(aContainer); return NS_OK; } #endif // XP_WIN -PluginAsyncSurrogate* -PluginInstanceParent::GetAsyncSurrogate() -{ - return mSurrogate; -} - bool PluginInstanceParent::CreateBackground(const nsIntSize& aSize) { MOZ_ASSERT(!mBackground, "Already have a background"); // XXX refactor me #if defined(MOZ_X11) @@ -1770,32 +1761,22 @@ PluginInstanceParent::NPP_NewStream(NPMI NullableString(stream->headers))) { return NPERR_GENERIC_ERROR; } Telemetry::AutoTimer<Telemetry::BLOCKED_ON_PLUGIN_STREAM_INIT_MS> timer(Module()->GetHistogramKey()); NPError err = NPERR_NO_ERROR; - if (mParent->IsStartingAsync()) { - MOZ_ASSERT(mSurrogate); - mSurrogate->AsyncCallDeparting(); - if (SendAsyncNPP_NewStream(bs, NullableString(type), seekable)) { - *stype = nsPluginStreamListenerPeer::STREAM_TYPE_UNKNOWN; - } else { - err = NPERR_GENERIC_ERROR; - } - } else { - bs->SetAlive(); - if (!CallNPP_NewStream(bs, NullableString(type), seekable, &err, stype)) { - err = NPERR_GENERIC_ERROR; - } - if (NPERR_NO_ERROR != err) { - Unused << PBrowserStreamParent::Send__delete__(bs); - } + bs->SetAlive(); + if (!CallNPP_NewStream(bs, NullableString(type), seekable, &err, stype)) { + err = NPERR_GENERIC_ERROR; + } + if (NPERR_NO_ERROR != err) { + Unused << PBrowserStreamParent::Send__delete__(bs); } return err; } NPError PluginInstanceParent::NPP_DestroyStream(NPStream* stream, NPReason reason) { @@ -2047,52 +2028,16 @@ PluginInstanceParent::GetOwner() nsNPAPIPluginInstance* inst = static_cast<nsNPAPIPluginInstance*>(mNPP->ndata); if (!inst) { return nullptr; } return inst->GetOwner(); } mozilla::ipc::IPCResult -PluginInstanceParent::RecvAsyncNPP_NewResult(const NPError& aResult) -{ - // NB: mUseSurrogate must be cleared before doing anything else, especially - // calling NPP_SetWindow! - mUseSurrogate = false; - - mSurrogate->AsyncCallArriving(); - if (aResult == NPERR_NO_ERROR) { - mSurrogate->SetAcceptingCalls(true); - } - - // It is possible for a plugin instance to outlive its owner (eg. When a - // PluginDestructionGuard was on the stack at the time the owner was being - // destroyed). We need to handle that case. - nsPluginInstanceOwner* owner = GetOwner(); - if (!owner) { - // We can't do anything at this point, just return. Any pending browser - // streams will be cleaned up when the plugin instance is destroyed. - return IPC_OK(); - } - - if (aResult != NPERR_NO_ERROR) { - mSurrogate->NotifyAsyncInitFailed(); - return IPC_OK(); - } - - // Now we need to do a bunch of exciting post-NPP_New housekeeping. - owner->NotifyHostCreateWidget(); - - MOZ_ASSERT(mSurrogate); - mSurrogate->OnInstanceCreated(this); - - return IPC_OK(); -} - -mozilla::ipc::IPCResult PluginInstanceParent::RecvSetNetscapeWindowAsParent(const NativeWindowHandle& childWindow) { #if defined(XP_WIN) nsPluginInstanceOwner* owner = GetOwner(); if (!owner || NS_FAILED(owner->SetNetscapeWindowAsParent(childWindow))) { NS_WARNING("Failed to set Netscape window as parent."); } @@ -2330,38 +2275,31 @@ PluginInstanceParent::AnswerPluginFocusC return IPC_OK(); #else NS_NOTREACHED("PluginInstanceParent::AnswerPluginFocusChange not implemented!"); return IPC_FAIL_NO_REASON(this); #endif } PluginInstanceParent* -PluginInstanceParent::Cast(NPP aInstance, PluginAsyncSurrogate** aSurrogate) +PluginInstanceParent::Cast(NPP aInstance) { - PluginDataResolver* resolver = - static_cast<PluginDataResolver*>(aInstance->pdata); + auto ip = static_cast<PluginInstanceParent*>(aInstance->pdata); // If the plugin crashed and the PluginInstanceParent was deleted, // aInstance->pdata will be nullptr. - if (!resolver) { + if (!ip) { return nullptr; } - PluginInstanceParent* instancePtr = resolver->GetInstance(); - - if (instancePtr && aInstance != instancePtr->mNPP) { + if (aInstance != ip->mNPP) { MOZ_CRASH("Corrupted plugin data."); } - if (aSurrogate) { - *aSurrogate = resolver->GetAsyncSurrogate(); - } - - return instancePtr; + return ip; } mozilla::ipc::IPCResult PluginInstanceParent::RecvGetCompositionString(const uint32_t& aIndex, nsTArray<uint8_t>* aDist, int32_t* aLength) { #if defined(OS_WIN)
--- a/dom/plugins/ipc/PluginInstanceParent.h +++ b/dom/plugins/ipc/PluginInstanceParent.h @@ -16,17 +16,16 @@ #elif defined(MOZ_WIDGET_COCOA) #include "mozilla/gfx/QuartzSupport.h" #endif #include "npfunctions.h" #include "nsDataHashtable.h" #include "nsHashKeys.h" #include "nsRect.h" -#include "PluginDataResolver.h" #include "mozilla/Unused.h" #include "mozilla/EventForwards.h" class gfxASurface; class gfxContext; class nsPluginInstanceOwner; @@ -38,17 +37,16 @@ class TextureClientRecycleAllocator; } // namespace layers namespace plugins { class PBrowserStreamParent; class PluginModuleParent; class D3D11SurfaceHolder; class PluginInstanceParent : public PPluginInstanceParent - , public PluginDataResolver { friend class PluginModuleParent; friend class BrowserStreamParent; friend class PluginStreamParent; friend class StreamNotifyParent; #if defined(XP_WIN) public: @@ -237,19 +235,16 @@ public: double *destX, double *destY, bool *result) override; virtual mozilla::ipc::IPCResult RecvRedrawPlugin() override; virtual mozilla::ipc::IPCResult - RecvAsyncNPP_NewResult(const NPError& aResult) override; - - virtual mozilla::ipc::IPCResult RecvSetNetscapeWindowAsParent(const NativeWindowHandle& childWindow) override; NPError NPP_SetWindow(const NPWindow* aWindow); NPError NPP_GetValue(NPPVariable variable, void* retval); NPError NPP_SetValue(NPNVariable variable, void* value); void NPP_URLRedirectNotify(const char* url, int32_t status, @@ -286,22 +281,16 @@ public: GetActorForNPObject(NPObject* aObject); NPP GetNPP() { return mNPP; } - bool - UseSurrogate() const - { - return mUseSurrogate; - } - void GetSrcAttribute(nsACString& aOutput) const { aOutput = mSrcAttribute; } virtual mozilla::ipc::IPCResult AnswerPluginFocusChange(const bool& gotFocus) override; @@ -322,22 +311,17 @@ public: #if defined(XP_WIN) nsresult SetScrollCaptureId(uint64_t aScrollCaptureId); nsresult GetScrollCaptureContainer(mozilla::layers::ImageContainer** aContainer); #endif void DidComposite(); bool IsUsingDirectDrawing(); - virtual PluginAsyncSurrogate* GetAsyncSurrogate() override; - - virtual PluginInstanceParent* GetInstance() override { return this; } - - static PluginInstanceParent* Cast(NPP instance, - PluginAsyncSurrogate** aSurrogate = nullptr); + static PluginInstanceParent* Cast(NPP instance); // for IME hook virtual mozilla::ipc::IPCResult RecvGetCompositionString(const uint32_t& aIndex, nsTArray<uint8_t>* aBuffer, int32_t* aLength) override; virtual mozilla::ipc::IPCResult RecvSetCandidateWindow( @@ -377,18 +361,16 @@ private: void SetCurrentImage(layers::Image* aImage); // Update Telemetry with the current drawing model. void RecordDrawingModel(); private: PluginModuleParent* mParent; - RefPtr<PluginAsyncSurrogate> mSurrogate; - bool mUseSurrogate; NPP mNPP; const NPNetscapeFuncs* mNPNIface; nsCString mSrcAttribute; NPWindowType mWindowType; int16_t mDrawingModel; // Since plugins may request different drawing models to find a compatible // one, we only record the drawing model after a SetWindow call and if the
--- a/dom/plugins/ipc/PluginModuleChild.cpp +++ b/dom/plugins/ipc/PluginModuleChild.cpp @@ -1837,26 +1837,16 @@ PluginModuleChild::AnswerNP_GetEntryPoin mozilla::ipc::IPCResult PluginModuleChild::AnswerNP_Initialize(const PluginSettings& aSettings, NPError* rv) { *rv = DoNP_Initialize(aSettings); return IPC_OK(); } -mozilla::ipc::IPCResult -PluginModuleChild::RecvAsyncNP_Initialize(const PluginSettings& aSettings) -{ - NPError error = DoNP_Initialize(aSettings); - if (!SendNP_InitializeResult(error)) { - return IPC_FAIL_NO_REASON(this); - } - return IPC_OK(); -} - NPError PluginModuleChild::DoNP_Initialize(const PluginSettings& aSettings) { PLUGIN_LOG_DEBUG_METHOD; AssertPluginThread(); MOZ_ASSERT(mIsChrome); mCachedSettings = aSettings; @@ -2381,61 +2371,16 @@ PluginModuleChild::AnswerSyncNPP_New(PPl PLUGIN_LOG_DEBUG_METHOD; PluginInstanceChild* childInstance = reinterpret_cast<PluginInstanceChild*>(aActor); AssertPluginThread(); *rv = childInstance->DoNPP_New(); return IPC_OK(); } -class AsyncNewResultSender : public ChildAsyncCall -{ -public: - AsyncNewResultSender(PluginInstanceChild* aInstance, NPError aResult) - : ChildAsyncCall(aInstance, nullptr, nullptr) - , mResult(aResult) - { - } - - NS_IMETHOD Run() override - { - RemoveFromAsyncList(); - DebugOnly<bool> sendOk = mInstance->SendAsyncNPP_NewResult(mResult); - MOZ_ASSERT(sendOk); - return NS_OK; - } - -private: - NPError mResult; -}; - -static void -RunAsyncNPP_New(void* aChildInstance) -{ - MOZ_ASSERT(aChildInstance); - PluginInstanceChild* childInstance = - static_cast<PluginInstanceChild*>(aChildInstance); - NPError rv = childInstance->DoNPP_New(); - RefPtr<AsyncNewResultSender> task = - new AsyncNewResultSender(childInstance, rv); - childInstance->PostChildAsyncCall(task.forget()); -} - -mozilla::ipc::IPCResult -PluginModuleChild::RecvAsyncNPP_New(PPluginInstanceChild* aActor) -{ - PLUGIN_LOG_DEBUG_METHOD; - PluginInstanceChild* childInstance = - reinterpret_cast<PluginInstanceChild*>(aActor); - AssertPluginThread(); - // We don't want to run NPP_New async from within nested calls - childInstance->AsyncCall(&RunAsyncNPP_New, childInstance); - return IPC_OK(); -} - bool PluginModuleChild::DeallocPPluginInstanceChild(PPluginInstanceChild* aActor) { PLUGIN_LOG_DEBUG_METHOD; AssertPluginThread(); delete aActor;
--- a/dom/plugins/ipc/PluginModuleChild.h +++ b/dom/plugins/ipc/PluginModuleChild.h @@ -67,20 +67,18 @@ protected: virtual mozilla::ipc::IPCResult RecvSettingChanged(const PluginSettings& aSettings) override; // Implement the PPluginModuleChild interface virtual mozilla::ipc::IPCResult RecvInitProfiler(Endpoint<mozilla::PProfilerChild>&& aEndpoint) override; virtual mozilla::ipc::IPCResult RecvDisableFlashProtectedMode() override; virtual mozilla::ipc::IPCResult AnswerNP_GetEntryPoints(NPError* rv) override; virtual mozilla::ipc::IPCResult AnswerNP_Initialize(const PluginSettings& aSettings, NPError* rv) override; - virtual mozilla::ipc::IPCResult RecvAsyncNP_Initialize(const PluginSettings& aSettings) override; virtual mozilla::ipc::IPCResult AnswerSyncNPP_New(PPluginInstanceChild* aActor, NPError* rv) override; - virtual mozilla::ipc::IPCResult RecvAsyncNPP_New(PPluginInstanceChild* aActor) override; virtual mozilla::ipc::IPCResult RecvInitPluginModuleChild(Endpoint<PPluginModuleChild>&& endpoint) override; virtual PPluginInstanceChild* AllocPPluginInstanceChild(const nsCString& aMimeType, const InfallibleTArray<nsCString>& aNames, const InfallibleTArray<nsCString>& aValues)
--- a/dom/plugins/ipc/PluginModuleParent.cpp +++ b/dom/plugins/ipc/PluginModuleParent.cpp @@ -9,17 +9,16 @@ #include "base/process_util.h" #include "mozilla/Attributes.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/ipc/GeckoChildProcessHost.h" #include "mozilla/ipc/MessageChannel.h" #include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/plugins/BrowserStreamParent.h" -#include "mozilla/plugins/PluginAsyncSurrogate.h" #include "mozilla/plugins/PluginBridge.h" #include "mozilla/plugins/PluginInstanceParent.h" #include "mozilla/Preferences.h" #include "mozilla/ProcessHangMonitor.h" #include "mozilla/Services.h" #include "mozilla/Telemetry.h" #include "mozilla/Unused.h" #include "nsAutoPtr.h" @@ -72,63 +71,52 @@ using namespace mozilla::plugins::parent using namespace CrashReporter; #endif static const char kContentTimeoutPref[] = "dom.ipc.plugins.contentTimeoutSecs"; static const char kChildTimeoutPref[] = "dom.ipc.plugins.timeoutSecs"; static const char kParentTimeoutPref[] = "dom.ipc.plugins.parentTimeoutSecs"; static const char kLaunchTimeoutPref[] = "dom.ipc.plugins.processLaunchTimeoutSecs"; -static const char kAsyncInitPref[] = "dom.ipc.plugins.asyncInit.enabled"; #ifdef XP_WIN static const char kHangUITimeoutPref[] = "dom.ipc.plugins.hangUITimeoutSecs"; static const char kHangUIMinDisplayPref[] = "dom.ipc.plugins.hangUIMinDisplaySecs"; #define CHILD_TIMEOUT_PREF kHangUITimeoutPref #else #define CHILD_TIMEOUT_PREF kChildTimeoutPref #endif bool mozilla::plugins::SetupBridge(uint32_t aPluginId, dom::ContentParent* aContentParent, - bool aForceBridgeNow, nsresult* rv, uint32_t* runID, ipc::Endpoint<PPluginModuleParent>* aEndpoint) { AUTO_PROFILER_LABEL("plugins::SetupBridge", OTHER); if (NS_WARN_IF(!rv) || NS_WARN_IF(!runID)) { return false; } - PluginModuleChromeParent::ClearInstantiationFlag(); RefPtr<nsPluginHost> host = nsPluginHost::GetInst(); RefPtr<nsNPAPIPlugin> plugin; *rv = host->GetPluginForContentProcess(aPluginId, getter_AddRefs(plugin)); if (NS_FAILED(*rv)) { return true; } PluginModuleChromeParent* chromeParent = static_cast<PluginModuleChromeParent*>(plugin->GetLibrary()); /* * We can't accumulate BLOCKED_ON_PLUGIN_MODULE_INIT_MS until here because * its histogram key is not available until *after* NP_Initialize. */ chromeParent->AccumulateModuleInitBlockedTime(); *rv = chromeParent->GetRunID(runID); if (NS_FAILED(*rv)) { return true; } - if (chromeParent->IsStartingAsync()) { - chromeParent->SetContentParent(aContentParent); - } - if (!aForceBridgeNow && chromeParent->IsStartingAsync() && - PluginModuleChromeParent::DidInstantiate()) { - // We'll handle the bridging asynchronously - return true; - } ipc::Endpoint<PPluginModuleParent> parent; ipc::Endpoint<PPluginModuleChild> child; *rv = PPluginModule::CreateEndpoints(aContentParent->OtherPid(), chromeParent->OtherPid(), &parent, &child); if (NS_FAILED(*rv)) { @@ -204,26 +192,24 @@ private: MessageLoop* mMainThreadMsgLoop; }; #endif // MOZ_CRASHREPORTER_INJECTOR namespace { /** - * Objects of this class remain linked until either an error occurs in the - * plugin initialization sequence, or until - * PluginModuleContentParent::OnLoadPluginResult has completed executing. + * Objects of this class remain linked until an error occurs in the + * plugin initialization sequence. */ class PluginModuleMapping : public PRCList { public: - explicit PluginModuleMapping(uint32_t aPluginId, bool aAllowAsyncInit) + explicit PluginModuleMapping(uint32_t aPluginId) : mPluginId(aPluginId) - , mAllowAsyncInit(aAllowAsyncInit) , mProcessIdValid(false) , mModule(nullptr) , mChannelOpened(false) { MOZ_COUNT_CTOR(PluginModuleMapping); PR_INIT_CLIST(this); PR_APPEND_LINK(this, &sModuleListHead); } @@ -245,17 +231,17 @@ public: { mChannelOpened = true; } PluginModuleContentParent* GetModule() { if (!mModule) { - mModule = new PluginModuleContentParent(mAllowAsyncInit); + mModule = new PluginModuleContentParent(); } return mModule; } static PluginModuleMapping* AssociateWithProcessId(uint32_t aPluginId, base::ProcessId aProcessId) { PluginModuleMapping* mapping = @@ -332,17 +318,16 @@ private: AssociateWithProcessId(base::ProcessId aProcessId) { MOZ_ASSERT(!mProcessIdValid); mProcessId = aProcessId; mProcessIdValid = true; } uint32_t mPluginId; - bool mAllowAsyncInit; bool mProcessIdValid; base::ProcessId mProcessId; PluginModuleContentParent* mModule; bool mChannelOpened; friend class NotifyLoadingModule; static PRCList sModuleListHead; @@ -413,18 +398,17 @@ mozilla::plugins::TerminatePlugin(uint32 } } /* static */ PluginLibrary* PluginModuleContentParent::LoadModule(uint32_t aPluginId, nsPluginTag* aPluginTag) { PluginModuleMapping::NotifyLoadingModule loadingModule; - nsAutoPtr<PluginModuleMapping> mapping( - new PluginModuleMapping(aPluginId, aPluginTag->mSupportsAsyncInit)); + nsAutoPtr<PluginModuleMapping> mapping(new PluginModuleMapping(aPluginId)); MOZ_ASSERT(XRE_IsContentProcess()); /* * We send a LoadPlugin message to the chrome process using an intr * message. Before it sends its response, it sends a message to create * PluginModuleParent instance. That message is handled by * PluginModuleContentParent::Initialize, which saves the instance in @@ -455,25 +439,16 @@ PluginModuleContentParent::LoadModule(ui parent->mPluginId = aPluginId; parent->mRunID = runID; return parent; } /* static */ void -PluginModuleContentParent::AssociatePluginId(uint32_t aPluginId, - base::ProcessId aOtherPid) -{ - DebugOnly<PluginModuleMapping*> mapping = - PluginModuleMapping::AssociateWithProcessId(aPluginId, aOtherPid); - MOZ_ASSERT(mapping); -} - -/* static */ void PluginModuleContentParent::Initialize(Endpoint<PPluginModuleParent>&& aEndpoint) { nsAutoPtr<PluginModuleMapping> moduleMapping( PluginModuleMapping::Resolve(aEndpoint.OtherPid())); MOZ_ASSERT(moduleMapping); PluginModuleContentParent* parent = moduleMapping->GetModule(); MOZ_ASSERT(parent); @@ -490,94 +465,60 @@ PluginModuleContentParent::Initialize(En TimeoutChanged(kContentTimeoutPref, parent); // moduleMapping is linked into PluginModuleMapping::sModuleListHead and is // needed later, so since this function is returning successfully we // forget it here. moduleMapping.forget(); } -/* static */ void -PluginModuleContentParent::OnLoadPluginResult(const uint32_t& aPluginId, - const bool& aResult, - Endpoint<PPluginModuleParent>&& aEndpoint) -{ - Initialize(Move(aEndpoint)); - nsAutoPtr<PluginModuleMapping> moduleMapping( - PluginModuleMapping::FindModuleByPluginId(aPluginId)); - MOZ_ASSERT(moduleMapping); - PluginModuleContentParent* parent = moduleMapping->GetModule(); - MOZ_ASSERT(parent); - parent->RecvNP_InitializeResult(aResult ? NPERR_NO_ERROR - : NPERR_GENERIC_ERROR); -} - -void -PluginModuleChromeParent::SetContentParent(dom::ContentParent* aContentParent) -{ - // mContentParent is to be used ONLY during async plugin init! - MOZ_ASSERT(aContentParent && mIsStartingAsync); - mContentParent = aContentParent; -} - -bool -PluginModuleChromeParent::SendAssociatePluginId() -{ - MOZ_ASSERT(mContentParent); - return mContentParent->SendAssociatePluginId(mPluginId, OtherPid()); -} - // static PluginLibrary* PluginModuleChromeParent::LoadModule(const char* aFilePath, uint32_t aPluginId, nsPluginTag* aPluginTag) { PLUGIN_LOG_DEBUG_FUNCTION; nsAutoPtr<PluginModuleChromeParent> parent( new PluginModuleChromeParent(aFilePath, aPluginId, - aPluginTag->mSandboxLevel, - aPluginTag->mSupportsAsyncInit)); + aPluginTag->mSandboxLevel)); UniquePtr<LaunchCompleteTask> onLaunchedRunnable(new LaunchedTask(parent)); - parent->mSubprocess->SetCallRunnableImmediately(!parent->mIsStartingAsync); TimeStamp launchStart = TimeStamp::Now(); bool launched = parent->mSubprocess->Launch(Move(onLaunchedRunnable), aPluginTag->mSandboxLevel); if (!launched) { // We never reached open parent->mShutdown = true; return nullptr; } parent->mIsFlashPlugin = aPluginTag->mIsFlashPlugin; uint32_t blocklistState; nsresult rv = aPluginTag->GetBlocklistState(&blocklistState); parent->mIsBlocklisted = NS_FAILED(rv) || blocklistState != 0; - if (!parent->mIsStartingAsync) { - int32_t launchTimeoutSecs = Preferences::GetInt(kLaunchTimeoutPref, 0); - if (!parent->mSubprocess->WaitUntilConnected(launchTimeoutSecs * 1000)) { - parent->mShutdown = true; - return nullptr; - } + int32_t launchTimeoutSecs = Preferences::GetInt(kLaunchTimeoutPref, 0); + if (!parent->mSubprocess->WaitUntilConnected(launchTimeoutSecs * 1000)) { + parent->mShutdown = true; + return nullptr; } TimeStamp launchEnd = TimeStamp::Now(); parent->mTimeBlocked = (launchEnd - launchStart); return parent.forget(); } void PluginModuleChromeParent::OnProcessLaunched(const bool aSucceeded) { if (!aSucceeded) { mShutdown = true; OnInitFailure(); return; } // We may have already been initialized by another call that was waiting // for process connect. If so, this function doesn't need to run. - if (mAsyncInitRv != NS_ERROR_NOT_INITIALIZED || mShutdown) { + if (mShutdown) { return; } Open(mSubprocess->GetChannel(), base::GetProcId(mSubprocess->GetChildProcessHandle())); // Request Windows message deferral behavior on our channel. This // applies to the top level and all sub plugin protocols since they @@ -609,60 +550,22 @@ PluginModuleChromeParent::OnProcessLaunc // Protected mode only applies to Windows and only to x86. if (!mIsBlocklisted && mIsFlashPlugin && (Preferences::GetBool("dom.ipc.plugins.flash.disable-protected-mode", false) || mSandboxLevel >= 2)) { SendDisableFlashProtectedMode(); } #endif - if (mInitOnAsyncConnect) { - mInitOnAsyncConnect = false; -#if defined(XP_WIN) - mAsyncInitRv = NP_GetEntryPoints(mNPPIface, - &mAsyncInitError); - if (NS_SUCCEEDED(mAsyncInitRv)) -#endif - { -#if defined(XP_UNIX) && !defined(XP_MACOSX) && !defined(MOZ_WIDGET_GONK) - mAsyncInitRv = NP_Initialize(mNPNIface, - mNPPIface, - &mAsyncInitError); -#else - mAsyncInitRv = NP_Initialize(mNPNIface, - &mAsyncInitError); -#endif - } - -#if defined(XP_MACOSX) - if (NS_SUCCEEDED(mAsyncInitRv)) { - mAsyncInitRv = NP_GetEntryPoints(mNPPIface, - &mAsyncInitError); - } -#endif - } - #ifdef MOZ_GECKO_PROFILER Unused << SendInitProfiler(ProfilerParent::CreateForProcess(OtherPid())); #endif } bool -PluginModuleChromeParent::WaitForIPCConnection() -{ - PluginProcessParent* process = Process(); - MOZ_ASSERT(process); - process->SetCallRunnableImmediately(true); - if (!process->WaitUntilConnected()) { - return false; - } - return true; -} - -bool PluginModuleChromeParent::InitCrashReporter() { #ifdef MOZ_CRASHREPORTER ipc::Shmem shmem; if (!ipc::CrashReporterClient::AllocShmem(this, &shmem)) { return false; } @@ -672,109 +575,86 @@ PluginModuleChromeParent::InitCrashRepor } { mozilla::MutexAutoLock lock(mCrashReporterMutex); mCrashReporter = MakeUnique<ipc::CrashReporterHost>( GeckoProcessType_Plugin, shmem, threadId); - - mCrashReporter->AddNote(NS_LITERAL_CSTRING("AsyncPluginInit"), - mIsStartingAsync ? - NS_LITERAL_CSTRING("1") : - NS_LITERAL_CSTRING("0")); } #endif return true; } -PluginModuleParent::PluginModuleParent(bool aIsChrome, bool aAllowAsyncInit) +PluginModuleParent::PluginModuleParent(bool aIsChrome) : mQuirks(QUIRKS_NOT_INITIALIZED) , mIsChrome(aIsChrome) , mShutdown(false) , mHadLocalInstance(false) , mClearSiteDataSupported(false) , mGetSitesWithDataSupported(false) , mNPNIface(nullptr) , mNPPIface(nullptr) , mPlugin(nullptr) , mTaskFactory(this) , mSandboxLevel(0) , mIsFlashPlugin(false) - , mIsStartingAsync(false) - , mNPInitialized(false) - , mIsNPShutdownPending(false) - , mAsyncNewRv(NS_ERROR_NOT_INITIALIZED) #ifdef MOZ_CRASHREPORTER , mCrashReporterMutex("PluginModuleChromeParent::mCrashReporterMutex") #endif { -#if defined(MOZ_CRASHREPORTER) - CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("AsyncPluginInit"), - mIsStartingAsync ? - NS_LITERAL_CSTRING("1") : - NS_LITERAL_CSTRING("0")); -#endif } PluginModuleParent::~PluginModuleParent() { if (!OkToCleanup()) { MOZ_CRASH("unsafe destruction"); } if (!mShutdown) { NS_WARNING("Plugin host deleted the module without shutting down."); NPError err; NP_Shutdown(&err); } } -PluginModuleContentParent::PluginModuleContentParent(bool aAllowAsyncInit) - : PluginModuleParent(false, aAllowAsyncInit) +PluginModuleContentParent::PluginModuleContentParent() + : PluginModuleParent(false) { Preferences::RegisterCallback(TimeoutChanged, kContentTimeoutPref, this); } PluginModuleContentParent::~PluginModuleContentParent() { Preferences::UnregisterCallback(TimeoutChanged, kContentTimeoutPref, this); } -bool PluginModuleChromeParent::sInstantiated = false; - PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId, - int32_t aSandboxLevel, - bool aAllowAsyncInit) - : PluginModuleParent(true, aAllowAsyncInit) + int32_t aSandboxLevel) + : PluginModuleParent(true) , mSubprocess(new PluginProcessParent(aFilePath)) , mPluginId(aPluginId) , mChromeTaskFactory(this) , mHangAnnotationFlags(0) #ifdef XP_WIN , mPluginCpuUsageOnHang() , mHangUIParent(nullptr) , mHangUIEnabled(true) , mIsTimerReset(true) #endif #ifdef MOZ_CRASHREPORTER_INJECTOR , mFlashProcess1(0) , mFlashProcess2(0) , mFinishInitTask(nullptr) #endif - , mInitOnAsyncConnect(false) - , mAsyncInitRv(NS_ERROR_NOT_INITIALIZED) - , mAsyncInitError(NPERR_NO_ERROR) - , mContentParent(nullptr) { NS_ASSERTION(mSubprocess, "Out of memory!"); - sInstantiated = true; mSandboxLevel = aSandboxLevel; mRunID = GeckoChildProcessHost::GetUniqueID(); mozilla::HangMonitor::RegisterAnnotator(*this); } PluginModuleChromeParent::~PluginModuleChromeParent() { @@ -1852,94 +1732,72 @@ PluginModuleParent::SetPluginFuncs(NPPlu Unused << CallOptionalFunctionsSupported(&urlRedirectSupported, &mClearSiteDataSupported, &mGetSitesWithDataSupported); if (urlRedirectSupported) { aFuncs->urlredirectnotify = NPP_URLRedirectNotify; } } -#define RESOLVE_AND_CALL(instance, func) \ -NP_BEGIN_MACRO \ - PluginAsyncSurrogate* surrogate = nullptr; \ - PluginInstanceParent* i = PluginInstanceParent::Cast(instance, &surrogate);\ - if (surrogate && (!i || i->UseSurrogate())) { \ - return surrogate->func; \ - } \ - if (!i) { \ - return NPERR_GENERIC_ERROR; \ - } \ - return i->func; \ -NP_END_MACRO - NPError PluginModuleParent::NPP_Destroy(NPP instance, NPSavedData** saved) { // FIXME/cjones: // (1) send a "destroy" message to the child // (2) the child shuts down its instance // (3) remove both parent and child IDs from map // (4) free parent PLUGIN_LOG_DEBUG_FUNCTION; - PluginAsyncSurrogate* surrogate = nullptr; - PluginInstanceParent* parentInstance = - PluginInstanceParent::Cast(instance, &surrogate); - if (surrogate && (!parentInstance || parentInstance->UseSurrogate())) { - return surrogate->NPP_Destroy(saved); - } - - if (!parentInstance) + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + if (!pip) return NPERR_NO_ERROR; - NPError retval = parentInstance->Destroy(); + NPError retval = pip->Destroy(); instance->pdata = nullptr; - Unused << PluginInstanceParent::Call__delete__(parentInstance); + Unused << PluginInstanceParent::Call__delete__(pip); return retval; } NPError PluginModuleParent::NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16_t* stype) { AUTO_PROFILER_LABEL("PluginModuleParent::NPP_NewStream", OTHER); - RESOLVE_AND_CALL(instance, NPP_NewStream(type, stream, seekable, stype)); + + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->NPP_NewStream(type, stream, seekable, stype) + : NPERR_GENERIC_ERROR; } NPError PluginModuleParent::NPP_SetWindow(NPP instance, NPWindow* window) { - RESOLVE_AND_CALL(instance, NPP_SetWindow(window)); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->NPP_SetWindow(window) : NPERR_GENERIC_ERROR; } NPError PluginModuleParent::NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) { - RESOLVE_AND_CALL(instance, NPP_DestroyStream(stream, reason)); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->NPP_DestroyStream(stream, reason) : NPERR_GENERIC_ERROR; } int32_t PluginModuleParent::NPP_WriteReady(NPP instance, NPStream* stream) { - PluginAsyncSurrogate* surrogate = nullptr; - BrowserStreamParent* s = StreamCast(instance, stream, &surrogate); - if (!s) { - if (surrogate) { - return surrogate->NPP_WriteReady(stream); - } - return -1; - } - - return s->WriteReady(); + BrowserStreamParent* s = StreamCast(instance, stream); + return s ? s->WriteReady() : -1; } int32_t PluginModuleParent::NPP_Write(NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer) @@ -1962,59 +1820,49 @@ PluginModuleParent::NPP_StreamAsFile(NPP s->StreamAsFile(fname); } void PluginModuleParent::NPP_Print(NPP instance, NPPrint* platformPrint) { - PluginInstanceParent* i = PluginInstanceParent::Cast(instance); - i->NPP_Print(platformPrint); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->NPP_Print(platformPrint) : (void)0; } int16_t PluginModuleParent::NPP_HandleEvent(NPP instance, void* event) { - RESOLVE_AND_CALL(instance, NPP_HandleEvent(event)); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->NPP_HandleEvent(event) : NPERR_GENERIC_ERROR; } void PluginModuleParent::NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData) { - PluginInstanceParent* i = PluginInstanceParent::Cast(instance); - if (!i) - return; - - i->NPP_URLNotify(url, reason, notifyData); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->NPP_URLNotify(url, reason, notifyData) : (void)0; } NPError PluginModuleParent::NPP_GetValue(NPP instance, NPPVariable variable, void *ret_value) { - // The rules are slightly different for this function. - // If there is a surrogate, we *always* use it. - PluginAsyncSurrogate* surrogate = nullptr; - PluginInstanceParent* i = PluginInstanceParent::Cast(instance, &surrogate); - if (surrogate) { - return surrogate->NPP_GetValue(variable, ret_value); - } - if (!i) { - return NPERR_GENERIC_ERROR; - } - return i->NPP_GetValue(variable, ret_value); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->NPP_GetValue(variable, ret_value) : NPERR_GENERIC_ERROR; } NPError PluginModuleParent::NPP_SetValue(NPP instance, NPNVariable variable, void *value) { - RESOLVE_AND_CALL(instance, NPP_SetValue(variable, value)); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->NPP_SetValue(variable, value) : NPERR_GENERIC_ERROR; } mozilla::ipc::IPCResult PluginModuleChromeParent::AnswerNPN_SetValue_NPPVpluginRequiresAudioDeviceChanges( const bool& shouldRegister, NPError* result) { #ifdef XP_WIN *result = NPERR_NO_ERROR; @@ -2047,156 +1895,125 @@ PluginModuleParent::RecvBackUpXResources #endif return IPC_OK(); } void PluginModuleParent::NPP_URLRedirectNotify(NPP instance, const char* url, int32_t status, void* notifyData) { - PluginInstanceParent* i = PluginInstanceParent::Cast(instance); - if (!i) - return; - - i->NPP_URLRedirectNotify(url, status, notifyData); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->NPP_URLRedirectNotify(url, status, notifyData) : (void)0; } BrowserStreamParent* -PluginModuleParent::StreamCast(NPP instance, NPStream* s, - PluginAsyncSurrogate** aSurrogate) +PluginModuleParent::StreamCast(NPP instance, NPStream* s) { - PluginInstanceParent* ip = PluginInstanceParent::Cast(instance, aSurrogate); - if (!ip || (aSurrogate && *aSurrogate && ip->UseSurrogate())) { + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + if (!pip) { return nullptr; } BrowserStreamParent* sp = static_cast<BrowserStreamParent*>(static_cast<AStream*>(s->pdata)); - if (sp && (sp->mNPP != ip || s != sp->mStream)) { + if (sp && (sp->mNPP != pip || s != sp->mStream)) { MOZ_CRASH("Corrupted plugin stream data."); } return sp; } bool PluginModuleParent::HasRequiredFunctions() { return true; } nsresult PluginModuleParent::AsyncSetWindow(NPP instance, NPWindow* window) { - PluginAsyncSurrogate* surrogate = nullptr; - PluginInstanceParent* i = PluginInstanceParent::Cast(instance, &surrogate); - if (surrogate && (!i || i->UseSurrogate())) { - return surrogate->AsyncSetWindow(window); - } else if (!i) { - return NS_ERROR_FAILURE; - } - return i->AsyncSetWindow(window); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->AsyncSetWindow(window) : NS_ERROR_FAILURE; } nsresult PluginModuleParent::GetImageContainer(NPP instance, mozilla::layers::ImageContainer** aContainer) { - PluginInstanceParent* i = PluginInstanceParent::Cast(instance); - return !i ? NS_ERROR_FAILURE : i->GetImageContainer(aContainer); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->GetImageContainer(aContainer) : NS_ERROR_FAILURE; } nsresult PluginModuleParent::GetImageSize(NPP instance, nsIntSize* aSize) { - PluginInstanceParent* i = PluginInstanceParent::Cast(instance); - return !i ? NS_ERROR_FAILURE : i->GetImageSize(aSize); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->GetImageSize(aSize) : NS_ERROR_FAILURE; } void PluginModuleParent::DidComposite(NPP aInstance) { - if (PluginInstanceParent* i = PluginInstanceParent::Cast(aInstance)) { - i->DidComposite(); - } + PluginInstanceParent* pip = PluginInstanceParent::Cast(aInstance); + return pip ? pip->DidComposite() : (void)0; } nsresult PluginModuleParent::SetBackgroundUnknown(NPP instance) { - PluginInstanceParent* i = PluginInstanceParent::Cast(instance); - if (!i) - return NS_ERROR_FAILURE; - - return i->SetBackgroundUnknown(); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->SetBackgroundUnknown() : NS_ERROR_FAILURE; } nsresult PluginModuleParent::BeginUpdateBackground(NPP instance, const nsIntRect& aRect, DrawTarget** aDrawTarget) { - PluginInstanceParent* i = PluginInstanceParent::Cast(instance); - if (!i) - return NS_ERROR_FAILURE; - - return i->BeginUpdateBackground(aRect, aDrawTarget); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->BeginUpdateBackground(aRect, aDrawTarget) + : NS_ERROR_FAILURE; } nsresult PluginModuleParent::EndUpdateBackground(NPP instance, const nsIntRect& aRect) { - PluginInstanceParent* i = PluginInstanceParent::Cast(instance); - if (!i) - return NS_ERROR_FAILURE; - - return i->EndUpdateBackground(aRect); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->EndUpdateBackground(aRect) : NS_ERROR_FAILURE; } #if defined(XP_WIN) nsresult PluginModuleParent::GetScrollCaptureContainer(NPP aInstance, mozilla::layers::ImageContainer** aContainer) { - PluginInstanceParent* inst = PluginInstanceParent::Cast(aInstance); - return !inst ? NS_ERROR_FAILURE : inst->GetScrollCaptureContainer(aContainer); + PluginInstanceParent* pip = PluginInstanceParent::Cast(aInstance); + return pip ? pip->GetScrollCaptureContainer(aContainer) : NS_ERROR_FAILURE; } #endif nsresult PluginModuleParent::HandledWindowedPluginKeyEvent( NPP aInstance, const NativeEventData& aNativeKeyData, bool aIsConsumed) { - PluginInstanceParent* parent = PluginInstanceParent::Cast(aInstance); - if (NS_WARN_IF(!parent)) { - return NS_ERROR_FAILURE; - } - return parent->HandledWindowedPluginKeyEvent(aNativeKeyData, aIsConsumed); + PluginInstanceParent* pip = PluginInstanceParent::Cast(aInstance); + return pip ? pip->HandledWindowedPluginKeyEvent(aNativeKeyData, aIsConsumed) + : NS_ERROR_FAILURE; } void PluginModuleParent::OnInitFailure() { if (GetIPCChannel()->CanSend()) { Close(); } mShutdown = true; - - if (mIsStartingAsync) { - /* If we've failed then we need to enumerate any pending NPP_New calls - and clean them up. */ - uint32_t len = mSurrogateInstances.Length(); - for (uint32_t i = 0; i < len; ++i) { - mSurrogateInstances[i]->NotifyAsyncInitFailed(); - } - mSurrogateInstances.Clear(); - } } class PluginOfflineObserver final : public nsIObserver { public: NS_DECL_ISUPPORTS NS_DECL_NSIOBSERVER @@ -2305,26 +2122,17 @@ PluginModuleParent::NP_Initialize(NPNets mNPPIface = pFuncs; if (mShutdown) { *error = NPERR_GENERIC_ERROR; return NS_ERROR_FAILURE; } *error = NPERR_NO_ERROR; - if (mIsStartingAsync) { - if (GetIPCChannel()->CanSend()) { - // We're already connected, so we may call this immediately. - RecvNP_InitializeResult(*error); - } else { - PluginAsyncSurrogate::NP_GetEntryPoints(pFuncs); - } - } else { - SetPluginFuncs(pFuncs); - } + SetPluginFuncs(pFuncs); return NS_OK; } nsresult PluginModuleChromeParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error) { PLUGIN_LOG_DEBUG_METHOD; @@ -2334,98 +2142,39 @@ PluginModuleChromeParent::NP_Initialize( return NS_ERROR_FAILURE; } *error = NPERR_NO_ERROR; mNPNIface = bFuncs; mNPPIface = pFuncs; - // NB: This *MUST* be set prior to checking whether the subprocess has - // been connected! - if (mIsStartingAsync) { - PluginAsyncSurrogate::NP_GetEntryPoints(pFuncs); - } - - if (!mSubprocess->IsConnected()) { - // The subprocess isn't connected yet. Defer NP_Initialize until - // OnProcessLaunched is invoked. - mInitOnAsyncConnect = true; - return NS_OK; - } - PluginSettings settings; GetSettings(&settings); TimeStamp callNpInitStart = TimeStamp::Now(); - // Asynchronous case - if (mIsStartingAsync) { - if (!SendAsyncNP_Initialize(settings)) { - Close(); - return NS_ERROR_FAILURE; - } - TimeStamp callNpInitEnd = TimeStamp::Now(); - mTimeBlocked += (callNpInitEnd - callNpInitStart); - return NS_OK; - } - - // Synchronous case if (!CallNP_Initialize(settings, error)) { Close(); return NS_ERROR_FAILURE; } else if (*error != NPERR_NO_ERROR) { Close(); return NS_ERROR_FAILURE; } TimeStamp callNpInitEnd = TimeStamp::Now(); mTimeBlocked += (callNpInitEnd - callNpInitStart); - RecvNP_InitializeResult(*error); - - return NS_OK; -} - -mozilla::ipc::IPCResult -PluginModuleParent::RecvNP_InitializeResult(const NPError& aError) -{ - if (aError != NPERR_NO_ERROR) { + if (*error != NPERR_NO_ERROR) { OnInitFailure(); - return IPC_OK(); + return NS_OK; } SetPluginFuncs(mNPPIface); - if (mIsStartingAsync) { - InitAsyncSurrogates(); - } - - mNPInitialized = true; - return IPC_OK(); -} - -mozilla::ipc::IPCResult -PluginModuleChromeParent::RecvNP_InitializeResult(const NPError& aError) -{ - if (!mContentParent) { - return PluginModuleParent::RecvNP_InitializeResult(aError); - } - bool initOk = aError == NPERR_NO_ERROR; - if (initOk) { - SetPluginFuncs(mNPPIface); - if (mIsStartingAsync && !SendAssociatePluginId()) { - initOk = false; - } - } - mNPInitialized = initOk; - bool result = mContentParent->SendLoadPluginResult(mPluginId, initOk); - mContentParent = nullptr; - if (!result) { - return IPC_FAIL_NO_REASON(this); - } - return IPC_OK(); + + return NS_OK; } #else nsresult PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) { PLUGIN_LOG_DEBUG_METHOD; @@ -2442,192 +2191,84 @@ PluginModuleParent::NP_Initialize(NPNets } #if defined(XP_WIN) || defined(XP_MACOSX) nsresult PluginModuleContentParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) { PLUGIN_LOG_DEBUG_METHOD; - nsresult rv = PluginModuleParent::NP_Initialize(bFuncs, error); - if (mIsStartingAsync && GetIPCChannel()->CanSend()) { - // We're already connected, so we may call this immediately. - RecvNP_InitializeResult(*error); - } - return rv; + return PluginModuleParent::NP_Initialize(bFuncs, error); } #endif nsresult PluginModuleChromeParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) { nsresult rv = PluginModuleParent::NP_Initialize(bFuncs, error); if (NS_FAILED(rv)) return rv; -#if defined(XP_MACOSX) - if (!mSubprocess->IsConnected()) { - // The subprocess isn't connected yet. Defer NP_Initialize until - // OnProcessLaunched is invoked. - mInitOnAsyncConnect = true; - *error = NPERR_NO_ERROR; - return NS_OK; - } -#else - if (mInitOnAsyncConnect) { - *error = NPERR_NO_ERROR; - return NS_OK; - } -#endif - PluginSettings settings; GetSettings(&settings); TimeStamp callNpInitStart = TimeStamp::Now(); - if (mIsStartingAsync) { - if (!SendAsyncNP_Initialize(settings)) { - return NS_ERROR_FAILURE; - } - TimeStamp callNpInitEnd = TimeStamp::Now(); - mTimeBlocked += (callNpInitEnd - callNpInitStart); - return NS_OK; - } - if (!CallNP_Initialize(settings, error)) { Close(); return NS_ERROR_FAILURE; } TimeStamp callNpInitEnd = TimeStamp::Now(); mTimeBlocked += (callNpInitEnd - callNpInitStart); - RecvNP_InitializeResult(*error); - return NS_OK; -} - -mozilla::ipc::IPCResult -PluginModuleParent::RecvNP_InitializeResult(const NPError& aError) -{ - if (aError != NPERR_NO_ERROR) { - OnInitFailure(); - return IPC_OK(); - } - - if (mIsStartingAsync && mNPPIface) { - SetPluginFuncs(mNPPIface); - InitAsyncSurrogates(); - } - - mNPInitialized = true; - return IPC_OK(); -} - -mozilla::ipc::IPCResult -PluginModuleChromeParent::RecvNP_InitializeResult(const NPError& aError) -{ + bool ok = true; - if (mContentParent) { - if ((ok = SendAssociatePluginId())) { - ok = mContentParent->SendLoadPluginResult(mPluginId, - aError == NPERR_NO_ERROR); - mContentParent = nullptr; - } - } else if (aError == NPERR_NO_ERROR) { + if (*error == NPERR_NO_ERROR) { // Initialization steps for (e10s && !asyncInit) || !e10s #if defined XP_WIN - if (mIsStartingAsync) { - SetPluginFuncs(mNPPIface); - } - - // Send the info needed to join the browser process's audio session to the - // plugin process. + // Send the info needed to join the browser process's audio session to + // the plugin process. nsID id; nsString sessionName; nsString iconPath; if (NS_SUCCEEDED(mozilla::widget::GetAudioSessionData(id, sessionName, iconPath))) { Unused << SendSetAudioSessionData(id, sessionName, iconPath); } #endif #ifdef MOZ_CRASHREPORTER_INJECTOR InitializeInjector(); #endif } if (!ok) { - return IPC_FAIL_NO_REASON(this); + return NS_ERROR_FAILURE; } - return PluginModuleParent::RecvNP_InitializeResult(aError); + + if (*error != NPERR_NO_ERROR) { + OnInitFailure(); + return NS_OK; + } + + return NS_OK; } #endif -void -PluginModuleParent::InitAsyncSurrogates() -{ - if (MaybeRunDeferredShutdown()) { - // We've shut down, so the surrogates are no longer valid. Clear - // mSurrogateInstances to ensure that these aren't used. - mSurrogateInstances.Clear(); - return; - } - - uint32_t len = mSurrogateInstances.Length(); - for (uint32_t i = 0; i < len; ++i) { - NPError err; - mAsyncNewRv = mSurrogateInstances[i]->NPP_New(&err); - if (NS_FAILED(mAsyncNewRv)) { - mSurrogateInstances[i]->NotifyAsyncInitFailed(); - continue; - } - } - mSurrogateInstances.Clear(); -} - -bool -PluginModuleParent::RemovePendingSurrogate( - const RefPtr<PluginAsyncSurrogate>& aSurrogate) -{ - return mSurrogateInstances.RemoveElement(aSurrogate); -} - -bool -PluginModuleParent::MaybeRunDeferredShutdown() -{ - if (!mIsStartingAsync || !mIsNPShutdownPending) { - return false; - } - MOZ_ASSERT(!mShutdown); - NPError error; - if (!DoShutdown(&error)) { - return false; - } - mIsNPShutdownPending = false; - return true; -} - nsresult PluginModuleParent::NP_Shutdown(NPError* error) { PLUGIN_LOG_DEBUG_METHOD; if (mShutdown) { *error = NPERR_GENERIC_ERROR; return NS_ERROR_FAILURE; } - /* If we're still running an async NP_Initialize then we need to defer - shutdown until we've received the result of the NP_Initialize call. */ - if (mIsStartingAsync && !mNPInitialized) { - mIsNPShutdownPending = true; - *error = NPERR_NO_ERROR; - return NS_OK; - } - if (!DoShutdown(error)) { return NS_ERROR_FAILURE; } return NS_OK; } bool @@ -2682,52 +2323,27 @@ PluginModuleParent::NP_GetValue(void *fu #if defined(XP_WIN) || defined(XP_MACOSX) nsresult PluginModuleParent::NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error) { NS_ASSERTION(pFuncs, "Null pointer!"); *error = NPERR_NO_ERROR; - if (mIsStartingAsync && !IsChrome()) { - mNPPIface = pFuncs; -#if defined(XP_MACOSX) - if (mNPInitialized) { - SetPluginFuncs(pFuncs); - InitAsyncSurrogates(); - } else { - PluginAsyncSurrogate::NP_GetEntryPoints(pFuncs); - } -#else - PluginAsyncSurrogate::NP_GetEntryPoints(pFuncs); -#endif - } else { - SetPluginFuncs(pFuncs); - } + SetPluginFuncs(pFuncs); return NS_OK; } nsresult PluginModuleChromeParent::NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error) { -#if defined(XP_MACOSX) - if (mInitOnAsyncConnect) { - PluginAsyncSurrogate::NP_GetEntryPoints(pFuncs); - mNPPIface = pFuncs; - *error = NPERR_NO_ERROR; - return NS_OK; - } -#else - if (mIsStartingAsync) { - PluginAsyncSurrogate::NP_GetEntryPoints(pFuncs); - } +#if !defined(XP_MACOSX) if (!mSubprocess->IsConnected()) { mNPPIface = pFuncs; - mInitOnAsyncConnect = true; *error = NPERR_NO_ERROR; return NS_OK; } #endif // We need to have the plugin process update its function table here by // actually calling NP_GetEntryPoints. The parent's function table will // reflect nullptr entries in the child's table once SetPluginFuncs is @@ -2753,47 +2369,26 @@ PluginModuleParent::NPP_New(NPMIMEType p { PLUGIN_LOG_DEBUG_METHOD; if (mShutdown) { *error = NPERR_GENERIC_ERROR; return NS_ERROR_FAILURE; } - if (mIsStartingAsync) { - if (!PluginAsyncSurrogate::Create(this, pluginType, instance, - argc, argn, argv)) { - *error = NPERR_GENERIC_ERROR; - return NS_ERROR_FAILURE; - } - - if (!mNPInitialized) { - RefPtr<PluginAsyncSurrogate> surrogate = - PluginAsyncSurrogate::Cast(instance); - mSurrogateInstances.AppendElement(surrogate); - *error = NPERR_NO_ERROR; - return NS_PLUGIN_INIT_PENDING; - } - } - // create the instance on the other side InfallibleTArray<nsCString> names; InfallibleTArray<nsCString> values; for (int i = 0; i < argc; ++i) { names.AppendElement(NullableString(argn[i])); values.AppendElement(NullableString(argv[i])); } - nsresult rv = NPP_NewInternal(pluginType, instance, names, values, - saved, error); - if (NS_FAILED(rv) || !mIsStartingAsync) { - return rv; - } - return NS_PLUGIN_INIT_PENDING; + return NPP_NewInternal(pluginType, instance, names, values, saved, error); } class nsCaseInsensitiveUTF8StringArrayComparator { public: template<class A, class B> bool Equals(const A& a, const B& b) const { return a.Equals(b.get(), nsCaseInsensitiveUTF8StringComparator()); @@ -2917,21 +2512,17 @@ PluginModuleParent::NPP_NewInternal(NPMI // specified. if (supportsAsyncRender && supportsForceDirect && gfxWindowsPlatform::GetPlatform()->SupportsPluginDirectDXGIDrawing()) { ForceDirect(names, values); } #endif } - // Release the surrogate reference that was in pdata - RefPtr<PluginAsyncSurrogate> surrogate( - dont_AddRef(PluginAsyncSurrogate::Cast(instance))); - // Now replace it with the instance - instance->pdata = static_cast<PluginDataResolver*>(parentInstance); + instance->pdata = parentInstance; // Any IPC messages for the PluginInstance actor should be dispatched to the // DocGroup for the plugin's document. RefPtr<nsPluginInstanceOwner> owner = parentInstance->GetOwner(); nsCOMPtr<nsIDOMElement> elt; owner->GetDOMElement(getter_AddRefs(elt)); if (nsCOMPtr<nsINode> node = do_QueryInterface(elt)) { nsCOMPtr<nsIDocument> doc = node->OwnerDoc(); @@ -2948,41 +2539,29 @@ PluginModuleParent::NPP_NewInternal(NPMI instance->pdata = nullptr; *error = NPERR_GENERIC_ERROR; return NS_ERROR_FAILURE; } { // Scope for timer Telemetry::AutoTimer<Telemetry::BLOCKED_ON_PLUGIN_INSTANCE_INIT_MS> timer(GetHistogramKey()); - if (mIsStartingAsync) { - MOZ_ASSERT(surrogate); - surrogate->AsyncCallDeparting(); - if (!SendAsyncNPP_New(parentInstance)) { + if (!CallSyncNPP_New(parentInstance, error)) { + // if IPC is down, we'll get an immediate "failed" return, but + // without *error being set. So make sure that the error + // condition is signaled to nsNPAPIPluginInstance + if (NPERR_NO_ERROR == *error) { *error = NPERR_GENERIC_ERROR; - return NS_ERROR_FAILURE; } - *error = NPERR_NO_ERROR; - } else { - if (!CallSyncNPP_New(parentInstance, error)) { - // if IPC is down, we'll get an immediate "failed" return, but - // without *error being set. So make sure that the error - // condition is signaled to nsNPAPIPluginInstance - if (NPERR_NO_ERROR == *error) { - *error = NPERR_GENERIC_ERROR; - } - return NS_ERROR_FAILURE; - } + return NS_ERROR_FAILURE; } } if (*error != NPERR_NO_ERROR) { - if (!mIsStartingAsync) { - NPP_Destroy(instance, 0); - } + NPP_Destroy(instance, 0); return NS_ERROR_FAILURE; } UpdatePluginTimeout(); return NS_OK; } @@ -3025,32 +2604,27 @@ PluginModuleParent::NPP_GetSitesWithData return NS_OK; } #if defined(XP_MACOSX) nsresult PluginModuleParent::IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) { - PluginInstanceParent* i = PluginInstanceParent::Cast(instance); - if (!i) - return NS_ERROR_FAILURE; - - return i->IsRemoteDrawingCoreAnimation(aDrawing); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->IsRemoteDrawingCoreAnimation(aDrawing) : NS_ERROR_FAILURE; } #endif #if defined(XP_MACOSX) || defined(XP_WIN) nsresult PluginModuleParent::ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor) { - PluginInstanceParent* i = PluginInstanceParent::Cast(instance); - if (!i) - return NS_ERROR_FAILURE; - - return i->ContentsScaleFactorChanged(aContentsScaleFactor); + PluginInstanceParent* pip = PluginInstanceParent::Cast(instance); + return pip ? pip->ContentsScaleFactorChanged(aContentsScaleFactor) + : NS_ERROR_FAILURE; } #endif // #if defined(XP_MACOSX) #if defined(XP_MACOSX) mozilla::ipc::IPCResult PluginModuleParent::AnswerProcessSomeEvents() { mozilla::plugins::PluginUtilsOSX::InvokeNativeEventLoop();
--- a/dom/plugins/ipc/PluginModuleParent.h +++ b/dom/plugins/ipc/PluginModuleParent.h @@ -42,17 +42,16 @@ namespace mozilla { namespace layers { class TextureClientRecycleAllocator; } // namespace layers namespace plugins { //----------------------------------------------------------------------------- class BrowserStreamParent; -class PluginAsyncSurrogate; class PluginInstanceParent; #ifdef XP_WIN class PluginHangUIParent; #endif #ifdef MOZ_CRASHREPORTER_INJECTOR class FinishInjectorInitTask; #endif @@ -89,26 +88,19 @@ protected: const InfallibleTArray<nsCString>& aNames, const InfallibleTArray<nsCString>& aValues) override; virtual bool DeallocPPluginInstanceParent(PPluginInstanceParent* aActor) override; public: - explicit PluginModuleParent(bool aIsChrome, bool aAllowAsyncInit); + explicit PluginModuleParent(bool aIsChrome); virtual ~PluginModuleParent(); - bool RemovePendingSurrogate(const RefPtr<PluginAsyncSurrogate>& aSurrogate); - - /** @return the state of the pref that controls async plugin init */ - bool IsStartingAsync() const { return mIsStartingAsync; } - /** @return whether this modules NP_Initialize has successfully completed - executing */ - bool IsInitialized() const { return mNPInitialized; } bool IsChrome() const { return mIsChrome; } virtual void SetPlugin(nsNPAPIPlugin* plugin) override { mPlugin = plugin; } virtual void ActorDestroy(ActorDestroyReason why) override; @@ -118,18 +110,16 @@ public: } bool OkToCleanup() const { return !IsOnCxxStack(); } void ProcessRemoteNativeEventsInInterruptCall() override; - virtual bool WaitForIPCConnection() { return true; } - nsCString GetHistogramKey() const { return mPluginName + mPluginVersion; } void AccumulateModuleInitBlockedTime(); virtual nsresult GetRunID(uint32_t* aRunID) override; virtual void SetHasLocalInstance() override { @@ -175,21 +165,17 @@ protected: RecvPopCursor() override; virtual mozilla::ipc::IPCResult RecvNPN_SetException(const nsCString& aMessage) override; virtual mozilla::ipc::IPCResult RecvNPN_ReloadPlugins(const bool& aReloadPages) override; - virtual mozilla::ipc::IPCResult - RecvNP_InitializeResult(const NPError& aError) override; - - static BrowserStreamParent* StreamCast(NPP instance, NPStream* s, - PluginAsyncSurrogate** aSurrogate = nullptr); + static BrowserStreamParent* StreamCast(NPP instance, NPStream* s); virtual mozilla::ipc::IPCResult AnswerNPN_SetValue_NPPVpluginRequiresAudioDeviceChanges( const bool& shouldRegister, NPError* result) override; virtual mozilla::ipc::IPCResult AnswerGetFileName(const GetFileNameFunc& aFunc, @@ -310,26 +296,23 @@ public: #if defined(XP_MACOSX) virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, bool *aDrawing) override; #endif #if defined(XP_MACOSX) || defined(XP_WIN) virtual nsresult ContentsScaleFactorChanged(NPP instance, double aContentsScaleFactor) override; #endif - void InitAsyncSurrogates(); - layers::TextureClientRecycleAllocator* EnsureTextureAllocatorForDirectBitmap(); layers::TextureClientRecycleAllocator* EnsureTextureAllocatorForDXGISurface(); protected: void NotifyFlashHang(); void NotifyPluginCrashed(); void OnInitFailure(); - bool MaybeRunDeferredShutdown(); bool DoShutdown(NPError* error); bool GetSetting(NPNVariable aVariable); void GetSettings(PluginSettings* aSettings); bool mIsChrome; bool mShutdown; bool mHadLocalInstance; @@ -350,23 +333,16 @@ protected: // Dup of plugin's X socket, used to scope its resources to this // object instead of the plugin process's lifetime ScopedClose mPluginXSocketFdDup; #endif bool GetPluginDetails(); - friend class mozilla::plugins::PluginAsyncSurrogate; - - bool mIsStartingAsync; - bool mNPInitialized; - bool mIsNPShutdownPending; - nsTArray<RefPtr<PluginAsyncSurrogate>> mSurrogateInstances; - nsresult mAsyncNewRv; uint32_t mRunID; RefPtr<layers::TextureClientRecycleAllocator> mTextureAllocatorForDirectBitmap; RefPtr<layers::TextureClientRecycleAllocator> mTextureAllocatorForDXGISurface; #ifdef MOZ_CRASHREPORTER /** * This mutex protects the crash reporter when the Plugin Hang UI event @@ -377,26 +353,20 @@ protected: mozilla::Mutex mCrashReporterMutex; UniquePtr<ipc::CrashReporterHost> mCrashReporter; #endif // MOZ_CRASHREPORTER }; class PluginModuleContentParent : public PluginModuleParent { public: - explicit PluginModuleContentParent(bool aAllowAsyncInit); + explicit PluginModuleContentParent(); static PluginLibrary* LoadModule(uint32_t aPluginId, nsPluginTag* aPluginTag); - static void OnLoadPluginResult(const uint32_t& aPluginId, - const bool& aResult, - Endpoint<PPluginModuleParent>&& aEndpoint); - - static void AssociatePluginId(uint32_t aPluginId, base::ProcessId aProcessId); - virtual ~PluginModuleContentParent(); #if defined(XP_WIN) || defined(XP_MACOSX) nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error) override; #endif private: static void Initialize(Endpoint<PPluginModuleParent>&& aEndpoint); @@ -427,24 +397,16 @@ class PluginModuleChromeParent * LoadModule * * This may or may not launch a plugin child process, * and may or may not be very expensive. */ static PluginLibrary* LoadModule(const char* aFilePath, uint32_t aPluginId, nsPluginTag* aPluginTag); - /** - * The following two functions are called by SetupBridge to determine - * whether an existing plugin module was reused, or whether a new module - * was instantiated by the plugin host. - */ - static void ClearInstantiationFlag() { sInstantiated = false; } - static bool DidInstantiate() { return sInstantiated; } - virtual ~PluginModuleChromeParent(); /* * Takes a full multi-process dump including the plugin process and the * content process. If aBrowserDumpId is not empty then the browser dump * associated with it will be paired to the resulting minidump. * Takes ownership of the file associated with aBrowserDumpId. * @@ -530,27 +492,16 @@ class PluginModuleChromeParent */ void OnHangUIContinue(); void EvaluateHangUIState(const bool aReset); #endif // XP_WIN - virtual bool WaitForIPCConnection() override; - - virtual mozilla::ipc::IPCResult - RecvNP_InitializeResult(const NPError& aError) override; - - void - SetContentParent(dom::ContentParent* aContentParent); - - bool - SendAssociatePluginId(); - void CachedSettingChanged(); virtual mozilla::ipc::IPCResult AnswerGetKeyState(const int32_t& aVirtKey, int16_t* aRet) override; // Proxy GetOpenFileName/GetSaveFileName on Windows. virtual mozilla::ipc::IPCResult AnswerGetFileName(const GetFileNameFunc& aFunc, @@ -595,18 +546,17 @@ private: #if defined(XP_WIN) || defined(XP_MACOSX) virtual nsresult NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error) override; #endif virtual void ActorDestroy(ActorDestroyReason why) override; // aFilePath is UTF8, not native! explicit PluginModuleChromeParent(const char* aFilePath, uint32_t aPluginId, - int32_t aSandboxLevel, - bool aAllowAsyncInit); + int32_t aSandboxLevel); void CleanupFromTimeout(const bool aByHangUI); virtual void UpdatePluginTimeout() override; void RegisterSettingsCallbacks(); void UnregisterSettingsCallbacks(); @@ -652,18 +602,16 @@ private: /** * Finishes the Plugin Hang UI and cancels if it is being shown to the user. */ void FinishHangUI(); #endif - friend class mozilla::plugins::PluginAsyncSurrogate; - #ifdef MOZ_CRASHREPORTER_INJECTOR friend class mozilla::plugins::FinishInjectorInitTask; void InitializeInjector(); void DoInjection(const nsAutoHandle& aSnapshot); static DWORD WINAPI GetToolhelpSnapshot(LPVOID aContext); void OnCrash(DWORD processID) override; @@ -691,27 +639,18 @@ private: } private: PluginModuleChromeParent* mModule; }; friend class LaunchedTask; - bool mInitOnAsyncConnect; - nsresult mAsyncInitRv; - NPError mAsyncInitError; - // mContentParent is to be used ONLY during the IPC dance that occurs - // when ContentParent::RecvLoadPlugin is called under async plugin init! - // In other contexts it is *unsafe*, as there might be multiple content - // processes in existence! - dom::ContentParent* mContentParent; nsCOMPtr<nsIObserver> mPluginOfflineObserver; bool mIsBlocklisted; - static bool sInstantiated; #if defined(XP_WIN) && defined(MOZ_SANDBOX) mozilla::SandboxPermissions mSandboxPermissions; #endif #ifdef MOZ_CRASHREPORTER nsCOMPtr<nsIFile> mBrowserDumpFile; TakeFullMinidumpCallback mTakeFullMinidumpCallback; #endif
--- a/dom/plugins/ipc/PluginProcessParent.cpp +++ b/dom/plugins/ipc/PluginProcessParent.cpp @@ -27,17 +27,16 @@ using base::ProcessArchitecture; PluginProcessParent::PidSet* PluginProcessParent::sPidSet = nullptr; #endif PluginProcessParent::PluginProcessParent(const std::string& aPluginFilePath) : GeckoChildProcessHost(GeckoProcessType_Plugin) , mPluginFilePath(aPluginFilePath) , mTaskFactory(this) , mMainMsgLoop(MessageLoop::current()) - , mRunCompleteTaskImmediately(false) #ifdef XP_WIN , mChildPid(0) #endif { } PluginProcessParent::~PluginProcessParent() { @@ -125,22 +124,16 @@ PluginProcessParent::Delete() } ioLoop->PostTask( NewNonOwningRunnableMethod("plugins::PluginProcessParent::Delete", this, &PluginProcessParent::Delete)); } -void -PluginProcessParent::SetCallRunnableImmediately(bool aCallImmediately) -{ - mRunCompleteTaskImmediately = aCallImmediately; -} - /** * This function exists so that we may provide an additional level of * indirection between the task being posted to main event loop (a * RunnableMethod) and the launch complete task itself. This is needed * for cases when both WaitUntilConnected or OnChannel* race to invoke the * task. */ void @@ -151,17 +144,17 @@ PluginProcessParent::RunLaunchCompleteTa mLaunchCompleteTask = nullptr; } } bool PluginProcessParent::WaitUntilConnected(int32_t aTimeoutMs) { bool result = GeckoChildProcessHost::WaitUntilConnected(aTimeoutMs); - if (mRunCompleteTaskImmediately && mLaunchCompleteTask) { + if (mLaunchCompleteTask) { if (result) { mLaunchCompleteTask->SetLaunchSucceeded(); } RunLaunchCompleteTask(); } return result; } @@ -172,31 +165,22 @@ PluginProcessParent::OnChannelConnected( mChildPid = static_cast<uint32_t>(peer_pid); if (!sPidSet) { sPidSet = new PluginProcessParent::PidSet(); } sPidSet->PutEntry(mChildPid); #endif GeckoChildProcessHost::OnChannelConnected(peer_pid); - if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) { - mLaunchCompleteTask->SetLaunchSucceeded(); - mMainMsgLoop->PostTask(mTaskFactory.NewRunnableMethod( - &PluginProcessParent::RunLaunchCompleteTask)); - } } void PluginProcessParent::OnChannelError() { GeckoChildProcessHost::OnChannelError(); - if (mLaunchCompleteTask && !mRunCompleteTaskImmediately) { - mMainMsgLoop->PostTask(mTaskFactory.NewRunnableMethod( - &PluginProcessParent::RunLaunchCompleteTask)); - } } bool PluginProcessParent::IsConnected() { mozilla::MonitorAutoLock lock(mMonitor); return mProcessState == PROCESS_CONNECTED; }
--- a/dom/plugins/ipc/PluginProcessParent.h +++ b/dom/plugins/ipc/PluginProcessParent.h @@ -63,34 +63,32 @@ public: { return true; } const std::string& GetPluginFilePath() { return mPluginFilePath; } using mozilla::ipc::GeckoChildProcessHost::GetChannel; - void SetCallRunnableImmediately(bool aCallImmediately); virtual bool WaitUntilConnected(int32_t aTimeoutMs = 0) override; virtual void OnChannelConnected(int32_t peer_pid) override; virtual void OnChannelError() override; bool IsConnected(); static bool IsPluginProcessId(base::ProcessId procId); private: void RunLaunchCompleteTask(); std::string mPluginFilePath; ipc::TaskFactory<PluginProcessParent> mTaskFactory; UniquePtr<LaunchCompleteTask> mLaunchCompleteTask; MessageLoop* mMainMsgLoop; - bool mRunCompleteTaskImmediately; #ifdef XP_WIN typedef nsTHashtable<nsUint32HashKey> PidSet; // Set of PIDs for all plugin child processes or NULL if empty. static PidSet* sPidSet; uint32_t mChildPid; #endif DISALLOW_EVIL_CONSTRUCTORS(PluginProcessParent);
--- a/dom/plugins/ipc/PluginScriptableObjectParent.cpp +++ b/dom/plugins/ipc/PluginScriptableObjectParent.cpp @@ -7,17 +7,16 @@ #include "PluginScriptableObjectParent.h" #include "jsapi.h" #include "mozilla/DebugOnly.h" #include "mozilla/dom/ScriptSettings.h" #include "mozilla/plugins/PluginTypes.h" #include "mozilla/Unused.h" #include "nsNPAPIPlugin.h" -#include "PluginAsyncSurrogate.h" #include "PluginScriptableObjectUtils.h" using namespace mozilla; using namespace mozilla::plugins; using namespace mozilla::plugins::parent; /** * NPIdentifiers in the chrome process are stored as jsids. The difficulty is in @@ -106,17 +105,16 @@ FromNPIdentifier(NPIdentifier aIdentifie } namespace { inline void ReleaseVariant(NPVariant& aVariant, PluginInstanceParent* aInstance) { - PushSurrogateAcceptCalls acceptCalls(aInstance); const NPNetscapeFuncs* npn = GetNetscapeFuncs(aInstance); if (npn) { npn->releasevariantvalue(&aVariant); } } } // namespace @@ -649,17 +647,16 @@ PluginScriptableObjectParent::Initialize } NPObject* PluginScriptableObjectParent::CreateProxyObject() { NS_ASSERTION(mInstance, "Must have an instance!"); NS_ASSERTION(mType == Proxy, "Shouldn't call this for non-proxy object!"); - PushSurrogateAcceptCalls acceptCalls(mInstance); const NPNetscapeFuncs* npn = GetNetscapeFuncs(mInstance); NPObject* npobject = npn->createobject(mInstance->GetNPP(), const_cast<NPClass*>(GetClass())); NS_ASSERTION(npobject, "Failed to create object?!"); NS_ASSERTION(npobject->_class == GetClass(), "Wrong kind of object!"); NS_ASSERTION(npobject->referenceCount == 1, "Some kind of live object!"); @@ -768,17 +765,16 @@ PluginScriptableObjectParent::AnswerHasM PluginInstanceParent* instance = GetInstance(); if (!instance) { NS_ERROR("No instance?!"); *aHasMethod = false; return IPC_OK(); } - PushSurrogateAcceptCalls acceptCalls(instance); const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); if (!npn) { NS_ERROR("No netscape funcs?!"); *aHasMethod = false; return IPC_OK(); } StackIdentifier stackID(aId); @@ -809,17 +805,16 @@ PluginScriptableObjectParent::AnswerInvo PluginInstanceParent* instance = GetInstance(); if (!instance) { NS_ERROR("No instance?!"); *aResult = void_t(); *aSuccess = false; return IPC_OK(); } - PushSurrogateAcceptCalls acceptCalls(instance); const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); if (!npn) { NS_ERROR("No netscape funcs?!"); *aResult = void_t(); *aSuccess = false; return IPC_OK(); } @@ -899,17 +894,16 @@ PluginScriptableObjectParent::AnswerInvo PluginInstanceParent* instance = GetInstance(); if (!instance) { NS_ERROR("No instance?!"); *aResult = void_t(); *aSuccess = false; return IPC_OK(); } - PushSurrogateAcceptCalls acceptCalls(instance); const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); if (!npn) { NS_ERROR("No netscape funcs?!"); *aResult = void_t(); *aSuccess = false; return IPC_OK(); } @@ -980,17 +974,16 @@ PluginScriptableObjectParent::AnswerHasP PluginInstanceParent* instance = GetInstance(); if (!instance) { NS_ERROR("No instance?!"); *aHasProperty = false; return IPC_OK(); } - PushSurrogateAcceptCalls acceptCalls(instance); const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); if (!npn) { NS_ERROR("No netscape funcs?!"); *aHasProperty = false; return IPC_OK(); } StackIdentifier stackID(aId); @@ -1023,17 +1016,16 @@ PluginScriptableObjectParent::AnswerGetP PluginInstanceParent* instance = GetInstance(); if (!instance) { NS_ERROR("No instance?!"); *aResult = void_t(); *aSuccess = false; return IPC_OK(); } - PushSurrogateAcceptCalls acceptCalls(instance); const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); if (!npn) { NS_ERROR("No netscape funcs?!"); *aResult = void_t(); *aSuccess = false; return IPC_OK(); } @@ -1080,17 +1072,16 @@ PluginScriptableObjectParent::AnswerSetP PluginInstanceParent* instance = GetInstance(); if (!instance) { NS_ERROR("No instance?!"); *aSuccess = false; return IPC_OK(); } - PushSurrogateAcceptCalls acceptCalls(instance); const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); if (!npn) { NS_ERROR("No netscape funcs?!"); *aSuccess = false; return IPC_OK(); } NPVariant converted; @@ -1127,17 +1118,16 @@ PluginScriptableObjectParent::AnswerRemo PluginInstanceParent* instance = GetInstance(); if (!instance) { NS_ERROR("No instance?!"); *aSuccess = false; return IPC_OK(); } - PushSurrogateAcceptCalls acceptCalls(instance); const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); if (!npn) { NS_ERROR("No netscape funcs?!"); *aSuccess = false; return IPC_OK(); } StackIdentifier stackID(aId); @@ -1166,17 +1156,16 @@ PluginScriptableObjectParent::AnswerEnum PluginInstanceParent* instance = GetInstance(); if (!instance) { NS_ERROR("No instance?!"); *aSuccess = false; return IPC_OK(); } - PushSurrogateAcceptCalls acceptCalls(instance); const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); if (!npn) { NS_WARNING("No netscape funcs?!"); *aSuccess = false; return IPC_OK(); } NPIdentifier* ids; @@ -1219,17 +1208,16 @@ PluginScriptableObjectParent::AnswerCons PluginInstanceParent* instance = GetInstance(); if (!instance) { NS_ERROR("No instance?!"); *aResult = void_t(); *aSuccess = false; return IPC_OK(); } - PushSurrogateAcceptCalls acceptCalls(instance); const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); if (!npn) { NS_ERROR("No netscape funcs?!"); *aResult = void_t(); *aSuccess = false; return IPC_OK(); } @@ -1312,17 +1300,16 @@ PluginScriptableObjectParent::AnswerNPN_ PluginInstanceParent* instance = GetInstance(); if (!instance) { NS_ERROR("No instance?!"); *aResult = void_t(); *aSuccess = false; return IPC_OK(); } - PushSurrogateAcceptCalls acceptCalls(instance); const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance); if (!npn) { NS_ERROR("No netscape funcs?!"); *aResult = void_t(); *aSuccess = false; return IPC_OK(); }
--- a/dom/plugins/ipc/PluginTypes.ipdlh +++ b/dom/plugins/ipc/PluginTypes.ipdlh @@ -13,17 +13,16 @@ struct PluginTag uint32_t id; nsCString name; nsCString description; nsCString[] mimeTypes; nsCString[] mimeDescriptions; nsCString[] extensions; bool isJavaPlugin; bool isFlashPlugin; - bool supportsAsyncInit; bool supportsAsyncRender; // flash specific nsCString filename; nsCString version; int64_t lastModifiedTime; bool isFromExtension; int32_t sandboxLevel; };
--- a/dom/plugins/ipc/moz.build +++ b/dom/plugins/ipc/moz.build @@ -16,19 +16,17 @@ EXPORTS.mozilla.plugins += [ 'BrowserStreamChild.h', 'BrowserStreamParent.h', 'ChildAsyncCall.h', 'ChildTimer.h', 'NPEventAndroid.h', 'NPEventOSX.h', 'NPEventUnix.h', 'NPEventWindows.h', - 'PluginAsyncSurrogate.h', 'PluginBridge.h', - 'PluginDataResolver.h', 'PluginInstanceChild.h', 'PluginInstanceParent.h', 'PluginMessageUtils.h', 'PluginModuleChild.h', 'PluginModuleParent.h', 'PluginProcessChild.h', 'PluginProcessParent.h', 'PluginQuirks.h', @@ -65,17 +63,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco 'PluginInterposeOSX.h', ] UNIFIED_SOURCES += [ 'BrowserStreamChild.cpp', 'BrowserStreamParent.cpp', 'ChildAsyncCall.cpp', 'ChildTimer.cpp', - 'PluginAsyncSurrogate.cpp', 'PluginBackgroundDestroyer.cpp', 'PluginInstanceParent.cpp', 'PluginMessageUtils.cpp', 'PluginModuleParent.cpp', 'PluginProcessChild.cpp', 'PluginProcessParent.cpp', 'PluginQuirks.cpp', 'PluginScriptableObjectChild.cpp',
--- a/dom/workers/ServiceWorkerClients.cpp +++ b/dom/workers/ServiceWorkerClients.cpp @@ -749,20 +749,24 @@ private: nsCOMPtr<nsIBrowserDOMWindow> bwin; chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin)); if (NS_WARN_IF(!bwin)) { return NS_ERROR_FAILURE; } + nsCOMPtr<nsIPrincipal> triggeringPrincipal = workerPrivate->GetPrincipal(); + MOZ_DIAGNOSTIC_ASSERT(triggeringPrincipal); + nsCOMPtr<mozIDOMWindowProxy> win; rv = bwin->OpenURI(uri, nullptr, nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW, nsIBrowserDOMWindow::OPEN_NEW, + triggeringPrincipal, getter_AddRefs(win)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } NS_ENSURE_STATE(win); nsCOMPtr<nsPIDOMWindowOuter> pWin = nsPIDOMWindowOuter::From(win); pWin.forget(aWindow);
--- a/gfx/layers/AnimationHelper.h +++ b/gfx/layers/AnimationHelper.h @@ -160,17 +160,17 @@ public: /** * Clear AnimatedValues and Animations data */ void Clear(); void ClearById(const uint64_t& aId); private: - ~CompositorAnimationStorage() { Clear(); }; + ~CompositorAnimationStorage() { }; private: AnimatedValueTable mAnimatedValues; AnimationsTable mAnimations; }; class AnimationHelper {
--- a/gfx/layers/PaintThread.cpp +++ b/gfx/layers/PaintThread.cpp @@ -1,58 +1,65 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=99: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "PaintThread.h" +#include "base/task.h" +#include "gfxPrefs.h" +#include "mozilla/layers/CompositorBridgeChild.h" #include "mozilla/gfx/2D.h" +#include "mozilla/Preferences.h" #include "mozilla/SyncRunnable.h" namespace mozilla { namespace layers { using namespace gfx; StaticAutoPtr<PaintThread> PaintThread::sSingleton; +StaticRefPtr<nsIThread> PaintThread::sThread; +PlatformThreadId PaintThread::sThreadId; void PaintThread::Release() { } void PaintThread::AddRef() { } void PaintThread::InitOnPaintThread() { MOZ_ASSERT(!NS_IsMainThread()); - mThreadId = PlatformThread::CurrentId(); + sThreadId = PlatformThread::CurrentId(); } bool PaintThread::Init() { MOZ_ASSERT(NS_IsMainThread()); - nsresult rv = NS_NewNamedThread("PaintThread", getter_AddRefs(mThread)); + RefPtr<nsIThread> thread; + nsresult rv = NS_NewNamedThread("PaintThread", getter_AddRefs(thread)); if (NS_FAILED(rv)) { return false; } + sThread = thread; nsCOMPtr<nsIRunnable> paintInitTask = NewRunnableMethod("PaintThread::InitOnPaintThread", this, &PaintThread::InitOnPaintThread); - - SyncRunnable::DispatchToThread(PaintThread::sSingleton->mThread, paintInitTask); + SyncRunnable::DispatchToThread(sThread, paintInitTask); return true; } /* static */ void PaintThread::Start() { PaintThread::sSingleton = new PaintThread(); @@ -64,55 +71,90 @@ PaintThread::Start() /* static */ PaintThread* PaintThread::Get() { MOZ_ASSERT(NS_IsMainThread()); return PaintThread::sSingleton.get(); } +void +DestroyPaintThread(UniquePtr<PaintThread>&& pt) +{ + MOZ_ASSERT(PaintThread::IsOnPaintThread()); + pt->ShutdownOnPaintThread(); +} + /* static */ void PaintThread::Shutdown() { - if (!PaintThread::sSingleton) { + MOZ_ASSERT(NS_IsMainThread()); + + UniquePtr<PaintThread> pt(sSingleton.forget()); + if (!pt) { return; } - PaintThread::sSingleton->ShutdownImpl(); - PaintThread::sSingleton = nullptr; + sThread->Dispatch(NewRunnableFunction(DestroyPaintThread, Move(pt))); + sThread->Shutdown(); + sThread = nullptr; } void -PaintThread::ShutdownImpl() +PaintThread::ShutdownOnPaintThread() { - MOZ_ASSERT(NS_IsMainThread()); - PaintThread::sSingleton->mThread->AsyncShutdown(); + MOZ_ASSERT(IsOnPaintThread()); +} + +/* static */ bool +PaintThread::IsOnPaintThread() +{ + return sThreadId == PlatformThread::CurrentId(); } -bool -PaintThread::IsOnPaintThread() +void +PaintThread::PaintContentsAsync(CompositorBridgeChild* aBridge, + gfx::DrawTargetCapture* aCapture, + gfx::DrawTarget* aTarget) { - MOZ_ASSERT(mThread); - return PlatformThread::CurrentId() == mThreadId; + MOZ_ASSERT(IsOnPaintThread()); + + // Draw all the things into the actual dest target. + aTarget->DrawCapturedDT(aCapture, Matrix()); + + if (aBridge) { + aBridge->NotifyFinishedAsyncPaint(); + } } void PaintThread::PaintContents(DrawTargetCapture* aCapture, DrawTarget* aTarget) { - if (!IsOnPaintThread()) { - MOZ_ASSERT(NS_IsMainThread()); - nsCOMPtr<nsIRunnable> paintTask = - NewRunnableMethod<DrawTargetCapture*, DrawTarget*>("PaintThread::PaintContents", - this, - &PaintThread::PaintContents, - aCapture, aTarget); + MOZ_ASSERT(NS_IsMainThread()); + + // If painting asynchronously, we need to acquire the compositor bridge which + // owns the underlying MessageChannel. Otherwise we leave it null and use + // synchronous dispatch. + RefPtr<CompositorBridgeChild> cbc; + if (!gfxPrefs::LayersOMTPForceSync()) { + cbc = CompositorBridgeChild::Get(); + cbc->NotifyBeginAsyncPaint(); + } + RefPtr<DrawTargetCapture> capture(aCapture); + RefPtr<DrawTarget> target(aTarget); - SyncRunnable::DispatchToThread(mThread, paintTask); - return; + RefPtr<PaintThread> self = this; + RefPtr<Runnable> task = NS_NewRunnableFunction("PaintThread::PaintContents", + [self, cbc, capture, target]() -> void + { + self->PaintContentsAsync(cbc, capture, target); + }); + + if (cbc) { + sThread->Dispatch(task.forget()); + } else { + SyncRunnable::DispatchToThread(sThread, task); } - - // Draw all the things into the actual dest target. - aTarget->DrawCapturedDT(aCapture, Matrix()); } } // namespace layers } // namespace mozilla
--- a/gfx/layers/PaintThread.h +++ b/gfx/layers/PaintThread.h @@ -4,48 +4,59 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef MOZILLA_LAYERS_PAINTTHREAD_H #define MOZILLA_LAYERS_PAINTTHREAD_H #include "base/platform_thread.h" #include "mozilla/StaticPtr.h" +#include "mozilla/UniquePtr.h" #include "nsThreadUtils.h" namespace mozilla { namespace gfx { class DrawTarget; class DrawTargetCapture; }; namespace layers { +class CompositorBridgeChild; + class PaintThread final { + friend void DestroyPaintThread(UniquePtr<PaintThread>&& aPaintThread); + public: static void Start(); static void Shutdown(); static PaintThread* Get(); void PaintContents(gfx::DrawTargetCapture* aCapture, gfx::DrawTarget* aTarget); + // Sync Runnables need threads to be ref counted, // But this thread lives through the whole process. // We're only temporarily using sync runnables so // Override release/addref but don't do anything. void Release(); void AddRef(); + // Helper for asserts. + static bool IsOnPaintThread(); + private: - bool IsOnPaintThread(); bool Init(); - void ShutdownImpl(); + void ShutdownOnPaintThread(); void InitOnPaintThread(); + void PaintContentsAsync(CompositorBridgeChild* aBridge, + gfx::DrawTargetCapture* aCapture, + gfx::DrawTarget* aTarget); static StaticAutoPtr<PaintThread> sSingleton; - RefPtr<nsIThread> mThread; - PlatformThreadId mThreadId; + static StaticRefPtr<nsIThread> sThread; + static PlatformThreadId sThreadId; }; } // namespace layers } // namespace mozilla -#endif \ No newline at end of file +#endif
--- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -221,16 +221,19 @@ ClientLayerManager::CreateReadbackLayer( { RefPtr<ReadbackLayer> layer = new ClientReadbackLayer(this); return layer.forget(); } bool ClientLayerManager::BeginTransactionWithTarget(gfxContext* aTarget) { + // Wait for any previous async paints to complete before starting to paint again. + GetCompositorBridgeChild()->FlushAsyncPaints(); + MOZ_ASSERT(mForwarder, "ClientLayerManager::BeginTransaction without forwarder"); if (!mForwarder->IPCOpen()) { gfxCriticalNote << "ClientLayerManager::BeginTransaction with IPC channel down. GPU process may have died."; return false; } if (XRE_IsContentProcess() && mForwarder->DeviceCanReset() &&
--- a/gfx/layers/composite/LayerManagerComposite.h +++ b/gfx/layers/composite/LayerManagerComposite.h @@ -308,16 +308,17 @@ public: virtual already_AddRefed<ImageLayer> CreateImageLayer() override; virtual already_AddRefed<ColorLayer> CreateColorLayer() override; virtual already_AddRefed<TextLayer> CreateTextLayer() override; virtual already_AddRefed<BorderLayer> CreateBorderLayer() override; virtual already_AddRefed<CanvasLayer> CreateCanvasLayer() override; virtual already_AddRefed<RefLayer> CreateRefLayer() override; virtual bool AreComponentAlphaLayersEnabled() override; + virtual bool SupportsBackdropCopyForComponentAlpha() override { return false; } virtual already_AddRefed<DrawTarget> CreateOptimalMaskDrawTarget(const IntSize &aSize) override; virtual const char* Name() const override { return ""; } virtual bool IsCompositingToScreen() const override; bool AlwaysScheduleComposite() const override; @@ -509,17 +510,17 @@ private: /** * Render paint and composite times above the frame. */ void DrawPaintTimes(Compositor* aCompositor); RefPtr<PaintCounter> mPaintCounter; #endif #if defined(MOZ_WIDGET_ANDROID) public: - virtual void RequestScreenPixels(UiCompositorControllerParent* aController) + virtual void RequestScreenPixels(UiCompositorControllerParent* aController) override { mScreenPixelsTarget = aController; } private: UiCompositorControllerParent* mScreenPixelsTarget; #endif // defined(MOZ_WIDGET_ANDROID) };
--- a/gfx/layers/ipc/CompositorBridgeChild.cpp +++ b/gfx/layers/ipc/CompositorBridgeChild.cpp @@ -14,16 +14,17 @@ #include "gfxPrefs.h" #include "mozilla/dom/TabGroup.h" #include "mozilla/layers/CompositorManagerChild.h" #include "mozilla/layers/ImageBridgeChild.h" #include "mozilla/layers/APZChild.h" #include "mozilla/layers/IAPZCTreeManager.h" #include "mozilla/layers/APZCTreeManagerChild.h" #include "mozilla/layers/LayerTransactionChild.h" +#include "mozilla/layers/PaintThread.h" #include "mozilla/layers/PLayerTransactionChild.h" #include "mozilla/layers/PTextureChild.h" #include "mozilla/layers/TextureClient.h"// for TextureClient #include "mozilla/layers/TextureClientPool.h"// for TextureClientPool #include "mozilla/layers/WebRenderBridgeChild.h" #include "mozilla/gfx/gfxVars.h" #include "mozilla/gfx/GPUProcessManager.h" #include "mozilla/gfx/Logging.h" @@ -84,16 +85,19 @@ CompositorBridgeChild::CompositorBridgeC , mResourceId(0) , mCanSend(false) , mActorDestroyed(false) , mFwdTransactionId(0) , mDeviceResetSequenceNumber(0) , mMessageLoop(MessageLoop::current()) , mProcessToken(0) , mSectionAllocator(nullptr) + , mPaintLock("CompositorBridgeChild.mPaintLock") + , mOutstandingAsyncPaints(0) + , mIsWaitingForPaint(false) { MOZ_ASSERT(NS_IsMainThread()); } CompositorBridgeChild::~CompositorBridgeChild() { if (mCanSend) { gfxCriticalError() << "CompositorBridgeChild was not deinitialized"; @@ -537,18 +541,30 @@ void CompositorBridgeChild::ActorDestroy(ActorDestroyReason aWhy) { if (aWhy == AbnormalShutdown) { // If the parent side runs into a problem then the actor will be destroyed. // There is nothing we can do in the child side, here sets mCanSend as false. gfxCriticalNote << "Receive IPC close with reason=AbnormalShutdown"; } - mCanSend = false; - mActorDestroyed = true; + { + // We take the lock to update these fields, since they are read from the + // paint thread. We don't need the lock to init them, since that happens + // on the main thread before the paint thread can ever grab a reference + // to the CompositorBridge object. + // + // Note that it is useful to take this lock for one other reason: It also + // tells us whether GetIPCChannel is safe to call. If we access the IPC + // channel within this lock, when mCanSend is true, then we know it has not + // been zapped by IPDL. + MonitorAutoLock lock(mPaintLock); + mCanSend = false; + mActorDestroyed = true; + } if (mProcessToken && XRE_IsParentProcess()) { GPUProcessManager::Get()->NotifyRemoteActorDestroyed(mProcessToken); } } mozilla::ipc::IPCResult CompositorBridgeChild::RecvSharedCompositorFrameMetrics( @@ -1109,11 +1125,91 @@ CompositorBridgeChild::GetNextExternalIm } wr::PipelineId CompositorBridgeChild::GetNextPipelineId() { return wr::AsPipelineId(GetNextResourceId()); } +void +CompositorBridgeChild::NotifyBeginAsyncPaint() +{ + MOZ_ASSERT(NS_IsMainThread()); + + MonitorAutoLock lock(mPaintLock); + + // We must not be waiting for paints to complete yet. This would imply we + // started a new paint without waiting for a previous one, which could lead to + // incorrect rendering or IPDL deadlocks. + MOZ_ASSERT(!mIsWaitingForPaint); + + mOutstandingAsyncPaints++; +} + +void +CompositorBridgeChild::NotifyFinishedAsyncPaint() +{ + MOZ_ASSERT(PaintThread::IsOnPaintThread()); + + MonitorAutoLock lock(mPaintLock); + + mOutstandingAsyncPaints--; + + // It's possible that we painted so fast that the main thread never reached + // the code that starts delaying messages. If so, mIsWaitingForPaint will be + // false, and we can safely return. + if (mIsWaitingForPaint && mOutstandingAsyncPaints == 0) { + ResumeIPCAfterAsyncPaint(); + + // Notify the main thread in case it's blocking. We do this unconditionally + // to avoid deadlocking. + lock.Notify(); + } +} + +void +CompositorBridgeChild::PostponeMessagesIfAsyncPainting() +{ + MOZ_ASSERT(NS_IsMainThread()); + + MonitorAutoLock lock(mPaintLock); + + MOZ_ASSERT(!mIsWaitingForPaint); + + if (mOutstandingAsyncPaints > 0) { + mIsWaitingForPaint = true; + GetIPCChannel()->BeginPostponingSends(); + } +} + +void +CompositorBridgeChild::ResumeIPCAfterAsyncPaint() +{ + // Note: the caller is responsible for holding the lock. + mPaintLock.AssertCurrentThreadOwns(); + MOZ_ASSERT(PaintThread::IsOnPaintThread()); + MOZ_ASSERT(mOutstandingAsyncPaints == 0); + MOZ_ASSERT(mIsWaitingForPaint); + + mIsWaitingForPaint = false; + + // It's also possible that the channel has shut down already. + if (!mCanSend || mActorDestroyed) { + return; + } + + GetIPCChannel()->StopPostponingSends(); +} + +void +CompositorBridgeChild::FlushAsyncPaints() +{ + MOZ_ASSERT(NS_IsMainThread()); + + MonitorAutoLock lock(mPaintLock); + while (mIsWaitingForPaint) { + lock.Wait(); + } +} + } // namespace layers } // namespace mozilla -
--- a/gfx/layers/ipc/CompositorBridgeChild.h +++ b/gfx/layers/ipc/CompositorBridgeChild.h @@ -5,16 +5,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef mozilla_layers_CompositorBridgeChild_h #define mozilla_layers_CompositorBridgeChild_h #include "base/basictypes.h" // for DISALLOW_EVIL_CONSTRUCTORS #include "mozilla/Assertions.h" // for MOZ_ASSERT_HELPER2 #include "mozilla/Attributes.h" // for override +#include "mozilla/Monitor.h" #include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/layers/PCompositorBridgeChild.h" #include "mozilla/layers/TextureForwarder.h" // for TextureForwarder #include "mozilla/webrender/WebRenderTypes.h" #include "nsClassHashtable.h" // for nsClassHashtable #include "nsRefPtrHashtable.h" #include "nsCOMPtr.h" // for nsCOMPtr #include "nsHashKeys.h" // for nsUint64HashKey @@ -215,20 +216,43 @@ public: uint64_t DeviceResetSequenceNumber() const { return mDeviceResetSequenceNumber; } wr::MaybeExternalImageId GetNextExternalImageId() override; wr::PipelineId GetNextPipelineId(); + // Must only be called from the main thread. Notifies the CompositorBridge + // that the paint thread is going to begin painting asynchronously. + void NotifyBeginAsyncPaint(); + + // Must only be called from the paint thread. Notifies the CompositorBridge + // that the paint thread has finished an asynchronous paint request. + void NotifyFinishedAsyncPaint(); + + // Must only be called from the main thread. Notifies the CompoistorBridge + // that a transaction is about to be sent, and if the paint thread is + // currently painting, to begin delaying IPC messages. + void PostponeMessagesIfAsyncPainting(); + + // Must only be called from the main thread. Ensures that any paints from + // previous frames have been flushed. The main thread blocks until the + // operation completes. + void FlushAsyncPaints(); + private: // Private destructor, to discourage deletion outside of Release(): virtual ~CompositorBridgeChild(); + // Must only be called from the paint thread. If the main thread is delaying + // IPC messages, this forwards all such delayed IPC messages to the I/O thread + // and resumes IPC. + void ResumeIPCAfterAsyncPaint(); + void AfterDestroy(); virtual PLayerTransactionChild* AllocPLayerTransactionChild(const nsTArray<LayersBackend>& aBackendHints, const uint64_t& aId) override; virtual bool DeallocPLayerTransactionChild(PLayerTransactionChild *aChild) override; @@ -323,14 +347,28 @@ private: MessageLoop* mMessageLoop; AutoTArray<RefPtr<TextureClientPool>,2> mTexturePools; uint64_t mProcessToken; FixedSizeSmallShmemSectionAllocator* mSectionAllocator; + + // Off-Main-Thread Painting state. This covers access to the OMTP-related + // state below. + Monitor mPaintLock; + + // Contains the number of outstanding asynchronous paints tied to a + // PLayerTransaction on this bridge. This is R/W on both the main and paint + // threads, and must be accessed within the paint lock. + size_t mOutstandingAsyncPaints; + + // True if this CompositorBridge is currently delaying its messages until the + // paint thread completes. This is R/W on both the main and paint threads, and + // must be accessed within the paint lock. + bool mIsWaitingForPaint; }; } // namespace layers } // namespace mozilla #endif // mozilla_layers_CompositorBrigedChild_h
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -1510,24 +1510,24 @@ CompositorBridgeParent::AllocPLayerTrans const uint64_t& aId) { MOZ_ASSERT(aId == 0); InitializeLayerManager(aBackendHints); if (!mLayerManager) { NS_WARNING("Failed to initialise Compositor"); - LayerTransactionParent* p = new LayerTransactionParent(nullptr, this, 0); + LayerTransactionParent* p = new LayerTransactionParent(/* aManager */ nullptr, this, /* aAnimStorage */ nullptr, 0); p->AddIPDLReference(); return p; } mCompositionManager = new AsyncCompositionManager(this, mLayerManager); - LayerTransactionParent* p = new LayerTransactionParent(mLayerManager, this, 0); + LayerTransactionParent* p = new LayerTransactionParent(mLayerManager, this, GetAnimationStorage(0), 0); p->AddIPDLReference(); return p; } bool CompositorBridgeParent::DeallocPLayerTransactionParent(PLayerTransactionParent* actor) { static_cast<LayerTransactionParent*>(actor)->ReleaseIPDLReference(); @@ -1639,17 +1639,17 @@ CompositorBridgeParent::RecvAdoptChild(c APZCTreeManagerParent* parent; { MonitorAutoLock lock(*sIndirectLayerTreesLock); // We currently don't support adopting children from one compositor to // another if the two compositors don't have the same options. MOZ_ASSERT(sIndirectLayerTrees[child].mParent->mOptions == mOptions); NotifyChildCreated(child); if (sIndirectLayerTrees[child].mLayerTree) { - sIndirectLayerTrees[child].mLayerTree->SetLayerManager(mLayerManager); + sIndirectLayerTrees[child].mLayerTree->SetLayerManager(mLayerManager, GetAnimationStorage(0)); // Trigger composition to handle a case that mLayerTree was not composited yet // by previous CompositorBridgeParent, since nsRefreshDriver might wait composition complete. ScheduleComposition(); } if (mWrBridge && sIndirectLayerTrees[child].mWrBridge) { sIndirectLayerTrees[child].mWrBridge->UpdateWebRender(mWrBridge->CompositorScheduler(), mWrBridge->GetWebRenderAPI(), mWrBridge->CompositableHolder(),
--- a/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CrossProcessCompositorBridgeParent.cpp @@ -83,24 +83,25 @@ CrossProcessCompositorBridgeParent::Allo LayerTreeMap::iterator itr = sIndirectLayerTrees.find(aId); if (sIndirectLayerTrees.end() != itr) { state = &itr->second; } if (state && state->mLayerManager) { state->mCrossProcessParent = this; HostLayerManager* lm = state->mLayerManager; - LayerTransactionParent* p = new LayerTransactionParent(lm, this, aId); + CompositorAnimationStorage* animStorage = state->mParent ? state->mParent->GetAnimationStorage(0) : nullptr; + LayerTransactionParent* p = new LayerTransactionParent(lm, this, animStorage, aId); p->AddIPDLReference(); sIndirectLayerTrees[aId].mLayerTree = p; return p; } NS_WARNING("Created child without a matching parent?"); - LayerTransactionParent* p = new LayerTransactionParent(nullptr, this, aId); + LayerTransactionParent* p = new LayerTransactionParent(/* aManager */ nullptr, this, /* aAnimStorage */ nullptr, aId); p->AddIPDLReference(); return p; } bool CrossProcessCompositorBridgeParent::DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) { LayerTransactionParent* slp = static_cast<LayerTransactionParent*>(aLayers);
--- a/gfx/layers/ipc/LayerTransactionParent.cpp +++ b/gfx/layers/ipc/LayerTransactionParent.cpp @@ -46,40 +46,50 @@ using mozilla::layout::RenderFrameParent namespace mozilla { namespace layers { //-------------------------------------------------- // LayerTransactionParent LayerTransactionParent::LayerTransactionParent(HostLayerManager* aManager, CompositorBridgeParentBase* aBridge, + CompositorAnimationStorage* aAnimStorage, uint64_t aId) : mLayerManager(aManager) , mCompositorBridge(aBridge) + , mAnimStorage(aAnimStorage) , mId(aId) , mChildEpoch(0) , mParentEpoch(0) , mPendingTransaction(0) , mDestroyed(false) , mIPCOpen(false) { } LayerTransactionParent::~LayerTransactionParent() { } void -LayerTransactionParent::SetLayerManager(HostLayerManager* aLayerManager) +LayerTransactionParent::SetLayerManager(HostLayerManager* aLayerManager, CompositorAnimationStorage* aAnimStorage) { + if (mDestroyed) { + return; + } mLayerManager = aLayerManager; for (auto iter = mLayerMap.Iter(); !iter.Done(); iter.Next()) { auto layer = iter.Data(); + if (mAnimStorage && + layer->GetCompositorAnimationsId()) { + mAnimStorage->ClearById(layer->GetCompositorAnimationsId()); + } layer->AsHostLayer()->SetLayerManager(aLayerManager); } + mAnimStorage = aAnimStorage; } mozilla::ipc::IPCResult LayerTransactionParent::RecvShutdown() { Destroy(); IProtocol* mgr = Manager(); if (!Send__delete__(this)) { @@ -96,17 +106,26 @@ LayerTransactionParent::RecvShutdownSync void LayerTransactionParent::Destroy() { if (mDestroyed) { return; } mDestroyed = true; + if (mAnimStorage) { + for (auto iter = mLayerMap.Iter(); !iter.Done(); iter.Next()) { + auto layer = iter.Data(); + if (layer->GetCompositorAnimationsId()) { + mAnimStorage->ClearById(layer->GetCompositorAnimationsId()); + } + } + } mCompositables.clear(); + mAnimStorage = nullptr; } class MOZ_STACK_CLASS AutoLayerTransactionParentAsyncMessageSender { public: explicit AutoLayerTransactionParentAsyncMessageSender(LayerTransactionParent* aLayerTransaction, const InfallibleTArray<OpDestroy>* aDestroyActors = nullptr) : mLayerTransaction(aLayerTransaction) @@ -530,24 +549,20 @@ LayerTransactionParent::SetLayerAttribut if (LayerHandle maskLayer = common.maskLayer()) { layer->SetMaskLayer(AsLayer(maskLayer)); } else { layer->SetMaskLayer(nullptr); } layer->SetCompositorAnimations(common.compositorAnimations()); // Clean up the Animations by id in the CompositorAnimationStorage // if there are no active animations on the layer - if (layer->GetCompositorAnimationsId() && + if (mAnimStorage && + layer->GetCompositorAnimationsId() && layer->GetAnimations().IsEmpty()) { - CompositorAnimationStorage* storage = - mCompositorBridge->GetAnimationStorage(GetId()); - - if (storage) { - storage->ClearById(layer->GetCompositorAnimationsId()); - } + mAnimStorage->ClearById(layer->GetCompositorAnimationsId()); } if (common.scrollMetadata() != layer->GetAllScrollMetadata()) { UpdateHitTestingTree(layer, "scroll metadata changed"); layer->SetScrollMetadata(common.scrollMetadata()); } layer->SetDisplayListLog(common.displayListLog().get()); // The updated invalid region is added to the existing one, since we can @@ -722,24 +737,21 @@ LayerTransactionParent::RecvGetAnimation { *aHasAnimationOpacity = false; if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) { return IPC_FAIL_NO_REASON(this); } mCompositorBridge->ApplyAsyncProperties(this); - CompositorAnimationStorage* storage = - mCompositorBridge->GetAnimationStorage(GetId()); - - if (!storage) { + if (!mAnimStorage) { return IPC_FAIL_NO_REASON(this); } - Maybe<float> opacity = storage->GetAnimationOpacity(aCompositorAnimationsId); + Maybe<float> opacity = mAnimStorage->GetAnimationOpacity(aCompositorAnimationsId); if (opacity) { *aOpacity = *opacity; *aHasAnimationOpacity = true; } return IPC_OK(); } mozilla::ipc::IPCResult @@ -751,24 +763,21 @@ LayerTransactionParent::RecvGetAnimation } // Make sure we apply the latest animation style or else we can end up with // a race between when we temporarily clear the animation transform (in // CompositorBridgeParent::SetShadowProperties) and when animation recalculates // the value. mCompositorBridge->ApplyAsyncProperties(this); - CompositorAnimationStorage* storage = - mCompositorBridge->GetAnimationStorage(GetId()); - - if (!storage) { + if (!mAnimStorage) { return IPC_FAIL_NO_REASON(this); } - Maybe<Matrix4x4> transform = storage->GetAnimationTransform(aCompositorAnimationsId); + Maybe<Matrix4x4> transform = mAnimStorage->GetAnimationTransform(aCompositorAnimationsId); if (transform) { *aTransform = *transform; } else { *aTransform = mozilla::void_t(); } return IPC_OK(); } @@ -1003,16 +1012,20 @@ LayerTransactionParent::RecvNewComposita mozilla::ipc::IPCResult LayerTransactionParent::RecvReleaseLayer(const LayerHandle& aHandle) { RefPtr<Layer> layer; if (!aHandle || !mLayerMap.Remove(aHandle.Value(), getter_AddRefs(layer))) { return IPC_FAIL_NO_REASON(this); } + if (mAnimStorage && + layer->GetCompositorAnimationsId()) { + mAnimStorage->ClearById(layer->GetCompositorAnimationsId()); + } layer->Disconnect(); return IPC_OK(); } mozilla::ipc::IPCResult LayerTransactionParent::RecvReleaseCompositable(const CompositableHandle& aHandle) { ReleaseCompositable(aHandle);
--- a/gfx/layers/ipc/LayerTransactionParent.h +++ b/gfx/layers/ipc/LayerTransactionParent.h @@ -28,42 +28,44 @@ class RenderFrameParent; } // namespace layout namespace layers { class Layer; class HostLayerManager; class ShadowLayerParent; class CompositableParent; +class CompositorAnimationStorage; class CompositorBridgeParentBase; class LayerTransactionParent final : public PLayerTransactionParent, public CompositableParentManager, public ShmemAllocator { typedef mozilla::layout::RenderFrameParent RenderFrameParent; typedef InfallibleTArray<Edit> EditArray; typedef InfallibleTArray<OpDestroy> OpDestroyArray; typedef InfallibleTArray<PluginWindowData> PluginsArray; typedef InfallibleTArray<ReadLockInit> ReadLockArray; public: LayerTransactionParent(HostLayerManager* aManager, CompositorBridgeParentBase* aBridge, + CompositorAnimationStorage* aAnimStorage, uint64_t aId); protected: ~LayerTransactionParent(); public: void Destroy(); HostLayerManager* layer_manager() const { return mLayerManager; } - void SetLayerManager(HostLayerManager* aLayerManager); + void SetLayerManager(HostLayerManager* aLayerManager, CompositorAnimationStorage* aAnimStorage); uint64_t GetId() const { return mId; } Layer* GetRoot() const { return mRoot; } uint64_t GetChildEpoch() const { return mChildEpoch; } bool ShouldParentObserveEpoch(); virtual ShmemAllocator* AsShmemAllocator() override { return this; } @@ -169,16 +171,17 @@ private: // testing tree changes are made. void UpdateHitTestingTree(Layer* aLayer, const char* aWhy) { mUpdateHitTestingTree = true; } private: RefPtr<HostLayerManager> mLayerManager; CompositorBridgeParentBase* mCompositorBridge; + RefPtr<CompositorAnimationStorage> mAnimStorage; // Hold the root because it might be grafted under various // containers in the "real" layer tree RefPtr<Layer> mRoot; // Mapping from LayerHandles to Layers. nsRefPtrHashtable<nsUint64HashKey, Layer> mLayerMap;
--- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -759,16 +759,20 @@ ShadowLayerForwarder::EndTransaction(con if (locks.Length()) { if (!mShadowManager->SendInitReadLocks(locks)) { MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending read locks failed!")); return false; } } } + // We delay at the last possible minute, to give the paint thread a chance to + // finish. If it does we don't have to delay messages at all. + GetCompositorBridgeChild()->PostponeMessagesIfAsyncPainting(); + MOZ_LAYERS_LOG(("[LayersForwarder] sending transaction...")); RenderTraceScope rendertrace3("Forward Transaction", "000093"); if (!mShadowManager->SendUpdate(info)) { MOZ_LAYERS_LOG(("[LayersForwarder] WARNING: sending transaction failed!")); return false; } if (startTime) {
--- a/gfx/layers/mlgpu/RenderPassMLGPU.cpp +++ b/gfx/layers/mlgpu/RenderPassMLGPU.cpp @@ -343,16 +343,20 @@ ShaderRenderPass::SetupPSBuffer0(float a MaskInformation cb(aOpacity, HasMask()); return mDevice->GetSharedPSBuffer()->Allocate(&mPSBuffer0, cb); } void ShaderRenderPass::ExecuteRendering() { + if (mVertices.IsEmpty() && mInstances.IsEmpty()) { + return; + } + mDevice->SetPSConstantBuffer(0, &mPSBuffer0); if (MaskOperation* mask = GetMask()) { mDevice->SetPSTexture(kMaskLayerTextureSlot, mask->GetTexture()); mDevice->SetSamplerMode(kMaskSamplerSlot, SamplerMode::LinearClampToZero); } SetupPipeline(); @@ -876,16 +880,20 @@ RenderViewPass::AddToPass(LayerMLGPU* aL { // We bake in the layer ahead of time, which also guarantees the blend mode // is baked in, as well as the geometry requirement. if (mAssignedLayer != aLayer) { return false; } mSource = mAssignedLayer->GetRenderTarget(); + if (!mSource) { + return false; + } + mParentView = aInfo.view; Txn txn(this); IntPoint offset = mAssignedLayer->GetTargetOffset(); IntSize size = mAssignedLayer->GetTargetSize(); // Clamp the visible region to the texture size.
--- a/gfx/thebes/gfxFT2FontList.h +++ b/gfx/thebes/gfxFT2FontList.h @@ -122,32 +122,32 @@ class gfxFT2FontList : public gfxPlatfor { public: gfxFT2FontList(); virtual ~gfxFT2FontList(); virtual gfxFontEntry* LookupLocalFont(const nsAString& aFontName, uint16_t aWeight, int16_t aStretch, - uint8_t aStyle); + uint8_t aStyle) override; virtual gfxFontEntry* MakePlatformFont(const nsAString& aFontName, uint16_t aWeight, int16_t aStretch, uint8_t aStyle, const uint8_t* aFontData, - uint32_t aLength); + uint32_t aLength) override; void GetSystemFontList(InfallibleTArray<FontListEntry>* retValue); static gfxFT2FontList* PlatformFontList() { return static_cast<gfxFT2FontList*>(gfxPlatformFontList::PlatformFontList()); } - virtual void GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily> >& aFamilyArray); + virtual void GetFontFamilyList(nsTArray<RefPtr<gfxFontFamily> >& aFamilyArray) override; void WillShutdown(); protected: typedef enum { kUnknown, kStandard } StandardFile;
--- a/gfx/thebes/gfxPrefs.h +++ b/gfx/thebes/gfxPrefs.h @@ -580,16 +580,17 @@ private: DECL_GFX_PREF(Once, "layers.mlgpu.enable-clear-view", AdvancedLayersEnableClearView, bool, true); DECL_GFX_PREF(Once, "layers.mlgpu.enable-cpu-occlusion", AdvancedLayersEnableCPUOcclusion, bool, true); DECL_GFX_PREF(Once, "layers.mlgpu.enable-depth-buffer", AdvancedLayersEnableDepthBuffer, bool, false); DECL_GFX_PREF(Live, "layers.mlgpu.enable-invalidation", AdvancedLayersUseInvalidation, bool, true); DECL_GFX_PREF(Once, "layers.mlgpu.enable-on-windows7", AdvancedLayersEnableOnWindows7, bool, false); DECL_GFX_PREF(Once, "layers.mlgpu.enable-container-resizing", AdvancedLayersEnableContainerResizing, bool, true); DECL_GFX_PREF(Once, "layers.offmainthreadcomposition.force-disabled", LayersOffMainThreadCompositionForceDisabled, bool, false); DECL_GFX_PREF(Live, "layers.offmainthreadcomposition.frame-rate", LayersCompositionFrameRate, int32_t,-1); + DECL_GFX_PREF(Live, "layers.omtp.force-sync", LayersOMTPForceSync, bool, true); DECL_GFX_PREF(Live, "layers.orientation.sync.timeout", OrientationSyncMillis, uint32_t, (uint32_t)0); DECL_GFX_PREF(Once, "layers.prefer-opengl", LayersPreferOpenGL, bool, false); DECL_GFX_PREF(Live, "layers.progressive-paint", ProgressivePaint, bool, false); DECL_GFX_PREF(Live, "layers.shared-buffer-provider.enabled", PersistentBufferProviderSharedEnabled, bool, false); DECL_GFX_PREF(Live, "layers.single-tile.enabled", LayersSingleTileEnabled, bool, true); DECL_GFX_PREF(Once, "layers.stereo-video.enabled", StereoVideoEnabled, bool, false); DECL_GFX_PREF(Live, "layers.force-synchronous-resize", LayersForceSynchronousResize, bool, false);
--- a/image/imgLoader.h +++ b/image/imgLoader.h @@ -536,17 +536,17 @@ class imgCacheValidator : public nsIStre { public: imgCacheValidator(nsProgressNotificationProxy* progress, imgLoader* loader, imgRequest* aRequest, nsISupports* aContext, bool forcePrincipalCheckForCacheEntry); void AddProxy(imgRequestProxy* aProxy); - NS_DECL_ISUPPORTS + NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSITHREADRETARGETABLESTREAMLISTENER NS_DECL_NSISTREAMLISTENER NS_DECL_NSIREQUESTOBSERVER NS_DECL_NSICHANNELEVENTSINK NS_DECL_NSIINTERFACEREQUESTOR NS_DECL_NSIASYNCVERIFYREDIRECTCALLBACK private:
--- a/ipc/mscom/MainThreadRuntime.cpp +++ b/ipc/mscom/MainThreadRuntime.cpp @@ -1,21 +1,23 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "mozilla/mscom/MainThreadRuntime.h" +#if defined(ACCESSIBILITY) +#include "mozilla/a11y/Compatibility.h" +#endif #include "mozilla/ArrayUtils.h" #include "mozilla/Assertions.h" #include "mozilla/RefPtr.h" #include "mozilla/UniquePtr.h" -#include "mozilla/WindowsVersion.h" #include "nsWindowsHelpers.h" #include "nsXULAppAPI.h" #include <accctrl.h> #include <aclapi.h> #include <objbase.h> #include <objidl.h> @@ -29,48 +31,25 @@ struct LocalFreeDeleter } }; } // anonymous namespace // This API from oleaut32.dll is not declared in Windows SDK headers extern "C" void __cdecl SetOaNoCache(void); -#if defined(ACCESSIBILITY) -static WORD -GetActCtxResourceId() -{ - // The manifest for 32-bit Windows is embedded with resource ID 32. - // The manifest for 64-bit Windows is embedded with resource ID 64. - // Beginning with Windows 10 Creators Update, 32-bit builds use the 64-bit - // manifest. - WORD actCtxResourceId; -#if defined(HAVE_64BIT_BUILD) - actCtxResourceId = 64; -#else - if (mozilla::IsWin10CreatorsUpdateOrLater()) { - actCtxResourceId = 64; - } else { - actCtxResourceId = 32; - } -#endif // defined(HAVE_64BIT_BUILD) - - return actCtxResourceId; -} -#endif // defined(ACCESSIBILITY) - namespace mozilla { namespace mscom { MainThreadRuntime* MainThreadRuntime::sInstance = nullptr; MainThreadRuntime::MainThreadRuntime() : mInitResult(E_UNEXPECTED) #if defined(ACCESSIBILITY) - , mActCtxRgn(::GetActCtxResourceId()) + , mActCtxRgn(a11y::Compatibility::GetActCtxResourceId()) #endif // defined(ACCESSIBILITY) { // We must be the outermost COM initialization on this thread. The COM runtime // cannot be configured once we start manipulating objects MOZ_ASSERT(mStaRegion.IsValidOutermost()); if (NS_WARN_IF(!mStaRegion.IsValidOutermost())) { return; }
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/coverage/getLcovInfo_twice.js @@ -0,0 +1,2 @@ +getLcovInfo(); +getLcovInfo();
--- a/layout/base/PresShell.cpp +++ b/layout/base/PresShell.cpp @@ -7164,19 +7164,16 @@ PresShell::HandleEvent(nsIFrame* aFrame, } #endif NS_ASSERTION(aFrame, "aFrame should be not null"); // Update the latest focus sequence number with this new sequence number if (mAPZFocusSequenceNumber < aEvent->mFocusSequenceNumber) { mAPZFocusSequenceNumber = aEvent->mFocusSequenceNumber; - - // Schedule an empty transaction to transmit this focus update - aFrame->SchedulePaint(nsIFrame::PAINT_COMPOSITE_ONLY); } if (sPointerEventEnabled) { AutoWeakFrame weakFrame(aFrame); nsCOMPtr<nsIContent> targetContent; DispatchPointerFromMouseOrTouch(this, aFrame, aEvent, aDontRetargetEvents, aEventStatus, getter_AddRefs(targetContent));
--- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -852,18 +852,20 @@ AddAndRemoveImageAssociations(nsFrame* a if (i >= aNewLayers->mImageCount || !aOldLayers->mLayers[i].mImage.ImageDataEquals( aNewLayers->mLayers[i].mImage)) { const nsStyleImage& oldImage = aOldLayers->mLayers[i].mImage; if (oldImage.GetType() != eStyleImageType_Image) { continue; } - if (imgRequestProxy* req = oldImage.GetImageData()) { - imageLoader->DisassociateRequestFromFrame(req, aFrame); + if (aFrame->HasImageRequest()) { + if (imgRequestProxy* req = oldImage.GetImageData()) { + imageLoader->DisassociateRequestFromFrame(req, aFrame); + } } } } } NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, (*aNewLayers)) { // If there is an image in newBG that's not in oldBG, add it. if (!aOldLayers || i >= aOldLayers->mImageCount || @@ -967,17 +969,17 @@ nsFrame::DidSetStyleContext(nsStyleConte // we'll never know that it's finished loading. Likewise, we want to // do this for freshly-created frames to prevent a similar race if the // image loads between reflow (which can depend on whether the image // is loaded) and paint. We also don't really care about any callers // who try to paint borders with a different style context, because // they won't have the correct size for the border either. if (oldBorderImage != newBorderImage) { // stop and restart the image loading/notification - if (oldBorderImage) { + if (oldBorderImage && HasImageRequest()) { imageLoader->DisassociateRequestFromFrame(oldBorderImage, this); } if (newBorderImage) { imageLoader->AssociateRequestToFrame(newBorderImage, this); } } // If the page contains markup that overrides text direction, and
--- a/layout/generic/nsGridContainerFrame.cpp +++ b/layout/generic/nsGridContainerFrame.cpp @@ -4744,16 +4744,17 @@ nsGridContainerFrame::Tracks::AlignJusti break; case NS_STYLE_ALIGN_SPACE_EVENLY: roundingError = NSCoordDivRem(space, mSizes.Length() + 1, &between); pos = between; break; default: MOZ_ASSERT_UNREACHABLE("unknown align-/justify-content value"); between = 0; // just to avoid a compiler warning + roundingError = 0; // just to avoid a compiler warning } between += mGridGap; for (TrackSize& sz : mSizes) { sz.mPosition = pos; nscoord spacing = between; if (roundingError) { roundingError -= 1; spacing += 1;
--- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -5132,18 +5132,17 @@ nsDisplayText::nsDisplayText(nsDisplayLi // a layer here. We have to deal with the problem that the ScreenReferenceDrawTarget // might not be compatible with the DT used for layer rendering. GlyphArray* g = mGlyphs.AppendElement(); std::vector<Glyph> glyphs; Color color; if (!capture->ContainsOnlyColoredGlyphs(mFont, color, glyphs) || !mFont - || !mFont->CanSerialize() - || XRE_IsParentProcess()) { + || !mFont->CanSerialize()) { mFont = nullptr; mGlyphs.Clear(); } else { g->glyphs().SetLength(glyphs.size()); PodCopy(g->glyphs().Elements(), glyphs.data(), glyphs.size()); g->color() = color; } }
--- a/layout/style/RuleNodeCacheConditions.h +++ b/layout/style/RuleNodeCacheConditions.h @@ -90,16 +90,21 @@ public: eHaveWritingMode; } void SetUncacheable() { mBits |= eUncacheable; } + void Clear() + { + *this = RuleNodeCacheConditions(); + } + bool Cacheable() const { return !(mBits & eUncacheable); } bool CacheableWithDependencies() const { return !(mBits & eUncacheable) &&
--- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -2673,16 +2673,52 @@ nsRuleNode::WalkRuleTree(const nsStyleSt if (!highestNode) highestNode = rootNode; MOZ_ASSERT(!(aSID == eStyleStruct_Variables && startStruct), "if we start caching Variables structs in the rule tree, then " "not forcing detail to eRulePartialMixed just below is no " "longer valid"); + if (detail == eRuleNone && isReset) { + // We specified absolutely no rule information for a reset struct, and we + // may or may not have found a parent rule in the tree that specified all + // the rule information. Regardless, we don't need to use any cache + // conditions if we cache this struct in the rule tree. + // + // Normally ruleData.mConditions would already indicate that the struct + // is cacheable without conditions if detail is eRuleNone, but because + // of the UnsetPropertiesWithoutFlags call above, we may have encountered + // some rules with dependencies, which we then cleared out of ruleData. + // + // ruleData.mConditions could also indicate we are not cacheable at all, + // such as when AnimValuesStyleRule prevents us from caching structs + // when attempting to apply animations to pseudos. + // + // So if we we are uncacheable, we leave it, but if we are cacheable + // with dependencies, we convert that to cacheable without dependencies. + if (ruleData.mConditions.CacheableWithDependencies()) { + MOZ_ASSERT(pseudoRestriction, + "should only be cacheable with dependencies if we had a " + "pseudo restriction"); + ruleData.mConditions.Clear(); + } else { + // XXXheycam We shouldn't have `|| GetLevel() == SheetType::Transition` + // in the assertion condition, but rule nodes created by + // ResolveStyleByAddingRules don't call SetIsAnimationRule(). + MOZ_ASSERT(ruleData.mConditions.CacheableWithoutDependencies() || + ((HasAnimationData() || + GetLevel() == SheetType::Transition) && + aContext->GetParent() && + aContext->GetParent()->HasPseudoElementData()), + "should only be uncacheable if we had an animation rule " + "and we're inside a pseudo"); + } + } + if (!ruleData.mConditions.CacheableWithoutDependencies() && aSID != eStyleStruct_Variables) { // Treat as though some data is specified to avoid the optimizations and // force data computation. // // We don't need to do this for Variables structs since we know those are // never cached in the rule tree, and it avoids wasteful computation of a // new Variables struct when we have no additional variable declarations,
--- a/layout/style/nsRuleNode.h +++ b/layout/style/nsRuleNode.h @@ -188,30 +188,35 @@ private: void* GetConditionalStyleData(nsStyleStructID aSID, mozilla::GeckoStyleContext* aStyleContext) const; public: void SetStyleData(nsStyleStructID aSID, void* aStyleStruct) { MOZ_ASSERT(!(mConditionalBits & GetBitForSID(aSID)), "rule node should not have unconditional and conditional style " "data for a given struct"); + mConditionalBits &= ~GetBitForSID(aSID); mEntries[aSID] = aStyleStruct; } void SetStyleData(nsStyleStructID aSID, nsPresContext* aPresContext, void* aStyleStruct, const mozilla::RuleNodeCacheConditions& aConditions) { - MOZ_ASSERT((mConditionalBits & GetBitForSID(aSID)) || - !mEntries[aSID], - "rule node should not have unconditional and conditional style " - "data for a given struct"); + if (!(mConditionalBits & GetBitForSID(aSID))) { + MOZ_ASSERT(!mEntries[aSID], + "rule node should not have unconditional and conditional " + "style data for a given struct"); + mEntries[aSID] = nullptr; + } + MOZ_ASSERT(aConditions.CacheableWithDependencies(), "don't call SetStyleData with a cache key that has no " "conditions or is uncacheable"); + #ifdef DEBUG for (Entry* e = static_cast<Entry*>(mEntries[aSID]); e; e = e->mNext) { NS_WARNING_ASSERTION(e->mConditions != aConditions, "wasteful to have duplicate conditional style data"); } #endif mConditionalBits |= GetBitForSID(aSID);
--- a/mobile/android/chrome/content/browser.js +++ b/mobile/android/chrome/content/browser.js @@ -3346,17 +3346,17 @@ var DesktopUserAgent = { function nsBrowserAccess() { } nsBrowserAccess.prototype = { QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow]), - _getBrowser: function _getBrowser(aURI, aOpener, aWhere, aFlags) { + _getBrowser: function _getBrowser(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) { let isExternal = !!(aFlags & Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL); if (isExternal && aURI && aURI.schemeIs("chrome")) return null; let loadflags = isExternal ? Ci.nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL : Ci.nsIWebNavigation.LOAD_FLAGS_NONE; if (aWhere == Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW) { @@ -3422,44 +3422,49 @@ nsBrowserAccess.prototype = { // BrowserApp.addTab calls loadURIWithFlags with the appropriate params let tab = BrowserApp.addTab(aURI ? aURI.spec : "about:blank", { flags: loadflags, referrerURI: referrer, external: isExternal, parentId: parentId, opener: openerWindow, selected: true, isPrivate: isPrivate, - pinned: pinned }); + pinned: pinned, + triggeringPrincipal: aTriggeringPrincipal}); return tab.browser; } // OPEN_CURRENTWINDOW and illegal values let browser = BrowserApp.selectedBrowser; if (aURI && browser) { - browser.loadURIWithFlags(aURI.spec, loadflags, referrer, null, null); + browser.loadURIWithFlags(aURI.spec, { + flags: loadflags, + referrerURI: referrer, + triggeringPrincipal: aTriggeringPrincipal, + }); } return browser; }, - openURI: function browser_openURI(aURI, aOpener, aWhere, aFlags) { - let browser = this._getBrowser(aURI, aOpener, aWhere, aFlags); + openURI: function browser_openURI(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal) { + let browser = this._getBrowser(aURI, aOpener, aWhere, aFlags, aTriggeringPrincipal); return browser ? browser.contentWindow : null; }, openURIInFrame: function browser_openURIInFrame(aURI, aParams, aWhere, aFlags, aNextTabParentId, aName) { // We currently ignore aNextTabParentId on mobile. This needs to change // when Fennec starts to support e10s. Assertions will fire if this code // isn't fixed by then. // // We also ignore aName if it is set, as it is currently only used on the // e10s codepath. - let browser = this._getBrowser(aURI, null, aWhere, aFlags); + let browser = this._getBrowser(aURI, null, aWhere, aFlags, null); if (browser) return browser.QueryInterface(Ci.nsIFrameLoaderOwner); return null; }, isTabContentWindow: function(aWindow) { return BrowserApp.getBrowserForWindow(aWindow) != null; },
--- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -3157,19 +3157,16 @@ pref("dom.ipc.plugins.flash.disable-prot pref("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", true); pref("dom.ipc.plugins.reportCrashURL", true); // How long we wait before unloading an idle plugin process. // Defaults to 30 seconds. pref("dom.ipc.plugins.unloadTimeoutSecs", 30); -// Asynchronous plugin initialization is on hold. -pref("dom.ipc.plugins.asyncInit.enabled", false); - // Allow Flash async drawing mode in 64-bit release builds pref("dom.ipc.plugins.asyncdrawing.enabled", true); // Force the accelerated direct path for a subset of Flash wmode values pref("dom.ipc.plugins.forcedirect.enabled", true); // Enable multi by default for Nightly and DevEdition only. // For Beta and Release builds, multi is controlled by the e10srollout addon. #if defined(RELEASE_OR_BETA) && !defined(MOZ_DEV_EDITION)
--- a/mozglue/build/WindowsDllBlocklist.cpp +++ b/mozglue/build/WindowsDllBlocklist.cpp @@ -774,48 +774,16 @@ continue_loading: // Prevent the stack walker from suspending this thread when LdrLoadDll // holds the RtlLookupFunctionEntry lock. AutoSuppressStackWalking suppress; #endif return stub_LdrLoadDll(filePath, flags, moduleFileName, handle); } -#ifdef _M_AMD64 -typedef NTSTATUS (NTAPI *LdrUnloadDll_func)(HMODULE module); -static LdrUnloadDll_func stub_LdrUnloadDll; - -static NTSTATUS NTAPI -patched_LdrUnloadDll(HMODULE module) -{ - // Prevent the stack walker from suspending this thread when LdrUnloadDll - // holds the RtlLookupFunctionEntry lock. - AutoSuppressStackWalking suppress; - return stub_LdrUnloadDll(module); -} - -// These pointers are disguised as PVOID to avoid pulling in obscure headers -typedef PVOID (WINAPI *LdrResolveDelayLoadedAPI_func)(PVOID ParentModuleBase, - PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook, - PVOID ThunkAddress, ULONG Flags); -static LdrResolveDelayLoadedAPI_func stub_LdrResolveDelayLoadedAPI; - -static PVOID WINAPI patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase, - PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook, - PVOID ThunkAddress, ULONG Flags) -{ - // Prevent the stack walker from suspending this thread when - // LdrResolveDelayLoadAPI holds the RtlLookupFunctionEntry lock. - AutoSuppressStackWalking suppress; - return stub_LdrResolveDelayLoadedAPI(ParentModuleBase, DelayloadDescriptor, - FailureDllHook, FailureSystemHook, - ThunkAddress, Flags); -} -#endif - #ifdef _M_IX86 static bool ShouldBlockThread(void* aStartAddress) { // Allows crashfirefox.exe to continue to work. Also if your threadproc is null, this crash is intentional. if (aStartAddress == 0) return false; @@ -885,24 +853,16 @@ DllBlocklist_Initialize(uint32_t aInitFl #ifdef DEBUG printf_stderr("LdrLoadDll hook failed, no dll blocklisting active\n"); #endif } Kernel32Intercept.Init("kernel32.dll"); #ifdef _M_AMD64 - NtDllIntercept.AddHook("LdrUnloadDll", - reinterpret_cast<intptr_t>(patched_LdrUnloadDll), - (void**)&stub_LdrUnloadDll); - if (IsWin8OrLater()) { // LdrResolveDelayLoadedAPI was introduced in Win8 - NtDllIntercept.AddHook("LdrResolveDelayLoadedAPI", - reinterpret_cast<intptr_t>(patched_LdrResolveDelayLoadedAPI), - (void**)&stub_LdrResolveDelayLoadedAPI); - } if (!IsWin8OrLater()) { // The crash that this hook works around is only seen on Win7. Kernel32Intercept.AddHook("RtlInstallFunctionTableCallback", reinterpret_cast<intptr_t>(patched_RtlInstallFunctionTableCallback), (void**)&stub_RtlInstallFunctionTableCallback); } #endif
--- a/netwerk/protocol/http/HttpChannelChild.cpp +++ b/netwerk/protocol/http/HttpChannelChild.cpp @@ -1593,36 +1593,38 @@ HttpChannelChild::SetupRedirect(nsIURI* mRedirectChannelChild = do_QueryInterface(newChannel); newChannel.forget(outChannel); return NS_OK; } void HttpChannelChild::Redirect1Begin(const uint32_t& registrarId, - const URIParams& newUri, + const URIParams& newOriginalURI, const uint32_t& redirectFlags, const nsHttpResponseHead& responseHead, const nsACString& securityInfoSerialization, const uint64_t& channelId) { + nsresult rv; + LOG(("HttpChannelChild::Redirect1Begin [this=%p]\n", this)); - nsCOMPtr<nsIURI> uri = DeserializeURI(newUri); + nsCOMPtr<nsIURI> uri = DeserializeURI(newOriginalURI); if (!securityInfoSerialization.IsEmpty()) { NS_DeserializeObject(securityInfoSerialization, getter_AddRefs(mSecurityInfo)); } nsCOMPtr<nsIChannel> newChannel; - nsresult rv = SetupRedirect(uri, - &responseHead, - redirectFlags, - getter_AddRefs(newChannel)); + rv = SetupRedirect(uri, + &responseHead, + redirectFlags, + getter_AddRefs(newChannel)); if (NS_SUCCEEDED(rv)) { if (mRedirectChannelChild) { // Set the channelId allocated in parent to the child instance nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(mRedirectChannelChild); if (httpChannel) { rv = httpChannel->SetChannelId(channelId); MOZ_ASSERT(NS_SUCCEEDED(rv));
--- a/netwerk/protocol/http/HttpChannelParent.cpp +++ b/netwerk/protocol/http/HttpChannelParent.cpp @@ -1749,39 +1749,46 @@ HttpChannelParent::Delete() //----------------------------------------------------------------------------- NS_IMETHODIMP HttpChannelParent::StartRedirect(uint32_t registrarId, nsIChannel* newChannel, uint32_t redirectFlags, nsIAsyncVerifyRedirectCallback* callback) { + nsresult rv; + LOG(("HttpChannelParent::StartRedirect [this=%p, registrarId=%" PRIu32 " " "newChannel=%p callback=%p]\n", this, registrarId, newChannel, callback)); if (mIPCClosed) return NS_BINDING_ABORTED; - nsCOMPtr<nsIURI> newURI; - newChannel->GetURI(getter_AddRefs(newURI)); + // Sending down the original URI, because that is the URI we have + // to construct the channel from - this is the URI we've been actually + // redirected to. URI of the channel may be an inner channel URI. + // URI of the channel will be reconstructed by the protocol handler + // on the child process, no need to send it then. + nsCOMPtr<nsIURI> newOriginalURI; + newChannel->GetOriginalURI(getter_AddRefs(newOriginalURI)); URIParams uriParams; - SerializeURI(newURI, uriParams); + SerializeURI(newOriginalURI, uriParams); nsCString secInfoSerialization; UpdateAndSerializeSecurityInfo(secInfoSerialization); // If the channel is a HTTP channel, we also want to inform the child // about the parent's channelId attribute, so that both parent and child // share the same ID. Useful for monitoring channel activity in devtools. uint64_t channelId; nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(newChannel); if (httpChannel) { - nsresult rv = httpChannel->GetChannelId(&channelId); + rv = httpChannel->GetChannelId(&channelId); NS_ENSURE_SUCCESS(rv, NS_BINDING_ABORTED); } nsHttpResponseHead *responseHead = mChannel->GetResponseHead(); bool result = false; if (!mIPCClosed) { result = SendRedirect1Begin(registrarId, uriParams, redirectFlags, responseHead ? *responseHead
--- a/netwerk/protocol/http/PHttpChannel.ipdl +++ b/netwerk/protocol/http/PHttpChannel.ipdl @@ -112,17 +112,17 @@ child: // Used to cancel child channel if we hit errors during creating and // AsyncOpen of nsHttpChannel on the parent. async FailedAsyncOpen(nsresult status); // Called to initiate content channel redirect, starts talking to sinks // on the content process and reports result via Redirect2Verify above async Redirect1Begin(uint32_t registrarId, - URIParams newUri, + URIParams newOriginalUri, uint32_t redirectFlags, nsHttpResponseHead responseHead, nsCString securityInfoSerialization, uint64_t channelId, NetAddr oldPeerAddr); // Called if redirect successful so that child can complete setup. async Redirect3Complete();
--- a/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc +++ b/security/sandbox/chromium/sandbox/win/src/restricted_token_utils.cc @@ -78,17 +78,21 @@ DWORD CreateRestrictedToken(TokenLevel s restricted_token.AddRestrictingSidLogonSession(); break; } case USER_LIMITED: { sid_exceptions.push_back(WinBuiltinUsersSid); sid_exceptions.push_back(WinWorldSid); sid_exceptions.push_back(WinInteractiveSid); privilege_exceptions.push_back(SE_CHANGE_NOTIFY_NAME); - restricted_token.AddUserSidForDenyOnly(); + // This breaks web audio, so we don't want to do this in the restricting + // SIDs (normal) case. See bug 1378061. + if (!gUseRestricting) { + restricted_token.AddUserSidForDenyOnly(); + } restricted_token.AddRestrictingSid(WinBuiltinUsersSid); restricted_token.AddRestrictingSid(WinWorldSid); restricted_token.AddRestrictingSid(WinRestrictedCodeSid); // This token has to be able to create objects in BNO. // Unfortunately, on Vista+, it needs the current logon sid // in the token to achieve this. You should also set the process to be // low integrity level so it can't access object created by other
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win32_clang.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_win32_clang.py @@ -65,14 +65,14 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser\\config\\mozconfigs\\win32\\clang', 'artifact_flag_build_variant_in_try': None, ######################################################################### }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win32_clang_debug.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_win32_clang_debug.py @@ -67,14 +67,14 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser\\config\\mozconfigs\\win32\\clang-debug', 'artifact_flag_build_variant_in_try': None, ######################################################################### }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win32_noopt_debug.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_win32_noopt_debug.py @@ -69,14 +69,14 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser\\config\\mozconfigs\\win32\\noopt-debug', 'artifact_flag_build_variant_in_try': None, ######################################################################### }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win64_asan_debug.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_win64_asan_debug.py @@ -63,13 +63,13 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\debug-asan', ######################################################################### }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win64_asan_opt.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_win64_asan_opt.py @@ -61,13 +61,13 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\nightly-asan', ######################################################################### }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win64_clang.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_win64_clang.py @@ -61,14 +61,14 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\clang', 'artifact_flag_build_variant_in_try': None, ######################################################################### }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win64_clang_debug.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_win64_clang_debug.py @@ -63,14 +63,14 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\clang-debug', 'artifact_flag_build_variant_in_try': None, ######################################################################### }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_win64_noopt_debug.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_win64_noopt_debug.py @@ -63,14 +63,14 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\noopt-debug', 'artifact_flag_build_variant_in_try': None, ######################################################################### }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_addondevel.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_addondevel.py @@ -65,13 +65,13 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser/config/mozconfigs/win32/add-on-devel', ######################################################################### }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_debug.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_debug.py @@ -67,13 +67,13 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser\\config\\mozconfigs\\win32\\debug', ######################################################################### }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_opt.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_32_opt.py @@ -65,13 +65,13 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win32\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser\\config\\mozconfigs\\win32\\nightly', ######################################################################### }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_addondevel.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_addondevel.py @@ -62,13 +62,13 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser/config/mozconfigs/win64/add-on-devel', ######################################################################### }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_debug.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_debug.py @@ -63,13 +63,13 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\debug', ######################################################################### }
--- a/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_opt.py +++ b/testing/mozharness/configs/builds/taskcluster_firefox_windows_64_opt.py @@ -61,13 +61,13 @@ config = { 'MSYSTEM': 'MINGW32', }, 'upload_env': { 'UPLOAD_HOST': 'localhost', 'UPLOAD_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, "check_test_env": { 'MINIDUMP_STACKWALK': '%(abs_tools_dir)s\\breakpad\\win64\\minidump_stackwalk.exe', - 'MINIDUMP_SAVE_PATH': '%(base_work_dir)s\\minidumps', + 'MINIDUMP_SAVE_PATH': os.path.join(os.getcwd(), 'public', 'build'), }, 'src_mozconfig': 'browser\\config\\mozconfigs\\win64\\nightly', ######################################################################### }
--- a/toolkit/components/telemetry/TelemetryEnvironment.jsm +++ b/toolkit/components/telemetry/TelemetryEnvironment.jsm @@ -182,17 +182,16 @@ const DEFAULT_ENVIRONMENT_PREFS = new Ma ["browser.startup.homepage", {what: RECORD_PREF_STATE}], ["browser.startup.page", {what: RECORD_PREF_VALUE}], ["toolkit.cosmeticAnimations.enabled", {what: RECORD_PREF_VALUE}], ["browser.urlbar.suggest.searches", {what: RECORD_PREF_VALUE}], ["browser.urlbar.userMadeSearchSuggestionsChoice", {what: RECORD_PREF_VALUE}], ["devtools.chrome.enabled", {what: RECORD_PREF_VALUE}], ["devtools.debugger.enabled", {what: RECORD_PREF_VALUE}], ["devtools.debugger.remote-enabled", {what: RECORD_PREF_VALUE}], - ["dom.ipc.plugins.asyncInit.enabled", {what: RECORD_PREF_VALUE}], ["dom.ipc.plugins.enabled", {what: RECORD_PREF_VALUE}], ["dom.ipc.processCount", {what: RECORD_PREF_VALUE}], ["dom.max_script_run_time", {what: RECORD_PREF_VALUE}], ["experiments.manifest.uri", {what: RECORD_PREF_VALUE}], ["extensions.allow-non-mpc-extensions", {what: RECORD_PREF_VALUE}], ["extensions.autoDisableScopes", {what: RECORD_PREF_VALUE}], ["extensions.enabledScopes", {what: RECORD_PREF_VALUE}], ["extensions.blocklist.enabled", {what: RECORD_PREF_VALUE}],
--- a/toolkit/components/telemetry/TelemetrySession.jsm +++ b/toolkit/components/telemetry/TelemetrySession.jsm @@ -53,17 +53,16 @@ const MS_IN_ONE_HOUR = 60 * 60 * 1000; const MIN_SUBSESSION_LENGTH_MS = Preferences.get("toolkit.telemetry.minSubsessionLength", 5 * 60) * 1000; const LOGGER_NAME = "Toolkit.Telemetry"; const LOGGER_PREFIX = "TelemetrySession" + (Utils.isContentProcess ? "#content::" : "::"); const PREF_BRANCH = "toolkit.telemetry."; const PREF_PREVIOUS_BUILDID = PREF_BRANCH + "previousBuildID"; const PREF_FHR_UPLOAD_ENABLED = "datareporting.healthreport.uploadEnabled"; -const PREF_ASYNC_PLUGIN_INIT = "dom.ipc.plugins.asyncInit.enabled"; const PREF_UNIFIED = PREF_BRANCH + "unified"; const PREF_SHUTDOWN_PINGSENDER = PREF_BRANCH + "shutdownPingSender.enabled"; const MESSAGE_TELEMETRY_PAYLOAD = "Telemetry:Payload"; const MESSAGE_TELEMETRY_THREAD_HANGS = "Telemetry:ChildThreadHangs"; const MESSAGE_TELEMETRY_GET_CHILD_THREAD_HANGS = "Telemetry:GetChildThreadHangs"; const MESSAGE_TELEMETRY_USS = "Telemetry:USS"; const MESSAGE_TELEMETRY_GET_CHILD_USS = "Telemetry:GetChildUSS"; @@ -1069,17 +1068,16 @@ var Impl = { getMetadata: function getMetadata(reason) { const sessionStartDate = Utils.toLocalTimeISOString(Utils.truncateToHours(this._sessionStartDate)); const subsessionStartDate = Utils.toLocalTimeISOString(Utils.truncateToHours(this._subsessionStartDate)); const monotonicNow = Policy.monotonicNow(); let ret = { reason, revision: AppConstants.SOURCE_REVISION_URL, - asyncPluginInit: Preferences.get(PREF_ASYNC_PLUGIN_INIT, false), // Date.getTimezoneOffset() unintuitively returns negative values if we are ahead of // UTC and vice versa (e.g. -60 for UTC+1). We invert the sign here. timezoneOffset: -this._subsessionStartDate.getTimezoneOffset(), previousBuildId: this._previousBuildId, sessionId: this._sessionId, subsessionId: this._subsessionId, @@ -1170,27 +1168,35 @@ var Impl = { if (!Telemetry.canRecordExtended) { return; } b("MEMORY_VSIZE", "vsize"); b("MEMORY_VSIZE_MAX_CONTIGUOUS", "vsizeMaxContiguous"); b("MEMORY_RESIDENT_FAST", "residentFast"); b("MEMORY_UNIQUE", "residentUnique"); - b("MEMORY_HEAP_ALLOCATED", "heapAllocated"); p("MEMORY_HEAP_OVERHEAD_FRACTION", "heapOverheadFraction"); b("MEMORY_JS_GC_HEAP", "JSMainRuntimeGCHeap"); c("MEMORY_JS_COMPARTMENTS_SYSTEM", "JSMainRuntimeCompartmentsSystem"); c("MEMORY_JS_COMPARTMENTS_USER", "JSMainRuntimeCompartmentsUser"); b("MEMORY_IMAGES_CONTENT_USED_UNCOMPRESSED", "imagesContentUsedUncompressed"); b("MEMORY_STORAGE_SQLITE", "storageSQLite"); cc("LOW_MEMORY_EVENTS_VIRTUAL", "lowMemoryEventsVirtual"); cc("LOW_MEMORY_EVENTS_PHYSICAL", "lowMemoryEventsPhysical"); cc("PAGE_FAULTS_HARD", "pageFaultsHard"); + try { + mgr.getHeapAllocatedAsync(heapAllocated => { + boundHandleMemoryReport("MEMORY_HEAP_ALLOCATED", + Ci.nsIMemoryReporter.UNITS_BYTES, + heapAllocated); + }); + } catch (e) { + } + if (!Utils.isContentProcess && !this._totalMemoryTimeout) { // Only the chrome process should gather total memory // total = parent RSS + sum(child USS) this._totalMemory = mgr.residentFast; if (ppmm.childCount > 1) { // Do not report If we time out waiting for the children to call this._totalMemoryTimeout = setTimeout( () => {
--- a/toolkit/components/timermanager/nsUpdateTimerManager.js +++ b/toolkit/components/timermanager/nsUpdateTimerManager.js @@ -1,17 +1,16 @@ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -Components.utils.import("resource://gre/modules/XPCOMUtils.jsm", this); -Components.utils.import("resource://gre/modules/Services.jsm", this); +const { classes: Cc, interfaces: Ci, utils: Cu } = Components; -const Cc = Components.classes; -const Ci = Components.interfaces; +Cu.import("resource://gre/modules/XPCOMUtils.jsm", this); +Cu.import("resource://gre/modules/Services.jsm", this); const PREF_APP_UPDATE_LASTUPDATETIME_FMT = "app.update.lastUpdateTime.%ID%"; const PREF_APP_UPDATE_TIMERMINIMUMDELAY = "app.update.timerMinimumDelay"; const PREF_APP_UPDATE_TIMERFIRSTINTERVAL = "app.update.timerFirstInterval"; const PREF_APP_UPDATE_LOG = "app.update.log"; const CATEGORY_UPDATE_TIMER = "update-timer"; @@ -303,16 +302,24 @@ TimerManager.prototype = { } }, /** * See nsIUpdateTimerManager.idl */ registerTimer: function TM_registerTimer(id, callback, interval) { LOG("TimerManager:registerTimer - id: " + id); + if (this._timers === null) { + // Use normal logging since reportError is not available while shutting + // down. + gLogEnabled = true; + LOG("TimerManager:registerTimer called after profile-before-change " + + "notification. Ignoring timer registration for id: " + id); + return; + } if (id in this._timers && callback != this._timers[id].callback) { LOG("TimerManager:registerTimer - Ignoring second registration for " + id); return; } let prefLastUpdate = PREF_APP_UPDATE_LASTUPDATETIME_FMT.replace(/%ID%/, id); // Initialize the last update time to 0 when the preference isn't set so // the timer will be notified soon after a new profile's first use. let lastUpdateTime = getPref("getIntPref", prefLastUpdate, 0); @@ -326,21 +333,22 @@ TimerManager.prototype = { this._timers[id] = {callback, interval, lastUpdateTime}; this._ensureTimer(interval * 1000); }, unregisterTimer: function TM_unregisterTimer(id) { - LOG(`TimerManager:unregisterTimer - id: ${id}`); + LOG("TimerManager:unregisterTimer - id: " + id); if (id in this._timers) { delete this._timers[id]; } else { - LOG(`TimerManager:registerTimer - Ignoring unregistration request for unknown id: ${id}`); + LOG("TimerManager:unregisterTimer - Ignoring unregistration request for " + + "unknown id: " + id); } }, classID: Components.ID("{B322A5C0-A419-484E-96BA-D7182163899F}"), QueryInterface: XPCOMUtils.generateQI([Ci.nsIUpdateTimerManager, Ci.nsITimerCallback, Ci.nsIObserver]) };
--- a/toolkit/xre/nsNativeAppSupportWin.cpp +++ b/toolkit/xre/nsNativeAppSupportWin.cpp @@ -1,16 +1,17 @@ /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsNativeAppSupportBase.h" #include "nsNativeAppSupportWin.h" #include "nsAppRunner.h" +#include "nsContentUtils.h" #include "nsXULAppAPI.h" #include "nsString.h" #include "nsIBrowserDOMWindow.h" #include "nsICommandLineRunner.h" #include "nsCOMPtr.h" #include "nsXPIDLString.h" #include "nsIComponentManager.h" #include "nsIServiceManager.h" @@ -1458,16 +1459,17 @@ nsNativeAppSupportWin::OpenBrowserWindow if ( bwin ) { nsCOMPtr<nsIURI> uri; NS_NewURI( getter_AddRefs( uri ), NS_LITERAL_CSTRING("about:blank"), 0, 0 ); if ( uri ) { nsCOMPtr<mozIDOMWindowProxy> container; rv = bwin->OpenURI( uri, 0, nsIBrowserDOMWindow::OPEN_DEFAULTWINDOW, nsIBrowserDOMWindow::OPEN_EXTERNAL, + nsContentUtils::GetSystemPrincipal(), getter_AddRefs( container ) ); if ( NS_SUCCEEDED( rv ) ) return NS_OK; } } NS_ERROR("failed to hand off external URL to extant window"); } while ( false );
--- a/tools/profiler/core/platform-win32.cpp +++ b/tools/profiler/core/platform-win32.cpp @@ -27,16 +27,20 @@ // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF // SUCH DAMAGE. #include <windows.h> #include <mmsystem.h> #include <process.h> +#include "nsWindowsDllInterceptor.h" +#include "mozilla/StackWalk_windows.h" +#include "mozilla/WindowsVersion.h" + /* static */ Thread::tid_t Thread::GetCurrentId() { return GetCurrentThreadId(); } static void PopulateRegsFromContext(Registers& aRegs, CONTEXT* aContext) @@ -277,8 +281,63 @@ void Registers::SyncPopulate() { CONTEXT context; RtlCaptureContext(&context); PopulateRegsFromContext(*this, &context); } #endif +#if defined(GP_PLAT_amd64_windows) +static WindowsDllInterceptor NtDllIntercept; + +typedef NTSTATUS (NTAPI *LdrUnloadDll_func)(HMODULE module); +static LdrUnloadDll_func stub_LdrUnloadDll; + +static NTSTATUS NTAPI +patched_LdrUnloadDll(HMODULE module) +{ + // Prevent the stack walker from suspending this thread when LdrUnloadDll + // holds the RtlLookupFunctionEntry lock. + AutoSuppressStackWalking suppress; + return stub_LdrUnloadDll(module); +} + +// These pointers are disguised as PVOID to avoid pulling in obscure headers +typedef PVOID (WINAPI *LdrResolveDelayLoadedAPI_func)(PVOID ParentModuleBase, + PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook, + PVOID ThunkAddress, ULONG Flags); +static LdrResolveDelayLoadedAPI_func stub_LdrResolveDelayLoadedAPI; + +static PVOID WINAPI +patched_LdrResolveDelayLoadedAPI(PVOID ParentModuleBase, + PVOID DelayloadDescriptor, PVOID FailureDllHook, PVOID FailureSystemHook, + PVOID ThunkAddress, ULONG Flags) +{ + // Prevent the stack walker from suspending this thread when + // LdrResolveDelayLoadAPI holds the RtlLookupFunctionEntry lock. + AutoSuppressStackWalking suppress; + return stub_LdrResolveDelayLoadedAPI(ParentModuleBase, DelayloadDescriptor, + FailureDllHook, FailureSystemHook, + ThunkAddress, Flags); +} + +void +InitializeWin64ProfilerHooks() +{ + static bool initialized = false; + if (initialized) { + return; + } + initialized = true; + + NtDllIntercept.Init("ntdll.dll"); + NtDllIntercept.AddHook("LdrUnloadDll", + reinterpret_cast<intptr_t>(patched_LdrUnloadDll), + (void**)&stub_LdrUnloadDll); + if (IsWin8OrLater()) { // LdrResolveDelayLoadedAPI was introduced in Win8 + NtDllIntercept.AddHook("LdrResolveDelayLoadedAPI", + reinterpret_cast<intptr_t>(patched_LdrResolveDelayLoadedAPI), + (void**)&stub_LdrResolveDelayLoadedAPI); + } +} +#endif // defined(GP_PLAT_amd64_windows) +
--- a/tools/profiler/core/platform.cpp +++ b/tools/profiler/core/platform.cpp @@ -2418,16 +2418,20 @@ locked_profiler_start(PSLockRef aLock, i for (uint32_t i = 0; i < aFilterCount; i++) { LOG("- threads = %s", aFilters[i]); } } MOZ_RELEASE_ASSERT(CorePS::Exists() && !ActivePS::Exists(aLock)); +#if defined(GP_PLAT_amd64_windows) + InitializeWin64ProfilerHooks(); +#endif + // Fall back to the default values if the passed-in values are unreasonable. int entries = aEntries > 0 ? aEntries : PROFILER_DEFAULT_ENTRIES; double interval = aInterval > 0 ? aInterval : PROFILER_DEFAULT_INTERVAL; ActivePS::Create(aLock, entries, interval, aFeatures, aFilters, aFilterCount); // Set up profiling for each registered thread, if appropriate. Thread::tid_t tid = Thread::GetCurrentId();
--- a/uriloader/exthandler/nsWebHandlerApp.js +++ b/uriloader/exthandler/nsWebHandlerApp.js @@ -7,16 +7,17 @@ const Ci = Components.interfaces; const Cr = Components.results; const Cc = Components.classes; const Cu = Components.utils; Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/NetUtil.jsm"); +Cu.import('resource://gre/modules/Services.jsm'); //////////////////////////////////////////////////////////////////////////////// //// nsWebHandler class function nsWebHandlerApp() {} nsWebHandlerApp.prototype = { ////////////////////////////////////////////////////////////////////////////// @@ -138,17 +139,18 @@ nsWebHandlerApp.prototype = { // // it's not clear how one would differentiate between the three cases // above, so for now we don't catch the exception // openURI browserDOMWin.openURI(uriToSend, null, // no window.opener Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW, - Ci.nsIBrowserDOMWindow.OPEN_NEW); + Ci.nsIBrowserDOMWindow.OPEN_NEW, + Services.scriptSecurityManager.getSystemPrincipal()); return; }, ////////////////////////////////////////////////////////////////////////////// //// nsIWebHandlerApp get uriTemplate() {
--- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -39,16 +39,17 @@ using mozilla::Unused; #include "nsIXULWindow.h" #include "nsAppShell.h" #include "nsFocusManager.h" #include "nsIdleService.h" #include "nsLayoutUtils.h" #include "nsViewManager.h" +#include "nsContentUtils.h" #include "WidgetUtils.h" #include "nsIDOMSimpleGestureEvent.h" #include "nsGkAtoms.h" #include "nsWidgetsCID.h" #include "nsGfxCIID.h" @@ -1404,16 +1405,17 @@ nsWindow::GeckoViewSupport::LoadUri(jni: nsIBrowserDOMWindow::OPEN_NEWTAB : aFlags == GeckoView::LOAD_SWITCH_TAB ? nsIBrowserDOMWindow::OPEN_SWITCHTAB : nsIBrowserDOMWindow::OPEN_CURRENTWINDOW; nsCOMPtr<mozIDOMWindowProxy> newWin; if (NS_FAILED(browserWin->OpenURI( uri, nullptr, flags, nsIBrowserDOMWindow::OPEN_EXTERNAL, + nsContentUtils::GetSystemPrincipal(), getter_AddRefs(newWin)))) { NS_WARNING("Failed to open URI"); } } void nsWindow::InitNatives() {
--- a/widget/windows/nsWidgetFactory.cpp +++ b/widget/windows/nsWidgetFactory.cpp @@ -70,17 +70,17 @@ WindowConstructor(nsISupports *aOuter, R static nsresult ChildWindowConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult) { *aResult = nullptr; if (aOuter != nullptr) { return NS_ERROR_NO_AGGREGATION; } - nsCOMPtr<nsIWidget> widget = new ChildWindow; + nsCOMPtr<nsIWidget> widget = new nsWindow(true); return widget->QueryInterface(aIID, aResult); } static nsresult FilePickerConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult) { *aResult = nullptr;
--- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -589,19 +589,20 @@ StaticAutoPtr<TIPMessageHandler> TIPMess **************************************************************/ /************************************************************** * * SECTION: nsWindow construction and destruction * **************************************************************/ -nsWindow::nsWindow() +nsWindow::nsWindow(bool aIsChildWindow) : nsWindowBase() , mResizeState(NOT_RESIZING) + , mIsChildWindow(aIsChildWindow) { mIconSmall = nullptr; mIconBig = nullptr; mWnd = nullptr; mTransitionWnd = nullptr; mPaintDC = nullptr; mPrevWndProc = nullptr; mNativeDragTarget = nullptr; @@ -1144,16 +1145,23 @@ DWORD nsWindow::WindowStyle() if (IsPopupWithTitleBar()) { style |= WS_CAPTION; if (mBorderStyle & eBorderStyle_close) { style |= WS_SYSMENU; } } } + if (mIsChildWindow) { + style |= WS_CLIPCHILDREN; + if (!(style & WS_POPUP)) { + style |= WS_CHILD; // WS_POPUP and WS_CHILD are mutually exclusive. + } + } + VERIFY_WINDOW_STYLE(style); return style; } // Return nsWindow extended styles DWORD nsWindow::WindowExStyle() { switch (mWindowType) @@ -8339,36 +8347,16 @@ bool nsWindow::OnPointerEvents(UINT msg, LPARAM newLParam = lParamToClient(aLParam); DispatchMouseEvent(message, aWParam, newLParam, false, button, nsIDOMMouseEvent::MOZ_SOURCE_PEN, &pointerInfo); // Consume WM_POINTER* to stop Windows fires WM_*BUTTONDOWN / WM_*BUTTONUP // WM_MOUSEMOVE. return true; } -/************************************************************** - ************************************************************** - ** - ** BLOCK: ChildWindow impl. - ** - ** Child window overrides. - ** - ************************************************************** - **************************************************************/ - -// return the style for a child nsWindow -DWORD ChildWindow::WindowStyle() -{ - DWORD style = WS_CLIPCHILDREN | nsWindow::WindowStyle(); - if (!(style & WS_POPUP)) - style |= WS_CHILD; // WS_POPUP and WS_CHILD are mutually exclusive. - VERIFY_WINDOW_STYLE(style); - return style; -} - void nsWindow::GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData) { aInitData->hWnd() = reinterpret_cast<uintptr_t>(mWnd); aInitData->widgetKey() = reinterpret_cast<uintptr_t>(static_cast<nsIWidget*>(this)); aInitData->transparencyMode() = mTransparencyMode; }
--- a/widget/windows/nsWindow.h +++ b/widget/windows/nsWindow.h @@ -62,28 +62,28 @@ class WinCompositorWidget; struct MSGResult; } // namespace widget } // namespacw mozilla; /** * Native WIN32 window wrapper. */ -class nsWindow : public nsWindowBase +class nsWindow final : public nsWindowBase { typedef mozilla::TimeStamp TimeStamp; typedef mozilla::TimeDuration TimeDuration; typedef mozilla::widget::WindowHook WindowHook; typedef mozilla::widget::TaskbarWindowPreview TaskbarWindowPreview; typedef mozilla::widget::NativeKey NativeKey; typedef mozilla::widget::MSGResult MSGResult; typedef mozilla::widget::IMEContext IMEContext; public: - nsWindow(); + explicit nsWindow(bool aIsChildWindow = false); NS_DECL_ISUPPORTS_INHERITED friend class nsWindowGfx; // nsWindowBase virtual void InitEvent(mozilla::WidgetGUIEvent& aEvent, LayoutDeviceIntPoint* aPoint = nullptr) override; @@ -630,16 +630,19 @@ protected: // Indicates that mouse events should be ignored and pass through to the // window below. This is currently only used for popups. bool mMouseTransparent; // Whether we're in the process of sending a WM_SETTEXT ourselves bool mSendingSetText; + // Whether we we're created as a NS_CHILD_CID window (aka ChildWindow) or not. + bool mIsChildWindow : 1; + // The point in time at which the last paint completed. We use this to avoid // painting too rapidly in response to frequent input events. TimeStamp mLastPaintEndTime; // Caching for hit test results POINT mCachedHitTestPoint; TimeStamp mCachedHitTestTime; int32_t mCachedHitTestResult; @@ -657,21 +660,9 @@ protected: // associated with a particular widget (since we exited the widget). static WPARAM sMouseExitwParam; static LPARAM sMouseExitlParamScreen; // Pointer events processing and management WinPointerEvents mPointerEvents; }; -/** - * A child window is a window with different style. - */ -class ChildWindow : public nsWindow { - -public: - ChildWindow() {} - -protected: - virtual DWORD WindowStyle(); -}; - #endif // Window_h__
--- a/xpcom/base/ErrorList.py +++ b/xpcom/base/ErrorList.py @@ -460,17 +460,16 @@ with modules["NETWORK"]: # 7: NS_ERROR_MODULE_PLUGINS # ======================================================================= with modules["PLUGINS"]: errors["NS_ERROR_PLUGINS_PLUGINSNOTCHANGED"] = FAILURE(1000) errors["NS_ERROR_PLUGIN_DISABLED"] = FAILURE(1001) errors["NS_ERROR_PLUGIN_BLOCKLISTED"] = FAILURE(1002) errors["NS_ERROR_PLUGIN_TIME_RANGE_NOT_SUPPORTED"] = FAILURE(1003) errors["NS_ERROR_PLUGIN_CLICKTOPLAY"] = FAILURE(1004) - errors["NS_PLUGIN_INIT_PENDING"] = SUCCESS(1005) # ======================================================================= # 8: NS_ERROR_MODULE_LAYOUT # ======================================================================= with modules["LAYOUT"]: # Return code for nsITableLayout
--- a/xpcom/base/StaticPtr.h +++ b/xpcom/base/StaticPtr.h @@ -62,16 +62,23 @@ public: T* operator->() const { MOZ_ASSERT(mRawPtr); return get(); } T& operator*() const { return *get(); } + T* forget() + { + T* temp = mRawPtr; + mRawPtr = nullptr; + return temp; + } + private: // Disallow copy constructor, but only in debug mode. We only define // a default constructor in debug mode (see above); if we declared // this constructor always, the compiler wouldn't generate a trivial // default constructor for us in non-debug mode. #ifdef DEBUG StaticAutoPtr(StaticAutoPtr<T>& aOther); #endif
--- a/xpcom/base/nsIMemoryReporter.idl +++ b/xpcom/base/nsIMemoryReporter.idl @@ -200,16 +200,22 @@ interface nsIMemoryReporter : nsISupport }; [scriptable, function, uuid(548b3909-c04d-4ca6-8466-b8bee3837457)] interface nsIFinishReportingCallback : nsISupports { void callback(in nsISupports data); }; +[scriptable, function, uuid(1a80cd0f-0d9e-4397-be69-68ad28fe5175)] +interface nsIHeapAllocatedCallback : nsISupports +{ + void callback(in int64_t bytesAllocated); +}; + [scriptable, builtinclass, uuid(2998574d-8993-407a-b1a5-8ad7417653e1)] interface nsIMemoryReporterManager : nsISupports { /* * Initialize. */ [must_use] void init(); @@ -407,16 +413,22 @@ interface nsIMemoryReporterManager : nsI /* * These attributes indicate DMD's status. "Enabled" means enabled at * build-time. */ [infallible] readonly attribute boolean isDMDEnabled; [infallible] readonly attribute boolean isDMDRunning; /* + * Asynchronously gets attribute 'heapAllocated'. The value is returned in + * the callback argument. + */ + [must_use] void getHeapAllocatedAsync(in nsIHeapAllocatedCallback callback); + + /* * Run a series of GC/CC's in an attempt to minimize the application's memory * usage. When we're finished, we invoke the given runnable if it's not * null. */ [must_use] void minimizeMemoryUsage(in nsIRunnable callback); /* * Measure the memory that is known to be owned by this tab, split up into
--- a/xpcom/base/nsMemoryReporterManager.cpp +++ b/xpcom/base/nsMemoryReporterManager.cpp @@ -4,28 +4,30 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsAtomTable.h" #include "nsAutoPtr.h" #include "nsCOMPtr.h" #include "nsCOMArray.h" #include "nsPrintfCString.h" +#include "nsProxyRelease.h" #include "nsServiceManagerUtils.h" #include "nsMemoryReporterManager.h" #include "nsITimer.h" #include "nsThreadUtils.h" #include "nsPIDOMWindow.h" #include "nsIObserverService.h" #include "nsIGlobalObject.h" #include "nsIXPConnect.h" #include "GeckoProfilerReporter.h" #if defined(XP_UNIX) || defined(MOZ_DMD) #include "nsMemoryInfoDumper.h" #endif +#include "nsNetCID.h" #include "mozilla/Attributes.h" #include "mozilla/MemoryReportingProcess.h" #include "mozilla/PodOperations.h" #include "mozilla/Preferences.h" #include "mozilla/Services.h" #include "mozilla/Telemetry.h" #include "mozilla/UniquePtrExtensions.h" #include "mozilla/dom/MemoryReportTypes.h" @@ -1590,16 +1592,19 @@ nsMemoryReporterManager::nsMemoryReporte , mIsRegistrationBlocked(false) , mStrongReporters(new StrongReportersTable()) , mWeakReporters(new WeakReportersTable()) , mSavedStrongReporters(nullptr) , mSavedWeakReporters(nullptr) , mNextGeneration(1) , mPendingProcessesState(nullptr) , mPendingReportersState(nullptr) +#ifdef HAVE_JEMALLOC_STATS + , mThreadPool(do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID)) +#endif { } nsMemoryReporterManager::~nsMemoryReporterManager() { delete mStrongReporters; delete mWeakReporters; NS_ASSERTION(!mSavedStrongReporters, "failed to restore strong reporters"); @@ -2368,16 +2373,59 @@ nsMemoryReporterManager::GetHeapAllocate *aAmount = stats.allocated; return NS_OK; #else *aAmount = 0; return NS_ERROR_NOT_AVAILABLE; #endif } +NS_IMETHODIMP +nsMemoryReporterManager::GetHeapAllocatedAsync(nsIHeapAllocatedCallback *aCallback) +{ +#ifdef HAVE_JEMALLOC_STATS + if (!mThreadPool) { + return NS_ERROR_UNEXPECTED; + } + + RefPtr<nsIMemoryReporterManager> self{this}; + nsMainThreadPtrHandle<nsIHeapAllocatedCallback> mainThreadCallback( + new nsMainThreadPtrHolder<nsIHeapAllocatedCallback>("HeapAllocatedCallback", + aCallback)); + + nsCOMPtr<nsIRunnable> getHeapAllocatedRunnable = NS_NewRunnableFunction( + "nsMemoryReporterManager::GetHeapAllocatedAsync", + [self, mainThreadCallback]() mutable { + MOZ_ASSERT(!NS_IsMainThread()); + + int64_t heapAllocated = 0; + nsresult rv = self->GetHeapAllocated(&heapAllocated); + + nsCOMPtr<nsIRunnable> resultCallbackRunnable = NS_NewRunnableFunction( + "nsMemoryReporterManager::GetHeapAllocatedAsync", + [mainThreadCallback, heapAllocated, rv]() mutable { + MOZ_ASSERT(NS_IsMainThread()); + + if (NS_FAILED(rv)) { + mainThreadCallback->Callback(0); + return; + } + + mainThreadCallback->Callback(heapAllocated); + }); // resultCallbackRunnable. + + Unused << NS_DispatchToMainThread(resultCallbackRunnable); + }); // getHeapAllocatedRunnable. + + return mThreadPool->Dispatch(getHeapAllocatedRunnable, NS_DISPATCH_NORMAL); +#else + return NS_ERROR_NOT_AVAILABLE; +#endif +} + // This has UNITS_PERCENTAGE, so it is multiplied by 100x. NS_IMETHODIMP nsMemoryReporterManager::GetHeapOverheadFraction(int64_t* aAmount) { #ifdef HAVE_JEMALLOC_STATS jemalloc_stats_t stats; jemalloc_stats(&stats); *aAmount = HeapOverheadFraction(&stats);
--- a/xpcom/base/nsMemoryReporterManager.h +++ b/xpcom/base/nsMemoryReporterManager.h @@ -5,16 +5,17 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef nsMemoryReporterManager_h__ #define nsMemoryReporterManager_h__ #include "mozilla/Mutex.h" #include "nsDataHashtable.h" #include "nsHashKeys.h" +#include "nsIEventTarget.h" #include "nsIMemoryReporter.h" #include "nsITimer.h" #include "nsServiceManagerUtils.h" #include "nsDataHashtable.h" namespace mozilla { class MemoryReportingProcess; namespace dom { @@ -271,16 +272,19 @@ private: // When this is non-null, a request is in flight. Note: We use manual // new/delete for this because its lifetime doesn't match block scope or // anything like that. PendingProcessesState* mPendingProcessesState; // This is reinitialized each time a call to GetReports is initiated. PendingReportersState* mPendingReportersState; + // Used in GetHeapAllocatedAsync() to run jemalloc_stats async. + nsCOMPtr<nsIEventTarget> mThreadPool; + PendingProcessesState* GetStateForGeneration(uint32_t aGeneration); static MOZ_MUST_USE bool StartChildReport(mozilla::MemoryReportingProcess* aChild, const PendingProcessesState* aState); }; #define NS_MEMORY_REPORTER_MANAGER_CID \ { 0xfb97e4f5, 0x32dd, 0x497a, \
--- a/xpfe/appshell/nsContentTreeOwner.cpp +++ b/xpfe/appshell/nsContentTreeOwner.cpp @@ -30,16 +30,17 @@ #include "nsIURIFixup.h" #include "nsCDefaultURIFixup.h" #include "nsIWebNavigation.h" #include "nsDocShellCID.h" #include "nsIExternalURLHandlerService.h" #include "nsIMIMEInfo.h" #include "nsIWidget.h" #include "nsWindowWatcher.h" +#include "NullPrincipal.h" #include "mozilla/BrowserElementParent.h" #include "nsIDOMDocument.h" #include "nsIScriptObjectPrincipal.h" #include "nsIURI.h" #include "nsIDocument.h" #if defined(XP_MACOSX) #include "nsThreadUtils.h" @@ -918,23 +919,25 @@ nsContentTreeOwner::ProvideWindow(mozIDO dom::AutoNoJSAPI nojsapi; uint32_t flags = nsIBrowserDOMWindow::OPEN_NEW; if (aForceNoOpener) { flags |= nsIBrowserDOMWindow::OPEN_NO_OPENER; } // Get a new rendering area from the browserDOMWin. We don't want - // to be starting any loads here, so get it with a null URI. + // to be starting any loads here, so get it with a null URI. Since/ + // we are not loading any URI, we follow the principle of least privlege + // and use a nullPrincipal as the triggeringPrincipal. // // This method handles setting the opener for us, so we don't need to set it // ourselves. - return browserDOMWin->OpenURI(nullptr, aParent, - openLocation, - flags, aReturn); + RefPtr<NullPrincipal> nullPrincipal = NullPrincipal::Create(); + return browserDOMWin->OpenURI(nullptr, aParent, openLocation, + flags, nullPrincipal, aReturn); } } //***************************************************************************** // nsContentTreeOwner: Accessors //***************************************************************************** #if defined(XP_MACOSX)