diff --git a/accessible/tests/mochitest/table/test_indexes_table.html b/accessible/tests/mochitest/table/test_indexes_table.html index 0db4bfa015..356a55933f 100644 --- a/accessible/tests/mochitest/table/test_indexes_table.html +++ b/accessible/tests/mochitest/table/test_indexes_table.html @@ -110,7 +110,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=410052 [ 0, 1, 2, -1, -1], [-1, -1, -1, -1, -1], [ 3, 4, 5, -1, -1], - [ 6, 7, 7, 7, 7], + [ 6, 7, -1, -1, -1], [ 6, 8, 9, -1, -1], [ 6, 10, 9, 11, 12] ]; diff --git a/caps/nsJSPrincipals.cpp b/caps/nsJSPrincipals.cpp index 023697a3d0..0083d3a657 100644 --- a/caps/nsJSPrincipals.cpp +++ b/caps/nsJSPrincipals.cpp @@ -114,7 +114,8 @@ nsJSPrincipals::ReadPrincipals(JSContext* aCx, JSStructuredCloneReader* aReader, if (!(tag == SCTAG_DOM_NULL_PRINCIPAL || tag == SCTAG_DOM_SYSTEM_PRINCIPAL || - tag == SCTAG_DOM_CONTENT_PRINCIPAL)) { + tag == SCTAG_DOM_CONTENT_PRINCIPAL || + tag == SCTAG_DOM_EXPANDED_PRINCIPAL)) { xpc::Throw(aCx, NS_ERROR_DOM_DATA_CLONE_ERR); return false; } @@ -122,27 +123,38 @@ nsJSPrincipals::ReadPrincipals(JSContext* aCx, JSStructuredCloneReader* aReader, return ReadKnownPrincipalType(aCx, aReader, tag, aOutPrincipals); } -/* static */ bool -nsJSPrincipals::ReadKnownPrincipalType(JSContext* aCx, - JSStructuredCloneReader* aReader, - uint32_t aTag, - JSPrincipals** aOutPrincipals) +static bool +ReadPrincipalInfo(JSStructuredCloneReader* aReader, + uint32_t aTag, + PrincipalInfo& aInfo) { - MOZ_ASSERT(aTag == SCTAG_DOM_NULL_PRINCIPAL || - aTag == SCTAG_DOM_SYSTEM_PRINCIPAL || - aTag == SCTAG_DOM_CONTENT_PRINCIPAL); - - if (NS_WARN_IF(!NS_IsMainThread())) { - xpc::Throw(aCx, NS_ERROR_UNCATCHABLE_EXCEPTION); - return false; - } - - PrincipalInfo info; if (aTag == SCTAG_DOM_SYSTEM_PRINCIPAL) { - info = SystemPrincipalInfo(); + aInfo = SystemPrincipalInfo(); } else if (aTag == SCTAG_DOM_NULL_PRINCIPAL) { - info = NullPrincipalInfo(); - } else { + aInfo = NullPrincipalInfo(); + } else if (aTag == SCTAG_DOM_EXPANDED_PRINCIPAL) { + uint32_t length, unused; + if (!JS_ReadUint32Pair(aReader, &length, &unused)) { + return false; + } + + ExpandedPrincipalInfo expanded; + + for (uint32_t i = 0; i < length; i++) { + uint32_t tag; + if (!JS_ReadUint32Pair(aReader, &tag, &unused)) { + return false; + } + + PrincipalInfo sub; + if (!ReadPrincipalInfo(aReader, tag, sub)) { + return false; + } + expanded.whitelist().AppendElement(sub); + } + + aInfo = expanded; + } else if (aTag == SCTAG_DOM_CONTENT_PRINCIPAL) { uint32_t suffixLength, specLength; if (!JS_ReadUint32Pair(aReader, &suffixLength, &specLength)) { return false; @@ -162,7 +174,32 @@ nsJSPrincipals::ReadKnownPrincipalType(JSContext* aCx, OriginAttributes attrs; attrs.PopulateFromSuffix(suffix); - info = ContentPrincipalInfo(attrs, spec); + aInfo = ContentPrincipalInfo(attrs, spec); + } else { + MOZ_CRASH("unexpected principal structured clone tag"); + } + + return true; +} + +/* static */ bool +nsJSPrincipals::ReadKnownPrincipalType(JSContext* aCx, + JSStructuredCloneReader* aReader, + uint32_t aTag, + JSPrincipals** aOutPrincipals) +{ + MOZ_ASSERT(aTag == SCTAG_DOM_NULL_PRINCIPAL || + aTag == SCTAG_DOM_SYSTEM_PRINCIPAL || + aTag == SCTAG_DOM_CONTENT_PRINCIPAL || + aTag == SCTAG_DOM_EXPANDED_PRINCIPAL); + if (NS_WARN_IF(!NS_IsMainThread())) { + xpc::Throw(aCx, NS_ERROR_UNCATCHABLE_EXCEPTION); + return false; + } + + PrincipalInfo info; + if (!ReadPrincipalInfo(aReader, aTag, info)) { + return false; } nsresult rv; @@ -176,6 +213,40 @@ nsJSPrincipals::ReadKnownPrincipalType(JSContext* aCx, return true; } +static bool +WritePrincipalInfo(JSStructuredCloneWriter* aWriter, const PrincipalInfo& aInfo) +{ + if (aInfo.type() == PrincipalInfo::TNullPrincipalInfo) { + return JS_WriteUint32Pair(aWriter, SCTAG_DOM_NULL_PRINCIPAL, 0); + } + if (aInfo.type() == PrincipalInfo::TSystemPrincipalInfo) { + return JS_WriteUint32Pair(aWriter, SCTAG_DOM_SYSTEM_PRINCIPAL, 0); + } + if (aInfo.type() == PrincipalInfo::TExpandedPrincipalInfo) { + const ExpandedPrincipalInfo& expanded = aInfo; + if (!JS_WriteUint32Pair(aWriter, SCTAG_DOM_EXPANDED_PRINCIPAL, 0) || + !JS_WriteUint32Pair(aWriter, expanded.whitelist().Length(), 0)) { + return false; + } + + for (uint32_t i = 0; i < expanded.whitelist().Length(); i++) { + if (!WritePrincipalInfo(aWriter, expanded.whitelist()[i])) { + return false; + } + } + return true; + } + + MOZ_ASSERT(aInfo.type() == PrincipalInfo::TContentPrincipalInfo); + const ContentPrincipalInfo& cInfo = aInfo; + nsAutoCString suffix; + cInfo.attrs().CreateSuffix(suffix); + return JS_WriteUint32Pair(aWriter, SCTAG_DOM_CONTENT_PRINCIPAL, 0) && + JS_WriteUint32Pair(aWriter, suffix.Length(), cInfo.spec().Length()) && + JS_WriteBytes(aWriter, suffix.get(), suffix.Length()) && + JS_WriteBytes(aWriter, cInfo.spec().get(), cInfo.spec().Length()); +} + bool nsJSPrincipals::write(JSContext* aCx, JSStructuredCloneWriter* aWriter) { @@ -185,19 +256,5 @@ nsJSPrincipals::write(JSContext* aCx, JSStructuredCloneWriter* aWriter) return false; } - if (info.type() == PrincipalInfo::TNullPrincipalInfo) { - return JS_WriteUint32Pair(aWriter, SCTAG_DOM_NULL_PRINCIPAL, 0); - } - if (info.type() == PrincipalInfo::TSystemPrincipalInfo) { - return JS_WriteUint32Pair(aWriter, SCTAG_DOM_SYSTEM_PRINCIPAL, 0); - } - - MOZ_ASSERT(info.type() == PrincipalInfo::TContentPrincipalInfo); - const ContentPrincipalInfo& cInfo = info; - nsAutoCString suffix; - cInfo.attrs().CreateSuffix(suffix); - return JS_WriteUint32Pair(aWriter, SCTAG_DOM_CONTENT_PRINCIPAL, 0) && - JS_WriteUint32Pair(aWriter, suffix.Length(), cInfo.spec().Length()) && - JS_WriteBytes(aWriter, suffix.get(), suffix.Length()) && - JS_WriteBytes(aWriter, cInfo.spec().get(), cInfo.spec().Length()); + return WritePrincipalInfo(aWriter, info); } diff --git a/dom/base/Navigator.cpp b/dom/base/Navigator.cpp index be24af28f0..26ea4af1dd 100644 --- a/dom/base/Navigator.cpp +++ b/dom/base/Navigator.cpp @@ -122,6 +122,11 @@ #include #endif +#ifdef MOZ_PAY +#include "nsIPaymentContentHelperService.h" +#include "mozilla/dom/DOMRequest.h" +#endif + namespace mozilla { namespace dom { @@ -2602,6 +2607,36 @@ Navigator::MozE10sEnabled() return true; } +#ifdef MOZ_PAY +already_AddRefed +Navigator::MozPay(JSContext* aCx, + JS::Handle aJwts, + ErrorResult& aRv) +{ + if (!mWindow || !mWindow->GetDocShell()) { + aRv.Throw(NS_ERROR_UNEXPECTED); + return nullptr; + } + + nsresult rv; + nsCOMPtr service = + do_GetService("@mozilla.org/payment/content-helper-service;1", &rv); + if (!service) { + aRv.Throw(rv); + return nullptr; + } + + RefPtr request; + rv = service->Pay(mWindow, aJwts, getter_AddRefs(request)); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return nullptr; + } + + return request.forget().downcast(); +} +#endif // MOZ_PAY + /* static */ already_AddRefed Navigator::GetWindowFromGlobal(JSObject* aGlobal) diff --git a/dom/base/Navigator.h b/dom/base/Navigator.h index 54beac6374..910e91f585 100644 --- a/dom/base/Navigator.h +++ b/dom/base/Navigator.h @@ -39,6 +39,7 @@ class WakeLock; class ArrayBufferViewOrBlobOrStringOrFormData; struct MobileIdOptions; class ServiceWorkerContainer; +class DOMRequest; } // namespace dom } // namespace mozilla @@ -312,6 +313,12 @@ public: bool MozE10sEnabled(); +#ifdef MOZ_PAY + already_AddRefed MozPay(JSContext* aCx, + JS::Handle aJwts, + ErrorResult& aRv); +#endif // MOZ_PAY + static void GetAcceptLanguages(nsTArray& aLanguages); // WebIDL helper methods diff --git a/dom/base/PerformanceObserver.cpp b/dom/base/PerformanceObserver.cpp index 8223f1270f..1b8ab37a87 100644 --- a/dom/base/PerformanceObserver.cpp +++ b/dom/base/PerformanceObserver.cpp @@ -168,7 +168,7 @@ PerformanceObserver::Observe(const PerformanceObserverInit& aOptions, return; } - mEntryTypes = validEntryTypes; + mEntryTypes.SwapElements(validEntryTypes); mPerformance->AddObserver(this); mConnected = true; diff --git a/dom/base/ResponsiveImageSelector.cpp b/dom/base/ResponsiveImageSelector.cpp index f0ec6c8000..75ff1a499c 100644 --- a/dom/base/ResponsiveImageSelector.cpp +++ b/dom/base/ResponsiveImageSelector.cpp @@ -293,7 +293,6 @@ ResponsiveImageSelector::SelectImage(bool aReselect) nsCOMPtr baseURI = mOwnerNode ? mOwnerNode->GetBaseURI() : nullptr; if (!pctx || !doc || !baseURI) { - MOZ_ASSERT(false, "Unable to find document prescontext and base URI"); return oldBest != -1; } diff --git a/dom/base/ScriptSettings.cpp b/dom/base/ScriptSettings.cpp index 132d7669e4..ef1e036e00 100644 --- a/dom/base/ScriptSettings.cpp +++ b/dom/base/ScriptSettings.cpp @@ -175,7 +175,7 @@ ClampToSubject(nsIGlobalObject* aGlobalOrNull) nsIPrincipal* globalPrin = aGlobalOrNull->PrincipalOrNull(); NS_ENSURE_TRUE(globalPrin, GetCurrentGlobal()); - if (!nsContentUtils::SubjectPrincipal()->SubsumesConsideringDomain(globalPrin)) { + if (!nsContentUtils::SubjectPrincipalOrSystemIfNativeCaller()->SubsumesConsideringDomain(globalPrin)) { return GetCurrentGlobal(); } @@ -505,8 +505,13 @@ AutoJSAPI::ReportException() // In this case, we enter the privileged junk scope and don't dispatch any // error events. JS::Rooted errorGlobal(cx(), JS::CurrentGlobalOrNull(cx())); - if (!errorGlobal) - errorGlobal = xpc::PrivilegedJunkScope(); + if (!errorGlobal) { + if (mIsMainThread) { + errorGlobal = xpc::PrivilegedJunkScope(); + } else { + errorGlobal = workers::GetCurrentThreadWorkerGlobal(); + } + } JSAutoCompartment ac(cx(), errorGlobal); JS::Rooted exn(cx()); js::ErrorReport jsReport(cx()); diff --git a/dom/base/SiteSpecificUserAgent.js b/dom/base/SiteSpecificUserAgent.js index d950b5a821..7e1bf44f8b 100644 --- a/dom/base/SiteSpecificUserAgent.js +++ b/dom/base/SiteSpecificUserAgent.js @@ -46,7 +46,7 @@ SiteSpecificUserAgent.prototype = { return cachedResult; } - let data = { uri: aURI }; + let data = { uri: aURI.spec }; let result = cpmm.sendRpcMessage("Useragent:GetOverride", data)[0] || HTTP_PROTO_HANDLER.userAgent; if (this.userAgentCache.size >= MAX_CACHE_SIZE) { diff --git a/dom/base/StructuredCloneHolder.cpp b/dom/base/StructuredCloneHolder.cpp index 16f0bc11dc..3540a00adc 100644 --- a/dom/base/StructuredCloneHolder.cpp +++ b/dom/base/StructuredCloneHolder.cpp @@ -417,7 +417,8 @@ StructuredCloneHolder::ReadFullySerializableObjects(JSContext* aCx, if (aTag == SCTAG_DOM_NULL_PRINCIPAL || aTag == SCTAG_DOM_SYSTEM_PRINCIPAL || - aTag == SCTAG_DOM_CONTENT_PRINCIPAL) { + aTag == SCTAG_DOM_CONTENT_PRINCIPAL || + aTag == SCTAG_DOM_EXPANDED_PRINCIPAL) { JSPrincipals* prin; if (!nsJSPrincipals::ReadKnownPrincipalType(aCx, aReader, aTag, &prin)) { return nullptr; diff --git a/dom/base/StructuredCloneTags.h b/dom/base/StructuredCloneTags.h index f1fec533d4..55be6f6ae6 100644 --- a/dom/base/StructuredCloneTags.h +++ b/dom/base/StructuredCloneTags.h @@ -51,6 +51,8 @@ enum StructuredCloneTags { // This tag is for OffscreenCanvas. SCTAG_DOM_CANVAS, + SCTAG_DOM_EXPANDED_PRINCIPAL, + SCTAG_DOM_MAX }; diff --git a/dom/base/ThirdPartyUtil.cpp b/dom/base/ThirdPartyUtil.cpp index 58f7681d52..6e8c819e85 100644 --- a/dom/base/ThirdPartyUtil.cpp +++ b/dom/base/ThirdPartyUtil.cpp @@ -46,7 +46,9 @@ ThirdPartyUtil::IsThirdPartyInternal(const nsCString& aFirstDomain, nsIURI* aSecondURI, bool* aResult) { - NS_ENSURE_ARG(aSecondURI); + if (!aSecondURI) { + return NS_ERROR_INVALID_ARG; + } // Get the base domain for aSecondURI. nsCString secondDomain; @@ -282,6 +284,10 @@ NS_IMETHODIMP ThirdPartyUtil::GetBaseDomain(nsIURI* aHostURI, nsACString& aBaseDomain) { + if (!aHostURI) { + return NS_ERROR_INVALID_ARG; + } + // Get the base domain. this will fail if the host contains a leading dot, // more than one trailing dot, or is otherwise malformed. nsresult rv = mTLDService->GetBaseDomain(aHostURI, 0, aBaseDomain); diff --git a/dom/base/UseCounters.conf b/dom/base/UseCounters.conf index 5a22e5bf44..697e7882dd 100644 --- a/dom/base/UseCounters.conf +++ b/dom/base/UseCounters.conf @@ -44,3 +44,7 @@ property FillOpacity // Push API method PushManager.subscribe method PushSubscription.unsubscribe + +// window.sidebar.addSearchEngine +attribute Window.sidebar +method External.addSearchEngine diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index 937de31b1a..88f6cd6138 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -8313,7 +8313,9 @@ nsDocument::IsScriptEnabled() if (!globalObject && mMasterDocument) { globalObject = do_QueryInterface(mMasterDocument->GetInnerWindow()); } - NS_ENSURE_TRUE(globalObject && globalObject->GetGlobalJSObject(), false); + if (!globalObject || !globalObject->GetGlobalJSObject()) { + return false; + } return sm->ScriptAllowed(globalObject->GetGlobalJSObject()); } @@ -10628,7 +10630,7 @@ nsDocument::SetImagesNeedAnimating(bool aAnimating) } already_AddRefed -nsIDocument::CreateTouch(nsIDOMWindow* aView, +nsIDocument::CreateTouch(nsGlobalWindow* aView, EventTarget* aTarget, int32_t aIdentifier, int32_t aPageX, int32_t aPageY, @@ -10638,6 +10640,7 @@ nsIDocument::CreateTouch(nsIDOMWindow* aView, float aRotationAngle, float aForce) { + MOZ_ASSERT_IF(aView, aView->IsInnerWindow()); RefPtr touch = new Touch(aTarget, aIdentifier, aPageX, aPageY, @@ -12110,7 +12113,7 @@ public: mUserInputOrChromeCaller(aUserInputOrChromeCaller) { nsCOMPtr doc = do_QueryReferent(mDocument); - if (doc) { + if (doc && doc->GetInnerWindow()) { mRequester = new nsContentPermissionRequester(doc->GetInnerWindow()); } } @@ -13395,7 +13398,7 @@ nsIDocument::ReportHasScrollLinkedEffect() nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, NS_LITERAL_CSTRING("Async Pan/Zoom"), this, nsContentUtils::eLAYOUT_PROPERTIES, - "ScrollLinkedEffectFound"); + "ScrollLinkedEffectFound2"); } Selection* diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index e3c1b59021..1c61a4b533 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2449,13 +2449,10 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, nsresult rv = NS_OK; - // Set mDoc even if this is an outer window to avoid + // We set mDoc even though this is an outer window to avoid // having to *always* reach into the inner window to find the // document. mDoc = aDocument; - if (IsInnerWindow()) { - ClearDocumentDependentSlots(cx); - } // Take this opportunity to clear mSuspendedDoc. Our old inner window is now // responsible for unsuspending it. @@ -5383,9 +5380,7 @@ nsGlobalWindow::GetScreenXY(ErrorResult& aError) LayoutDeviceRect screenRectDev = LayoutDevicePixel::FromAppUnits(screenRect, dc->AppUnitsPerDevPixel()); - nsCOMPtr widget = GetMainWidget(); - DesktopToLayoutDeviceScale scale = widget ? widget->GetDesktopToDeviceScale() - : DesktopToLayoutDeviceScale(1.0); + DesktopToLayoutDeviceScale scale = dc->GetDesktopToDeviceScale(); DesktopRect screenRectDesk = screenRectDev / scale; CSSPoint cssPt = @@ -6008,9 +6003,7 @@ int32_t nsGlobalWindow::GetScrollMinX(ErrorResult& aError) { MOZ_ASSERT(IsInnerWindow()); - int32_t scrollMinX = 0; - FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideLeft), aError, scrollMinX); - return scrollMinX; + FORWARD_TO_OUTER_OR_THROW(GetScrollBoundaryOuter, (eSideLeft), aError, 0); } NS_IMETHODIMP @@ -8710,6 +8703,7 @@ void nsGlobalWindow::ForceClose() { MOZ_ASSERT(IsOuterWindow()); + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); if (IsFrame() || !mDocShell) { // This may be a frame in a frameset, or a window that's already closed. @@ -8738,6 +8732,12 @@ nsGlobalWindow::FinalClose() // Flag that we were closed. mIsClosed = true; + // If we get here from CloseOuter then it means that the parent process is + // going to close our window for us. It's just important to set mIsClosed. + if (XRE_GetProcessType() == GeckoProcessType_Content) { + return; + } + // This stuff is non-sensical but incredibly fragile. The reasons for the // behavior here don't make sense today and may not have ever made sense, // but various bits of frontend code break when you change them. If you need diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index d2c5078b8d..5a28e9e4b0 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -45,6 +45,7 @@ class nsIDocShell; class nsDocShell; class nsDOMNavigationTiming; class nsFrameLoader; +class nsGlobalWindow; class nsHTMLCSSStyleSheet; class nsHTMLDocument; class nsHTMLStyleSheet; @@ -354,17 +355,32 @@ public: } /** - * Return the base URI for relative URIs in the document (the document uri - * unless it's overridden by SetBaseURI, HTML tags, etc.). The - * returned URI could be null if there is no document URI. If the document - * is a srcdoc document, return the parent document's base URL. + * Return the fallback base URL for this document, as defined in the HTML + * specification. Note that this can return null if there is no document URI. + * + * XXXbz: This doesn't implement the bits for about:blank yet. */ - nsIURI* GetDocBaseURI() const + nsIURI* GetFallbackBaseURI() const { if (mIsSrcdocDocument && mParentDocument) { return mParentDocument->GetDocBaseURI(); } - return mDocumentBaseURI ? mDocumentBaseURI : mDocumentURI; + return mDocumentURI; + } + + /** + * Return the base URI for relative URIs in the document (the document uri + * unless it's overridden by SetBaseURI, HTML tags, etc.). The + * returned URI could be null if there is no document URI. If the document is + * a srcdoc document and has no explicit base URL, return the parent + * document's base URL. + */ + nsIURI* GetDocBaseURI() const + { + if (mDocumentBaseURI) { + return mDocumentBaseURI; + } + return GetFallbackBaseURI(); } virtual already_AddRefed GetBaseURI(bool aTryUseXHRDocBaseURI = false) const override; @@ -2597,7 +2613,7 @@ public: JS::Handle aResult, mozilla::ErrorResult& rv); // Touch event handlers already on nsINode already_AddRefed - CreateTouch(nsIDOMWindow* aView, mozilla::dom::EventTarget* aTarget, + CreateTouch(nsGlobalWindow* aView, mozilla::dom::EventTarget* aTarget, int32_t aIdentifier, int32_t aPageX, int32_t aPageY, int32_t aScreenX, int32_t aScreenY, int32_t aClientX, int32_t aClientY, int32_t aRadiusX, int32_t aRadiusY, diff --git a/dom/base/nsObjectLoadingContent.cpp b/dom/base/nsObjectLoadingContent.cpp index bf0ecdd811..178976cf72 100644 --- a/dom/base/nsObjectLoadingContent.cpp +++ b/dom/base/nsObjectLoadingContent.cpp @@ -2542,8 +2542,7 @@ nsObjectLoadingContent::GetCapabilities() const { return eSupportImages | eSupportPlugins | - eSupportDocuments | - eSupportSVG; + eSupportDocuments; } void @@ -2691,10 +2690,7 @@ nsObjectLoadingContent::GetTypeOfContent(const nsCString& aMIMEType) return eType_Document; } - // SVGs load as documents, but are their own capability - bool isSVG = aMIMEType.LowerCaseEqualsLiteral("image/svg+xml"); - Capabilities supportType = isSVG ? eSupportSVG : eSupportDocuments; - if ((caps & supportType) && IsSupportedDocument(aMIMEType)) { + if ((caps & eSupportDocuments) && IsSupportedDocument(aMIMEType)) { return eType_Document; } diff --git a/dom/base/nsObjectLoadingContent.h b/dom/base/nsObjectLoadingContent.h index 19d5c6ca5a..99c141de25 100644 --- a/dom/base/nsObjectLoadingContent.h +++ b/dom/base/nsObjectLoadingContent.h @@ -287,15 +287,14 @@ class nsObjectLoadingContent : public nsImageLoadingContent eSupportDocuments = 1u << 2, // Documents are supported // (nsIDocumentLoaderFactory) // This flag always includes SVG - eSupportSVG = 1u << 3, // SVG is supported (image/svg+xml) - eSupportClassID = 1u << 4, // The classid attribute is supported + eSupportClassID = 1u << 3, // The classid attribute is supported // If possible to get a *plugin* type from the type attribute *or* file // extension, we can use that type and begin loading the plugin before // opening a channel. // A side effect of this is if the channel fails, the plugin is still // running. - eAllowPluginSkipChannel = 1u << 5 + eAllowPluginSkipChannel = 1u << 4 }; /** diff --git a/dom/base/nsScreen.cpp b/dom/base/nsScreen.cpp index 83685cff0d..cda394af36 100644 --- a/dom/base/nsScreen.cpp +++ b/dom/base/nsScreen.cpp @@ -124,9 +124,15 @@ nsScreen::GetRect(nsRect& aRect) } context->GetRect(aRect); + LayoutDevicePoint screenTopLeftDev = + LayoutDevicePixel::FromAppUnits(aRect.TopLeft(), + context->AppUnitsPerDevPixel()); + DesktopPoint screenTopLeftDesk = + screenTopLeftDev / context->GetDesktopToDeviceScale(); + + aRect.x = NSToIntRound(screenTopLeftDesk.x); + aRect.y = NSToIntRound(screenTopLeftDesk.y); - aRect.x = nsPresContext::AppUnitsToIntCSSPixels(aRect.x); - aRect.y = nsPresContext::AppUnitsToIntCSSPixels(aRect.y); aRect.height = nsPresContext::AppUnitsToIntCSSPixels(aRect.height); aRect.width = nsPresContext::AppUnitsToIntCSSPixels(aRect.width); @@ -147,10 +153,21 @@ nsScreen::GetAvailRect(nsRect& aRect) return NS_ERROR_FAILURE; } + nsRect r; + context->GetRect(r); + LayoutDevicePoint screenTopLeftDev = + LayoutDevicePixel::FromAppUnits(r.TopLeft(), + context->AppUnitsPerDevPixel()); + DesktopPoint screenTopLeftDesk = + screenTopLeftDev / context->GetDesktopToDeviceScale(); + context->GetClientRect(aRect); - aRect.x = nsPresContext::AppUnitsToIntCSSPixels(aRect.x); - aRect.y = nsPresContext::AppUnitsToIntCSSPixels(aRect.y); + aRect.x = NSToIntRound(screenTopLeftDesk.x) + + nsPresContext::AppUnitsToIntCSSPixels(aRect.x - r.x); + aRect.y = NSToIntRound(screenTopLeftDesk.y) + + nsPresContext::AppUnitsToIntCSSPixels(aRect.y - r.y); + aRect.height = nsPresContext::AppUnitsToIntCSSPixels(aRect.height); aRect.width = nsPresContext::AppUnitsToIntCSSPixels(aRect.width); diff --git a/dom/base/test/test_messagemanager_send_principal.html b/dom/base/test/test_messagemanager_send_principal.html index 21f895228f..611a142581 100644 --- a/dom/base/test/test_messagemanager_send_principal.html +++ b/dom/base/test/test_messagemanager_send_principal.html @@ -47,6 +47,13 @@ (secMan.isSystemPrincipal(message.data) ? "OK" : "KO")); }); + addMessageListener("test:ep", function(message) { + sendAsyncMessage("test:result", "expanded principal: " + + (message.data.isExpandedPrincipal ? "OK" : "KO")); + sendAsyncMessage("test:result", "correct origin: " + + (message.data.origin == "[Expanded Principal [http://bar.example.com, http://foo.example.com]]" ? "OK" : "KO")); + }); + addMessageListener("test:null", function(message) { sendAsyncMessage("test:result", "is nsIPrincipal: " + (message.data instanceof Ci.nsIPrincipal ? "OK" : "KO")); @@ -65,6 +72,9 @@ iframe.id = "iframe"; iframe.src = childFrameURL; + let sb = new Cu.Sandbox(['http://foo.example.com', 'http://bar.example.com']); + let ep = Components.utils.getObjectPrincipal(sb); + iframe.addEventListener("mozbrowserloadend", function() { ok(true, "Got iframe load event."); @@ -92,6 +102,8 @@ createInstance(Ci.nsIPrincipal); mm.sendAsyncMessage("test:system", system); + mm.sendAsyncMessage("test:ep", ep); + let nullP = Cc["@mozilla.org/nullprincipal;1"]. createInstance(Ci.nsIPrincipal); mm.sendAsyncMessage("test:null", nullP); diff --git a/dom/bindings/BindingUtils.cpp b/dom/bindings/BindingUtils.cpp index eaa07807ab..24b1c25964 100644 --- a/dom/bindings/BindingUtils.cpp +++ b/dom/bindings/BindingUtils.cpp @@ -3239,8 +3239,7 @@ UnprivilegedJunkScopeOrWorkerGlobal() return xpc::UnprivilegedJunkScope(); } - return workers::GetCurrentThreadWorkerPrivate()-> - GlobalScope()->GetGlobalJSObject(); + return workers::GetCurrentThreadWorkerGlobal(); } } // namespace binding_detail diff --git a/dom/fetch/InternalResponse.cpp b/dom/fetch/InternalResponse.cpp index 0d90d1365f..0f584b45de 100644 --- a/dom/fetch/InternalResponse.cpp +++ b/dom/fetch/InternalResponse.cpp @@ -131,6 +131,16 @@ InternalResponse::GetTainting() const } } +already_AddRefed +InternalResponse::Unfiltered() +{ + RefPtr ref = mWrappedResponse; + if (!ref) { + ref = this; + } + return ref.forget(); +} + already_AddRefed InternalResponse::OpaqueResponse() { diff --git a/dom/fetch/InternalResponse.h b/dom/fetch/InternalResponse.h index 716e8b3f9b..bd0ec9fd44 100644 --- a/dom/fetch/InternalResponse.h +++ b/dom/fetch/InternalResponse.h @@ -221,6 +221,9 @@ public: LoadTainting GetTainting() const; + already_AddRefed + Unfiltered(); + private: ~InternalResponse(); diff --git a/dom/fetch/Response.cpp b/dom/fetch/Response.cpp index e0c53f8536..86e503db09 100644 --- a/dom/fetch/Response.cpp +++ b/dom/fetch/Response.cpp @@ -238,6 +238,20 @@ Response::Clone(ErrorResult& aRv) const return response.forget(); } +already_AddRefed +Response::CloneUnfiltered(ErrorResult& aRv) const +{ + if (BodyUsed()) { + aRv.ThrowTypeError(); + return nullptr; + } + + RefPtr clone = mInternalResponse->Clone(); + RefPtr ir = clone->Unfiltered(); + RefPtr ref = new Response(mOwner, ir); + return ref.forget(); +} + void Response::SetBody(nsIInputStream* aBody) { diff --git a/dom/fetch/Response.h b/dom/fetch/Response.h index 54540f1ee8..9b237f239c 100644 --- a/dom/fetch/Response.h +++ b/dom/fetch/Response.h @@ -124,6 +124,9 @@ public: already_AddRefed Clone(ErrorResult& aRv) const; + already_AddRefed + CloneUnfiltered(ErrorResult& aRv) const; + void SetBody(nsIInputStream* aBody); diff --git a/dom/geolocation/nsGeolocation.cpp b/dom/geolocation/nsGeolocation.cpp index bc7691f9e0..675ff84048 100644 --- a/dom/geolocation/nsGeolocation.cpp +++ b/dom/geolocation/nsGeolocation.cpp @@ -31,6 +31,7 @@ #include "mozilla/Preferences.h" #include "mozilla/ClearOnShutdown.h" #include "mozilla/dom/Event.h" +#include "mozilla/WeakPtr.h" #include "mozilla/dom/PermissionMessageUtils.h" #include "mozilla/dom/SettingChangeNotificationBinding.h" #include "mozilla/dom/WakeLock.h" @@ -58,6 +59,7 @@ class nsIPrincipal; #ifdef XP_WIN #include "WindowsLocationProvider.h" +#include "mozilla/WindowsVersion.h" #endif // Some limit to the number of get or watch geolocation requests @@ -74,13 +76,12 @@ using namespace mozilla::hal; class nsGeolocationRequest final : public nsIContentPermissionRequest - , public nsITimerCallback , public nsIGeolocationUpdate + , public SupportsWeakPtr { public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS NS_DECL_NSICONTENTPERMISSIONREQUEST - NS_DECL_NSITIMERCALLBACK NS_DECL_NSIGEOLOCATIONUPDATE NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGeolocationRequest, nsIContentPermissionRequest) @@ -92,6 +93,9 @@ class nsGeolocationRequest final uint8_t aProtocolType, bool aWatchPositionRequest = false, int32_t aWatchId = 0); + + MOZ_DECLARE_WEAKREFERENCE_TYPENAME(nsGeolocationRequest) + void Shutdown(); void SendLocation(nsIDOMGeoPosition* aLocation); @@ -106,6 +110,23 @@ class nsGeolocationRequest final private: virtual ~nsGeolocationRequest(); + class TimerCallbackHolder final : public nsITimerCallback + { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSITIMERCALLBACK + + explicit TimerCallbackHolder(nsGeolocationRequest* aRequest) + : mRequest(aRequest) + {} + + private: + ~TimerCallbackHolder() {} + WeakPtr mRequest; + }; + + void Notify(); + already_AddRefed AdjustedLocation(nsIDOMGeoPosition*); bool mIsWatchPositionRequest; @@ -378,12 +399,12 @@ nsGeolocationRequest::nsGeolocationRequest(Geolocation* aLocator, nsGeolocationRequest::~nsGeolocationRequest() { + StopTimeoutTimer(); } NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGeolocationRequest) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContentPermissionRequest) NS_INTERFACE_MAP_ENTRY(nsIContentPermissionRequest) - NS_INTERFACE_MAP_ENTRY(nsITimerCallback) NS_INTERFACE_MAP_ENTRY(nsIGeolocationUpdate) NS_INTERFACE_MAP_END @@ -392,12 +413,11 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGeolocationRequest) NS_IMPL_CYCLE_COLLECTION(nsGeolocationRequest, mCallback, mErrorCallback, mLocator) -NS_IMETHODIMP -nsGeolocationRequest::Notify(nsITimer* aTimer) +void +nsGeolocationRequest::Notify() { StopTimeoutTimer(); NotifyErrorAndShutdown(nsIDOMGeoPositionError::TIMEOUT); - return NS_OK; } void @@ -509,6 +529,12 @@ nsGeolocationRequest::Allow(JS::HandleValue aChoices) // getCurrentPosition requests serviced by the cache // will now be owned by the RequestSendLocationEvent Update(lastPosition.position); + + // After Update is called, getCurrentPosition finishes it's job. + if (!mIsWatchPositionRequest) { + return NS_OK; + } + } else { // if it is not a watch request and timeout is 0, // invoke the errorCallback (if present) with TIMEOUT code @@ -517,14 +543,15 @@ nsGeolocationRequest::Allow(JS::HandleValue aChoices) return NS_OK; } - // Kick off the geo device, if it isn't already running - nsresult rv = gs->StartDevice(GetPrincipal()); + } - if (NS_FAILED(rv)) { - // Location provider error - NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE); - return NS_OK; - } + // Kick off the geo device, if it isn't already running + nsresult rv = gs->StartDevice(GetPrincipal()); + + if (NS_FAILED(rv)) { + // Location provider error + NotifyError(nsIDOMGeoPositionError::POSITION_UNAVAILABLE); + return NS_OK; } if (mLocator->ContainsRequest(this)) { @@ -567,7 +594,8 @@ nsGeolocationRequest::SetTimeoutTimer() } mTimeoutTimer = do_CreateInstance("@mozilla.org/timer;1"); - mTimeoutTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT); + RefPtr holder = new TimerCallbackHolder(this); + mTimeoutTimer->InitWithCallback(holder, timeout, nsITimer::TYPE_ONE_SHOT); } } @@ -747,10 +775,7 @@ nsGeolocationRequest::Shutdown() MOZ_ASSERT(!mShutdown, "request shutdown twice"); mShutdown = true; - if (mTimeoutTimer) { - mTimeoutTimer->Cancel(); - mTimeoutTimer = nullptr; - } + StopTimeoutTimer(); // If there are no other high accuracy requests, the geolocation service will // notify the provider to switch to the default accuracy. @@ -762,6 +787,23 @@ nsGeolocationRequest::Shutdown() } } + +//////////////////////////////////////////////////// +// nsGeolocationRequest::TimerCallbackHolder +//////////////////////////////////////////////////// + +NS_IMPL_ISUPPORTS(nsGeolocationRequest::TimerCallbackHolder, nsISupports, nsITimerCallback) + +NS_IMETHODIMP +nsGeolocationRequest::TimerCallbackHolder::Notify(nsITimer*) +{ + if (mRequest) { + mRequest->Notify(); + } + return NS_OK; +} + + //////////////////////////////////////////////////// // nsGeolocationService //////////////////////////////////////////////////// @@ -840,7 +882,7 @@ nsresult nsGeolocationService::Init() return NS_ERROR_FAILURE; } - obs->AddObserver(this, "quit-application", false); + obs->AddObserver(this, "xpcom-shutdown", false); obs->AddObserver(this, "mozsettings-changed", false); #ifdef MOZ_ENABLE_QT5GEOPOSITION @@ -867,7 +909,8 @@ nsresult nsGeolocationService::Init() #endif #ifdef XP_WIN - if (Preferences::GetBool("geo.provider.ms-windows-location", false)) { + if (Preferences::GetBool("geo.provider.ms-windows-location", false) && + IsWin8OrLater()) { mProvider = new WindowsLocationProvider(); } #endif @@ -947,10 +990,10 @@ nsGeolocationService::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) { - if (!strcmp("quit-application", aTopic)) { + if (!strcmp("xpcom-shutdown", aTopic)) { nsCOMPtr obs = services::GetObserverService(); if (obs) { - obs->RemoveObserver(this, "quit-application"); + obs->RemoveObserver(this, "xpcom-shutdown"); obs->RemoveObserver(this, "mozsettings-changed"); } @@ -987,7 +1030,9 @@ nsGeolocationService::Observe(nsISupports* aSubject, NS_IMETHODIMP nsGeolocationService::Update(nsIDOMGeoPosition *aSomewhere) { - SetCachedPosition(aSomewhere); + if (aSomewhere) { + SetCachedPosition(aSomewhere); + } for (uint32_t i = 0; i< mGeolocators.Length(); i++) { mGeolocators[i]->Update(aSomewhere); @@ -1247,7 +1292,8 @@ Geolocation::Init(nsIDOMWindow* aContentDom) mPrincipal = doc->NodePrincipal(); - if (XRE_IsContentProcess()) { + if (Preferences::GetBool("dom.wakelock.enabled") && + XRE_IsContentProcess()) { doc->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"), /* listener */ this, /* use capture */ true, @@ -1258,19 +1304,21 @@ Geolocation::Init(nsIDOMWindow* aContentDom) nsresult rv = mPrincipal->GetURI(getter_AddRefs(uri)); NS_ENSURE_SUCCESS(rv, rv); - bool isHttp; - rv = uri->SchemeIs("http", &isHttp); - NS_ENSURE_SUCCESS(rv, rv); + if (uri) { + bool isHttp; + rv = uri->SchemeIs("http", &isHttp); + NS_ENSURE_SUCCESS(rv, rv); - bool isHttps; - rv = uri->SchemeIs("https", &isHttps); - NS_ENSURE_SUCCESS(rv, rv); + bool isHttps; + rv = uri->SchemeIs("https", &isHttps); + NS_ENSURE_SUCCESS(rv, rv); - // Store the protocol to send via telemetry later. - if (isHttp) { - mProtocolType = ProtocolType::HTTP; - } else if (isHttps) { - mProtocolType = ProtocolType::HTTPS; + // Store the protocol to send via telemetry later. + if (isHttp) { + mProtocolType = ProtocolType::HTTP; + } else if (isHttps) { + mProtocolType = ProtocolType::HTTPS; + } } } @@ -1325,6 +1373,11 @@ Geolocation::HandleEvent(nsIDOMEvent* aEvent) } } else { mService->SetDisconnectTimer(); + + // We will unconditionally allow all the requests in the callbacks + // because if a request is put into either of these two callbacks, + // it means that it has been allowed before. + // That's why when we resume them, we unconditionally allow them again. for (uint32_t i = 0, length = mWatchingCallbacks.Length(); i < length; ++i) { mWatchingCallbacks[i]->Allow(JS::UndefinedHandleValue); } @@ -1343,7 +1396,8 @@ Geolocation::Shutdown() mPendingCallbacks.Clear(); mWatchingCallbacks.Clear(); - if (XRE_IsContentProcess()) { + if (Preferences::GetBool("dom.wakelock.enabled") && + XRE_IsContentProcess()) { nsCOMPtr window = do_QueryReferent(mOwner); if (window) { nsCOMPtr doc = window->GetExtantDoc(); @@ -1585,7 +1639,7 @@ Geolocation::WatchPosition(PositionCallback& aCallback, const PositionOptions& aOptions, ErrorResult& aRv) { - int32_t ret; + int32_t ret = 0; GeoPositionCallback successCallback(&aCallback); GeoPositionErrorCallback errorCallback(aErrorCallback); diff --git a/dom/html/HTMLMetaElement.cpp b/dom/html/HTMLMetaElement.cpp index 274eadaa28..43371db34f 100644 --- a/dom/html/HTMLMetaElement.cpp +++ b/dom/html/HTMLMetaElement.cpp @@ -172,7 +172,7 @@ HTMLMetaElement::CreateAndDispatchEvent(nsIDocument* aDoc, RefPtr asyncDispatcher = new AsyncEventDispatcher(this, aEventName, true, true); - asyncDispatcher->PostDOMEvent(); + asyncDispatcher->RunDOMEventWhenSafe(); } JSObject* diff --git a/dom/html/HTMLSharedElement.cpp b/dom/html/HTMLSharedElement.cpp index 0b8099b4aa..a2c6fc6d1e 100644 --- a/dom/html/HTMLSharedElement.cpp +++ b/dom/html/HTMLSharedElement.cpp @@ -164,14 +164,15 @@ SetBaseURIUsingFirstBaseWithHref(nsIDocument* aDocument, nsIContent* aMustMatch) return; } - // Resolve the element's href relative to our document URI + // Resolve the element's href relative to our document's + // fallback base URI. nsAutoString href; child->GetAttr(kNameSpaceID_None, nsGkAtoms::href, href); nsCOMPtr newBaseURI; nsContentUtils::NewURIWithDocumentCharset( getter_AddRefs(newBaseURI), href, aDocument, - aDocument->GetDocumentURI()); + aDocument->GetFallbackBaseURI()); // Try to set our base URI. If that fails, try to set base URI to null nsresult rv = aDocument->SetBaseURI(newBaseURI); diff --git a/dom/html/HTMLSharedObjectElement.cpp b/dom/html/HTMLSharedObjectElement.cpp index bb2df743db..eac747e25b 100644 --- a/dom/html/HTMLSharedObjectElement.cpp +++ b/dom/html/HTMLSharedObjectElement.cpp @@ -343,7 +343,7 @@ HTMLSharedObjectElement::GetCapabilities() const { uint32_t capabilities = eSupportPlugins | eAllowPluginSkipChannel; if (mNodeInfo->Equals(nsGkAtoms::embed)) { - capabilities |= eSupportSVG | eSupportImages | eSupportDocuments; + capabilities |= eSupportImages | eSupportDocuments; } return capabilities; diff --git a/dom/html/HTMLSourceElement.cpp b/dom/html/HTMLSourceElement.cpp index e4ed940935..378c86abf7 100644 --- a/dom/html/HTMLSourceElement.cpp +++ b/dom/html/HTMLSourceElement.cpp @@ -74,7 +74,6 @@ HTMLSourceElement::WouldMatchMediaForDocument(const nsAString& aMedia, nsIPresShell* presShell = aDocument->GetShell(); nsPresContext* pctx = presShell ? presShell->GetPresContext() : nullptr; - MOZ_ASSERT(pctx, "Called for document with no prescontext"); nsCSSParser cssParser; RefPtr mediaList = new nsMediaList(); @@ -83,6 +82,20 @@ HTMLSourceElement::WouldMatchMediaForDocument(const nsAString& aMedia, return pctx && mediaList->Matches(pctx, nullptr); } +void +HTMLSourceElement::UpdateMediaList(const nsAttrValue* aValue) +{ + mMediaList = nullptr; + nsString mediaStr; + if (!aValue || (mediaStr = aValue->GetStringValue()).IsEmpty()) { + return; + } + + nsCSSParser cssParser; + mMediaList = new nsMediaList(); + cssParser.ParseMediaList(mediaStr, nullptr, 0, mMediaList, false); +} + nsresult HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, const nsAttrValue* aValue, bool aNotify) @@ -106,23 +119,17 @@ HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName, img->PictureSourceSrcsetChanged(AsContent(), strVal, aNotify); } else if (aName == nsGkAtoms::sizes) { img->PictureSourceSizesChanged(AsContent(), strVal, aNotify); - } else if (aName == nsGkAtoms::media || - aName == nsGkAtoms::type) { + } else if (aName == nsGkAtoms::media) { + UpdateMediaList(aValue); + img->PictureSourceMediaOrTypeChanged(AsContent(), aNotify); + } else if (aName == nsGkAtoms::type) { img->PictureSourceMediaOrTypeChanged(AsContent(), aNotify); } } } } else if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::media) { - mMediaList = nullptr; - if (aValue) { - nsString mediaStr = aValue->GetStringValue(); - if (!mediaStr.IsEmpty()) { - nsCSSParser cssParser; - mMediaList = new nsMediaList(); - cssParser.ParseMediaList(mediaStr, nullptr, 0, mMediaList, false); - } - } + UpdateMediaList(aValue); } else if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) { mSrcMediaSource = nullptr; if (aValue) { diff --git a/dom/html/HTMLSourceElement.h b/dom/html/HTMLSourceElement.h index a49685765d..cce02930ef 100644 --- a/dom/html/HTMLSourceElement.h +++ b/dom/html/HTMLSourceElement.h @@ -13,6 +13,7 @@ #include "mozilla/dom/HTMLMediaElement.h" class nsMediaList; +class nsAttrValue; namespace mozilla { namespace dom { @@ -118,6 +119,9 @@ protected: private: RefPtr mMediaList; RefPtr mSrcMediaSource; + + // Generates a new nsMediaList using the given input + void UpdateMediaList(const nsAttrValue* aValue); }; } // namespace dom diff --git a/dom/html/HTMLTableCellElement.cpp b/dom/html/HTMLTableCellElement.cpp index 013ec6c653..10ceabd392 100644 --- a/dom/html/HTMLTableCellElement.cpp +++ b/dom/html/HTMLTableCellElement.cpp @@ -388,9 +388,7 @@ HTMLTableCellElement::ParseAttribute(int32_t aNamespaceID, if (res) { int32_t val = aResult.GetIntegerValue(); // reset large colspan values as IE and opera do - // quirks mode does not honor the special html 4 value of 0 - if (val > MAX_COLSPAN || val < 0 || - (0 == val && InNavQuirksMode(OwnerDoc()))) { + if (val > MAX_COLSPAN || val <= 0) { aResult.SetTo(1, &aValue); } } diff --git a/dom/html/ImageDocument.cpp b/dom/html/ImageDocument.cpp index 8165db0703..9a7030b544 100644 --- a/dom/html/ImageDocument.cpp +++ b/dom/html/ImageDocument.cpp @@ -416,8 +416,12 @@ ImageDocument::RestoreImage() imageContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::width, true); imageContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::height, true); - if (mImageIsOverflowing) { - SetModeClass(eOverflowing); + if (ImageIsOverflowing()) { + if (!mImageIsOverflowingVertically) { + SetModeClass(eOverflowingHorizontalOnly); + } else { + SetModeClass(eOverflowingVertical); + } } else { SetModeClass(eNone); @@ -444,7 +448,7 @@ ImageDocument::ToggleImageSize() ResetZoomLevel(); RestoreImage(); } - else if (mImageIsOverflowing) { + else if (ImageIsOverflowing()) { ResetZoomLevel(); ShrinkToFit(); } @@ -509,10 +513,16 @@ ImageDocument::SetModeClass(eModeClasses mode) classList->Remove(NS_LITERAL_STRING("shrinkToFit"), rv); } - if (mode == eOverflowing) { - classList->Add(NS_LITERAL_STRING("overflowing"), rv); + if (mode == eOverflowingVertical) { + classList->Add(NS_LITERAL_STRING("overflowingVertical"), rv); } else { - classList->Remove(NS_LITERAL_STRING("overflowing"), rv); + classList->Remove(NS_LITERAL_STRING("overflowingVertical"), rv); + } + + if (mode == eOverflowingHorizontalOnly) { + classList->Add(NS_LITERAL_STRING("overflowingHorizontalOnly"), rv); + } else { + classList->Remove(NS_LITERAL_STRING("overflowingHorizontalOnly"), rv); } } @@ -582,7 +592,7 @@ ImageDocument::HandleEvent(nsIDOMEvent* aEvent) mShouldResize = false; RestoreImageTo(x, y); } - else if (mImageIsOverflowing) { + else if (ImageIsOverflowing()) { ShrinkToFit(); } } else if (eventType.EqualsLiteral("load")) { @@ -703,18 +713,27 @@ ImageDocument::CheckOverflowing(bool changeState) mVisibleHeight = nsPresContext::AppUnitsToFloatCSSPixels(visibleArea.height); } - bool imageWasOverflowing = mImageIsOverflowing; - mImageIsOverflowing = - mImageWidth > mVisibleWidth || mImageHeight > mVisibleHeight; - bool windowBecameBigEnough = imageWasOverflowing && !mImageIsOverflowing; + bool imageWasOverflowing = ImageIsOverflowing(); + bool imageWasOverflowingVertically = mImageIsOverflowingVertically; + mImageIsOverflowingHorizontally = mImageWidth > mVisibleWidth; + mImageIsOverflowingVertically = mImageHeight > mVisibleHeight; + bool windowBecameBigEnough = imageWasOverflowing && !ImageIsOverflowing(); + bool verticalOverflowChanged = + mImageIsOverflowingVertically != imageWasOverflowingVertically; if (changeState || mShouldResize || mFirstResize || - windowBecameBigEnough) { - if (mImageIsOverflowing && (changeState || mShouldResize)) { + windowBecameBigEnough || verticalOverflowChanged) { + if (ImageIsOverflowing() && (changeState || mShouldResize)) { ShrinkToFit(); } else if (mImageIsResized || mFirstResize || windowBecameBigEnough) { RestoreImage(); + } else if (!mImageIsResized && verticalOverflowChanged) { + if (mImageIsOverflowingVertically) { + SetModeClass(eOverflowingVertical); + } else { + SetModeClass(eOverflowingHorizontalOnly); + } } } mFirstResize = false; diff --git a/dom/html/ImageDocument.h b/dom/html/ImageDocument.h index f3f1fee7b6..987de5d63b 100644 --- a/dom/html/ImageDocument.h +++ b/dom/html/ImageDocument.h @@ -62,7 +62,7 @@ public: } bool ImageIsOverflowing() const { - return mImageIsOverflowing; + return mImageIsOverflowingHorizontally || mImageIsOverflowingVertically; } bool ImageIsResized() const { @@ -101,7 +101,8 @@ protected: enum eModeClasses { eNone, eShrinkToFit, - eOverflowing + eOverflowingVertical, // And maybe horizontal too. + eOverflowingHorizontalOnly }; void SetModeClass(eModeClasses mode); @@ -121,7 +122,8 @@ protected: bool mResizeImageByDefault; bool mClickResizingEnabled; - bool mImageIsOverflowing; + bool mImageIsOverflowingHorizontally; + bool mImageIsOverflowingVertically; // mImageIsResized is true if the image is currently resized bool mImageIsResized; // mShouldResize is true if the image should be resized when it doesn't fit diff --git a/dom/html/test/test_bug369370.html b/dom/html/test/test_bug369370.html index 508282eadd..d6576722e0 100644 --- a/dom/html/test/test_bug369370.html +++ b/dom/html/test/test_bug369370.html @@ -88,8 +88,53 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=369370 is(kidDoc.body.scrollLeft, 0, "Checking scrollLeft"); is(kidDoc.body.scrollTop, 0, "Checking scrollTop"); - kidWin.close(); - SimpleTest.finish(); + // ========== test 5 ========== + // Click in the upper left to zoom in again + event = makeClickFor(25, 25); + img.dispatchEvent(event); + ok(true, "----- click 5 -----"); + is(img.width, 800, "image width"); + is(img.height, 600, "image height"); + is(kidDoc.body.scrollLeft, 0, "Checking scrollLeft"); + is(kidDoc.body.scrollTop, 0, "Checking scrollTop"); + is(img.getBoundingClientRect().top, 0, "Image is in view vertically"); + + // ========== test 6 ========== + // Now try resizing the window so the image fits vertically. + function test6() { + kidWin.addEventListener("resize", function resizeListener() { + kidWin.removeEventListener("resize", resizeListener); + // Give the image document time to respond + SimpleTest.executeSoon(function() { + is(img.height, 600, "image height"); + is(img.getBoundingClientRect().top, 25, "Image is vertically centered"); + test7(); + }); + }); + + var decorationSize = kidWin.outerHeight - kidWin.innerHeight; + kidWin.resizeTo(400, 600 + 50 + decorationSize); + } + + // ========== test 7 ========== + // Now try resizing the window so the image no longer fits vertically. + function test7() { + kidWin.addEventListener("resize", function resizeListener() { + kidWin.removeEventListener("resize", resizeListener); + // Give the image document time to respond + SimpleTest.executeSoon(function() { + is(img.height, 600, "image height"); + is(img.getBoundingClientRect().top, 0, "Image is at top again"); + kidWin.close(); + SimpleTest.finish(); + }); + }); + + var decorationSize = kidWin.outerHeight - kidWin.innerHeight; + kidWin.resizeTo(400, 300 + decorationSize); + } + + test6(); } var kidWin; var kidDoc; diff --git a/dom/locales/en-US/chrome/layout/layout_errors.properties b/dom/locales/en-US/chrome/layout/layout_errors.properties index b276ea27a7..11acea9ebb 100644 --- a/dom/locales/en-US/chrome/layout/layout_errors.properties +++ b/dom/locales/en-US/chrome/layout/layout_errors.properties @@ -9,4 +9,4 @@ ImageMapPolyWrongNumberOfCoords=The "coords" attribute of the tag is missing the last "y" coordinate (the correct format is "x1,y1,x2,y2 …"). TablePartRelPosWarning=Relative positioning of table rows and row groups is now supported. This site may need to be updated because it may depend on this feature having no effect. -ScrollLinkedEffectFound=This site appears to use a scroll-linked positioning effect. This may not work well with asynchronous panning; see https://developers.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects for further details and to join the discussion on related tools and features! +ScrollLinkedEffectFound2=This site appears to use a scroll-linked positioning effect. This may not work well with asynchronous panning; see https://developer.mozilla.org/docs/Mozilla/Performance/ScrollLinkedEffects for further details and to join the discussion on related tools and features! diff --git a/dom/payment/Payment.js b/dom/payment/Payment.js index e17565fc44..95e4dc074e 100644 --- a/dom/payment/Payment.js +++ b/dom/payment/Payment.js @@ -10,9 +10,6 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/DOMRequestHelper.jsm"); -const PAYMENTCONTENTHELPER_CID = - Components.ID("{a920adc0-c36e-4fd0-8de0-aac1ac6ebbd0}"); - const PAYMENT_IPC_MSG_NAMES = ["Payment:Success", "Payment:Failed"]; @@ -22,39 +19,82 @@ XPCOMUtils.defineLazyServiceGetter(this, "cpmm", "@mozilla.org/childprocessmessagemanager;1", "nsIMessageSender"); -function PaymentContentHelper() { +var _debug; +try { + _debug = Services.prefs.getPrefType(PREF_DEBUG) == Ci.nsIPrefBranch.PREF_BOOL + && Services.prefs.getBoolPref(PREF_DEBUG); +} catch(e) { + _debug = false; +} + +function LOG(s) { + if (!_debug) { + return; + } + dump("-*- PaymentContentHelper: " + s + "\n"); +} + +function PaymentContentHelper(aWindow) { + this.initDOMRequestHelper(aWindow, PAYMENT_IPC_MSG_NAMES); }; PaymentContentHelper.prototype = { __proto__: DOMRequestIpcHelper.prototype, - QueryInterface: XPCOMUtils.generateQI([Ci.nsINavigatorPayment, - Ci.nsIDOMGlobalPropertyInitializer, - Ci.nsISupportsWeakReference, - Ci.nsIObserver]), - classID: PAYMENTCONTENTHELPER_CID, - classInfo: XPCOMUtils.generateCI({ - classID: PAYMENTCONTENTHELPER_CID, - contractID: "@mozilla.org/payment/content-helper;1", - classDescription: "Payment Content Helper", - flags: Ci.nsIClassInfo.DOM_OBJECT, - interfaces: [Ci.nsINavigatorPayment] - }), + receiveMessage: function receiveMessage(aMessage) { + let name = aMessage.name; + let msg = aMessage.json; + if (_debug) { + LOG("Received message '" + name + "': " + JSON.stringify(msg)); + } + let requestId = msg.requestId; + let request = this.takeRequest(requestId); + if (!request) { + return; + } + switch (name) { + case "Payment:Success": + Services.DOMRequest.fireSuccess(request, msg.result); + break; + case "Payment:Failed": + Services.DOMRequest.fireError(request, msg.errorMsg); + break; + } + }, +}; + +function PaymentContentHelperService() { +}; + +PaymentContentHelperService.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentContentHelperService]), + classID: Components.ID("{80035846-6732-4fcc-961b-f336b65218f4}"), + contractID: "@mozilla.org/payment/content-helper-service;1", + + _xpcom_factory: XPCOMUtils.generateSingletonFactory(PaymentContentHelperService), + + // keys are windows and values are PaymentContentHelpers + helpers: new WeakMap(), // nsINavigatorPayment + pay: function pay(aWindow, aJwts) { + let requestHelper = this.helpers.get(aWindow); + if (!requestHelper) { + requestHelper = new PaymentContentHelper(aWindow); + this.helpers.set(aWindow, requestHelper); + } + let request = requestHelper.createRequest(); + let requestId = requestHelper.getRequestId(request); - pay: function pay(aJwts) { - let request = this.createRequest(); - let requestId = this.getRequestId(request); - - let docShell = this._window.QueryInterface(Ci.nsIInterfaceRequestor) + let docShell = aWindow.QueryInterface(Ci.nsIInterfaceRequestor) .getInterface(Ci.nsIWebNavigation) .QueryInterface(Ci.nsIDocShell); if (!docShell.isActive) { - if (this._debug) { - this.LOG("The caller application is a background app. No request " + - "will be sent"); + if (_debug) { + LOG("The caller application is a background app. No request will be " + + "sent"); } + let runnable = { run: function run() { Services.DOMRequest.fireError(request, "BACKGROUND_APP"); @@ -75,61 +115,6 @@ PaymentContentHelper.prototype = { }); return request; }, - - // nsIDOMGlobalPropertyInitializer - - init: function(aWindow) { - try { - if (!Services.prefs.getBoolPref("dom.mozPay.enabled")) { - return null; - } - } catch (e) { - return null; - } - - this._window = aWindow; - this.initDOMRequestHelper(aWindow, PAYMENT_IPC_MSG_NAMES); - - try { - this._debug = - Services.prefs.getPrefType(PREF_DEBUG) == Ci.nsIPrefBranch.PREF_BOOL - && Services.prefs.getBoolPref(PREF_DEBUG); - } catch(e) { - this._debug = false; - } - - return Cu.exportFunction(this.pay.bind(this), aWindow); - }, - - // nsIFrameMessageListener - - receiveMessage: function receiveMessage(aMessage) { - let name = aMessage.name; - let msg = aMessage.json; - if (this._debug) { - this.LOG("Received message '" + name + "': " + JSON.stringify(msg)); - } - let requestId = msg.requestId; - let request = this.takeRequest(requestId); - if (!request) { - return; - } - switch (name) { - case "Payment:Success": - Services.DOMRequest.fireSuccess(request, msg.result); - break; - case "Payment:Failed": - Services.DOMRequest.fireError(request, msg.errorMsg); - break; - } - }, - - LOG: function LOG(s) { - if (!this._debug) { - return; - } - dump("-*- PaymentContentHelper: " + s + "\n"); - } }; -this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentContentHelper]); +this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentContentHelperService]); diff --git a/dom/payment/Payment.manifest b/dom/payment/Payment.manifest index 90fc340900..42d8ccd5fd 100644 --- a/dom/payment/Payment.manifest +++ b/dom/payment/Payment.manifest @@ -1,6 +1,5 @@ -component {a920adc0-c36e-4fd0-8de0-aac1ac6ebbd0} Payment.js -contract @mozilla.org/payment/content-helper;1 {a920adc0-c36e-4fd0-8de0-aac1ac6ebbd0} -category JavaScript-navigator-property mozPay @mozilla.org/payment/content-helper;1 +component {80035846-6732-4fcc-961b-f336b65218f4} Payment.js +contract @mozilla.org/payment/content-helper-service;1 {80035846-6732-4fcc-961b-f336b65218f4} component {b8bce4e7-fbf0-4719-a634-b1bf9018657c} PaymentFlowInfo.js contract @mozilla.org/payment/flow-info;1 {b8bce4e7-fbf0-4719-a634-b1bf9018657c} diff --git a/dom/payment/interfaces/moz.build b/dom/payment/interfaces/moz.build index 7046187080..3c199ed30d 100644 --- a/dom/payment/interfaces/moz.build +++ b/dom/payment/interfaces/moz.build @@ -5,7 +5,7 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. XPIDL_SOURCES += [ - 'nsINavigatorPayment.idl', + 'nsIPaymentContentHelperService.idl', 'nsIPaymentFlowInfo.idl', 'nsIPaymentProviderStrategy.idl', 'nsIPaymentUIGlue.idl', diff --git a/dom/payment/interfaces/nsINavigatorPayment.idl b/dom/payment/interfaces/nsIPaymentContentHelperService.idl similarity index 72% rename from dom/payment/interfaces/nsINavigatorPayment.idl rename to dom/payment/interfaces/nsIPaymentContentHelperService.idl index 091cec982c..a02bc55a58 100644 --- a/dom/payment/interfaces/nsINavigatorPayment.idl +++ b/dom/payment/interfaces/nsIPaymentContentHelperService.idl @@ -5,13 +5,14 @@ #include "domstubs.idl" interface nsIDOMDOMRequest; +interface mozIDOMWindow; -[scriptable, uuid(44fb7308-7d7b-4975-8a27-e01fe9623bdb)] -interface nsINavigatorPayment : nsISupports +[scriptable, uuid(80035846-6732-4fcc-961b-f336b65218f4)] +interface nsIPaymentContentHelperService : nsISupports { // The 'jwts' parameter can be either a single DOMString or an array of // DOMStrings. In both cases, it represents the base64url encoded and // digitally signed payment information. Each payment provider should // define its supported JWT format. - nsIDOMDOMRequest pay(in jsval jwts); + nsIDOMDOMRequest pay(in mozIDOMWindow window, in jsval jwts); }; diff --git a/dom/payment/tests/mochitest/MockPaymentsUIChromeScript.js b/dom/payment/tests/mochitest/MockPaymentsUIChromeScript.js new file mode 100644 index 0000000000..7d991784d2 --- /dev/null +++ b/dom/payment/tests/mochitest/MockPaymentsUIChromeScript.js @@ -0,0 +1,91 @@ +/* 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/. */ + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cm = Components.manager; +const Cu = Components.utils; + +const CONTRACT_ID = "@mozilla.org/payment/ui-glue;1"; + +Cu.import("resource://gre/modules/Services.jsm"); +Cu.import("resource://gre/modules/XPCOMUtils.jsm"); + +var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); +var oldClassID, oldFactory; +var newClassID = Cc["@mozilla.org/uuid-generator;1"].getService(Ci.nsIUUIDGenerator).generateUUID(); +var newFactory = { + createInstance: function(aOuter, aIID) { + if (aOuter) { + throw Components.results.NS_ERROR_NO_AGGREGATION; + } + return new MockPaymentsUIGlueInstance().QueryInterface(aIID); + }, + lockFactory: function(aLock) { + throw Components.results.NS_ERROR_NOT_IMPLEMENTED; + }, + QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]) +}; + +addMessageListener("MockPaymentsUIGlue.init", function (message) { + try { + oldClassID = registrar.contractIDToCID(CONTRACT_ID); + oldFactory = Cm.getClassObject(oldClassID, Ci.nsIFactory); + } catch (ex) { + oldClassID = ""; + oldFactory = null; + dump("TEST-INFO | can't get payments ui glue registered component, " + + "assuming there is none\n"); + } + if (oldFactory) { + registrar.unregisterFactory(oldClassID, oldFactory); + } + registrar.registerFactory(newClassID, "", CONTRACT_ID, newFactory);}); + +addMessageListener("MockPaymentsUIGlue.cleanup", function (message) { + if (oldClassID) { + registrar.registerFactory(oldClassID, "", CONTRACT_ID, null); + } +}); + +var payments = new Map(); + +function MockPaymentsUIGlueInstance() { +}; + +MockPaymentsUIGlueInstance.prototype = { + QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIGlue]), + + confirmPaymentRequest: function(aRequestId, + aRequests, + aSuccessCb, + aErrorCb) { + aSuccessCb.onresult(aRequestId, aRequests[0].type); + }, + + showPaymentFlow: function(aRequestId, + aPaymentFlowInfo, + aErrorCb) { + let win = Services.ww.openWindow(null, + null, + "_blank", + "chrome,dialog=no,resizable,scrollbars,centerscreen", + null); + + payments.set(aRequestId, win); + let docshell = win.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell); + docshell.paymentRequestId = aRequestId; + + win.document.location = aPaymentFlowInfo.uri + aPaymentFlowInfo.jwt; + }, + + closePaymentFlow: function(aRequestId) { + payments.get(aRequestId).close(); + payments.delete(aRequestId); + + return Promise.resolve(); + }, +}; diff --git a/dom/payment/tests/mochitest/mochitest.ini b/dom/payment/tests/mochitest/mochitest.ini index 3d02e22a17..46c9ebd400 100644 --- a/dom/payment/tests/mochitest/mochitest.ini +++ b/dom/payment/tests/mochitest/mochitest.ini @@ -1,12 +1,11 @@ [DEFAULT] -skip-if=true # This test uses MockPaymentsUIGlue which uses __exposedProps__ - # we need to move this to a chrome test, but these are not - # available in b2g or android for now. +skip-if=buildapp != 'b2g' && toolkit != 'android' support-files= file_mozpayproviderchecker.html file_payprovidersuccess.html file_payproviderfailure.html + MockPaymentsUIChromeScript.js [test_mozpaymentprovider.html] [test_mozpay_callbacks.html] diff --git a/dom/payment/tests/mochitest/test_mozpay_callbacks.html b/dom/payment/tests/mochitest/test_mozpay_callbacks.html index 7d6439b614..e373f78608 100644 --- a/dom/payment/tests/mochitest/test_mozpay_callbacks.html +++ b/dom/payment/tests/mochitest/test_mozpay_callbacks.html @@ -79,7 +79,11 @@ function runTest() { tests.shift()(); } -SpecialPowers.MockPaymentsUIGlue.init(window); +const uiGlue = SpecialPowers.loadChromeScript(SimpleTest.getTestFileURL('MockPaymentsUIChromeScript.js')); +SimpleTest.registerCleanupFunction(() => { + uiGlue.sendAsyncMessage("MockPaymentsUIGlue.cleanup", {}); +}); +uiGlue.sendAsyncMessage("MockPaymentsUIGlue.init", {}); SpecialPowers.pushPrefEnv({ "set": [ @@ -88,13 +92,13 @@ SpecialPowers.pushPrefEnv({ ["dom.payment.provider.1.name", "SuccessProvider"], ["dom.payment.provider.1.description", ""], ["dom.payment.provider.1.uri", - "http://mochi.test:8888/tests/dom/payment/tests/mochitest/file_payprovidersuccess.html?req="], + "https://example.com:443/tests/dom/payment/tests/mochitest/file_payprovidersuccess.html?req="], ["dom.payment.provider.1.type", "mozilla/payments/test/success"], ["dom.payment.provider.1.requestMethod", "GET"], ["dom.payment.provider.2.name", "FailureProvider"], ["dom.payment.provider.2.description", ""], ["dom.payment.provider.2.uri", - "http://mochi.test:8888/tests/dom/payment/tests/mochitest/file_payproviderfailure.html?req="], + "https://example.com:443/tests/dom/payment/tests/mochitest/file_payproviderfailure.html?req="], ["dom.payment.provider.2.type", "mozilla/payments/test/failure"], ["dom.payment.provider.2.requestMethod", "GET"], ] diff --git a/dom/system/windows/WindowsLocationProvider.cpp b/dom/system/windows/WindowsLocationProvider.cpp index 702a68ece0..aa6609d951 100644 --- a/dom/system/windows/WindowsLocationProvider.cpp +++ b/dom/system/windows/WindowsLocationProvider.cpp @@ -7,16 +7,59 @@ #include "WindowsLocationProvider.h" #include "nsGeoPosition.h" #include "nsIDOMGeoPositionError.h" +#include "nsComponentManagerUtils.h" #include "prtime.h" +#include "MLSFallback.h" namespace mozilla { namespace dom { +NS_IMPL_ISUPPORTS(WindowsLocationProvider::MLSUpdate, nsIGeolocationUpdate); + +WindowsLocationProvider::MLSUpdate::MLSUpdate(nsIGeolocationUpdate* aCallback) +: mCallback(aCallback) +{ +} + +NS_IMETHODIMP +WindowsLocationProvider::MLSUpdate::Update(nsIDOMGeoPosition *aPosition) +{ + if (!mCallback) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr coords; + aPosition->GetCoords(getter_AddRefs(coords)); + if (!coords) { + return NS_ERROR_FAILURE; + } + + // TODO add telemetry here to track volume of MLS vs native geo responses + + return mCallback->Update(aPosition); +} + +NS_IMETHODIMP +WindowsLocationProvider::MLSUpdate::LocationUpdatePending() +{ + return NS_OK; +} + +NS_IMETHODIMP +WindowsLocationProvider::MLSUpdate::NotifyError(uint16_t aError) +{ + if (!mCallback) { + return NS_ERROR_FAILURE; + } + return mCallback->NotifyError(aError); +} + + class LocationEvent final : public ILocationEvents { public: - LocationEvent(nsIGeolocationUpdate* aCallback) - : mCallback(aCallback), mCount(0) { + LocationEvent(nsIGeolocationUpdate* aCallback, WindowsLocationProvider *aProvider) + : mCallback(aCallback), mProvider(aProvider), mCount(0) { } // IUnknown interface @@ -32,6 +75,7 @@ public: private: nsCOMPtr mCallback; + RefPtr mProvider; ULONG mCount; }; @@ -75,18 +119,34 @@ LocationEvent::OnStatusChanged(REFIID aReportType, return S_OK; } + // When registering event, REPORT_INITIALIZING is fired at first. + // Then, when the location is found, REPORT_RUNNING is fired. + if (aStatus == REPORT_RUNNING) { + // location is found by Windows Location provider, we use it. + mProvider->CancelMLSProvider(); + return S_OK; + } + + // Cannot get current location at this time. We use MLS instead until + // Location API returns RUNNING status. + if (NS_SUCCEEDED(mProvider->CreateAndWatchMLSProvider(mCallback))) { + return S_OK; + } + + // Cannot watch location by MLS provider. We must return error by + // Location API. uint16_t err; switch (aStatus) { case REPORT_ACCESS_DENIED: err = nsIDOMGeoPositionError::PERMISSION_DENIED; break; + case REPORT_NOT_SUPPORTED: case REPORT_ERROR: err = nsIDOMGeoPositionError::POSITION_UNAVAILABLE; break; default: return S_OK; } - mCallback->NotifyError(err); return S_OK; } @@ -134,6 +194,10 @@ WindowsLocationProvider::WindowsLocationProvider() { } +WindowsLocationProvider::~WindowsLocationProvider() +{ +} + NS_IMETHODIMP WindowsLocationProvider::Startup() { @@ -141,12 +205,14 @@ WindowsLocationProvider::Startup() if (FAILED(::CoCreateInstance(CLSID_Location, nullptr, CLSCTX_INPROC_SERVER, IID_ILocation, getter_AddRefs(location)))) { - return NS_ERROR_FAILURE; + // We will use MLS provider + return NS_OK; } IID reportTypes[] = { IID_ILatLongReport }; if (FAILED(location->RequestPermissions(nullptr, reportTypes, 1, FALSE))) { - return NS_ERROR_FAILURE; + // We will use MLS provider + return NS_OK; } mLocation = location; @@ -156,11 +222,17 @@ WindowsLocationProvider::Startup() NS_IMETHODIMP WindowsLocationProvider::Watch(nsIGeolocationUpdate* aCallback) { - RefPtr event = new LocationEvent(aCallback); - if (FAILED(mLocation->RegisterForReport(event, IID_ILatLongReport, 0))) { - return NS_ERROR_FAILURE; + if (mLocation) { + RefPtr event = new LocationEvent(aCallback, this); + if (SUCCEEDED(mLocation->RegisterForReport(event, IID_ILatLongReport, 0))) { + return NS_OK; + } } - return NS_OK; + + // Cannot use Location API. We will use MLS instead. + mLocation = nullptr; + + return CreateAndWatchMLSProvider(aCallback); } NS_IMETHODIMP @@ -171,6 +243,8 @@ WindowsLocationProvider::Shutdown() mLocation = nullptr; } + CancelMLSProvider(); + return NS_OK; } @@ -178,7 +252,8 @@ NS_IMETHODIMP WindowsLocationProvider::SetHighAccuracy(bool enable) { if (!mLocation) { - return NS_ERROR_FAILURE; + // MLS provider doesn't support HighAccuracy + return NS_OK; } LOCATION_DESIRED_ACCURACY desiredAccuracy; @@ -194,5 +269,28 @@ WindowsLocationProvider::SetHighAccuracy(bool enable) return NS_OK; } +nsresult +WindowsLocationProvider::CreateAndWatchMLSProvider( + nsIGeolocationUpdate* aCallback) +{ + if (mMLSProvider) { + return NS_OK; + } + + mMLSProvider = new MLSFallback(); + return mMLSProvider->Startup(new MLSUpdate(aCallback)); +} + +void +WindowsLocationProvider::CancelMLSProvider() +{ + if (!mMLSProvider) { + return; + } + + mMLSProvider->Shutdown(); + mMLSProvider = nullptr; +} + } // namespace dom } // namespace mozilla diff --git a/dom/system/windows/WindowsLocationProvider.h b/dom/system/windows/WindowsLocationProvider.h index 23dc67e250..fdf2ff853c 100644 --- a/dom/system/windows/WindowsLocationProvider.h +++ b/dom/system/windows/WindowsLocationProvider.h @@ -12,6 +12,8 @@ #include +class MLSFallback; + namespace mozilla { namespace dom { @@ -23,10 +25,25 @@ public: WindowsLocationProvider(); + nsresult CreateAndWatchMLSProvider(nsIGeolocationUpdate* aCallback); + void CancelMLSProvider(); + + class MLSUpdate : public nsIGeolocationUpdate + { + public: + NS_DECL_ISUPPORTS + NS_DECL_NSIGEOLOCATIONUPDATE + explicit MLSUpdate(nsIGeolocationUpdate* aCallback); + + private: + nsCOMPtr mCallback; + virtual ~MLSUpdate() {} + }; private: - ~WindowsLocationProvider() {} + ~WindowsLocationProvider(); RefPtr mLocation; + RefPtr mMLSProvider; }; } // namespace dom diff --git a/dom/system/windows/moz.build b/dom/system/windows/moz.build index 55dadbf099..6a5cb3bf8d 100644 --- a/dom/system/windows/moz.build +++ b/dom/system/windows/moz.build @@ -9,6 +9,10 @@ SOURCES += [ 'WindowsLocationProvider.cpp' ] +LOCAL_INCLUDES += [ + '/dom/geolocation' +] + FINAL_LIBRARY = 'xul' if CONFIG['GNU_CXX']: diff --git a/dom/tests/browser/browser.ini b/dom/tests/browser/browser.ini index 3fc0938a8e..9a67de3dff 100644 --- a/dom/tests/browser/browser.ini +++ b/dom/tests/browser/browser.ini @@ -7,6 +7,7 @@ support-files = test-console-api.html test_bug1004814.html worker_bug1004814.js + geo_leak_test.html [browser_bug1008941_dismissGeolocationHanger.js] skip-if = buildapp == 'mulet' @@ -17,6 +18,7 @@ skip-if = buildapp == 'mulet' [browser_autofocus_background.js] skip-if= buildapp == 'mulet' [browser_autofocus_preference.js] +[browser_bug1238427.js] [browser_bug396843.js] [browser_focus_steal_from_chrome.js] [browser_focus_steal_from_chrome_during_mousedown.js] diff --git a/dom/tests/browser/browser_bug1238427.js b/dom/tests/browser/browser_bug1238427.js new file mode 100644 index 0000000000..18e39ad950 --- /dev/null +++ b/dom/tests/browser/browser_bug1238427.js @@ -0,0 +1,31 @@ +/* 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/. + */ + +"use strict"; + +const TEST_URI = "http://example.com/" + + "browser/dom/tests/browser/geo_leak_test.html"; + +const BASE_GEO_URL = "http://mochi.test:8888/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs"; + +add_task(function* () { + Services.prefs.setBoolPref("geo.prompt.testing", true); + Services.prefs.setBoolPref("geo.prompt.testing.allow", true); + + // Make the geolocation provider responder very slowly to ensure that + // it does not reply before we close the tab. + Services.prefs.setCharPref("geo.wifi.uri", BASE_GEO_URL + "?delay=100000"); + + // Open the test URI and close it. The test harness will make sure that the + // page is cleaned up after some GCs. If geolocation is not shut down properly, + // it will show up as a non-shutdown leak. + yield BrowserTestUtils.withNewTab({ + gBrowser, + url: TEST_URI + }, function* (browser) { /* ... */ }); + + ok(true, "Need to do something in this test"); +}); + diff --git a/dom/tests/browser/geo_leak_test.html b/dom/tests/browser/geo_leak_test.html new file mode 100644 index 0000000000..fb3fabac40 --- /dev/null +++ b/dom/tests/browser/geo_leak_test.html @@ -0,0 +1,17 @@ + + + +Geolocation incomplete position leak test + + + + + diff --git a/dom/tests/mochitest/fetch/test_response.js b/dom/tests/mochitest/fetch/test_response.js index 6adde58827..e396184ee3 100644 --- a/dom/tests/mochitest/fetch/test_response.js +++ b/dom/tests/mochitest/fetch/test_response.js @@ -67,6 +67,30 @@ function testClone() { }); } +function testCloneUnfiltered() { + var url = 'http://example.com/tests/dom/security/test/cors/file_CrossSiteXHR_server.sjs?status=200'; + return fetch(url, { mode: 'no-cors' }).then(function(response) { + // By default the chrome-only function should not be available. + is(response.type, 'opaque', 'response should be opaque'); + is(response.cloneUnfiltered, undefined, + 'response.cloneUnfiltered should be undefined'); + + // When the test is run in a worker context we can't actually try to use + // the chrome-only function. SpecialPowers is not defined. + if (typeof SpecialPowers !== 'object') { + return; + } + + // With a chrome code, however, should be able to get an unfiltered response. + var chromeResponse = SpecialPowers.wrap(response); + is(typeof chromeResponse.cloneUnfiltered, 'function', + 'chromeResponse.cloneFiltered should be a function'); + var unfiltered = chromeResponse.cloneUnfiltered(); + is(unfiltered.type, 'default', 'unfiltered response should be default'); + is(unfiltered.status, 200, 'unfiltered response should have 200 status'); + }); +} + function testError() { var res = Response.error(); is(res.status, 0, "Error response status should be 0"); @@ -234,5 +258,10 @@ function runTest() { .then(testBodyUsed) .then(testBodyExtraction) .then(testClone) + .then(testCloneUnfiltered) // Put more promise based tests here. + .catch(function(e) { + dump('### ### ' + e + '\n'); + ok(false, 'got unexpected error!'); + }); } diff --git a/dom/tests/mochitest/general/test_picture_mutations.html b/dom/tests/mochitest/general/test_picture_mutations.html index bdfd9f7db5..752b02fa7b 100644 --- a/dom/tests/mochitest/general/test_picture_mutations.html +++ b/dom/tests/mochitest/general/test_picture_mutations.html @@ -165,7 +165,6 @@ expectEvents(1, 0, function() { is(img.currentSrc, testPNG50, "Should have switched to testPNG50"); -Math.sin(90); // Now add a source *also* wanting that DPI *just before* the // selected source. Properly re-running the algorithm should @@ -231,7 +230,7 @@ Math.sin(90); is(img.currentSrc, testPNG100, "Should still have testPNG100"); // And a valid MQ - source1.media = "(min-resolution: 3dppx)"; + source1.media = "(min-resolution: 1dppx)"; expectEvents(1, 0, function() { // And a valid type... source1.type = "image/png"; diff --git a/dom/tests/mochitest/geolocation/network_geolocation.sjs b/dom/tests/mochitest/geolocation/network_geolocation.sjs index 5938a53ade..6c7ca47bed 100644 --- a/dom/tests/mochitest/geolocation/network_geolocation.sjs +++ b/dom/tests/mochitest/geolocation/network_geolocation.sjs @@ -18,7 +18,7 @@ function parseQueryString(str) } function getPosition(action) -{ +{ var response = { status: "OK", location: { @@ -27,7 +27,7 @@ function getPosition(action) }, accuracy: (action == "worse-accuracy") ? 100 : 42, }; - + return JSON.stringify(response); } diff --git a/dom/webidl/External.webidl b/dom/webidl/External.webidl index ef80179493..890dff306e 100644 --- a/dom/webidl/External.webidl +++ b/dom/webidl/External.webidl @@ -13,6 +13,7 @@ interface External // Mozilla extension partial interface External { - [UnsafeInPrerendering] void addSearchEngine(DOMString engineURL, DOMString iconURL, - DOMString suggestedTitle, DOMString suggestedCategory); + [UnsafeInPrerendering, UseCounter] + void addSearchEngine(DOMString engineURL, DOMString iconURL, + DOMString suggestedTitle, DOMString suggestedCategory); }; diff --git a/dom/webidl/Navigator.webidl b/dom/webidl/Navigator.webidl index 004639fcd4..b70832d9af 100644 --- a/dom/webidl/Navigator.webidl +++ b/dom/webidl/Navigator.webidl @@ -454,3 +454,14 @@ partial interface Navigator { readonly attribute boolean mozE10sEnabled; }; #endif + +#ifdef MOZ_PAY +partial interface Navigator { + [Throws, NewObject, Pref="dom.mozPay.enabled"] + // The 'jwts' parameter can be either a single DOMString or an array of + // DOMStrings. In both cases, it represents the base64url encoded and + // digitally signed payment information. Each payment provider should + // define its supported JWT format. + DOMRequest mozPay(any jwts); +}; +#endif diff --git a/dom/webidl/Response.webidl b/dom/webidl/Response.webidl index edc4a520d2..fb8b0f0442 100644 --- a/dom/webidl/Response.webidl +++ b/dom/webidl/Response.webidl @@ -24,6 +24,8 @@ interface Response { [Throws, NewObject] Response clone(); + + [ChromeOnly, NewObject, Throws] Response cloneUnfiltered(); }; Response implements Body; diff --git a/dom/webidl/Window.webidl b/dom/webidl/Window.webidl index 9b620b7d99..2c4d2bee0b 100644 --- a/dom/webidl/Window.webidl +++ b/dom/webidl/Window.webidl @@ -421,7 +421,7 @@ partial interface Window { #ifdef HAVE_SIDEBAR // Mozilla extension partial interface Window { - [Replaceable, Throws] + [Replaceable, Throws, UseCounter] readonly attribute (External or WindowProxy) sidebar; }; #endif diff --git a/dom/workers/RuntimeService.cpp b/dom/workers/RuntimeService.cpp index e2d8833592..7e19582888 100644 --- a/dom/workers/RuntimeService.cpp +++ b/dom/workers/RuntimeService.cpp @@ -1369,6 +1369,12 @@ GetCurrentThreadJSContext() return GetCurrentThreadWorkerPrivate()->GetJSContext(); } +JSObject* +GetCurrentThreadWorkerGlobal() +{ + return GetCurrentThreadWorkerPrivate()->GlobalScope()->GetGlobalJSObject(); +} + END_WORKERS_NAMESPACE struct RuntimeService::IdleThreadInfo diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index c00f4171c3..4c0a03755b 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -1445,6 +1445,9 @@ IsCurrentThreadRunningChromeWorker(); JSContext* GetCurrentThreadJSContext(); +JSObject* +GetCurrentThreadWorkerGlobal(); + class AutoSyncLoopHolder { WorkerPrivate* mWorkerPrivate; diff --git a/gfx/gl/GLContext.cpp b/gfx/gl/GLContext.cpp index 85143e5f25..4e626c2fe7 100644 --- a/gfx/gl/GLContext.cpp +++ b/gfx/gl/GLContext.cpp @@ -30,7 +30,6 @@ #include "TextureGarbageBin.h" #include "gfx2DGlue.h" #include "gfxPrefs.h" -#include "DriverCrashGuard.h" #include "mozilla/IntegerPrintfMacros.h" #include "OGLShaderProgram.h" // for ShaderProgramType @@ -461,11 +460,6 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl) return true; } - GLContextCrashGuard crashGuard; - if (crashGuard.Crashed()) { - return false; - } - mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs(); SymLoadStruct symbols[] = { diff --git a/gfx/gl/SharedSurface.cpp b/gfx/gl/SharedSurface.cpp index bdd9d1cd30..72d1a320b2 100644 --- a/gfx/gl/SharedSurface.cpp +++ b/gfx/gl/SharedSurface.cpp @@ -249,27 +249,6 @@ SharedSurface::UnlockProd() mIsLocked = false; } -void -SharedSurface::Fence_ContentThread() -{ - MOZ_ASSERT(NS_GetCurrentThread() == mOwningThread); - Fence_ContentThread_Impl(); -} - -bool -SharedSurface::WaitSync_ContentThread() -{ - MOZ_ASSERT(NS_GetCurrentThread() == mOwningThread); - return WaitSync_ContentThread_Impl(); -} - -bool -SharedSurface::PollSync_ContentThread() -{ - MOZ_ASSERT(NS_GetCurrentThread() == mOwningThread); - return PollSync_ContentThread_Impl(); -} - //////////////////////////////////////////////////////////////////////// // SurfaceFactory diff --git a/gfx/gl/SharedSurface.h b/gfx/gl/SharedSurface.h index dd74f87294..32eb015004 100644 --- a/gfx/gl/SharedSurface.h +++ b/gfx/gl/SharedSurface.h @@ -100,16 +100,10 @@ protected: virtual void LockProdImpl() = 0; virtual void UnlockProdImpl() = 0; - virtual void ProducerAcquireImpl() {} - virtual void ProducerReleaseImpl() { - Fence(); - } - virtual void ProducerReadAcquireImpl() {} - virtual void ProducerReadReleaseImpl() {} - virtual void ConsumerAcquireImpl() { - WaitSync(); - } - virtual void ConsumerReleaseImpl() {} + virtual void ProducerAcquireImpl() = 0; + virtual void ProducerReleaseImpl() = 0; + virtual void ProducerReadAcquireImpl() { ProducerAcquireImpl(); } + virtual void ProducerReadReleaseImpl() { ProducerReleaseImpl(); } public: void ProducerAcquire() { @@ -132,39 +126,7 @@ public: ProducerReadReleaseImpl(); mIsProducerAcquired = false; } - void ConsumerAcquire() { - MOZ_ASSERT(!mIsConsumerAcquired); - ConsumerAcquireImpl(); - mIsConsumerAcquired = true; - } - void ConsumerRelease() { - MOZ_ASSERT(mIsConsumerAcquired); - ConsumerReleaseImpl(); - mIsConsumerAcquired = false; - } - virtual void Fence() = 0; - virtual bool WaitSync() = 0; - virtual bool PollSync() = 0; - - // Use these if you can. They can only be called from the Content - // thread, though! - void Fence_ContentThread(); - bool WaitSync_ContentThread(); - bool PollSync_ContentThread(); - -protected: - virtual void Fence_ContentThread_Impl() { - Fence(); - } - virtual bool WaitSync_ContentThread_Impl() { - return WaitSync(); - } - virtual bool PollSync_ContentThread_Impl() { - return PollSync(); - } - -public: // This function waits until the buffer is no longer being used. // To optimize the performance, some implementaions recycle SharedSurfaces // even when its buffer is still being used. diff --git a/gfx/gl/SharedSurfaceANGLE.cpp b/gfx/gl/SharedSurfaceANGLE.cpp index c2ea412a67..70cd2bffe2 100644 --- a/gfx/gl/SharedSurfaceANGLE.cpp +++ b/gfx/gl/SharedSurfaceANGLE.cpp @@ -134,24 +134,6 @@ SharedSurface_ANGLEShareHandle::UnlockProdImpl() { } -void -SharedSurface_ANGLEShareHandle::Fence() -{ - mGL->fFinish(); -} - -bool -SharedSurface_ANGLEShareHandle::WaitSync() -{ - return true; -} - -bool -SharedSurface_ANGLEShareHandle::PollSync() -{ - return true; -} - void SharedSurface_ANGLEShareHandle::ProducerAcquireImpl() { @@ -174,7 +156,7 @@ SharedSurface_ANGLEShareHandle::ProducerReleaseImpl() mKeyedMutex->ReleaseSync(0); return; } - Fence(); + mGL->fFinish(); } void @@ -192,77 +174,6 @@ SharedSurface_ANGLEShareHandle::ProducerReadReleaseImpl() } } -void -SharedSurface_ANGLEShareHandle::ConsumerAcquireImpl() -{ - if (!mConsumerTexture) { - RefPtr tex; - HRESULT hr = gfxWindowsPlatform::GetPlatform()->GetD3D11Device()->OpenSharedResource(mShareHandle, - __uuidof(ID3D11Texture2D), - (void**)(ID3D11Texture2D**)getter_AddRefs(tex)); - if (SUCCEEDED(hr)) { - mConsumerTexture = tex; - RefPtr mutex; - hr = tex->QueryInterface((IDXGIKeyedMutex**)getter_AddRefs(mutex)); - - if (SUCCEEDED(hr)) { - mConsumerKeyedMutex = mutex; - } - } - } - - if (mConsumerKeyedMutex) { - HRESULT hr = mConsumerKeyedMutex->AcquireSync(0, 10000); - if (hr == WAIT_TIMEOUT) { - MOZ_CRASH("GFX: ANGLE consumer mutex timeout"); - } - } -} - -void -SharedSurface_ANGLEShareHandle::ConsumerReleaseImpl() -{ - if (mConsumerKeyedMutex) { - mConsumerKeyedMutex->ReleaseSync(0); - } -} - -void -SharedSurface_ANGLEShareHandle::Fence_ContentThread_Impl() -{ - if (mFence) { - MOZ_ASSERT(mGL->IsExtensionSupported(GLContext::NV_fence)); - mGL->fSetFence(mFence, LOCAL_GL_ALL_COMPLETED_NV); - mGL->fFlush(); - return; - } - - Fence(); -} - -bool -SharedSurface_ANGLEShareHandle::WaitSync_ContentThread_Impl() -{ - if (mFence) { - mGL->MakeCurrent(); - mGL->fFinishFence(mFence); - return true; - } - - return WaitSync(); -} - -bool -SharedSurface_ANGLEShareHandle::PollSync_ContentThread_Impl() -{ - if (mFence) { - mGL->MakeCurrent(); - return mGL->fTestFence(mFence); - } - - return PollSync(); -} - bool SharedSurface_ANGLEShareHandle::ToSurfaceDescriptor(layers::SurfaceDescriptor* const out_descriptor) { diff --git a/gfx/gl/SharedSurfaceANGLE.h b/gfx/gl/SharedSurfaceANGLE.h index f37b50ed98..349edcc051 100644 --- a/gfx/gl/SharedSurfaceANGLE.h +++ b/gfx/gl/SharedSurfaceANGLE.h @@ -62,19 +62,10 @@ public: virtual void LockProdImpl() override; virtual void UnlockProdImpl() override; - virtual void Fence() override; virtual void ProducerAcquireImpl() override; virtual void ProducerReleaseImpl() override; virtual void ProducerReadAcquireImpl() override; virtual void ProducerReadReleaseImpl() override; - virtual void ConsumerAcquireImpl() override; - virtual void ConsumerReleaseImpl() override; - virtual bool WaitSync() override; - virtual bool PollSync() override; - - virtual void Fence_ContentThread_Impl() override; - virtual bool WaitSync_ContentThread_Impl() override; - virtual bool PollSync_ContentThread_Impl() override; const RefPtr& GetConsumerTexture() const { return mConsumerTexture; diff --git a/gfx/gl/SharedSurfaceD3D11Interop.cpp b/gfx/gl/SharedSurfaceD3D11Interop.cpp index 045610e700..9ba40e47e1 100644 --- a/gfx/gl/SharedSurfaceD3D11Interop.cpp +++ b/gfx/gl/SharedSurfaceD3D11Interop.cpp @@ -328,25 +328,6 @@ void SharedSurface_D3D11Interop::UnlockProdImpl() { } -void -SharedSurface_D3D11Interop::Fence() -{ - // TODO fence properly. This kills performance. - mGL->fFinish(); -} - -bool -SharedSurface_D3D11Interop::WaitSync() -{ - return true; -} - -bool -SharedSurface_D3D11Interop::PollSync() -{ - return true; -} - void SharedSurface_D3D11Interop::ProducerAcquireImpl() { @@ -382,81 +363,9 @@ SharedSurface_D3D11Interop::ProducerReleaseImpl() if (mKeyedMutex) { mKeyedMutex->ReleaseSync(0); } - Fence(); -} -void -SharedSurface_D3D11Interop::ConsumerAcquireImpl() -{ - if (!mConsumerTexture) { - RefPtr tex; - RefPtr device = gfxWindowsPlatform::GetPlatform()->GetD3D11Device(); - HRESULT hr = device->OpenSharedResource(mSharedHandle, - __uuidof(ID3D11Texture2D), - (void**)(ID3D11Texture2D**) getter_AddRefs(tex)); - if (SUCCEEDED(hr)) { - mConsumerTexture = tex; - RefPtr mutex; - hr = tex->QueryInterface((IDXGIKeyedMutex**) getter_AddRefs(mutex)); - - if (SUCCEEDED(hr)) { - mConsumerKeyedMutex = mutex; - } - } - } - - if (mConsumerKeyedMutex) { - const uint64_t keyValue = 0; - const DWORD timeoutMs = 10000; - HRESULT hr = mConsumerKeyedMutex->AcquireSync(keyValue, timeoutMs); - if (hr == WAIT_TIMEOUT) { - MOZ_CRASH(); - } - } -} - -void -SharedSurface_D3D11Interop::ConsumerReleaseImpl() -{ - if (mConsumerKeyedMutex) { - mConsumerKeyedMutex->ReleaseSync(0); - } -} - -void -SharedSurface_D3D11Interop::Fence_ContentThread_Impl() -{ - if (mFence) { - MOZ_ASSERT(mGL->IsExtensionSupported(GLContext::NV_fence)); - mGL->fSetFence(mFence, LOCAL_GL_ALL_COMPLETED_NV); - mGL->fFlush(); - return; - } - - Fence(); -} - -bool -SharedSurface_D3D11Interop::WaitSync_ContentThread_Impl() -{ - if (mFence) { - mGL->MakeCurrent(); - mGL->fFinishFence(mFence); - return true; - } - - return WaitSync(); -} - -bool -SharedSurface_D3D11Interop::PollSync_ContentThread_Impl() -{ - if (mFence) { - mGL->MakeCurrent(); - return mGL->fTestFence(mFence); - } - - return PollSync(); + // TODO fence properly. This kills performance. + mGL->fFinish(); } bool diff --git a/gfx/gl/SharedSurfaceD3D11Interop.h b/gfx/gl/SharedSurfaceD3D11Interop.h index 28e5bd41ce..60cd05b90e 100644 --- a/gfx/gl/SharedSurfaceD3D11Interop.h +++ b/gfx/gl/SharedSurfaceD3D11Interop.h @@ -65,17 +65,8 @@ public: virtual void LockProdImpl() override; virtual void UnlockProdImpl() override; - virtual void Fence() override; virtual void ProducerAcquireImpl() override; virtual void ProducerReleaseImpl() override; - virtual void ConsumerAcquireImpl() override; - virtual void ConsumerReleaseImpl() override; - virtual bool WaitSync() override; - virtual bool PollSync() override; - - virtual void Fence_ContentThread_Impl() override; - virtual bool WaitSync_ContentThread_Impl() override; - virtual bool PollSync_ContentThread_Impl() override; virtual GLuint ProdRenderbuffer() override { return mProdRB; diff --git a/gfx/gl/SharedSurfaceEGL.cpp b/gfx/gl/SharedSurfaceEGL.cpp index b735bf9ba3..45ecf6a5c3 100644 --- a/gfx/gl/SharedSurfaceEGL.cpp +++ b/gfx/gl/SharedSurfaceEGL.cpp @@ -113,7 +113,7 @@ SharedSurface_EGLImage::GetTextureFlags() const } void -SharedSurface_EGLImage::Fence() +SharedSurface_EGLImage::ProducerReleaseImpl() { MutexAutoLock lock(mMutex); mGL->MakeCurrent(); @@ -140,48 +140,6 @@ SharedSurface_EGLImage::Fence() mGL->fFinish(); } -bool -SharedSurface_EGLImage::WaitSync() -{ - MutexAutoLock lock(mMutex); - if (!mSync) { - // We must not be needed. - return true; - } - MOZ_ASSERT(mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync)); - - // Wait FOREVER, primarily because some NVIDIA (at least Tegra) drivers - // have ClientWaitSync returning immediately if the timeout delay is anything - // else than FOREVER. - // - // FIXME: should we try to use a finite timeout delay where possible? - EGLint status = mEGL->fClientWaitSync(Display(), - mSync, - 0, - LOCAL_EGL_FOREVER); - - return status == LOCAL_EGL_CONDITION_SATISFIED; -} - -bool -SharedSurface_EGLImage::PollSync() -{ - MutexAutoLock lock(mMutex); - if (!mSync) { - // We must not be needed. - return true; - } - MOZ_ASSERT(mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync)); - - EGLint status = 0; - MOZ_ALWAYS_TRUE( mEGL->fGetSyncAttrib(mEGL->Display(), - mSync, - LOCAL_EGL_SYNC_STATUS_KHR, - &status) ); - - return status == LOCAL_EGL_SIGNALED_KHR; -} - EGLDisplay SharedSurface_EGLImage::Display() const { diff --git a/gfx/gl/SharedSurfaceEGL.h b/gfx/gl/SharedSurfaceEGL.h index 0c5041d7b0..53f4bb084a 100644 --- a/gfx/gl/SharedSurfaceEGL.h +++ b/gfx/gl/SharedSurfaceEGL.h @@ -68,9 +68,8 @@ public: virtual void LockProdImpl() override {} virtual void UnlockProdImpl() override {} - virtual void Fence() override; - virtual bool WaitSync() override; - virtual bool PollSync() override; + virtual void ProducerAcquireImpl() override {} + virtual void ProducerReleaseImpl() override; virtual GLuint ProdTexture() override { return mProdTex; diff --git a/gfx/gl/SharedSurfaceGL.h b/gfx/gl/SharedSurfaceGL.h index eb13d141cb..775e166969 100644 --- a/gfx/gl/SharedSurfaceGL.h +++ b/gfx/gl/SharedSurfaceGL.h @@ -66,9 +66,8 @@ public: virtual void LockProdImpl() override {} virtual void UnlockProdImpl() override {} - virtual void Fence() override {} - virtual bool WaitSync() override { return true; } - virtual bool PollSync() override { return true; } + virtual void ProducerAcquireImpl() override {} + virtual void ProducerReleaseImpl() override {} virtual GLuint ProdTexture() override { return mTex; @@ -134,12 +133,9 @@ public: virtual void LockProdImpl() override {} virtual void UnlockProdImpl() override {} + virtual void ProducerAcquireImpl() override {} virtual void ProducerReleaseImpl() override; - virtual void Fence() override {} - virtual bool WaitSync() override { MOZ_CRASH("should not be called"); } - virtual bool PollSync() override { MOZ_CRASH("should not be called"); } - virtual GLuint ProdTexture() override { return mTex; } diff --git a/gfx/gl/SharedSurfaceGLX.cpp b/gfx/gl/SharedSurfaceGLX.cpp index 51242d5907..64f9eb0559 100644 --- a/gfx/gl/SharedSurfaceGLX.cpp +++ b/gfx/gl/SharedSurfaceGLX.cpp @@ -55,7 +55,7 @@ SharedSurface_GLXDrawable::SharedSurface_GLXDrawable(GLContext* gl, {} void -SharedSurface_GLXDrawable::Fence() +SharedSurface_GLXDrawable::ProducerReleaseImpl() { mGL->MakeCurrent(); mGL->fFlush(); diff --git a/gfx/gl/SharedSurfaceGLX.h b/gfx/gl/SharedSurfaceGLX.h index 528c223400..c60200c2cb 100644 --- a/gfx/gl/SharedSurfaceGLX.h +++ b/gfx/gl/SharedSurfaceGLX.h @@ -24,9 +24,8 @@ public: bool deallocateClient, bool inSameProcess); - virtual void Fence() override; - virtual bool WaitSync() override { return true; } - virtual bool PollSync() override { return true; } + virtual void ProducerAcquireImpl() override {} + virtual void ProducerReleaseImpl() override; virtual void LockProdImpl() override; virtual void UnlockProdImpl() override; diff --git a/gfx/gl/SharedSurfaceGralloc.cpp b/gfx/gl/SharedSurfaceGralloc.cpp index 2decfa086e..3537780ef1 100644 --- a/gfx/gl/SharedSurfaceGralloc.cpp +++ b/gfx/gl/SharedSurfaceGralloc.cpp @@ -158,7 +158,7 @@ SharedSurface_Gralloc::~SharedSurface_Gralloc() } void -SharedSurface_Gralloc::Fence() +SharedSurface_Gralloc::ProducerReleaseImpl() { if (mSync) { MOZ_ALWAYS_TRUE( mEGL->fDestroySync(mEGL->Display(), mSync) ); @@ -222,54 +222,6 @@ SharedSurface_Gralloc::Fence() } } -bool -SharedSurface_Gralloc::WaitSync() -{ - if (!mSync) { - // We must not be needed. - return true; - } - MOZ_ASSERT(mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync)); - - EGLint status = mEGL->fClientWaitSync(mEGL->Display(), - mSync, - 0, - LOCAL_EGL_FOREVER); - - if (status != LOCAL_EGL_CONDITION_SATISFIED) { - return false; - } - - MOZ_ALWAYS_TRUE( mEGL->fDestroySync(mEGL->Display(), mSync) ); - mSync = 0; - - return true; -} - -bool -SharedSurface_Gralloc::PollSync() -{ - if (!mSync) { - // We must not be needed. - return true; - } - MOZ_ASSERT(mEGL->IsExtensionSupported(GLLibraryEGL::KHR_fence_sync)); - - EGLint status = 0; - MOZ_ALWAYS_TRUE( mEGL->fGetSyncAttrib(mEGL->Display(), - mSync, - LOCAL_EGL_SYNC_STATUS_KHR, - &status) ); - if (status != LOCAL_EGL_SIGNALED_KHR) { - return false; - } - - MOZ_ALWAYS_TRUE( mEGL->fDestroySync(mEGL->Display(), mSync) ); - mSync = 0; - - return true; -} - void SharedSurface_Gralloc::WaitForBufferOwnership() { diff --git a/gfx/gl/SharedSurfaceGralloc.h b/gfx/gl/SharedSurfaceGralloc.h index 7220acf5d6..09b4c12782 100644 --- a/gfx/gl/SharedSurfaceGralloc.h +++ b/gfx/gl/SharedSurfaceGralloc.h @@ -57,9 +57,8 @@ protected: public: virtual ~SharedSurface_Gralloc(); - virtual void Fence() override; - virtual bool WaitSync() override; - virtual bool PollSync() override; + virtual void ProducerAcquireImpl() override {} + virtual void ProducerReleaseImpl() override; virtual void WaitForBufferOwnership() override; diff --git a/gfx/gl/SharedSurfaceIO.cpp b/gfx/gl/SharedSurfaceIO.cpp index 2154327daf..d26b9966ce 100644 --- a/gfx/gl/SharedSurfaceIO.cpp +++ b/gfx/gl/SharedSurfaceIO.cpp @@ -30,7 +30,7 @@ SharedSurface_IOSurface::Create(const RefPtr& ioSurf, } void -SharedSurface_IOSurface::Fence() +SharedSurface_IOSurface::ProducerReleaseImpl() { mGL->MakeCurrent(); mGL->fFlush(); diff --git a/gfx/gl/SharedSurfaceIO.h b/gfx/gl/SharedSurfaceIO.h index fe787ef9cf..bbb9d7f893 100644 --- a/gfx/gl/SharedSurfaceIO.h +++ b/gfx/gl/SharedSurfaceIO.h @@ -36,9 +36,8 @@ public: virtual void LockProdImpl() override { } virtual void UnlockProdImpl() override { } - virtual void Fence() override; - virtual bool WaitSync() override { return true; } - virtual bool PollSync() override { return true; } + virtual void ProducerAcquireImpl() override {} + virtual void ProducerReleaseImpl() override; virtual bool CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, diff --git a/gfx/layers/client/CanvasClient.cpp b/gfx/layers/client/CanvasClient.cpp index 10df9420be..a11c8c35f4 100644 --- a/gfx/layers/client/CanvasClient.cpp +++ b/gfx/layers/client/CanvasClient.cpp @@ -337,8 +337,13 @@ CloneSurface(gl::SharedSurface* src, gl::SurfaceFactory* factory) if (!dest) { return nullptr; } + + gl::SharedSurface* destSurf = dest->Surf(); + + destSurf->ProducerAcquire(); SharedSurface::ProdCopy(src, dest->Surf(), factory); - dest->Surf()->Fence(); + destSurf->ProducerRelease(); + return dest.forget(); } diff --git a/gfx/src/DriverCrashGuard.cpp b/gfx/src/DriverCrashGuard.cpp index af21b14be8..6609d59301 100644 --- a/gfx/src/DriverCrashGuard.cpp +++ b/gfx/src/DriverCrashGuard.cpp @@ -525,13 +525,13 @@ GLContextCrashGuard::UpdateEnvironment() void GLContextCrashGuard::LogCrashRecovery() { - gfxCriticalNote << "GLContext just crashed and is now disabled."; + gfxCriticalNote << "GLContext just crashed."; } void GLContextCrashGuard::LogFeatureDisabled() { - gfxCriticalNote << "GLContext is disabled due to a previous crash."; + gfxCriticalNote << "GLContext remains enabled despite a previous crash."; } } // namespace gfx diff --git a/gfx/src/FilterSupport.cpp b/gfx/src/FilterSupport.cpp index ed7072e1c0..715e9a0df0 100644 --- a/gfx/src/FilterSupport.cpp +++ b/gfx/src/FilterSupport.cpp @@ -310,6 +310,13 @@ FilterCachedColorModels::FilterCachedColorModels(DrawTarget* aDT, already_AddRefed FilterCachedColorModels::ForColorModel(ColorModel aColorModel) { + if (aColorModel == mOriginalColorModel) { + // Make sure to not call WrapForColorModel if our original filter node was + // null, because then we'd get an infinite recursion. + RefPtr filter = mFilterForColorModel[mOriginalColorModel.ToIndex()]; + return filter.forget(); + } + if (!mFilterForColorModel[aColorModel.ToIndex()]) { mFilterForColorModel[aColorModel.ToIndex()] = WrapForColorModel(aColorModel); } diff --git a/gfx/src/nsDeviceContext.cpp b/gfx/src/nsDeviceContext.cpp index 8a9be4bb32..8948c588e3 100644 --- a/gfx/src/nsDeviceContext.cpp +++ b/gfx/src/nsDeviceContext.cpp @@ -722,3 +722,18 @@ nsDeviceContext::UpdateAppUnitsForFullZoom() // adjust mFullZoom to reflect appunit rounding mFullZoom = float(mAppUnitsPerDevPixelAtUnitFullZoom) / mAppUnitsPerDevPixel; } + +DesktopToLayoutDeviceScale +nsDeviceContext::GetDesktopToDeviceScale() +{ + nsCOMPtr screen; + FindScreen(getter_AddRefs(screen)); + + if (screen) { + double scale; + screen->GetContentsScaleFactor(&scale); + return DesktopToLayoutDeviceScale(scale); + } + + return DesktopToLayoutDeviceScale(1.0); +} diff --git a/gfx/src/nsDeviceContext.h b/gfx/src/nsDeviceContext.h index 975ad620b4..401b0c56ee 100644 --- a/gfx/src/nsDeviceContext.h +++ b/gfx/src/nsDeviceContext.h @@ -251,6 +251,8 @@ public: */ bool IsPrinterSurface(); + mozilla::DesktopToLayoutDeviceScale GetDesktopToDeviceScale(); + private: // Private destructor, to discourage deletion outside of Release(): ~nsDeviceContext(); diff --git a/gfx/src/nsFont.cpp b/gfx/src/nsFont.cpp index 99693ccb18..777a320228 100644 --- a/gfx/src/nsFont.cpp +++ b/gfx/src/nsFont.cpp @@ -52,29 +52,7 @@ nsFont::Init() variantPosition = NS_FONT_VARIANT_POSITION_NORMAL; } -nsFont::nsFont(const nsFont& aOther) - : fontlist(aOther.fontlist) -{ - style = aOther.style; - systemFont = aOther.systemFont; - weight = aOther.weight; - stretch = aOther.stretch; - smoothing = aOther.smoothing; - size = aOther.size; - sizeAdjust = aOther.sizeAdjust; - kerning = aOther.kerning; - synthesis = aOther.synthesis; - fontFeatureSettings = aOther.fontFeatureSettings; - languageOverride = aOther.languageOverride; - variantAlternates = aOther.variantAlternates; - variantCaps = aOther.variantCaps; - variantEastAsian = aOther.variantEastAsian; - variantLigatures = aOther.variantLigatures; - variantNumeric = aOther.variantNumeric; - variantPosition = aOther.variantPosition; - alternateValues = aOther.alternateValues; - featureValueLookup = aOther.featureValueLookup; -} +nsFont::nsFont(const nsFont& aOther) = default; nsFont::nsFont() { @@ -111,30 +89,7 @@ bool nsFont::Equals(const nsFont& aOther) const return false; } -nsFont& nsFont::operator=(const nsFont& aOther) -{ - fontlist = aOther.fontlist; - style = aOther.style; - systemFont = aOther.systemFont; - weight = aOther.weight; - stretch = aOther.stretch; - smoothing = aOther.smoothing; - size = aOther.size; - sizeAdjust = aOther.sizeAdjust; - kerning = aOther.kerning; - synthesis = aOther.synthesis; - fontFeatureSettings = aOther.fontFeatureSettings; - languageOverride = aOther.languageOverride; - variantAlternates = aOther.variantAlternates; - variantCaps = aOther.variantCaps; - variantEastAsian = aOther.variantEastAsian; - variantLigatures = aOther.variantLigatures; - variantNumeric = aOther.variantNumeric; - variantPosition = aOther.variantPosition; - alternateValues = aOther.alternateValues; - featureValueLookup = aOther.featureValueLookup; - return *this; -} +nsFont& nsFont::operator=(const nsFont& aOther) = default; void nsFont::CopyAlternates(const nsFont& aOther) diff --git a/gfx/src/nsRegion.cpp b/gfx/src/nsRegion.cpp index a46944e680..3b0bec1e31 100644 --- a/gfx/src/nsRegion.cpp +++ b/gfx/src/nsRegion.cpp @@ -738,13 +738,24 @@ nsIntRegion nsRegion::ScaleToNearestPixels (float aScaleX, float aScaleY, nsIntRegion nsRegion::ScaleToOutsidePixels (float aScaleX, float aScaleY, nscoord aAppUnitsPerPixel) const { - nsIntRegion result; - for (auto iter = RectIter(); !iter.Done(); iter.Next()) { - mozilla::gfx::IntRect deviceRect = - iter.Get().ScaleToOutsidePixels(aScaleX, aScaleY, aAppUnitsPerPixel); - result.Or(result, deviceRect); + // make a copy of the region so that we can mutate it inplace + nsRegion region = *this; + int n; + pixman_box32_t *boxes = pixman_region32_rectangles(®ion.mImpl, &n); + boxes = pixman_region32_rectangles(®ion.mImpl, &n); + for (int i=0; i(blurDataSize); if (!mData) { return nullptr; } - memset(mData, 0, blurDataSize); + memset(mData.get(), 0, blurDataSize); RefPtr dt = - gfxPlatform::GetPlatform()->CreateDrawTargetForData(mData, size, + gfxPlatform::GetPlatform()->CreateDrawTargetForData(mData.get(), size, mBlur->GetStride(), SurfaceFormat::A8); if (!dt) { @@ -119,11 +120,11 @@ DrawBlur(gfxContext* aDestinationCtx, already_AddRefed gfxAlphaBoxBlur::DoBlur(DrawTarget* aDT, IntPoint* aTopLeft) { - mBlur->Blur(mData); + mBlur->Blur(mData.get()); *aTopLeft = mBlur->GetRect().TopLeft(); - return aDT->CreateSourceSurfaceFromData(mData, + return aDT->CreateSourceSurfaceFromData(mData.get(), mBlur->GetSize(), mBlur->GetStride(), SurfaceFormat::A8); diff --git a/gfx/thebes/gfxBlur.h b/gfx/thebes/gfxBlur.h index 2210949b67..d76c7236bf 100644 --- a/gfx/thebes/gfxBlur.h +++ b/gfx/thebes/gfxBlur.h @@ -188,7 +188,7 @@ protected: /** * The temporary alpha surface. */ - nsAutoArrayPtr mData; + mozilla::UniquePtr mData; /** * The object that actually does the blurring for us. diff --git a/gfx/thebes/gfxDWriteFontList.cpp b/gfx/thebes/gfxDWriteFontList.cpp index 829a27b553..0585850e7f 100644 --- a/gfx/thebes/gfxDWriteFontList.cpp +++ b/gfx/thebes/gfxDWriteFontList.cpp @@ -1358,7 +1358,7 @@ static HRESULT GetFamilyName(IDWriteFont *aFont, nsString& aFamilyName) // used to invoke the DirectWrite layout engine to determine the fallback font // for a given character. -IFACEMETHODIMP FontFallbackRenderer::DrawGlyphRun( +IFACEMETHODIMP DWriteFontFallbackRenderer::DrawGlyphRun( void* clientDrawingContext, FLOAT baselineOriginX, FLOAT baselineOriginY, @@ -1423,7 +1423,7 @@ gfxDWriteFontList::GlobalFontFallback(const uint32_t aCh, // initialize fallback renderer if (!mFallbackRenderer) { - mFallbackRenderer = new FontFallbackRenderer(dwFactory); + mFallbackRenderer = new DWriteFontFallbackRenderer(dwFactory); } // initialize text format diff --git a/gfx/thebes/gfxDWriteFontList.h b/gfx/thebes/gfxDWriteFontList.h index 0ed9131867..e9d992b0d2 100644 --- a/gfx/thebes/gfxDWriteFontList.h +++ b/gfx/thebes/gfxDWriteFontList.h @@ -208,10 +208,10 @@ protected: }; // custom text renderer used to determine the fallback font for a given char -class FontFallbackRenderer final : public IDWriteTextRenderer +class DWriteFontFallbackRenderer final : public IDWriteTextRenderer { public: - FontFallbackRenderer(IDWriteFactory *aFactory) + DWriteFontFallbackRenderer(IDWriteFactory *aFactory) : mRefCount(0) { HRESULT hr = S_OK; @@ -220,7 +220,7 @@ public: NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!"); } - ~FontFallbackRenderer() + ~DWriteFontFallbackRenderer() {} // IDWriteTextRenderer methods @@ -432,7 +432,7 @@ private: bool mGDIFontTableAccess; RefPtr mGDIInterop; - RefPtr mFallbackRenderer; + RefPtr mFallbackRenderer; RefPtr mFallbackFormat; RefPtr mSystemFonts; diff --git a/gfx/thebes/gfxFT2FontList.cpp b/gfx/thebes/gfxFT2FontList.cpp index 4b1fe1cc92..a5e8386cf9 100644 --- a/gfx/thebes/gfxFT2FontList.cpp +++ b/gfx/thebes/gfxFT2FontList.cpp @@ -544,7 +544,7 @@ FT2FontEntry::GetFontTable(uint32_t aTableTag) FTUserFontData *userFontData = static_cast( cairo_font_face_get_user_data(mFontFace, &sFTUserFontDataKey)); if (userFontData && userFontData->FontData()) { - return gfxFontUtils::GetTableFromFontData(userFontData->FontData(), aTableTag); + return GetTableFromFontData(userFontData->FontData(), aTableTag); } } @@ -643,7 +643,21 @@ public: } nsAutoCString buf; - PL_DHashTableEnumerate(&mMap, WriteOutMap, &buf); + for (auto iter = mMap.Iter(); !iter.Done(); iter.Next()) { + auto entry = static_cast(iter.Get()); + if (!entry->mFileExists) { + // skip writing entries for files that are no longer present + continue; + } + buf.Append(entry->mFilename); + buf.Append(';'); + buf.Append(entry->mFaces); + buf.Append(';'); + buf.AppendInt(entry->mTimestamp); + buf.Append(';'); + buf.AppendInt(entry->mFilesize); + buf.Append(';'); + } mCache->PutBuffer(CACHE_KEY, buf.get(), buf.Length() + 1); } @@ -739,28 +753,6 @@ private: PLDHashTableOps mOps; - static PLDHashOperator WriteOutMap(PLDHashTable *aTable, - PLDHashEntryHdr *aHdr, - uint32_t aNumber, void *aData) - { - FNCMapEntry* entry = static_cast(aHdr); - if (!entry->mFileExists) { - // skip writing entries for files that are no longer present - return PL_DHASH_NEXT; - } - - nsAutoCString* buf = reinterpret_cast(aData); - buf->Append(entry->mFilename); - buf->Append(';'); - buf->Append(entry->mFaces); - buf->Append(';'); - buf->AppendInt(entry->mTimestamp); - buf->Append(';'); - buf->AppendInt(entry->mFilesize); - buf->Append(';'); - return PL_DHASH_NEXT; - } - typedef struct : public PLDHashEntryHdr { public: nsCString mFilename; @@ -1213,6 +1205,22 @@ gfxFT2FontList::FindFonts() FindFontsInOmnijar(&fnc); } + // Look for downloaded fonts in a profile-agnostic "fonts" directory. + nsCOMPtr dirSvc = + do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID); + if (dirSvc) { + nsCOMPtr appDir; + nsresult rv = dirSvc->Get(NS_XPCOM_CURRENT_PROCESS_DIR, + NS_GET_IID(nsIFile), getter_AddRefs(appDir)); + if (NS_SUCCEEDED(rv)) { + appDir->AppendNative(NS_LITERAL_CSTRING("fonts")); + nsCString localPath; + if (NS_SUCCEEDED(appDir->GetNativePath(localPath))) { + FindFontsInDir(localPath, &fnc, FT2FontFamily::kVisible); + } + } + } + // look for locally-added fonts in a "fonts" subdir of the profile nsCOMPtr localDir; nsresult rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_LOCAL_50_DIR, diff --git a/gfx/thebes/gfxFontEntry.cpp b/gfx/thebes/gfxFontEntry.cpp index 528a869497..8d7ed4653b 100644 --- a/gfx/thebes/gfxFontEntry.cpp +++ b/gfx/thebes/gfxFontEntry.cpp @@ -590,11 +590,12 @@ ShareTableAndGetBlob(nsTArray&& aTable, Clear(); // adopts elements of aTable mSharedBlobData = new FontTableBlobData(Move(aTable)); + mBlob = hb_blob_create(mSharedBlobData->GetTable(), mSharedBlobData->GetTableLength(), HB_MEMORY_MODE_READONLY, mSharedBlobData, DeleteFontTableBlobData); - if (!mSharedBlobData) { + if (mBlob == hb_blob_get_empty() ) { // The FontTableBlobData was destroyed during hb_blob_create(). // The (empty) blob is still be held in the hashtable with a strong // reference. diff --git a/gfx/thebes/gfxFontFamilyList.h b/gfx/thebes/gfxFontFamilyList.h index 94bc95bc2a..6e5e93f631 100644 --- a/gfx/thebes/gfxFontFamilyList.h +++ b/gfx/thebes/gfxFontFamilyList.h @@ -153,14 +153,10 @@ struct FontFamilyName final { } // memory reporting - size_t SizeOfExcludingThis2(mozilla::MallocSizeOf aMallocSizeOf) const { + size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { return mName.SizeOfExcludingThisIfUnshared(aMallocSizeOf); } - size_t SizeOfIncludingThis2(mozilla::MallocSizeOf aMallocSizeOf) const { - return aMallocSizeOf(this) + SizeOfExcludingThis2(aMallocSizeOf); - } - FontFamilyType mType; nsString mName; // empty if mType != eFamily_named }; @@ -341,7 +337,12 @@ public: // memory reporting size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { - return mFontlist.ShallowSizeOfExcludingThis(aMallocSizeOf); + size_t n = 0; + n += mFontlist.ShallowSizeOfExcludingThis(aMallocSizeOf); + for (size_t i = 0; i < mFontlist.Length(); i++) { + n += mFontlist[i].SizeOfExcludingThis(aMallocSizeOf); + } + return n; } size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { diff --git a/gfx/thebes/gfxFontInfoLoader.cpp b/gfx/thebes/gfxFontInfoLoader.cpp index 62e8b39524..d1c398c4d2 100644 --- a/gfx/thebes/gfxFontInfoLoader.cpp +++ b/gfx/thebes/gfxFontInfoLoader.cpp @@ -25,8 +25,15 @@ FontInfoData::Load() uint32_t i, n = mFontFamiliesToLoad.Length(); mLoadStats.families = n; - for (i = 0; i < n; i++) { - LoadFontFamilyData(mFontFamiliesToLoad[i]); + for (i = 0; i < n && !mCanceled; i++) { + // font file memory mapping sometimes causes exceptions - bug 1100949 + MOZ_SEH_TRY { + LoadFontFamilyData(mFontFamiliesToLoad[i]); + } MOZ_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { + gfxCriticalError() << + "Exception occurred reading font data for " << + NS_ConvertUTF16toUTF8(mFontFamiliesToLoad[i]).get(); + } } mLoadTime = TimeStamp::Now() - start; @@ -217,6 +224,8 @@ gfxFontInfoLoader::CancelLoader() mTimer->Cancel(); mTimer = nullptr; } + if (mFontInfo) // null during any initial delay + mFontInfo->mCanceled = true; if (mFontLoaderThread) { NS_DispatchToMainThread(new ShutdownThreadEvent(mFontLoaderThread)); mFontLoaderThread = nullptr; diff --git a/gfx/thebes/gfxFontInfoLoader.h b/gfx/thebes/gfxFontInfoLoader.h index f474c5a912..cde5d3ea35 100644 --- a/gfx/thebes/gfxFontInfoLoader.h +++ b/gfx/thebes/gfxFontInfoLoader.h @@ -15,6 +15,7 @@ #include "nsString.h" #include "gfxFont.h" #include "nsIRunnable.h" +#include "mozilla/Atomics.h" #include "mozilla/TimeStamp.h" #include "nsISupportsImpl.h" @@ -52,6 +53,7 @@ public: FontInfoData(bool aLoadOtherNames, bool aLoadFaceNames, bool aLoadCmaps) : + mCanceled(false), mLoadOtherNames(aLoadOtherNames), mLoadFaceNames(aLoadFaceNames), mLoadCmaps(aLoadCmaps) @@ -115,6 +117,10 @@ public: nsTArray mFontFamiliesToLoad; + // currently non-issue but beware, + // this is also set during cleanup after finishing + mozilla::Atomic mCanceled; + // time spent on the loader thread mozilla::TimeDuration mLoadTime; diff --git a/gfx/thebes/gfxGDIFontList.cpp b/gfx/thebes/gfxGDIFontList.cpp index 52acc8549d..1e4499dcc6 100644 --- a/gfx/thebes/gfxGDIFontList.cpp +++ b/gfx/thebes/gfxGDIFontList.cpp @@ -1109,7 +1109,7 @@ int CALLBACK GDIFontInfo::EnumerateFontsForFamily( famData->mFontInfo.mFontFaceData.Put(fontName, fontData); } - return 1; + return famData->mFontInfo.mCanceled ? 0 : 1; } void diff --git a/hal/Hal.cpp b/hal/Hal.cpp index b825475654..50b443bf1c 100644 --- a/hal/Hal.cpp +++ b/hal/Hal.cpp @@ -5,27 +5,28 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "Hal.h" + #include "HalImpl.h" #include "HalLog.h" #include "HalSandbox.h" +#include "nsIDOMDocument.h" +#include "nsIDOMWindow.h" +#include "nsIDocument.h" +#include "nsIDocShell.h" +#include "nsITabChild.h" +#include "nsIWebNavigation.h" #include "nsThreadUtils.h" #include "nsXULAppAPI.h" -#include "mozilla/Observer.h" -#include "nsIDocument.h" -#include "nsIDOMDocument.h" #include "nsPIDOMWindow.h" -#include "nsIDOMWindow.h" -#include "mozilla/Services.h" -#include "nsIWebNavigation.h" -#include "nsITabChild.h" -#include "nsIDocShell.h" -#include "mozilla/StaticPtr.h" -#include "mozilla/ClearOnShutdown.h" -#include "WindowIdentifier.h" #include "nsJSUtils.h" -#include "mozilla/dom/ScreenOrientation.h" +#include "mozilla/ClearOnShutdown.h" +#include "mozilla/Observer.h" +#include "mozilla/Services.h" +#include "mozilla/StaticPtr.h" #include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentParent.h" +#include "mozilla/dom/ScreenOrientation.h" +#include "WindowIdentifier.h" #ifdef XP_WIN #include @@ -148,7 +149,7 @@ Vibrate(const nsTArray& pattern, const WindowIdentifier &id) *gLastIDToVibrate = id.AsArray(); } - // Don't forward our ID if we are not in the sandbox, because hal_impl + // Don't forward our ID if we are not in the sandbox, because hal_impl // doesn't need it, and we don't want it to be tempted to read it. The // empty identifier will assert if it's used. PROXY_IF_SANDBOXED(Vibrate(pattern, InSandbox() ? id : WindowIdentifier())); @@ -183,7 +184,7 @@ CancelVibrate(const WindowIdentifier &id) // the same window. All other cancellation requests are ignored. if (InSandbox() || (gLastIDToVibrate && *gLastIDToVibrate == id.AsArray())) { - // Don't forward our ID if we are not in the sandbox, because hal_impl + // Don't forward our ID if we are not in the sandbox, because hal_impl // doesn't need it, and we don't want it to be tempted to read it. The // empty identifier will assert if it's used. PROXY_IF_SANDBOXED(CancelVibrate(InSandbox() ? id : WindowIdentifier())); @@ -497,14 +498,14 @@ NotifySystemTimezoneChange(const SystemTimezoneChangeInformation& aSystemTimezon sSystemTimezoneChangeObservers.BroadcastInformation(aSystemTimezoneChangeInfo); } -void +void AdjustSystemClock(int64_t aDeltaMilliseconds) { AssertMainThread(); PROXY_IF_SANDBOXED(AdjustSystemClock(aDeltaMilliseconds)); } -void +void SetTimezone(const nsCString& aTimezoneSpec) { AssertMainThread(); @@ -543,7 +544,7 @@ static SensorObserverList* gSensorObservers = nullptr; static SensorObserverList & GetSensorObservers(SensorType sensor_type) { MOZ_ASSERT(sensor_type < NUM_SENSOR_TYPE); - + if(!gSensorObservers) { gSensorObservers = new SensorObserverList[NUM_SENSOR_TYPE]; } @@ -555,7 +556,7 @@ RegisterSensorObserver(SensorType aSensor, ISensorObserver *aObserver) { SensorObserverList &observers = GetSensorObservers(aSensor); AssertMainThread(); - + observers.AddObserver(aObserver); if(observers.Length() == 1) { EnableSensorNotifications(aSensor); @@ -591,7 +592,7 @@ NotifySensorChange(const SensorData &aSensorData) { SensorObserverList &observers = GetSensorObservers(aSensorData.sensor()); AssertMainThread(); - + observers.Broadcast(aSensorData); } @@ -761,7 +762,7 @@ static SwitchObserverList *sSwitchObserverLists = nullptr; static SwitchObserverList& GetSwitchObserverList(SwitchDevice aDevice) { - MOZ_ASSERT(0 <= aDevice && aDevice < NUM_SWITCH_DEVICE); + MOZ_ASSERT(0 <= aDevice && aDevice < NUM_SWITCH_DEVICE); if (sSwitchObserverLists == nullptr) { sSwitchObserverLists = new SwitchObserverList[NUM_SWITCH_DEVICE]; } @@ -1195,5 +1196,23 @@ bool IsHeadphoneEventFromInputDev() RETURN_PROXY_IF_SANDBOXED(IsHeadphoneEventFromInputDev(), false); } +nsresult StartSystemService(const char* aSvcName, const char* aArgs) +{ + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(StartSystemService(aSvcName, aArgs), NS_ERROR_FAILURE); +} + +void StopSystemService(const char* aSvcName) +{ + AssertMainThread(); + PROXY_IF_SANDBOXED(StopSystemService(aSvcName)); +} + +bool SystemServiceIsRunning(const char* aSvcName) +{ + AssertMainThread(); + RETURN_PROXY_IF_SANDBOXED(SystemServiceIsRunning(aSvcName), false); +} + } // namespace hal } // namespace mozilla diff --git a/hal/Hal.h b/hal/Hal.h index 8b58585e3f..1893714a35 100644 --- a/hal/Hal.h +++ b/hal/Hal.h @@ -7,19 +7,19 @@ #ifndef mozilla_Hal_h #define mozilla_Hal_h -#include "mozilla/hal_sandbox/PHal.h" -#include "mozilla/HalTypes.h" #include "base/basictypes.h" #include "base/platform_thread.h" -#include "mozilla/Observer.h" -#include "mozilla/Types.h" #include "nsTArray.h" -#include "mozilla/dom/MozPowerManagerBinding.h" #include "mozilla/dom/battery/Types.h" +#include "mozilla/dom/MozPowerManagerBinding.h" #include "mozilla/dom/network/Types.h" #include "mozilla/dom/power/Types.h" #include "mozilla/dom/ScreenOrientation.h" +#include "mozilla/hal_sandbox/PHal.h" #include "mozilla/HalScreenConfiguration.h" +#include "mozilla/HalTypes.h" +#include "mozilla/Observer.h" +#include "mozilla/Types.h" /* * Hal.h contains the public Hal API. @@ -640,6 +640,21 @@ uint32_t GetTotalSystemMemoryLevel(); */ bool IsHeadphoneEventFromInputDev(); +/** + * Start the system service with the specified name and arguments. + */ +nsresult StartSystemService(const char* aSvcName, const char* aArgs); + +/** + * Stop the system service with the specified name. + */ +void StopSystemService(const char* aSvcName); + +/** + * Determine whether the system service with the specified name is running. + */ +bool SystemServiceIsRunning(const char* aSvcName); + } // namespace MOZ_HAL_NAMESPACE } // namespace mozilla diff --git a/hal/WindowIdentifier.cpp b/hal/WindowIdentifier.cpp index ef26240031..2e43094168 100644 --- a/hal/WindowIdentifier.cpp +++ b/hal/WindowIdentifier.cpp @@ -4,8 +4,9 @@ * 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/dom/ContentChild.h" #include "WindowIdentifier.h" + +#include "mozilla/dom/ContentChild.h" #include "nsPIDOMWindow.h" namespace mozilla { diff --git a/hal/WindowIdentifier.h b/hal/WindowIdentifier.h index f8b71d618c..78af8cc469 100644 --- a/hal/WindowIdentifier.h +++ b/hal/WindowIdentifier.h @@ -8,8 +8,8 @@ #define mozilla_hal_WindowIdentifier_h #include "mozilla/Types.h" -#include "nsTArray.h" #include "nsCOMPtr.h" +#include "nsTArray.h" #include "nsIDOMWindow.h" namespace mozilla { diff --git a/hal/fallback/FallbackSystemService.cpp b/hal/fallback/FallbackSystemService.cpp new file mode 100644 index 0000000000..93365c47cd --- /dev/null +++ b/hal/fallback/FallbackSystemService.cpp @@ -0,0 +1,35 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et ft=cpp : */ +/* 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 "Hal.h" + +namespace mozilla { +namespace hal_impl { + +nsresult +StartSystemService(const char* aSvcName, const char* aArgs) +{ + MOZ_ASSERT(NS_IsMainThread()); + + return NS_ERROR_NOT_IMPLEMENTED; +} + +void +StopSystemService(const char* aSvcName) +{ + MOZ_ASSERT(NS_IsMainThread()); +} + +bool +SystemServiceIsRunning(const char* aSvcName) +{ + MOZ_ASSERT(NS_IsMainThread()); + + return false; +} + +} // namespace hal_impl +} // namespace mozilla diff --git a/hal/gonk/SystemService.cpp b/hal/gonk/SystemService.cpp new file mode 100644 index 0000000000..4c78c5f0db --- /dev/null +++ b/hal/gonk/SystemService.cpp @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set sw=2 ts=8 et ft=cpp : */ +/* 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 "Hal.h" + +#include +#include +#include + +#include "HalLog.h" +#include "nsITimer.h" +#include "mozilla/unused.h" + +namespace mozilla { +namespace hal_impl { + +static const int sRetryInterval = 100; // ms + +bool +SystemServiceIsRunning(const char* aSvcName) +{ + MOZ_ASSERT(NS_IsMainThread()); + + char key[PROPERTY_KEY_MAX]; + auto res = snprintf(key, sizeof(key), "init.svc.%s", aSvcName); + + if (res < 0) { + HAL_ERR("snprintf: %s", strerror(errno)); + return false; + } else if (static_cast(res) >= sizeof(key)) { + HAL_ERR("snprintf: trunctated service name %s", aSvcName); + return false; + } + + char value[PROPERTY_VALUE_MAX]; + NS_WARN_IF(property_get(key, value, "") < 0); + + return !strcmp(value, "running"); +} + +class StartSystemServiceTimerCallback final : public nsITimerCallback +{ + NS_DECL_THREADSAFE_ISUPPORTS; + +public: + StartSystemServiceTimerCallback(const char* aSvcName, const char* aArgs) + : mSvcName(aSvcName) + , mArgs(aArgs) + { + MOZ_COUNT_CTOR_INHERITED(StartSystemServiceTimerCallback, + nsITimerCallback); + } + + NS_IMETHOD Notify(nsITimer* aTimer) override + { + MOZ_ASSERT(NS_IsMainThread()); + + return StartSystemService(mSvcName.get(), mArgs.get()); + } + +protected: + ~StartSystemServiceTimerCallback() + { + MOZ_COUNT_DTOR_INHERITED(StartSystemServiceTimerCallback, + nsITimerCallback); + } + +private: + nsCString mSvcName; + nsCString mArgs; +}; + +NS_IMPL_ISUPPORTS0(StartSystemServiceTimerCallback); + +nsresult +StartSystemService(const char* aSvcName, const char* aArgs) +{ + MOZ_ASSERT(NS_IsMainThread()); + + char value[PROPERTY_VALUE_MAX]; + auto res = snprintf(value, sizeof(value), "%s:%s", aSvcName, aArgs); + + if (res < 0) { + HAL_ERR("snprintf: %s", strerror(errno)); + return NS_ERROR_FAILURE; + } else if (static_cast(res) >= sizeof(value)) { + HAL_ERR("snprintf: trunctated service name %s", aSvcName); + return NS_ERROR_OUT_OF_MEMORY; + } + + if (NS_WARN_IF(property_set("ctl.start", value) < 0)) { + return NS_ERROR_FAILURE; + } + + /* If the system service is not running, re-try later to start it. + * + * This condition happens when we restart a service immediately + * after it crashed, as the service state remains 'stopping' + * instead of 'stopped'. Due to the limitation of property service, + * hereby add delay. See Bug 1143925 Comment 41. + */ + if (!SystemServiceIsRunning(aSvcName)) { + nsCOMPtr timer = do_CreateInstance("@mozilla.org/timer;1"); + if (!timer) { + return NS_ERROR_FAILURE; + } + + RefPtr timerCallback = + new StartSystemServiceTimerCallback(aSvcName, aArgs); + + timer->InitWithCallback(timerCallback, + sRetryInterval, + nsITimer::TYPE_ONE_SHOT); + } + + return NS_OK; +} + +void +StopSystemService(const char* aSvcName) +{ + MOZ_ASSERT(NS_IsMainThread()); + + Unused << NS_WARN_IF(property_set("ctl.stop", aSvcName)); +} + +} // namespace hal_impl +} // namespace mozilla diff --git a/hal/moz.build b/hal/moz.build index 2efa171493..b089f8e490 100644 --- a/hal/moz.build +++ b/hal/moz.build @@ -50,6 +50,7 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': 'gonk/GonkSensor.cpp', 'gonk/GonkSensorsHelpers.cpp', 'gonk/GonkSwitch.cpp', + 'gonk/SystemService.cpp', 'gonk/UeventPoller.cpp', 'linux/LinuxMemory.cpp', 'linux/LinuxPower.cpp', @@ -134,6 +135,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk': 'fallback/FallbackProcessPriority.cpp', 'fallback/FallbackScreenPower.cpp', 'fallback/FallbackSwitch.cpp', + 'fallback/FallbackSystemService.cpp', 'fallback/FallbackThreadPriority.cpp', 'fallback/FallbackTime.cpp', 'fallback/FallbackWakeLocks.cpp', diff --git a/hal/sandbox/SandboxHal.cpp b/hal/sandbox/SandboxHal.cpp index 376500cc3d..45677bc01d 100644 --- a/hal/sandbox/SandboxHal.cpp +++ b/hal/sandbox/SandboxHal.cpp @@ -191,7 +191,7 @@ SetScreenBrightness(double aBrightness) Hal()->SendSetScreenBrightness(aBrightness); } -void +void AdjustSystemClock(int64_t aDeltaMilliseconds) { Hal()->SendAdjustSystemClock(aDeltaMilliseconds); @@ -201,7 +201,7 @@ void SetTimezone(const nsCString& aTimezoneSpec) { Hal()->SendSetTimezone(nsCString(aTimezoneSpec)); -} +} nsCString GetTimezone() @@ -466,6 +466,23 @@ bool IsHeadphoneEventFromInputDev() return false; } +nsresult StartSystemService(const char* aSvcName, const char* aArgs) +{ + NS_RUNTIMEABORT("System services cannot be controlled from sandboxed contexts."); + return NS_ERROR_NOT_IMPLEMENTED; +} + +void StopSystemService(const char* aSvcName) +{ + NS_RUNTIMEABORT("System services cannot be controlled from sandboxed contexts."); +} + +bool SystemServiceIsRunning(const char* aSvcName) +{ + NS_RUNTIMEABORT("System services cannot be controlled from sandboxed contexts."); + return false; +} + class HalParent : public PHalParent , public BatteryObserver , public NetworkObserver @@ -703,14 +720,14 @@ public: return true; } - virtual bool + virtual bool RecvSetTimezone(const nsCString& aTimezoneSpec) override { if (!AssertAppProcessPermission(this, "time")) { return false; } hal::SetTimezone(aTimezoneSpec); - return true; + return true; } virtual bool @@ -768,13 +785,13 @@ public: hal::RegisterSensorObserver(aSensor, this); return true; } - + virtual bool RecvDisableSensorNotifications(const SensorType &aSensor) override { hal::UnregisterSensorObserver(aSensor, this); return true; } - + void Notify(const SensorData& aSensorData) override { Unused << SendNotifySensorChange(aSensorData); } @@ -799,7 +816,7 @@ public: hal::RegisterWakeLockObserver(this); return true; } - + virtual bool RecvDisableWakeLockNotifications() override { @@ -813,7 +830,7 @@ public: hal::GetWakeLockInfo(aTopic, aWakeLockInfo); return true; } - + void Notify(const WakeLockInformation& aWakeLockInfo) override { Unused << SendNotifyWakeLockChange(aWakeLockInfo); @@ -951,7 +968,7 @@ public: bool HalChild::RecvNotifySensorChange(const hal::SensorData &aSensorData) { hal::NotifySensorChange(aSensorData); - + return true; } diff --git a/intl/hyphenation/glue/hnjstdio.cpp b/intl/hyphenation/glue/hnjstdio.cpp index 06fd98e0b5..660ebaf132 100644 --- a/intl/hyphenation/glue/hnjstdio.cpp +++ b/intl/hyphenation/glue/hnjstdio.cpp @@ -42,14 +42,14 @@ hnjFopen(const char* aURISpec, const char* aMode) rv = NS_NewChannel(getter_AddRefs(channel), uri, nsContentUtils::GetSystemPrincipal(), - nsILoadInfo::SEC_NORMAL, + nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, nsIContentPolicy::TYPE_OTHER); if (NS_FAILED(rv)) { return nullptr; } nsCOMPtr instream; - rv = channel->Open(getter_AddRefs(instream)); + rv = channel->Open2(getter_AddRefs(instream)); if (NS_FAILED(rv)) { return nullptr; } diff --git a/layout/forms/test/mochitest.ini b/layout/forms/test/mochitest.ini index 739f2eab09..14d5c73a99 100644 --- a/layout/forms/test/mochitest.ini +++ b/layout/forms/test/mochitest.ini @@ -24,7 +24,7 @@ skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(needs copy support) b2 [test_bug477531.html] [test_bug477700.html] [test_bug478219.xhtml] -skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s #window.closed not working, bug 907795 # b2g(window.closed not working, bug 907795) b2g-debug(window.closed not working, bug 907795) b2g-desktop(window.closed not working, bug 907795) +skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #window.closed not working, bug 907795 # b2g(window.closed not working, bug 907795) b2g-debug(window.closed not working, bug 907795) b2g-desktop(window.closed not working, bug 907795) [test_bug534785.html] [test_bug542914.html] skip-if = (toolkit == 'gonk' && debug) #debug-only failure diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index 70430b7e71..ed3e625ed5 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -1805,15 +1805,10 @@ nsHTMLReflowState::InitAbsoluteConstraints(nsPresContext* aPresContext, if (marginBStartIsAuto) { if (marginBEndIsAuto) { - if (availMarginSpace < 0) { - // FIXME: Note that the spec doesn't actually say we should do this! - margin.BEnd(cbwm) = availMarginSpace; - } else { - // Both margin-block-start and -end are 'auto', so they get - // equal values - margin.BStart(cbwm) = availMarginSpace / 2; - margin.BEnd(cbwm) = availMarginSpace - margin.BStart(cbwm); - } + // Both 'margin-top' and 'margin-bottom' are 'auto', so they get + // equal values + margin.BStart(cbwm) = availMarginSpace / 2; + margin.BEnd(cbwm) = availMarginSpace - margin.BStart(cbwm); } else { // Just margin-block-start is 'auto' margin.BStart(cbwm) = availMarginSpace; diff --git a/layout/mathml/nsMathMLmtableFrame.cpp b/layout/mathml/nsMathMLmtableFrame.cpp index 959927086c..5f522c7060 100644 --- a/layout/mathml/nsMathMLmtableFrame.cpp +++ b/layout/mathml/nsMathMLmtableFrame.cpp @@ -1191,7 +1191,7 @@ nsMathMLmtdFrame::GetColSpan() if (!value.IsEmpty()) { nsresult error; colspan = value.ToInteger(&error); - if (NS_FAILED(error) || colspan < 0 || colspan > MAX_COLSPAN) + if (NS_FAILED(error) || colspan <= 0 || colspan > MAX_COLSPAN) colspan = 1; } } diff --git a/layout/reftests/abs-pos/abs-pos-auto-margin-centered-ref.html b/layout/reftests/abs-pos/abs-pos-auto-margin-centered-ref.html new file mode 100644 index 0000000000..169c4d37bf --- /dev/null +++ b/layout/reftests/abs-pos/abs-pos-auto-margin-centered-ref.html @@ -0,0 +1,32 @@ + + absolutely positioned element should be vertically centered even if the height is bigger than that of the containing block (reference) - bug 812899 + + + +
+
+
+ + + diff --git a/layout/reftests/abs-pos/abs-pos-auto-margin-centered.html b/layout/reftests/abs-pos/abs-pos-auto-margin-centered.html new file mode 100644 index 0000000000..9ca4bdbe50 --- /dev/null +++ b/layout/reftests/abs-pos/abs-pos-auto-margin-centered.html @@ -0,0 +1,32 @@ + + absolutely positioned element should be vertically centered even if the height is bigger than that of the containing block (reference) - bug 812899 + + + +
+
+
+ + + diff --git a/layout/style/ImageDocument.css b/layout/style/ImageDocument.css index dc24066c38..a79d2213f4 100644 --- a/layout/style/ImageDocument.css +++ b/layout/style/ImageDocument.css @@ -9,7 +9,7 @@ */ @media not print { - .overflowing { + .overflowingVertical, .overflowingHorizontalOnly { cursor: zoom-out; } diff --git a/layout/style/TopLevelImageDocument.css b/layout/style/TopLevelImageDocument.css index 1c0f6b4efe..bfbf0dcbf6 100644 --- a/layout/style/TopLevelImageDocument.css +++ b/layout/style/TopLevelImageDocument.css @@ -23,6 +23,13 @@ left: 0; } + img.overflowingVertical { + /* If we're overflowing vertically, we need to set margin-top to + 0. Otherwise we'll end up trying to vertically center, and end + up cutting off the top part of the image. */ + margin-top: 0; + } + .completeRotation { transition: transform 0.3s ease 0s; } diff --git a/netwerk/protocol/http/UserAgentOverrides.jsm b/netwerk/protocol/http/UserAgentOverrides.jsm index 136d6b642f..037aa575b2 100644 --- a/netwerk/protocol/http/UserAgentOverrides.jsm +++ b/netwerk/protocol/http/UserAgentOverrides.jsm @@ -125,7 +125,7 @@ this.UserAgentOverrides = { let name = aMessage.name; switch (name) { case OVERRIDE_MESSAGE: - let uri = aMessage.data.uri; + let uri = Services.io.newURI(aMessage.data.uri, null, null); return this.getOverrideForURI(uri); default: throw("Wrong Message in UserAgentOverride: " + name); diff --git a/testing/marionette/jar.mn b/testing/marionette/jar.mn index f7780bee38..f72455caab 100644 --- a/testing/marionette/jar.mn +++ b/testing/marionette/jar.mn @@ -39,5 +39,4 @@ marionette.jar: modules/MockFilePicker.jsm (../specialpowers/content/MockFilePicker.jsm) modules/MockColorPicker.jsm (../specialpowers/content/MockColorPicker.jsm) modules/MockPermissionPrompt.jsm (../specialpowers/content/MockPermissionPrompt.jsm) - modules/MockPaymentsUIGlue.jsm (../specialpowers/content/MockPaymentsUIGlue.jsm) modules/Assert.jsm (../modules/Assert.jsm) diff --git a/testing/specialpowers/content/MockPaymentsUIGlue.jsm b/testing/specialpowers/content/MockPaymentsUIGlue.jsm deleted file mode 100644 index c9d7f69ed2..0000000000 --- a/testing/specialpowers/content/MockPaymentsUIGlue.jsm +++ /dev/null @@ -1,110 +0,0 @@ -/* 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/. */ - -this.EXPORTED_SYMBOLS = ["MockPaymentsUIGlue"]; - -const Cc = Components.classes; -const Ci = Components.interfaces; -const Cm = Components.manager; -const Cu = Components.utils; - -const CONTRACT_ID = "@mozilla.org/payment/ui-glue;1"; - -Cu.import("resource://gre/modules/FileUtils.jsm"); -Cu.import("resource://gre/modules/Services.jsm"); -Cu.import("resource://gre/modules/XPCOMUtils.jsm"); - -var registrar = Cm.QueryInterface(Ci.nsIComponentRegistrar); -var classID; -var oldFactory; -var newFactory = function(window) { - return { - createInstance: function(aOuter, aIID) { - if (aOuter) { - throw Components.results.NS_ERROR_NO_AGGREGATION; - } - return new MockPaymentsUIGlueInstance(window).QueryInterface(aIID); - }, - lockFactory: function(aLock) { - throw Components.results.NS_ERROR_NOT_IMPLEMENTED; - }, - QueryInterface: XPCOMUtils.generateQI([Ci.nsIFactory]) - }; -}; - -this.MockPaymentsUIGlue = { - init: function(aWindow) { - try { - classID = registrar.contractIDToCID(CONTRACT_ID); - oldFactory = Cm.getClassObject(Cc[CONTRACT_ID], Ci.nsIFactory); - } catch (ex) { - oldClassID = ""; - oldFactory = null; - dump("TEST-INFO | can't get payments ui glue registered component, " + - "assuming there is none"); - } - if (oldFactory) { - registrar.unregisterFactory(classID, oldFactory); - } - registrar.registerFactory(classID, "", CONTRACT_ID, - new newFactory(aWindow)); - }, - - reset: function() { - }, - - cleanup: function() { - this.reset(); - if (oldFactory) { - registrar.unregisterFactory(classID, newFactory); - registrar.registerFactory(classID, "", CONTRACT_ID, oldFactory); - } - } -}; - -function MockPaymentsUIGlueInstance(aWindow) { - this.window = aWindow; -}; - -MockPaymentsUIGlueInstance.prototype = { - QueryInterface: XPCOMUtils.generateQI([Ci.nsIPaymentUIGlue]), - - confirmPaymentRequest: function(aRequestId, - aRequests, - aSuccessCb, - aErrorCb) { - aSuccessCb.onresult(aRequestId, aRequests[0].type); - }, - - showPaymentFlow: function(aRequestId, - aPaymentFlowInfo, - aErrorCb) { - let document = this.window.document; - let frame = document.createElement("iframe"); - frame.setAttribute("mozbrowser", true); - frame.setAttribute("remote", true); - document.body.appendChild(frame); - let docshell = frame.contentWindow - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebNavigation) - .QueryInterface(Ci.nsIDocShell); - docshell.paymentRequestId = aRequestId; - frame.src = aPaymentFlowInfo.uri + aPaymentFlowInfo.jwt; - }, - - closePaymentFlow: function(aRequestId) { - return Promise.resolve(); - } -}; -// Expose everything to content. We call reset() here so that all of the relevant -// lazy expandos get added. -MockPaymentsUIGlue.reset(); -function exposeAll(obj) { - var props = {}; - for (var prop in obj) - props[prop] = 'rw'; - obj.__exposedProps__ = props; -} -exposeAll(MockPaymentsUIGlue); -exposeAll(MockPaymentsUIGlueInstance.prototype); diff --git a/testing/specialpowers/content/specialpowersAPI.js b/testing/specialpowers/content/specialpowersAPI.js index 73b90e8045..348ed6497e 100644 --- a/testing/specialpowers/content/specialpowersAPI.js +++ b/testing/specialpowers/content/specialpowersAPI.js @@ -14,7 +14,6 @@ var Cu = Components.utils; Cu.import("resource://specialpowers/MockFilePicker.jsm"); Cu.import("resource://specialpowers/MockColorPicker.jsm"); Cu.import("resource://specialpowers/MockPermissionPrompt.jsm"); -Cu.import("resource://specialpowers/MockPaymentsUIGlue.jsm"); Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); Cu.import("resource://gre/modules/XPCOMUtils.jsm"); @@ -540,10 +539,6 @@ SpecialPowersAPI.prototype = { return MockPermissionPrompt; }, - get MockPaymentsUIGlue() { - return MockPaymentsUIGlue; - }, - loadChromeScript: function (url) { // Create a unique id for this chrome script let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"] diff --git a/testing/specialpowers/jar.mn b/testing/specialpowers/jar.mn index f58be5e921..8208f162b6 100644 --- a/testing/specialpowers/jar.mn +++ b/testing/specialpowers/jar.mn @@ -9,7 +9,6 @@ specialpowers.jar: modules/MockFilePicker.jsm (content/MockFilePicker.jsm) modules/MockColorPicker.jsm (content/MockColorPicker.jsm) modules/MockPermissionPrompt.jsm (content/MockPermissionPrompt.jsm) - modules/MockPaymentsUIGlue.jsm (content/MockPaymentsUIGlue.jsm) modules/Assert.jsm (../modules/Assert.jsm) % component {59a52458-13e0-4d93-9d85-a637344f29a1} components/SpecialPowersObserver.js diff --git a/testing/web-platform/meta/html/dom/reflection-tabular.html.ini b/testing/web-platform/meta/html/dom/reflection-tabular.html.ini index 9eb83f56d4..cdeaf6f095 100644 --- a/testing/web-platform/meta/html/dom/reflection-tabular.html.ini +++ b/testing/web-platform/meta/html/dom/reflection-tabular.html.ini @@ -579,3 +579,68 @@ [th.sorted: IDL set to object "test-valueOf" followed by IDL get] expected: FAIL + [colgroup.span: IDL set to 2147483648 followed by getAttribute()] + expected: FAIL + + [colgroup.span: IDL set to 4294967295 followed by getAttribute()] + expected: FAIL + + [col.span: IDL set to 2147483648 followed by getAttribute()] + expected: FAIL + + [col.span: IDL set to 4294967295 followed by getAttribute()] + expected: FAIL + + [td.colSpan: IDL set to 2147483648 followed by getAttribute()] + expected: FAIL + + [td.colSpan: IDL set to 4294967295 followed by getAttribute()] + expected: FAIL + + [td.rowSpan: IDL set to 2147483648 followed by getAttribute()] + expected: FAIL + + [td.rowSpan: IDL set to 4294967295 followed by getAttribute()] + expected: FAIL + + [th.colSpan: IDL set to 2147483648 followed by getAttribute()] + expected: FAIL + + [th.colSpan: IDL set to 4294967295 followed by getAttribute()] + expected: FAIL + + [th.rowSpan: IDL set to 2147483648 followed by getAttribute()] + expected: FAIL + + [th.rowSpan: IDL set to 4294967295 followed by getAttribute()] + expected: FAIL + + [td.colSpan: setAttribute() to 0 followed by IDL get] + expected: FAIL + + [td.colSpan: setAttribute() to "-0" followed by IDL get] + expected: FAIL + + [td.colSpan: setAttribute() to "0" followed by IDL get] + expected: FAIL + + [td.colSpan: IDL set to 0 followed by IDL get] + expected: FAIL + + [td.colSpan: IDL set to "-0" followed by IDL get] + expected: FAIL + + [th.colSpan: setAttribute() to 0 followed by IDL get] + expected: FAIL + + [th.colSpan: setAttribute() to "-0" followed by IDL get] + expected: FAIL + + [th.colSpan: setAttribute() to "0" followed by IDL get] + expected: FAIL + + [th.colSpan: IDL set to 0 followed by IDL get] + expected: FAIL + + [th.colSpan: IDL set to "-0" followed by IDL get] + expected: FAIL diff --git a/testing/web-platform/tests/html/infrastructure/urls/terminology-0/document-base-url.html b/testing/web-platform/tests/html/infrastructure/urls/terminology-0/document-base-url.html index 8f37873cae..3999a3beb8 100644 --- a/testing/web-platform/tests/html/infrastructure/urls/terminology-0/document-base-url.html +++ b/testing/web-platform/tests/html/infrastructure/urls/terminology-0/document-base-url.html @@ -48,5 +48,17 @@ iframe.setAttribute("srcdoc", "

foobar

"); document.body.appendChild(iframe); }, "The fallback base URL of an iframe srcdoc document is the document base URL of the document's browsing context's browsing context container's document."); + + async_test(function () { + var iframe = document.createElement("iframe"); + iframe.onload = this.step_func_done(function () { + var doc = iframe.contentDocument; + assert_resolve_url(doc, location.href.replace("/document-base-url.html", "/sub")); + assert_equals(doc.baseURI, document.baseURI.replace("/document-base-url.html", "/sub/"), + "The srcdoc document's base URL should be set by the tag."); + }); + iframe.setAttribute("srcdoc", "

foobar

"); + document.body.appendChild(iframe); + }, "The base URL of an iframe srcdoc document with a tag should be set by that tag."); diff --git a/toolkit/content/browser-child.js b/toolkit/content/browser-child.js index 148fa1ea1e..ae6e6b7eb5 100644 --- a/toolkit/content/browser-child.js +++ b/toolkit/content/browser-child.js @@ -345,7 +345,6 @@ addEventListener("DOMWindowClose", function (aEvent) { if (!aEvent.isTrusted) return; sendAsyncMessage("DOMWindowClose"); - aEvent.preventDefault(); }, false); addEventListener("ImageContentLoaded", function (aEvent) { diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp index 276ac0d788..e5af86c2e2 100644 --- a/widget/PuppetWidget.cpp +++ b/widget/PuppetWidget.cpp @@ -92,6 +92,8 @@ PuppetWidget::PuppetWidget(TabChild* aTabChild) PuppetWidget::~PuppetWidget() { MOZ_COUNT_DTOR(PuppetWidget); + + Destroy(); } NS_IMETHODIMP @@ -537,9 +539,9 @@ PuppetWidget::ExecuteNativeKeyBinding(NativeKeyBindingsType aType, void* aCallbackData) { // B2G doesn't have native key bindings. -#ifdef MOZ_B2G +#ifdef MOZ_WIDGET_GONK return false; -#else // #ifdef MOZ_B2G +#else // #ifdef MOZ_WIDGET_GONK MOZ_ASSERT(mNativeKeyCommandsValid); const nsTArray* commands = nullptr; @@ -953,9 +955,12 @@ PuppetWidget::NotifyIMEOfPositionChange(const IMENotification& aIMENotification) NS_IMETHODIMP PuppetWidget::SetCursor(nsCursor aCursor) { + // Don't cache on windows, Windowless flash breaks this via async cursor updates. +#if !defined(XP_WIN) if (mCursor == aCursor && !mCustomCursor && !mUpdateCursor) { return NS_OK; } +#endif mCustomCursor = nullptr; @@ -978,12 +983,14 @@ PuppetWidget::SetCursor(imgIContainer* aCursor, return NS_OK; } +#if !defined(XP_WIN) if (mCustomCursor == aCursor && mCursorHotspotX == aHotspotX && mCursorHotspotY == aHotspotY && !mUpdateCursor) { return NS_OK; } +#endif RefPtr surface = aCursor->GetFrame(imgIContainer::FRAME_CURRENT, @@ -1174,13 +1181,13 @@ PuppetWidget::GetNativeData(uint32_t aDataType) } return (void*)nativeData; } + case NS_NATIVE_WINDOW: case NS_NATIVE_WIDGET: case NS_NATIVE_DISPLAY: - // These types are ignored (see bug 1183828). + // These types are ignored (see bug 1183828, bug 1240891). break; case NS_RAW_NATIVE_IME_CONTEXT: MOZ_CRASH("You need to call GetNativeIMEContext() instead"); - case NS_NATIVE_WINDOW: case NS_NATIVE_PLUGIN_PORT: case NS_NATIVE_GRAPHIC: case NS_NATIVE_SHELLWIDGET: diff --git a/widget/cocoa/nsMenuUtilsX.mm b/widget/cocoa/nsMenuUtilsX.mm index 2bfd9224f6..0ca969c061 100644 --- a/widget/cocoa/nsMenuUtilsX.mm +++ b/widget/cocoa/nsMenuUtilsX.mm @@ -116,7 +116,7 @@ NSMenuItem* nsMenuUtilsX::GetStandardEditMenuItem() NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL; // In principle we should be able to allocate this once and then always - // return the same object. But wierd interactions happen between native + // return the same object. But weird interactions happen between native // app-modal dialogs and Gecko-modal dialogs that open above them. So what // we return here isn't always released before it needs to be added to // another menu. See bmo bug 468393. diff --git a/widget/nsContentProcessWidgetFactory.cpp b/widget/nsContentProcessWidgetFactory.cpp index 88e6ec48ff..5703b2607e 100644 --- a/widget/nsContentProcessWidgetFactory.cpp +++ b/widget/nsContentProcessWidgetFactory.cpp @@ -17,7 +17,7 @@ using namespace mozilla; using namespace mozilla::widget; -#ifndef MOZ_B2G +#ifndef MOZ_WIDGET_GONK NS_GENERIC_FACTORY_CONSTRUCTOR(nsClipboardProxy) NS_GENERIC_FACTORY_CONSTRUCTOR(nsColorPickerProxy) @@ -66,4 +66,4 @@ static const mozilla::Module kWidgetModule = { NSMODULE_DEFN(nsContentProcessWidgetModule) = &kWidgetModule; -#endif /* MOZ_B2G */ +#endif /* MOZ_WIDGET_GONK */