author | Carsten "Tomcat" Book <cbook@mozilla.com> |
Wed, 24 Jun 2015 16:01:47 +0200 | |
changeset 250094 | 4cdc1a95a672aaae593448b89b1caee33a159ab7 |
parent 250093 | 3ae7fd12f53fa7955ab952273870f205a82de527 (current diff) |
parent 250050 | d0114c0ca3a182e9af020513b7e21b6135ad01d3 (diff) |
child 250095 | d12f46ccb758b83e304ecc5e68d59eace4d0303f |
child 250152 | 7b0df70e27ea18748e2841506cbe9e23cae18b2f |
child 250155 | 14f96e9b415aa5002bfb4fd41462038be2ecfbf2 |
child 250164 | 5e376b895220eeb611705a7dbce4f4fe53d1aa78 |
push id | 61434 |
push user | cbook@mozilla.com |
push date | Wed, 24 Jun 2015 14:04:25 +0000 |
treeherder | mozilla-inbound@d12f46ccb758 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 41.0a1 |
first release with | nightly linux32
4cdc1a95a672
/
41.0a1
/
20150624080416
/
files
nightly linux64
4cdc1a95a672
/
41.0a1
/
20150624080416
/
files
nightly mac
4cdc1a95a672
/
41.0a1
/
20150624080416
/
files
nightly win32
4cdc1a95a672
/
41.0a1
/
20150624080416
/
files
nightly win64
4cdc1a95a672
/
41.0a1
/
20150624080416
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
41.0a1
/
20150624080416
/
pushlog to previous
nightly linux64
41.0a1
/
20150624080416
/
pushlog to previous
nightly mac
41.0a1
/
20150624080416
/
pushlog to previous
nightly win32
41.0a1
/
20150624080416
/
pushlog to previous
nightly win64
41.0a1
/
20150624080416
/
pushlog to previous
|
--- a/accessible/atk/AccessibleWrap.cpp +++ b/accessible/atk/AccessibleWrap.cpp @@ -678,17 +678,17 @@ getRoleCB(AtkObject *aAtkObj) #undef ROLE if (aAtkObj->role == ATK_ROLE_LIST_BOX && !IsAtkVersionAtLeast(2, 1)) aAtkObj->role = ATK_ROLE_LIST; else if (aAtkObj->role == ATK_ROLE_TABLE_ROW && !IsAtkVersionAtLeast(2, 1)) aAtkObj->role = ATK_ROLE_LIST_ITEM; else if (aAtkObj->role == ATK_ROLE_MATH && !IsAtkVersionAtLeast(2, 12)) - aAtkObj->role = ATK_ROLE_PANEL; + aAtkObj->role = ATK_ROLE_SECTION; else if (aAtkObj->role == ATK_ROLE_STATIC && !IsAtkVersionAtLeast(2, 16)) aAtkObj->role = ATK_ROLE_TEXT; else if ((aAtkObj->role == ATK_ROLE_MATH_FRACTION || aAtkObj->role == ATK_ROLE_MATH_ROOT) && !IsAtkVersionAtLeast(2, 16)) aAtkObj->role = ATK_ROLE_SECTION; return aAtkObj->role; }
--- a/accessible/base/RoleMap.h +++ b/accessible/base/RoleMap.h @@ -1062,281 +1062,281 @@ ROLE(SWITCH, NSAccessibilityCheckBoxRole, ROLE_SYSTEM_CHECKBUTTON, IA2_ROLE_TOGGLE_BUTTON, eNameFromSubtreeRule) ROLE(MATHML_MATH, "math", ATK_ROLE_MATH, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, ROLE_SYSTEM_EQUATION, ROLE_SYSTEM_EQUATION, eNoNameRule) ROLE(MATHML_IDENTIFIER, "mathml identifier", ATK_ROLE_STATIC, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNameFromSubtreeRule) ROLE(MATHML_NUMBER, "mathml number", ATK_ROLE_STATIC, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNameFromSubtreeRule) ROLE(MATHML_OPERATOR, "mathml operator", ATK_ROLE_STATIC, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNameFromSubtreeRule) ROLE(MATHML_TEXT, "mathml text", ATK_ROLE_STATIC, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNameFromSubtreeRule) ROLE(MATHML_STRING_LITERAL, "mathml string literal", ATK_ROLE_STATIC, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNameFromSubtreeRule) ROLE(MATHML_GLYPH, "mathml glyph", ATK_ROLE_IMAGE, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNameFromSubtreeRule) ROLE(MATHML_ROW, "mathml row", - ATK_ROLE_PANEL, - NSAccessibilityUnknownRole, + ATK_ROLE_SECTION, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_FRACTION, "mathml fraction", ATK_ROLE_MATH_FRACTION, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_SQUARE_ROOT, "mathml square root", ATK_ROLE_MATH_ROOT, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_ROOT, "mathml root", ATK_ROLE_MATH_ROOT, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_FENCED, "mathml fenced", - ATK_ROLE_PANEL, - NSAccessibilityUnknownRole, + ATK_ROLE_SECTION, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_ENCLOSED, "mathml enclosed", - ATK_ROLE_PANEL, - NSAccessibilityUnknownRole, + ATK_ROLE_SECTION, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_STYLE, "mathml style", - ATK_ROLE_PANEL, - NSAccessibilityUnknownRole, + ATK_ROLE_SECTION, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_SUB, "mathml sub", - ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + ATK_ROLE_SECTION, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_SUP, "mathml sup", - ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + ATK_ROLE_SECTION, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_SUB_SUP, "mathml sub sup", - ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + ATK_ROLE_SECTION, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_UNDER, "mathml under", - ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + ATK_ROLE_SECTION, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_OVER, "mathml over", - ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + ATK_ROLE_SECTION, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_UNDER_OVER, "mathml under over", - ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + ATK_ROLE_SECTION, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_MULTISCRIPTS, "mathml multiscripts", - ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + ATK_ROLE_SECTION, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_TABLE, "mathml table", ATK_ROLE_TABLE, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_LABELED_ROW, "mathml labeled row", ATK_ROLE_TABLE_ROW, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_TABLE_ROW, "mathml table row", ATK_ROLE_TABLE_ROW, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_CELL, "mathml cell", ATK_ROLE_TABLE_CELL, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_ACTION, "mathml action", - ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + ATK_ROLE_SECTION, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_ERROR, "mathml error", - ATK_ROLE_PANEL, - NSAccessibilityUnknownRole, + ATK_ROLE_SECTION, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_STACK, "mathml stack", ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_LONG_DIVISION, "mathml long division", ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_STACK_GROUP, "mathml stack group", ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_STACK_ROW, "mathml stack row", ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_STACK_CARRIES, "mathml stack carries", ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_STACK_CARRY, "mathml stack carry", ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(MATHML_STACK_LINE, "mathml stack line", ATK_ROLE_UNKNOWN, - NSAccessibilityUnknownRole, + NSAccessibilityGroupRole, 0, IA2_ROLE_UNKNOWN, eNoNameRule) ROLE(RADIO_GROUP, "grouping", ATK_ROLE_PANEL, NSAccessibilityRadioGroupRole,
--- a/accessible/mac/mozAccessible.mm +++ b/accessible/mac/mozAccessible.mm @@ -498,16 +498,76 @@ GetClosestInterestingAccessible(id anObj return @"AXDefinitionList"; // 10.6+ NSAccessibilityDefinitionListSubrole; case roles::TERM: return @"AXTerm"; case roles::DEFINITION: return @"AXDefinition"; + case roles::MATHML_MATH: + return @"AXDocumentMath"; + + case roles::MATHML_FRACTION: + return @"AXMathFraction"; + + case roles::MATHML_FENCED: + // XXX This should be AXMathFence, but doing so without implementing the + // whole fence interface seems to make VoiceOver crash, so we present it + // as a row for now. + return @"AXMathRow"; + + case roles::MATHML_SUB: + case roles::MATHML_SUP: + case roles::MATHML_SUB_SUP: + return @"AXMathSubscriptSuperscript"; + + case roles::MATHML_ROW: + return @"AXMathRow"; + + case roles::MATHML_UNDER: + case roles::MATHML_OVER: + case roles::MATHML_UNDER_OVER: + return @"AXMathUnderOver"; + + case roles::MATHML_SQUARE_ROOT: + return @"AXMathSquareRoot"; + + case roles::MATHML_ROOT: + return @"AXMathRoot"; + + case roles::MATHML_TEXT: + return @"AXMathText"; + + case roles::MATHML_NUMBER: + return @"AXMathNumber"; + + case roles::MATHML_IDENTIFIER: + return @"AXMathIdentifier"; + + case roles::MATHML_TABLE: + return @"AXMathTable"; + + case roles::MATHML_TABLE_ROW: + return @"AXMathTableRow"; + + case roles::MATHML_CELL: + return @"AXMathTableCell"; + + // XXX: NSAccessibility also uses subroles AXMathSeparatorOperator and + // AXMathFenceOperator. We should use the NS_MATHML_OPERATOR_FENCE and + // NS_MATHML_OPERATOR_SEPARATOR bits of nsOperatorFlags, but currently they + // are only available from the MathML layout code. Hence we just fallback + // to subrole AXMathOperator for now. + case roles::MATHML_OPERATOR: + return @"AXMathOperator"; + + case roles::MATHML_MULTISCRIPTS: + return @"AXMathMultiscript"; + case roles::SWITCH: return @"AXSwitch"; default: break; } return nil;
--- a/b2g/installer/package-manifest.in +++ b/b2g/installer/package-manifest.in @@ -300,17 +300,16 @@ @RESPATH@/components/parentalcontrols.xpt #ifdef MOZ_WEBRTC @RESPATH@/components/peerconnection.xpt #endif @RESPATH@/components/places.xpt @RESPATH@/components/plugin.xpt @RESPATH@/components/pref.xpt @RESPATH@/components/prefetch.xpt -@RESPATH@/components/profile.xpt #ifdef MOZ_ENABLE_PROFILER_SPS @RESPATH@/components/profiler.xpt #endif @RESPATH@/components/proxyObject.xpt @RESPATH@/components/rdf.xpt @RESPATH@/components/satchel.xpt @RESPATH@/components/saxparser.xpt @RESPATH@/components/sessionstore.xpt
--- a/browser/base/content/test/general/browser.ini +++ b/browser/base/content/test/general/browser.ini @@ -470,16 +470,17 @@ skip-if = e10s # Bug 940206 - nsIWebCont [browser_addCertException.js] skip-if = e10s # Bug 1100687 - test directly manipulates content (content.document.getElementById) [browser_bug1045809.js] [browser_e10s_switchbrowser.js] [browser_e10s_about_process.js] [browser_e10s_chrome_process.js] [browser_e10s_javascript.js] [browser_blockHPKP.js] +tags = psm skip-if = e10s # bug 1100687 - test directly manipulates content (content.document.getElementById) [browser_mcb_redirect.js] [browser_windowactivation.js] [browser_contextmenu_childprocess.js] [browser_bug963945.js] [browser_readerMode.js] support-files = readerModeArticle.html
--- a/browser/installer/package-manifest.in +++ b/browser/installer/package-manifest.in @@ -301,17 +301,16 @@ @RESPATH@/components/parentalcontrols.xpt #ifdef MOZ_WEBRTC @RESPATH@/components/peerconnection.xpt #endif @RESPATH@/components/places.xpt @RESPATH@/components/plugin.xpt @RESPATH@/components/pref.xpt @RESPATH@/components/prefetch.xpt -@RESPATH@/components/profile.xpt #ifdef MOZ_ENABLE_PROFILER_SPS @RESPATH@/components/profiler.xpt #endif @RESPATH@/components/rdf.xpt @RESPATH@/components/satchel.xpt @RESPATH@/components/saxparser.xpt @RESPATH@/browser/components/sessionstore.xpt @RESPATH@/components/services-crypto-component.xpt
--- a/dom/base/Attr.h +++ b/dom/base/Attr.h @@ -93,16 +93,18 @@ public: bool Specified() const; // XPCOM GetNamespaceURI() is OK // XPCOM GetPrefix() is OK // XPCOM GetLocalName() is OK Element* GetOwnerElement(ErrorResult& aRv); + bool IsNSAware() const { return mNsAware; } + protected: virtual Element* GetNameSpaceElement() override { return GetElement(); } static bool sInitialized;
--- a/dom/base/nsDOMAttributeMap.cpp +++ b/dom/base/nsDOMAttributeMap.cpp @@ -10,16 +10,17 @@ #include "nsDOMAttributeMap.h" #include "mozilla/MemoryReporting.h" #include "mozilla/dom/Attr.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/NamedNodeMapBinding.h" #include "mozilla/dom/NodeInfoInlines.h" +#include "mozilla/Telemetry.h" #include "nsAttrName.h" #include "nsContentUtils.h" #include "nsError.h" #include "nsIContentInlines.h" #include "nsIDocument.h" #include "nsNameSpaceManager.h" #include "nsNodeInfoManager.h" #include "nsUnicharUtils.h" @@ -266,16 +267,31 @@ nsDOMAttributeMap::SetNamedItemNS(nsIDOM already_AddRefed<Attr> nsDOMAttributeMap::SetNamedItemInternal(Attr& aAttr, bool aWithNS, ErrorResult& aError) { NS_ENSURE_TRUE(mContent, nullptr); + if (!aAttr.IsNSAware() && + !mContent->IsHTMLElement() && + aAttr.OwnerDoc()->IsHTMLDocument()) { + // Check whether we have a non-lowercase name, and if so log some telemetry. + // We check whether the attr's document is HTML _before_ the adopt we do + // below, because we're trying to figure out whether we could lowercase the + // attr name at creation time. We restrict this to the !IsNSAware() case, + // because we only care about Attr nodes created via createAttribute. + nsIAtom* nameAtom = aAttr.NodeInfo()->NameAtom(); + if (nsContentUtils::StringContainsASCIIUpper(nsDependentAtomString(nameAtom))) { + Telemetry::Accumulate(Telemetry::NONLOWERCASE_NONHTML_ATTR_NODE_SET, + true); + } + } + // XXX should check same-origin between mContent and aAttr however // nsContentUtils::CheckSameOrigin can't deal with attributenodes yet // Check that attribute is not owned by somebody else nsDOMAttributeMap* owner = aAttr.GetMap(); if (owner) { if (owner != this) { aError.Throw(NS_ERROR_DOM_INUSE_ATTRIBUTE_ERR);
--- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -7586,28 +7586,16 @@ nsGlobalWindow::ClearInterval(int32_t aH { ErrorResult rv; ClearInterval(aHandle, rv); return rv.StealNSResult(); } NS_IMETHODIMP -nsGlobalWindow::SetTimeout(int32_t *_retval) -{ - return SetTimeoutOrInterval(false, _retval); -} - -NS_IMETHODIMP -nsGlobalWindow::SetInterval(int32_t *_retval) -{ - return SetTimeoutOrInterval(true, _retval); -} - -NS_IMETHODIMP nsGlobalWindow::SetResizable(bool aResizable) { // nop return NS_OK; } NS_IMETHODIMP @@ -11940,60 +11928,16 @@ nsGlobalWindow::SetTimeoutOrInterval(nsI timeout->mPublicId = ++mTimeoutPublicIdCounter; *aReturn = timeout->mPublicId; return NS_OK; } -nsresult -nsGlobalWindow::SetTimeoutOrInterval(bool aIsInterval, int32_t *aReturn) -{ - // This needs to forward to the inner window, but since the current - // inner may not be the inner in the calling scope, we need to treat - // this specially here as we don't want timeouts registered in a - // dying inner window to get registered and run on the current inner - // window. To get this right, we need to forward this call to the - // inner window that's calling window.setTimeout(). - - if (IsOuterWindow()) { - nsGlobalWindow* callerInner = CallerInnerWindow(); - NS_ENSURE_TRUE(callerInner || nsContentUtils::IsCallerChrome(), NS_ERROR_NOT_AVAILABLE); - - // If the caller and the callee share the same outer window, - // forward to the callee inner. Else, we forward to the current - // inner (e.g. someone is calling setTimeout() on a reference to - // some other window). - - if (callerInner && - callerInner->GetOuterWindow() == this && - callerInner->IsInnerWindow()) { - return callerInner->SetTimeoutOrInterval(aIsInterval, aReturn); - } - - FORWARD_TO_INNER(SetTimeoutOrInterval, (aIsInterval, aReturn), - NS_ERROR_NOT_INITIALIZED); - } - - int32_t interval = 0; - bool isInterval = aIsInterval; - nsCOMPtr<nsIScriptTimeoutHandler> handler; - nsresult rv = NS_CreateJSTimeoutHandler(this, - &isInterval, - &interval, - getter_AddRefs(handler)); - if (!handler) { - *aReturn = 0; - return rv; - } - - return SetTimeoutOrInterval(handler, interval, isInterval, aReturn); -} - int32_t nsGlobalWindow::SetTimeoutOrInterval(Function& aFunction, int32_t aTimeout, const Sequence<JS::Value>& aArguments, bool aIsInterval, ErrorResult& aError) { nsGlobalWindow* inner = InnerForSetTimeoutOrInterval(aError); if (!inner) { return -1;
--- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -124,22 +124,16 @@ namespace indexedDB { class IDBFactory; } // namespace indexedDB } // namespace dom namespace gfx { class VRHMDInfo; } // namespace gfx } // namespace mozilla -extern nsresult -NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow, - bool *aIsInterval, - int32_t *aInterval, - nsIScriptTimeoutHandler **aRet); - extern already_AddRefed<nsIScriptTimeoutHandler> NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow, mozilla::dom::Function& aFunction, const mozilla::dom::Sequence<JS::Value>& aArguments, mozilla::ErrorResult& aError); extern already_AddRefed<nsIScriptTimeoutHandler> NS_CreateJSTimeoutHandler(JSContext* aCx, nsGlobalWindow *aWindow, @@ -1330,17 +1324,16 @@ public: nsresult ClearTimeoutOrInterval(int32_t aTimerID) override { mozilla::ErrorResult rv; ClearTimeoutOrInterval(aTimerID, rv); return rv.StealNSResult(); } // JS specific timeout functions (JS args grabbed from context). - nsresult SetTimeoutOrInterval(bool aIsInterval, int32_t* aReturn); nsresult ResetTimersForNonBackgroundWindow(); // The timeout implementation functions. void RunTimeout(nsTimeout *aTimeout); void RunTimeout() { RunTimeout(nullptr); } // Return true if |aTimeout| was cleared while its handler ran. bool RunTimeoutHandler(nsTimeout* aTimeout, nsIScriptContext* aScx); // Return true if |aTimeout| needs to be reinserted into the timeout list.
--- a/dom/base/nsJSTimeoutHandler.cpp +++ b/dom/base/nsJSTimeoutHandler.cpp @@ -53,19 +53,16 @@ public: *aLineNo = mLineNo; } virtual const nsTArray<JS::Value>& GetArgs() override { return mArgs; } - nsresult Init(nsGlobalWindow *aWindow, bool *aIsInterval, - int32_t *aInterval, bool* aAllowEval); - void ReleaseJSObjects(); private: ~nsJSScriptTimeoutHandler(); // filename, line number and JS language version string of the // caller of setTimeout() nsCString mFileName; @@ -243,171 +240,23 @@ nsJSScriptTimeoutHandler::ReleaseJSObjec { if (mFunction) { mFunction = nullptr; mArgs.Clear(); mozilla::DropJSObjects(this); } } -nsresult -nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval, - int32_t *aInterval, bool *aAllowEval) -{ - if (!aWindow->GetContextInternal() || !aWindow->FastGetGlobalJSObject()) { - // This window was already closed, or never properly initialized, - // don't let a timer be scheduled on such a window. - - return NS_ERROR_NOT_INITIALIZED; - } - - nsAXPCNativeCallContext *ncc = nullptr; - nsresult rv = nsContentUtils::XPConnect()-> - GetCurrentNativeCallContext(&ncc); - NS_ENSURE_SUCCESS(rv, rv); - - if (!ncc) - return NS_ERROR_NOT_AVAILABLE; - - JSContext *cx = nullptr; - - rv = ncc->GetJSContext(&cx); - NS_ENSURE_SUCCESS(rv, rv); - - uint32_t argc; - JS::Value *argv = nullptr; - - ncc->GetArgc(&argc); - ncc->GetArgvPtr(&argv); - - JS::Rooted<JSFlatString*> expr(cx); - JS::Rooted<JSObject*> funobj(cx); - - if (argc < 1) { - ::JS_ReportError(cx, "Function %s requires at least 2 parameter", - *aIsInterval ? kSetIntervalStr : kSetTimeoutStr); - return NS_ERROR_DOM_TYPE_ERR; - } - - int32_t interval = 0; - if (argc > 1) { - JS::Rooted<JS::Value> arg(cx, argv[1]); - - if (!JS::ToInt32(cx, arg, &interval)) { - ::JS_ReportError(cx, - "Second argument to %s must be a millisecond interval", - aIsInterval ? kSetIntervalStr : kSetTimeoutStr); - return NS_ERROR_DOM_TYPE_ERR; - } - } - - if (argc == 1) { - // If no interval was specified, treat this like a timeout, to avoid - // setting an interval of 0 milliseconds. - *aIsInterval = false; - } - - JS::Rooted<JS::Value> arg(cx, argv[0]); - switch (::JS_TypeOfValue(cx, arg)) { - case JSTYPE_FUNCTION: - funobj = &arg.toObject(); - break; - - case JSTYPE_STRING: - case JSTYPE_OBJECT: - { - JSString *str = JS::ToString(cx, arg); - if (!str) - return NS_ERROR_OUT_OF_MEMORY; - - expr = ::JS_FlattenString(cx, str); - if (!expr) - return NS_ERROR_OUT_OF_MEMORY; - - argv[0] = JS::StringValue(str); - } - break; - - default: - ::JS_ReportError(cx, "useless %s call (missing quotes around argument?)", - *aIsInterval ? kSetIntervalStr : kSetTimeoutStr); - - // Return an error that nsGlobalWindow can recognize and turn into NS_OK. - return NS_ERROR_DOM_TYPE_ERR; - } - - if (expr) { - // if CSP is enabled, and setTimeout/setInterval was called with a string, - // disable the registration and log an error - ErrorResult error; - *aAllowEval = CheckCSPForEval(cx, aWindow, error); - if (error.Failed() || !*aAllowEval) { - return error.StealNSResult(); - } - - MOZ_ASSERT(mExpr.IsEmpty()); - AssignJSFlatString(mExpr, expr); - - // Get the calling location. - nsJSUtils::GetCallingLocation(cx, mFileName, &mLineNo); - } else if (funobj) { - *aAllowEval = true; - - mozilla::HoldJSObjects(this); - - mFunction = new Function(funobj, GetIncumbentGlobal()); - - // Create our arg array. argc is the number of arguments passed - // to setTimeout or setInterval; the first two are our callback - // and the delay, so only arguments after that need to go in our - // array. - // std::max(argc - 2, 0) wouldn't work right because argc is unsigned. - uint32_t argCount = std::max(argc, 2u) - 2; - - FallibleTArray<JS::Heap<JS::Value> > args; - if (!args.SetCapacity(argCount, fallible)) { - // No need to drop here, since we already have a non-null mFunction - return NS_ERROR_OUT_OF_MEMORY; - } - for (uint32_t idx = 0; idx < argCount; ++idx) { - *args.AppendElement(fallible) = argv[idx + 2]; - } - args.SwapElements(mArgs); - } else { - NS_WARNING("No func and no expr - why are we here?"); - } - *aInterval = interval; - return NS_OK; -} - const char16_t * nsJSScriptTimeoutHandler::GetHandlerText() { NS_ASSERTION(!mFunction, "No expression, so no handler text!"); return mExpr.get(); } -nsresult NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow, - bool *aIsInterval, - int32_t *aInterval, - nsIScriptTimeoutHandler **aRet) -{ - *aRet = nullptr; - nsRefPtr<nsJSScriptTimeoutHandler> handler = new nsJSScriptTimeoutHandler(); - bool allowEval; - nsresult rv = handler->Init(aWindow, aIsInterval, aInterval, &allowEval); - if (NS_FAILED(rv) || !allowEval) { - return rv; - } - - handler.forget(aRet); - - return NS_OK; -} - already_AddRefed<nsIScriptTimeoutHandler> NS_CreateJSTimeoutHandler(nsGlobalWindow *aWindow, Function& aFunction, const Sequence<JS::Value>& aArguments, ErrorResult& aError) { FallibleTArray<JS::Heap<JS::Value> > args; if (!args.AppendElements(aArguments, fallible)) { aError.Throw(NS_ERROR_OUT_OF_MEMORY);
--- a/dom/base/nsXMLHttpRequest.cpp +++ b/dom/base/nsXMLHttpRequest.cpp @@ -673,38 +673,45 @@ nsXMLHttpRequest::AppendToResponseText(c { NS_ENSURE_STATE(mDecoder); int32_t destBufferLen; nsresult rv = mDecoder->GetMaxLength(aSrcBuffer, aSrcBufferLen, &destBufferLen); NS_ENSURE_SUCCESS(rv, rv); - if (!mResponseText.SetCapacity(mResponseText.Length() + destBufferLen, fallible)) { + uint32_t size = mResponseText.Length() + destBufferLen; + if (size < (uint32_t)destBufferLen) { + return NS_ERROR_OUT_OF_MEMORY; + } + + if (!mResponseText.SetCapacity(size, fallible)) { return NS_ERROR_OUT_OF_MEMORY; } char16_t* destBuffer = mResponseText.BeginWriting() + mResponseText.Length(); - int32_t totalChars = mResponseText.Length(); + CheckedInt32 totalChars = mResponseText.Length(); // This code here is basically a copy of a similar thing in // nsScanner::Append(const char* aBuffer, uint32_t aLen). int32_t srclen = (int32_t)aSrcBufferLen; int32_t destlen = (int32_t)destBufferLen; rv = mDecoder->Convert(aSrcBuffer, &srclen, destBuffer, &destlen); MOZ_ASSERT(NS_SUCCEEDED(rv)); totalChars += destlen; - - mResponseText.SetLength(totalChars); - + if (!totalChars.isValid()) { + return NS_ERROR_OUT_OF_MEMORY; + } + + mResponseText.SetLength(totalChars.value()); return NS_OK; } /* readonly attribute AString responseText; */ NS_IMETHODIMP nsXMLHttpRequest::GetResponseText(nsAString& aResponseText) { ErrorResult rv;
--- a/dom/indexedDB/IDBFactory.cpp +++ b/dom/indexedDB/IDBFactory.cpp @@ -751,16 +751,21 @@ IDBFactory::OpenInternal(nsIPrincipal* a MOZ_ASSERT(scriptOwner); request = IDBOpenDBRequest::CreateForWindow(this, mWindow, scriptOwner); } else { autoJS.Init(mOwningObject.get()); JS::Rooted<JSObject*> scriptOwner(autoJS.cx(), mOwningObject); request = IDBOpenDBRequest::CreateForJS(this, scriptOwner); + if (!request) { + MOZ_ASSERT(!NS_IsMainThread()); + aRv.ThrowUncatchableException(); + return nullptr; + } } MOZ_ASSERT(request); if (aDeleting) { IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: " "indexedDB.deleteDatabase(\"%s\")", "IndexedDB %s: C R[%llu]: IDBFactory.deleteDatabase()",
--- a/dom/indexedDB/IDBRequest.cpp +++ b/dom/indexedDB/IDBRequest.cpp @@ -437,35 +437,56 @@ IDBRequest::PreHandleEvent(EventChainPre aVisitor.mParentTarget = mTransaction; return NS_OK; } class IDBOpenDBRequest::WorkerFeature final : public mozilla::dom::workers::WorkerFeature { WorkerPrivate* mWorkerPrivate; +#ifdef DEBUG + // This is only here so that assertions work in the destructor even if + // NoteAddFeatureFailed was called. + WorkerPrivate* mWorkerPrivateDEBUG; +#endif public: explicit WorkerFeature(WorkerPrivate* aWorkerPrivate) : mWorkerPrivate(aWorkerPrivate) +#ifdef DEBUG + , mWorkerPrivateDEBUG(aWorkerPrivate) +#endif { MOZ_ASSERT(aWorkerPrivate); aWorkerPrivate->AssertIsOnWorkerThread(); MOZ_COUNT_CTOR(IDBOpenDBRequest::WorkerFeature); } ~WorkerFeature() { - mWorkerPrivate->AssertIsOnWorkerThread(); +#ifdef DEBUG + mWorkerPrivateDEBUG->AssertIsOnWorkerThread(); +#endif MOZ_COUNT_DTOR(IDBOpenDBRequest::WorkerFeature); - mWorkerPrivate->RemoveFeature(mWorkerPrivate->GetJSContext(), this); + if (mWorkerPrivate) { + mWorkerPrivate->RemoveFeature(mWorkerPrivate->GetJSContext(), this); + } + } + + void + NoteAddFeatureFailed() + { + MOZ_ASSERT(mWorkerPrivate); + mWorkerPrivate->AssertIsOnWorkerThread(); + + mWorkerPrivate = nullptr; } private: virtual bool Notify(JSContext* aCx, Status aStatus) override; }; IDBOpenDBRequest::IDBOpenDBRequest(IDBFactory* aFactory, nsPIDOMWindow* aOwner) @@ -522,16 +543,17 @@ IDBOpenDBRequest::CreateForJS(IDBFactory workerPrivate->AssertIsOnWorkerThread(); JSContext* cx = workerPrivate->GetJSContext(); MOZ_ASSERT(cx); nsAutoPtr<WorkerFeature> feature(new WorkerFeature(workerPrivate)); if (NS_WARN_IF(!workerPrivate->AddFeature(cx, feature))) { + feature->NoteAddFeatureFailed(); return nullptr; } request->mWorkerFeature = Move(feature); } return request.forget(); }
--- a/dom/interfaces/base/nsIDOMJSWindow.idl +++ b/dom/interfaces/base/nsIDOMJSWindow.idl @@ -1,30 +1,21 @@ /* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* 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 "domstubs.idl" -[scriptable, uuid(4237c376-d637-4b6e-9f8a-1da57e867834)] +[scriptable, uuid(e0f739e3-47e2-4007-af30-181939e97a51)] interface nsIDOMJSWindow : nsISupports { void dump(in DOMString str); /** - * These methods take typeless arguments and optional arguments, the - * first argument is either a function or a string, the second - * argument must be a number (ms) and the rest of the arguments (2 - * ... n) are passed to the callback function - */ - long setTimeout(); - long setInterval(); - - /** * These methods take one optional argument that's the timer ID to * clear. Often in existing code these methods are passed undefined, * which is a nop so we need to support that as well. */ void clearTimeout([optional] in long handle); void clearInterval([optional] in long handle); /**
--- a/dom/media/CubebUtils.cpp +++ b/dom/media/CubebUtils.cpp @@ -99,23 +99,22 @@ void InitPreferredSampleRate() // Query failed, use a sensible default. sPreferredSampleRate = 44100; } } cubeb* GetCubebContextUnlocked() { sMutex.AssertCurrentThreadOwns(); - if (!sCubebContext) { - MOZ_ASSERT(NS_IsMainThread()); - if (cubeb_init(&sCubebContext, "CubebUtils") != CUBEB_OK) { - NS_WARNING("cubeb_init failed"); - } + if (sCubebContext || + cubeb_init(&sCubebContext, "CubebUtils") == CUBEB_OK) { + return sCubebContext; } - return sCubebContext; + NS_WARNING("cubeb_init failed"); + return nullptr; } uint32_t GetCubebLatency() { StaticMutexAutoLock lock(sMutex); return sCubebLatency; }
--- a/dom/media/MediaDecoder.cpp +++ b/dom/media/MediaDecoder.cpp @@ -5,17 +5,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "MediaDecoder.h" #include "mozilla/FloatingPoint.h" #include "mozilla/MathAlgorithms.h" #include <limits> #include "nsIObserver.h" #include "nsTArray.h" -#include "CubebUtils.h" #include "VideoUtils.h" #include "MediaDecoderStateMachine.h" #include "ImageContainer.h" #include "MediaResource.h" #include "nsError.h" #include "mozilla/Preferences.h" #include "mozilla/StaticPtr.h" #include "nsIMemoryReporter.h" @@ -397,21 +396,16 @@ MediaDecoder::MediaDecoder() : } bool MediaDecoder::Init(MediaDecoderOwner* aOwner) { MOZ_ASSERT(NS_IsMainThread()); mOwner = aOwner; mVideoFrameContainer = aOwner->GetVideoFrameContainer(); MediaShutdownManager::Instance().Register(this); - // We don't use the cubeb context yet, but need to ensure it is created on - // the main thread. - if (!CubebUtils::GetCubebContext()) { - NS_WARNING("Audio backend initialization failed."); - } return true; } void MediaDecoder::Shutdown() { MOZ_ASSERT(NS_IsMainThread()); if (mShuttingDown)
--- a/dom/media/MediaInfo.h +++ b/dom/media/MediaInfo.h @@ -281,16 +281,21 @@ public: nsRefPtr<MediaByteBuffer> mCodecSpecificConfig; nsRefPtr<MediaByteBuffer> mExtraData; }; class EncryptionInfo { public: + EncryptionInfo() + : mEncrypted(false) + { + } + struct InitData { template<typename AInitDatas> InitData(const nsAString& aType, AInitDatas&& aInitData) : mType(aType) , mInitData(Forward<AInitDatas>(aInitData)) { } @@ -300,32 +305,36 @@ public: // Encryption data. nsTArray<uint8_t> mInitData; }; typedef nsTArray<InitData> InitDatas; // True if the stream has encryption metadata bool IsEncrypted() const { - return !mInitDatas.IsEmpty(); + return mEncrypted; } template<typename AInitDatas> void AddInitData(const nsAString& aType, AInitDatas&& aInitData) { mInitDatas.AppendElement(InitData(aType, Forward<AInitDatas>(aInitData))); + mEncrypted = true; } void AddInitData(const EncryptionInfo& aInfo) { mInitDatas.AppendElements(aInfo.mInitDatas); + mEncrypted = !!mInitDatas.Length(); } // One 'InitData' per encrypted buffer. InitDatas mInitDatas; +private: + bool mEncrypted; }; class MediaInfo { public: bool HasVideo() const { return mVideo.IsValid(); }
--- a/dom/media/gmp/GMPParent.cpp +++ b/dom/media/gmp/GMPParent.cpp @@ -26,16 +26,17 @@ #endif #include "GMPContentParent.h" #include "mozilla/dom/CrashReporterParent.h" using mozilla::dom::CrashReporterParent; using mozilla::ipc::GeckoChildProcessHost; #ifdef MOZ_CRASHREPORTER +#include "nsPrintfCString.h" using CrashReporter::AnnotationTable; using CrashReporter::GetIDFromMinidump; #endif #include "mozilla/Telemetry.h" namespace mozilla { @@ -191,16 +192,21 @@ GMPParent::LoadProcess() return NS_OK; } void AbortWaitingForGMPAsyncShutdown(nsITimer* aTimer, void* aClosure) { NS_WARNING("Timed out waiting for GMP async shutdown!"); GMPParent* parent = reinterpret_cast<GMPParent*>(aClosure); +#if defined(MOZ_CRASHREPORTER) + CrashReporter::AnnotateCrashReport( + nsPrintfCString("AsyncPluginShutdown-%s@%p", parent->GetDisplayName().get(), parent), + NS_LITERAL_CSTRING("Timed out waiting for async shutdown")); +#endif nsRefPtr<GeckoMediaPluginServiceParent> service = GeckoMediaPluginServiceParent::GetSingleton(); if (service) { service->AsyncShutdownComplete(parent); } } nsresult @@ -234,18 +240,30 @@ GMPParent::EnsureAsyncShutdownTimeoutSet nsITimer::TYPE_ONE_SHOT); } bool GMPParent::RecvPGMPContentChildDestroyed() { --mGMPContentChildCount; if (!IsUsed()) { +#if defined(MOZ_CRASHREPORTER) + CrashReporter::AnnotateCrashReport( + nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this), + NS_LITERAL_CSTRING("Content children destroyed")); +#endif CloseIfUnused(); } +#if defined(MOZ_CRASHREPORTER) + else { + CrashReporter::AnnotateCrashReport( + nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this), + nsPrintfCString("Content child destroyed, remaining: %u", mGMPContentChildCount)); + } +#endif return true; } void GMPParent::CloseIfUnused() { MOZ_ASSERT(GMPThread() == NS_GetCurrentThread()); LOGD("%s: mAsyncShutdownRequired=%d", __FUNCTION__, mAsyncShutdownRequired); @@ -257,19 +275,29 @@ GMPParent::CloseIfUnused() // Ensure all timers are killed. for (uint32_t i = mTimers.Length(); i > 0; i--) { mTimers[i - 1]->Shutdown(); } if (mAsyncShutdownRequired) { if (!mAsyncShutdownInProgress) { LOGD("%s: sending async shutdown notification", __FUNCTION__); +#if defined(MOZ_CRASHREPORTER) + CrashReporter::AnnotateCrashReport( + nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this), + NS_LITERAL_CSTRING("Sent BeginAsyncShutdown")); +#endif mAsyncShutdownInProgress = true; if (!SendBeginAsyncShutdown() || NS_FAILED(EnsureAsyncShutdownTimeoutSet())) { +#if defined(MOZ_CRASHREPORTER) + CrashReporter::AnnotateCrashReport( + nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this), + NS_LITERAL_CSTRING("Could not send BeginAsyncShutdown - Aborting")); +#endif AbortAsyncShutdown(); } } } else { // Any async shutdown must be complete. Shutdown GMPStorage. for (size_t i = mStorage.Length(); i > 0; i--) { mStorage[i - 1]->Shutdown(); } @@ -308,16 +336,21 @@ GMPParent::CloseActive(bool aDieWhenUnlo if (aDieWhenUnloaded) { mDeleteProcessOnlyOnUnload = true; // don't allow this to go back... } if (mState == GMPStateLoaded) { mState = GMPStateUnloading; } if (mState != GMPStateNotLoaded && IsUsed()) { +#if defined(MOZ_CRASHREPORTER) + CrashReporter::AnnotateCrashReport( + nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this), + nsPrintfCString("Sent CloseActive, content children to close: %u", mGMPContentChildCount)); +#endif unused << SendCloseActive(); } } void GMPParent::MarkForDeletion() { mDeleteProcessOnlyOnUnload = true; @@ -563,16 +596,21 @@ GMPParent::ActorDestroy(ActorDestroyReas mState = GMPStateClosing; mAbnormalShutdownInProgress = true; CloseActive(false); // Normal Shutdown() will delete the process on unwind. if (AbnormalShutdown == aWhy) { nsRefPtr<GMPParent> self(this); if (mAsyncShutdownRequired) { +#if defined(MOZ_CRASHREPORTER) + CrashReporter::AnnotateCrashReport( + nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this), + NS_LITERAL_CSTRING("Actor destroyed")); +#endif mService->AsyncShutdownComplete(this); mAsyncShutdownRequired = false; } // Must not call Close() again in DeleteProcess(), as we'll recurse // infinitely if we do. MOZ_ASSERT(mState == GMPStateClosing); DeleteProcess(); // Note: final destruction will be Dispatched to ourself @@ -865,16 +903,21 @@ GMPParent::RecvAsyncShutdownRequired() } bool GMPParent::RecvAsyncShutdownComplete() { LOGD("%s", __FUNCTION__); MOZ_ASSERT(mAsyncShutdownRequired); +#if defined(MOZ_CRASHREPORTER) + CrashReporter::AnnotateCrashReport( + nsPrintfCString("AsyncPluginShutdown-%s@%p", GetDisplayName().get(), this), + NS_LITERAL_CSTRING("Received AsyncShutdownComplete")); +#endif AbortAsyncShutdown(); return true; } class RunCreateContentParentCallbacks : public nsRunnable { public: explicit RunCreateContentParentCallbacks(GMPContentParent* aGMPContentParent)
--- a/dom/media/mediasource/SourceBuffer.cpp +++ b/dom/media/mediasource/SourceBuffer.cpp @@ -311,17 +311,17 @@ SourceBuffer::SourceBuffer(MediaSource* , mActive(false) , mUpdateID(0) , mReportedOffset(0) , mType(aType) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aMediaSource); mEvictionThreshold = Preferences::GetUint("media.mediasource.eviction_threshold", - 75 * (1 << 20)); + 100 * (1 << 20)); mContentManager = SourceBufferContentManager::CreateManager(this, aMediaSource->GetDecoder(), aType); MSE_DEBUG("Create mContentManager=%p", mContentManager.get()); if (aType.LowerCaseEqualsLiteral("audio/mpeg") || aType.LowerCaseEqualsLiteral("audio/aac")) { @@ -576,30 +576,29 @@ SourceBuffer::PrepareAppend(const uint8_ // We notify that we've evicted from the time range 0 through to // the current start point. mMediaSource->NotifyEvicted(0.0, newBufferStartTime.ToSeconds()); } // See if we have enough free space to append our new data. // As we can only evict once we have playable data, we must give a chance // to the DASH player to provide a complete media segment. - if (aLength > mEvictionThreshold || + if (aLength > mEvictionThreshold || evicted == Result::BUFFER_FULL || ((!mIsUsingFormatReader && mContentManager->GetSize() > mEvictionThreshold - aLength) && evicted != Result::CANT_EVICT)) { aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR); return nullptr; } nsRefPtr<MediaByteBuffer> data = new MediaByteBuffer(); if (!data->AppendElements(aData, aLength, fallible)) { aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR); return nullptr; } - // TODO: Test buffer full flag. return data.forget(); } double SourceBuffer::GetBufferedStart() { MOZ_ASSERT(NS_IsMainThread()); ErrorResult dummy;
--- a/dom/media/mediasource/SourceBufferContentManager.h +++ b/dom/media/mediasource/SourceBufferContentManager.h @@ -52,16 +52,17 @@ public: // http://w3c.github.io/media-source/#sourcebuffer-coded-frame-removal virtual nsRefPtr<RangeRemovalPromise> RangeRemoval(TimeUnit aStart, TimeUnit aEnd) = 0; enum class EvictDataResult : int8_t { NO_DATA_EVICTED, DATA_EVICTED, CANT_EVICT, + BUFFER_FULL, }; // Evicts data up to aPlaybackTime. aThreshold is used to // bound the data being evicted. It will not evict more than aThreshold // bytes. aBufferStartTime contains the new start time of the data after the // eviction. virtual EvictDataResult EvictData(TimeUnit aPlaybackTime, uint32_t aThreshold, TimeUnit* aBufferStartTime) = 0;
--- a/dom/media/mediasource/TrackBuffersManager.cpp +++ b/dom/media/mediasource/TrackBuffersManager.cpp @@ -34,32 +34,63 @@ AppendStateToStr(TrackBuffersManager::Ap return "PARSING_MEDIA_SEGMENT"; default: return "IMPOSSIBLE"; } } static Atomic<uint32_t> sStreamSourceID(0u); +#ifdef MOZ_EME +class DispatchKeyNeededEvent : public nsRunnable { +public: + DispatchKeyNeededEvent(AbstractMediaDecoder* aDecoder, + nsTArray<uint8_t>& aInitData, + const nsString& aInitDataType) + : mDecoder(aDecoder) + , mInitData(aInitData) + , mInitDataType(aInitDataType) + { + } + NS_IMETHOD Run() { + // Note: Null check the owner, as the decoder could have been shutdown + // since this event was dispatched. + MediaDecoderOwner* owner = mDecoder->GetOwner(); + if (owner) { + owner->DispatchEncrypted(mInitData, mInitDataType); + } + mDecoder = nullptr; + return NS_OK; + } +private: + nsRefPtr<AbstractMediaDecoder> mDecoder; + nsTArray<uint8_t> mInitData; + nsString mInitDataType; +}; +#endif // MOZ_EME + TrackBuffersManager::TrackBuffersManager(dom::SourceBuffer* aParent, MediaSourceDecoder* aParentDecoder, const nsACString& aType) : mInputBuffer(new MediaByteBuffer) , mAppendState(AppendState::WAITING_FOR_SEGMENT) , mBufferFull(false) , mFirstInitializationSegmentReceived(false) , mActiveTrack(false) , mType(aType) , mParser(ContainerParser::CreateForMIMEType(aType)) , mProcessedInput(0) , mAppendRunning(false) , mTaskQueue(aParentDecoder->GetDemuxer()->GetTaskQueue()) , mParent(new nsMainThreadPtrHolder<dom::SourceBuffer>(aParent, false /* strict */)) , mParentDecoder(new nsMainThreadPtrHolder<MediaSourceDecoder>(aParentDecoder, false /* strict */)) , mMediaSourceDemuxer(mParentDecoder->GetDemuxer()) , mMediaSourceDuration(mTaskQueue, Maybe<double>(), "TrackBuffersManager::mMediaSourceDuration (Mirror)") , mAbort(false) + , mEvictionThreshold(Preferences::GetUint("media.mediasource.eviction_threshold", + 100 * (1 << 20))) + , mEvictionOccurred(false) , mMonitor("TrackBuffersManager") { MOZ_ASSERT(NS_IsMainThread(), "Must be instanciated on the main thread"); nsRefPtr<TrackBuffersManager> self = this; nsCOMPtr<nsIRunnable> task = NS_NewRunnableFunction([self] () { self->mMediaSourceDuration.Connect(self->mParentDecoder->CanonicalExplicitDuration()); }); @@ -171,16 +202,21 @@ TrackBuffersManager::EvictData(TimeUnit int64_t toEvict = GetSize() - aThreshold; if (toEvict <= 0) { return EvictDataResult::NO_DATA_EVICTED; } if (toEvict <= 512*1024) { // Don't bother evicting less than 512KB. return EvictDataResult::CANT_EVICT; } + + if (mBufferFull && mEvictionOccurred) { + return EvictDataResult::BUFFER_FULL; + } + MSE_DEBUG("Reaching our size limit, schedule eviction of %lld bytes", toEvict); nsCOMPtr<nsIRunnable> task = NS_NewRunnableMethodWithArgs<TimeUnit, uint32_t>( this, &TrackBuffersManager::DoEvictData, aPlaybackTime, toEvict); GetTaskQueue()->Dispatch(task.forget()); @@ -340,22 +376,22 @@ TrackBuffersManager::CompleteResetParser } void TrackBuffersManager::DoEvictData(const TimeUnit& aPlaybackTime, uint32_t aSizeToEvict) { MOZ_ASSERT(OnTaskQueue()); - // Remove any data we've already played, up to 5s behind. - TimeUnit lowerLimit = aPlaybackTime - TimeUnit::FromSeconds(5); - TimeUnit to; // Video is what takes the most space, only evict there if we have video. const auto& track = HasVideo() ? mVideoTracks : mAudioTracks; const auto& buffer = track.mBuffers.LastElement(); + // Remove any data we've already played, or before the next sample to be + // demuxed whichever is lowest. + TimeUnit lowerLimit = std::min(track.mNextSampleTime, aPlaybackTime); uint32_t lastKeyFrameIndex = 0; int64_t toEvict = aSizeToEvict; uint32_t partialEvict = 0; for (uint32_t i = 0; i < buffer.Length(); i++) { const auto& frame = buffer[i]; if (frame->mKeyframe) { lastKeyFrameIndex = i; toEvict -= partialEvict; @@ -364,46 +400,59 @@ TrackBuffersManager::DoEvictData(const T } partialEvict = 0; } if (frame->mTime >= lowerLimit.ToMicroseconds()) { break; } partialEvict += sizeof(*frame) + frame->mSize; } + + int64_t finalSize = mSizeSourceBuffer - aSizeToEvict; + if (lastKeyFrameIndex > 0) { + MSE_DEBUG("Step1. Evicting %u bytes prior currentTime", + aSizeToEvict - toEvict); CodedFrameRemoval( TimeInterval(TimeUnit::FromMicroseconds(0), - TimeUnit::FromMicroseconds(buffer[lastKeyFrameIndex-1]->mTime))); + TimeUnit::FromMicroseconds(buffer[lastKeyFrameIndex]->mTime - 1))); } - if (toEvict <= 0) { + + if (mSizeSourceBuffer <= finalSize) { return; } - // Still some to remove. Remove data starting from the end, up to 5s ahead - // of our playtime. - TimeUnit upperLimit = aPlaybackTime + TimeUnit::FromSeconds(5); + toEvict = mSizeSourceBuffer - finalSize; + + // Still some to remove. Remove data starting from the end, up to 30s ahead + // of the later of the playback time or the next sample to be demuxed. + // 30s is a value chosen as it appears to work with YouTube. + TimeUnit upperLimit = + std::max(aPlaybackTime, track.mNextSampleTime) + TimeUnit::FromSeconds(30); + lastKeyFrameIndex = buffer.Length(); for (int32_t i = buffer.Length() - 1; i >= 0; i--) { const auto& frame = buffer[i]; if (frame->mKeyframe) { lastKeyFrameIndex = i; toEvict -= partialEvict; if (toEvict < 0) { break; } partialEvict = 0; } if (frame->mTime <= upperLimit.ToMicroseconds()) { break; } partialEvict += sizeof(*frame) + frame->mSize; } - if (lastKeyFrameIndex + 1 < buffer.Length()) { + if (lastKeyFrameIndex < buffer.Length()) { + MSE_DEBUG("Step2. Evicting %u bytes from trailing data", + mSizeSourceBuffer - finalSize); CodedFrameRemoval( - TimeInterval(TimeUnit::FromMicroseconds(buffer[lastKeyFrameIndex+1]->mTime), + TimeInterval(TimeUnit::FromMicroseconds(buffer[lastKeyFrameIndex]->GetEndTime() + 1), TimeUnit::FromInfinity())); } } nsRefPtr<TrackBuffersManager::RangeRemovalPromise> TrackBuffersManager::CodedFrameRemovalWithPromise(TimeInterval aInterval) { MOZ_ASSERT(OnTaskQueue()); @@ -554,19 +603,17 @@ TrackBuffersManager::CodedFrameRemoval(T // 5. If this object is in activeSourceBuffers, the current playback position // is greater than or equal to start and less than the remove end timestamp, // and HTMLMediaElement.readyState is greater than HAVE_METADATA, then set the // HTMLMediaElement.readyState attribute to HAVE_METADATA and stall playback. // This will be done by the MDSM during playback. // TODO properly, so it works even if paused. } - // 4. If buffer full flag equals true and this object is ready to accept more bytes, then set the buffer full flag to false. - // TODO. - mBufferFull = false; + { MonitorAutoLock mon(mMonitor); mVideoBufferedRanges = mVideoTracks.mBufferedRanges; mAudioBufferedRanges = mAudioTracks.mBufferedRanges; } if (HasVideo()) { MSE_DEBUG("after video ranges=%s", @@ -575,16 +622,22 @@ TrackBuffersManager::CodedFrameRemoval(T if (HasAudio()) { MSE_DEBUG("after audio ranges=%s", DumpTimeRanges(mAudioTracks.mBufferedRanges).get()); } // Update our reported total size. mSizeSourceBuffer = mVideoTracks.mSizeBuffer + mAudioTracks.mSizeBuffer; + // 4. If buffer full flag equals true and this object is ready to accept more bytes, then set the buffer full flag to false. + if (mBufferFull && mSizeSourceBuffer < mEvictionThreshold) { + mBufferFull = false; + } + mEvictionOccurred = true; + // Tell our demuxer that data was removed. mMediaSourceDemuxer->NotifyTimeRangesChanged(); return dataRemoved; } nsRefPtr<TrackBuffersManager::AppendPromise> TrackBuffersManager::InitSegmentParserLoop() @@ -948,27 +1001,29 @@ TrackBuffersManager::OnDemuxerInitDone(n // 6. Set first initialization segment received flag to true. mFirstInitializationSegmentReceived = true; } else { mAudioTracks.mLastInfo = new SharedTrackInfo(info.mAudio, streamID); mVideoTracks.mLastInfo = new SharedTrackInfo(info.mVideo, streamID); } - // TODO CHECK ENCRYPTION UniquePtr<EncryptionInfo> crypto = mInputDemuxer->GetCrypto(); if (crypto && crypto->IsEncrypted()) { #ifdef MOZ_EME // Try and dispatch 'encrypted'. Won't go if ready state still HAVE_NOTHING. for (uint32_t i = 0; i < crypto->mInitDatas.Length(); i++) { -// NS_DispatchToMainThread( -// new DispatchKeyNeededEvent(mParentDecoder, crypto->mInitDatas[i].mInitData, NS_LITERAL_STRING("cenc"))); + NS_DispatchToMainThread( + new DispatchKeyNeededEvent(mParentDecoder, crypto->mInitDatas[i].mInitData, NS_LITERAL_STRING("cenc"))); } #endif // MOZ_EME info.mCrypto = *crypto; + // We clear our crypto init data array, so the MediaFormatReader will + // not emit an encrypted event for the same init data again. + info.mCrypto.mInitDatas.Clear(); mEncrypted = true; } { MonitorAutoLock mon(mMonitor); mInfo = info; } @@ -1175,18 +1230,20 @@ TrackBuffersManager::CompleteCodedFrameP } } // Update our reported total size. mSizeSourceBuffer = mVideoTracks.mSizeBuffer + mAudioTracks.mSizeBuffer; // Return to step 6.4 of Segment Parser Loop algorithm // 4. If this SourceBuffer is full and cannot accept more media data, then set the buffer full flag to true. - // TODO - mBufferFull = false; + if (mSizeSourceBuffer >= mEvictionThreshold) { + mBufferFull = true; + mEvictionOccurred = false; + } // 5. If the input buffer does not contain a complete media segment, then jump to the need more data step below. if (mParser->MediaSegmentRange().IsNull()) { ResolveProcessing(true, __func__); return; } // 6. Remove the media segment bytes from the beginning of the input buffer. @@ -1355,88 +1412,94 @@ TrackBuffersManager::ProcessFrame(MediaR // Remove all coded frames from track buffer that have a presentation timestamp greater than or equal to highest end timestamp and less than frame end timestamp // There is an ambiguity on how to remove frames, which was lodged with: // https://www.w3.org/Bugs/Public/show_bug.cgi?id=28710, implementing as per // bug description. Maybe<uint32_t> firstRemovedIndex; TimeInterval removedInterval; TrackBuffer& data = trackBuffer.mBuffers.LastElement(); - if (trackBuffer.mBufferedRanges.ContainsStrict(presentationTimestamp)) { + bool removeCodedFrames = + trackBuffer.mHighestEndTimestamp.isSome() + ? trackBuffer.mHighestEndTimestamp.ref() <= presentationTimestamp + : true; + if (removeCodedFrames) { TimeUnit lowerBound = trackBuffer.mHighestEndTimestamp.valueOr(presentationTimestamp); - for (uint32_t i = 0; i < data.Length();) { - MediaRawData* sample = data[i].get(); - if (sample->mTime >= lowerBound.ToMicroseconds() && - sample->mTime < frameEndTimestamp.ToMicroseconds()) { - if (firstRemovedIndex.isNothing()) { - removedInterval = - TimeInterval(TimeUnit::FromMicroseconds(sample->mTime), - TimeUnit::FromMicroseconds(sample->GetEndTime())); - firstRemovedIndex = Some(i); + if (trackBuffer.mBufferedRanges.ContainsStrict(lowerBound)) { + for (uint32_t i = 0; i < data.Length();) { + MediaRawData* sample = data[i].get(); + if (sample->mTime >= lowerBound.ToMicroseconds() && + sample->mTime < frameEndTimestamp.ToMicroseconds()) { + if (firstRemovedIndex.isNothing()) { + removedInterval = + TimeInterval(TimeUnit::FromMicroseconds(sample->mTime), + TimeUnit::FromMicroseconds(sample->GetEndTime())); + firstRemovedIndex = Some(i); + } else { + removedInterval = removedInterval.Span( + TimeInterval(TimeUnit::FromMicroseconds(sample->mTime), + TimeUnit::FromMicroseconds(sample->GetEndTime()))); + } + trackBuffer.mSizeBuffer -= sizeof(*sample) + sample->mSize; + MSE_DEBUGV("Overlapping frame:%u ([%f, %f))", + i, + TimeUnit::FromMicroseconds(sample->mTime).ToSeconds(), + TimeUnit::FromMicroseconds(sample->GetEndTime()).ToSeconds()); + data.RemoveElementAt(i); + + if (trackBuffer.mNextGetSampleIndex.isSome()) { + if (trackBuffer.mNextGetSampleIndex.ref() == i) { + MSE_DEBUG("Next sample to be played got evicted"); + trackBuffer.mNextGetSampleIndex.reset(); + } else if (trackBuffer.mNextGetSampleIndex.ref() > i) { + trackBuffer.mNextGetSampleIndex.ref()--; + } + } } else { - removedInterval = removedInterval.Span( - TimeInterval(TimeUnit::FromMicroseconds(sample->mTime), - TimeUnit::FromMicroseconds(sample->GetEndTime()))); + i++; } - trackBuffer.mSizeBuffer -= sizeof(*sample) + sample->mSize; - MSE_DEBUGV("Overlapping frame:%u ([%f, %f))", - i, - TimeUnit::FromMicroseconds(sample->mTime).ToSeconds(), - TimeUnit::FromMicroseconds(sample->GetEndTime()).ToSeconds()); - data.RemoveElementAt(i); - - if (trackBuffer.mNextGetSampleIndex.isSome()) { - if (trackBuffer.mNextGetSampleIndex.ref() == i) { - MSE_DEBUG("Next sample to be played got evicted"); - trackBuffer.mNextGetSampleIndex.reset(); - } else if (trackBuffer.mNextGetSampleIndex.ref() > i) { - trackBuffer.mNextGetSampleIndex.ref()--; - } - } - } else { - i++; } } - } - // 15. Remove decoding dependencies of the coded frames removed in the previous step: - // Remove all coded frames between the coded frames removed in the previous step and the next random access point after those removed frames. - if (firstRemovedIndex.isSome()) { - uint32_t start = firstRemovedIndex.ref(); - uint32_t end = start; - for (;end < data.Length(); end++) { - MediaRawData* sample = data[end].get(); - if (sample->mKeyframe) { - break; + // 15. Remove decoding dependencies of the coded frames removed in the previous step: + // Remove all coded frames between the coded frames removed in the previous step and the next random access point after those removed frames. + if (firstRemovedIndex.isSome()) { + uint32_t start = firstRemovedIndex.ref(); + uint32_t end = start; + for (;end < data.Length(); end++) { + MediaRawData* sample = data[end].get(); + if (sample->mKeyframe) { + break; + } + removedInterval = removedInterval.Span( + TimeInterval(TimeUnit::FromMicroseconds(sample->mTime), + TimeUnit::FromMicroseconds(sample->GetEndTime()))); + trackBuffer.mSizeBuffer -= sizeof(*sample) + sample->mSize; } - removedInterval = removedInterval.Span( - TimeInterval(TimeUnit::FromMicroseconds(sample->mTime), - TimeUnit::FromMicroseconds(sample->GetEndTime()))); - trackBuffer.mSizeBuffer -= sizeof(*sample) + sample->mSize; - } - data.RemoveElementsAt(start, end - start); + data.RemoveElementsAt(start, end - start); - MSE_DEBUG("Removing undecodable frames from:%u (frames:%u) ([%f, %f))", - start, end - start, - removedInterval.mStart.ToSeconds(), removedInterval.mEnd.ToSeconds()); + MSE_DEBUG("Removing undecodable frames from:%u (frames:%u) ([%f, %f))", + start, end - start, + removedInterval.mStart.ToSeconds(), removedInterval.mEnd.ToSeconds()); - if (trackBuffer.mNextGetSampleIndex.isSome()) { - if (trackBuffer.mNextGetSampleIndex.ref() >= start && - trackBuffer.mNextGetSampleIndex.ref() < end) { - MSE_DEBUG("Next sample to be played got evicted"); - trackBuffer.mNextGetSampleIndex.reset(); - } else if (trackBuffer.mNextGetSampleIndex.ref() >= end) { - trackBuffer.mNextGetSampleIndex.ref() -= end - start; + if (trackBuffer.mNextGetSampleIndex.isSome()) { + if (trackBuffer.mNextGetSampleIndex.ref() >= start && + trackBuffer.mNextGetSampleIndex.ref() < end) { + MSE_DEBUG("Next sample to be played got evicted"); + trackBuffer.mNextGetSampleIndex.reset(); + } else if (trackBuffer.mNextGetSampleIndex.ref() >= end) { + trackBuffer.mNextGetSampleIndex.ref() -= end - start; + } } + + // Update our buffered range to exclude the range just removed. + trackBuffer.mBufferedRanges -= removedInterval; + MOZ_ASSERT(trackBuffer.mNextInsertionIndex.isNothing() || + trackBuffer.mNextInsertionIndex.ref() <= start); } - - // Update our buffered range to exclude the range just removed. - trackBuffer.mBufferedRanges -= removedInterval; - MOZ_ASSERT(trackBuffer.mNextInsertionIndex.isNothing() || - trackBuffer.mNextInsertionIndex.ref() <= start); } // 16. Add the coded frame with the presentation timestamp, decode timestamp, and frame duration to the track buffer. aSample->mTime = presentationTimestamp.ToMicroseconds(); aSample->mTimecode = decodeTimestamp.ToMicroseconds(); aSample->mTrackInfo = trackBuffer.mLastInfo; if (data.IsEmpty()) { @@ -1559,21 +1622,21 @@ TrackBuffersManager::GetTracksList() return tracks; } void TrackBuffersManager::RestoreCachedVariables() { MOZ_ASSERT(OnTaskQueue()); if (mTimestampOffset != mLastTimestampOffset) { + nsRefPtr<TrackBuffersManager> self = this; nsCOMPtr<nsIRunnable> task = - NS_NewRunnableMethodWithArg<TimeUnit>( - mParent.get(), - static_cast<void (dom::SourceBuffer::*)(const TimeUnit&)>(&dom::SourceBuffer::SetTimestampOffset), /* beauty uh? :) */ - mTimestampOffset); + NS_NewRunnableFunction([self] { + self->mParent->SetTimestampOffset(self->mTimestampOffset); + }); AbstractThread::MainThread()->Dispatch(task.forget()); } } void TrackBuffersManager::SetAppendState(TrackBuffersManager::AppendState aAppendState) { MSE_DEBUG("AppendState changed from %s to %s",
--- a/dom/media/mediasource/TrackBuffersManager.h +++ b/dom/media/mediasource/TrackBuffersManager.h @@ -305,16 +305,18 @@ private: // Set to true if abort was called. Atomic<bool> mAbort; // Set to true if mediasource state changed to ended. Atomic<bool> mEnded; // Global size of this source buffer content. Atomic<int64_t> mSizeSourceBuffer; + uint32_t mEvictionThreshold; + Atomic<bool> mEvictionOccurred; // Monitor to protect following objects accessed across multipple threads. mutable Monitor mMonitor; // Stable audio and video track time ranges. TimeIntervals mVideoBufferedRanges; TimeIntervals mAudioBufferedRanges; // MediaInfo of the first init segment read. MediaInfo mInfo;
--- a/dom/media/webaudio/AudioContext.cpp +++ b/dom/media/webaudio/AudioContext.cpp @@ -105,21 +105,16 @@ AudioContext::AudioContext(nsPIDOMWindow // bound to the window. mDestination = new AudioDestinationNode(this, aIsOffline, aChannel, aNumberOfChannels, aLength, aSampleRate); // We skip calling SetIsOnlyNodeForContext and the creation of the // audioChannelAgent during mDestination's constructor, because we can only // call them after mDestination has been set up. mDestination->CreateAudioChannelAgent(); mDestination->SetIsOnlyNodeForContext(true); - // We don't use the cubeb context yet, but need to ensure it is created on - // the main thread. - if (!aIsOffline && !CubebUtils::GetCubebContext()) { - NS_WARNING("Audio backend initialization failed."); - } } AudioContext::~AudioContext() { nsPIDOMWindow* window = GetOwner(); if (window) { window->RemoveAudioContext(this); }
--- a/dom/storage/DOMStorageCache.cpp +++ b/dom/storage/DOMStorageCache.cpp @@ -766,18 +766,21 @@ DOMStorageCache::StartDatabase() nsresult rv = db->Init(); if (NS_FAILED(rv)) { return nullptr; } sDatabase = db.forget(); } else { + // Use DOMLocalStorageManager::Ensure in case we're called from + // DOMSessionStorageManager's initializer and we haven't yet initialized the + // local storage manager. nsRefPtr<DOMStorageDBChild> db = new DOMStorageDBChild( - DOMLocalStorageManager::Self()); + DOMLocalStorageManager::Ensure()); nsresult rv = db->Init(); if (NS_FAILED(rv)) { return nullptr; } db.forget(&sDatabase); }
--- a/dom/storage/DOMStorageManager.cpp +++ b/dom/storage/DOMStorageManager.cpp @@ -623,16 +623,31 @@ DOMLocalStorageManager::DOMLocalStorageM } } DOMLocalStorageManager::~DOMLocalStorageManager() { sSelf = nullptr; } +DOMLocalStorageManager* +DOMLocalStorageManager::Ensure() +{ + if (sSelf) { + return sSelf; + } + + // Cause sSelf to be populated. + nsCOMPtr<nsIDOMStorageManager> initializer = + do_GetService("@mozilla.org/dom/localStorage-manager;1"); + MOZ_ASSERT(sSelf, "Didn't initialize?"); + + return sSelf; +} + // DOMSessionStorageManager DOMSessionStorageManager::DOMSessionStorageManager() : DOMStorageManager(SessionStorage) { if (XRE_GetProcessType() != GeckoProcessType_Default) { // Do this only on the child process. The thread IPC bridge // is also used to communicate chrome observer notifications.
--- a/dom/storage/DOMStorageManager.h +++ b/dom/storage/DOMStorageManager.h @@ -121,16 +121,19 @@ class DOMLocalStorageManager final : pub { public: DOMLocalStorageManager(); virtual ~DOMLocalStorageManager(); // Global getter of localStorage manager service static DOMLocalStorageManager* Self() { return sSelf; } + // Like Self, but creates an instance if we're not yet initialized. + static DOMLocalStorageManager* Ensure(); + private: static DOMLocalStorageManager* sSelf; }; class DOMSessionStorageManager final : public DOMStorageManager { public: DOMSessionStorageManager();
--- a/dom/workers/ServiceWorkerManager.cpp +++ b/dom/workers/ServiceWorkerManager.cpp @@ -374,51 +374,49 @@ NS_INTERFACE_MAP_BEGIN(ServiceWorkerMana NS_INTERFACE_MAP_ENTRY(nsIServiceWorkerManager) NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback) NS_INTERFACE_MAP_ENTRY(nsIObserver) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIServiceWorkerManager) NS_INTERFACE_MAP_END ServiceWorkerManager::ServiceWorkerManager() : mActor(nullptr) + , mShuttingDown(false) { // Register this component to PBackground. MOZ_ALWAYS_TRUE(BackgroundChild::GetOrCreateForCurrentThread(this)); } ServiceWorkerManager::~ServiceWorkerManager() { // The map will assert if it is not empty when destroyed. mRegistrationInfos.Clear(); - - if (mActor) { - mActor->ManagerShuttingDown(); - - nsRefPtr<TeardownRunnable> runnable = new TeardownRunnable(mActor); - nsresult rv = NS_DispatchToMainThread(runnable); - unused << NS_WARN_IF(NS_FAILED(rv)); - } + MOZ_ASSERT(!mActor); } void ServiceWorkerManager::Init() { + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); + if (obs) { + DebugOnly<nsresult> rv; + rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false /* ownsWeak */); + MOZ_ASSERT(NS_SUCCEEDED(rv)); + } + if (XRE_GetProcessType() == GeckoProcessType_Default) { nsRefPtr<ServiceWorkerRegistrar> swr = ServiceWorkerRegistrar::Get(); MOZ_ASSERT(swr); nsTArray<ServiceWorkerRegistrationData> data; swr->GetRegistrations(data); LoadRegistrations(data); - nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (obs) { DebugOnly<nsresult> rv; - rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false /* ownsWeak */); - MOZ_ASSERT(NS_SUCCEEDED(rv)); rv = obs->AddObserver(this, PURGE_SESSION_HISTORY, false /* ownsWeak */); MOZ_ASSERT(NS_SUCCEEDED(rv)); rv = obs->AddObserver(this, PURGE_DOMAIN_DATA, false /* ownsWeak */); MOZ_ASSERT(NS_SUCCEEDED(rv)); rv = obs->AddObserver(this, WEBAPPS_CLEAR_DATA, false /* ownsWeak */); MOZ_ASSERT(NS_SUCCEEDED(rv)); } } @@ -867,16 +865,17 @@ class ServiceWorkerRegisterJob final : p friend class ContinueInstallTask; nsCString mScope; nsCString mScriptSpec; nsRefPtr<ServiceWorkerRegistrationInfo> mRegistration; nsRefPtr<ServiceWorkerUpdateFinishCallback> mCallback; nsCOMPtr<nsIPrincipal> mPrincipal; nsRefPtr<ServiceWorkerInfo> mUpdateAndInstallInfo; + nsCOMPtr<nsILoadGroup> mLoadGroup; ~ServiceWorkerRegisterJob() { } enum { REGISTER_JOB = 0, UPDATE_JOB = 1, @@ -887,25 +886,29 @@ class ServiceWorkerRegisterJob final : p public: NS_DECL_ISUPPORTS_INHERITED // [[Register]] ServiceWorkerRegisterJob(ServiceWorkerJobQueue* aQueue, const nsCString& aScope, const nsCString& aScriptSpec, ServiceWorkerUpdateFinishCallback* aCallback, - nsIPrincipal* aPrincipal) + nsIPrincipal* aPrincipal, + nsILoadGroup* aLoadGroup) : ServiceWorkerJob(aQueue) , mScope(aScope) , mScriptSpec(aScriptSpec) , mCallback(aCallback) , mPrincipal(aPrincipal) + , mLoadGroup(aLoadGroup) , mJobType(REGISTER_JOB) , mCanceled(false) - { } + { + MOZ_ASSERT(mLoadGroup); + } // [[Update]] ServiceWorkerRegisterJob(ServiceWorkerJobQueue* aQueue, ServiceWorkerRegistrationInfo* aRegistration, ServiceWorkerUpdateFinishCallback* aCallback) : ServiceWorkerJob(aQueue) , mRegistration(aRegistration) , mCallback(aCallback) @@ -1225,17 +1228,17 @@ private: // byte-for-byte match with the script resource of newestWorker... if (workerInfo && workerInfo->ScriptSpec().Equals(mRegistration->mScriptSpec)) { cacheName = workerInfo->CacheName(); } nsresult rv = serviceWorkerScriptCache::Compare(mRegistration->mPrincipal, cacheName, NS_ConvertUTF8toUTF16(mRegistration->mScriptSpec), - this); + this, mLoadGroup); if (NS_WARN_IF(NS_FAILED(rv))) { return Fail(rv); } } void Succeed() { @@ -1529,18 +1532,30 @@ ServiceWorkerManager::Register(nsIDOMWin } ServiceWorkerJobQueue* queue = GetOrCreateJobQueue(originSuffix, cleanedScope); MOZ_ASSERT(queue); nsRefPtr<ServiceWorkerResolveWindowPromiseOnUpdateCallback> cb = new ServiceWorkerResolveWindowPromiseOnUpdateCallback(window, promise); + nsCOMPtr<nsILoadGroup> docLoadGroup = doc->GetDocumentLoadGroup(); + nsRefPtr<WorkerLoadInfo::InterfaceRequestor> ir = + new WorkerLoadInfo::InterfaceRequestor(documentPrincipal, docLoadGroup); + ir->MaybeAddTabChild(docLoadGroup); + + // Create a load group that is separate from, yet related to, the document's load group. + // This allows checks for interfaces like nsILoadContext to yield the values used by the + // the document, yet will not cancel the update job if the document's load group is cancelled. + nsCOMPtr<nsILoadGroup> loadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID); + rv = loadGroup->SetNotificationCallbacks(ir); + MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv)); + nsRefPtr<ServiceWorkerRegisterJob> job = - new ServiceWorkerRegisterJob(queue, cleanedScope, spec, cb, documentPrincipal); + new ServiceWorkerRegisterJob(queue, cleanedScope, spec, cb, documentPrincipal, loadGroup); queue->Append(job); AssertIsOnMainThread(); Telemetry::Accumulate(Telemetry::SERVICE_WORKER_REGISTRATIONS, 1); promise.forget(aPromise); return NS_OK; } @@ -1548,29 +1563,33 @@ ServiceWorkerManager::Register(nsIDOMWin void ServiceWorkerManager::AppendPendingOperation(ServiceWorkerJobQueue* aQueue, ServiceWorkerJob* aJob) { MOZ_ASSERT(!mActor); MOZ_ASSERT(aQueue); MOZ_ASSERT(aJob); - PendingOperation* opt = mPendingOperations.AppendElement(); - opt->mQueue = aQueue; - opt->mJob = aJob; + if (!mShuttingDown) { + PendingOperation* opt = mPendingOperations.AppendElement(); + opt->mQueue = aQueue; + opt->mJob = aJob; + } } void ServiceWorkerManager::AppendPendingOperation(nsIRunnable* aRunnable) { MOZ_ASSERT(!mActor); MOZ_ASSERT(aRunnable); - PendingOperation* opt = mPendingOperations.AppendElement(); - opt->mRunnable = aRunnable; + if (!mShuttingDown) { + PendingOperation* opt = mPendingOperations.AppendElement(); + opt->mRunnable = aRunnable; + } } /* * Used to handle ExtendableEvent::waitUntil() and proceed with * installation/activation. */ class LifecycleEventPromiseHandler final : public PromiseNativeHandler { @@ -2378,18 +2397,20 @@ private: PrincipalInfo principalInfo; if (NS_WARN_IF(NS_FAILED(PrincipalToPrincipalInfo(mPrincipal, &principalInfo)))) { return mCallback ? mCallback->UnregisterSucceeded(false) : NS_OK; } nsRefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance(); - MOZ_ASSERT(swm->mActor); - swm->mActor->SendUnregister(principalInfo, NS_ConvertUTF8toUTF16(mScope)); + // Could it be that we are shutting down. + if (swm->mActor) { + swm->mActor->SendUnregister(principalInfo, NS_ConvertUTF8toUTF16(mScope)); + } nsAutoCString scopeKey; nsresult rv = swm->PrincipalToScopeKey(mPrincipal, scopeKey); if (NS_WARN_IF(NS_FAILED(rv))) { return mCallback ? mCallback->UnregisterSucceeded(false) : NS_OK; } // "Let registration be the result of running [[Get Registration]] @@ -2730,20 +2751,25 @@ ServiceWorkerManager::ActorCreated(mozil mPendingOperations.Clear(); } void ServiceWorkerManager::StoreRegistration( nsIPrincipal* aPrincipal, ServiceWorkerRegistrationInfo* aRegistration) { - MOZ_ASSERT(mActor); MOZ_ASSERT(aPrincipal); MOZ_ASSERT(aRegistration); + if (mShuttingDown) { + return; + } + + MOZ_ASSERT(mActor); + ServiceWorkerRegistrationData data; nsresult rv = PopulateRegistrationData(aPrincipal, aRegistration, data); if (NS_WARN_IF(NS_FAILED(rv))) { return; } PrincipalInfo principalInfo; if (NS_WARN_IF(NS_FAILED(PrincipalToPrincipalInfo(aPrincipal, @@ -4059,16 +4085,20 @@ ServiceWorkerManager::MaybeRemoveRegistr } void ServiceWorkerManager::RemoveRegistrationInternal(ServiceWorkerRegistrationInfo* aRegistration) { MOZ_ASSERT(aRegistration); MOZ_ASSERT(!aRegistration->IsControllingDocuments()); + if (mShuttingDown) { + return; + } + // All callers should be either from a job in which case the actor is // available, or from MaybeStopControlling(), in which case, this will only be // called if a valid registration is found. If a valid registration exists, // it means the actor is available since the original map of registrations is // populated by it, and any new registrations wait until the actor is // available before proceeding (See ServiceWorkerRegisterJob::Start). MOZ_ASSERT(mActor); @@ -4492,31 +4522,32 @@ ServiceWorkerManager::UpdateAllRegistrat return NS_OK; } NS_IMETHODIMP ServiceWorkerManager::Observe(nsISupports* aSubject, const char* aTopic, const char16_t* aData) { - MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); - if (strcmp(aTopic, PURGE_SESSION_HISTORY) == 0) { + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); RemoveAll(); PropagateRemoveAll(); return NS_OK; } if (strcmp(aTopic, PURGE_DOMAIN_DATA) == 0) { + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); nsAutoString domain(aData); RemoveAndPropagate(NS_ConvertUTF16toUTF8(domain)); return NS_OK; } if (strcmp(aTopic, WEBAPPS_CLEAR_DATA) == 0) { + MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); nsCOMPtr<mozIApplicationClearPrivateDataParams> params = do_QueryInterface(aSubject); if (NS_WARN_IF(!params)) { return NS_OK; } uint32_t appId; nsresult rv = params->GetAppId(&appId); @@ -4536,28 +4567,45 @@ ServiceWorkerManager::Observe(nsISupport nsCOMPtr<nsIPrincipal> principal; app->GetPrincipal(getter_AddRefs(principal)); if (NS_WARN_IF(!principal)) { return NS_OK; } RemoveAllRegistrations(principal); - } else if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) { + return NS_OK; + } + + if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) { + mShuttingDown = true; + nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (obs) { obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID); - obs->RemoveObserver(this, PURGE_SESSION_HISTORY); - obs->RemoveObserver(this, PURGE_DOMAIN_DATA); - obs->RemoveObserver(this, WEBAPPS_CLEAR_DATA); + + if (XRE_GetProcessType() == GeckoProcessType_Default) { + obs->RemoveObserver(this, PURGE_SESSION_HISTORY); + obs->RemoveObserver(this, PURGE_DOMAIN_DATA); + obs->RemoveObserver(this, WEBAPPS_CLEAR_DATA); + } } - } else { - MOZ_CRASH("Received message we aren't supposed to be registered for!"); - } - + + if (mActor) { + mActor->ManagerShuttingDown(); + + nsRefPtr<TeardownRunnable> runnable = new TeardownRunnable(mActor); + nsresult rv = NS_DispatchToMainThread(runnable); + unused << NS_WARN_IF(NS_FAILED(rv)); + mActor = nullptr; + } + return NS_OK; + } + + MOZ_CRASH("Received message we aren't supposed to be registered for!"); return NS_OK; } NS_IMETHODIMP ServiceWorkerManager::PropagateSoftUpdate(JS::Handle<JS::Value> aOriginAttributes, const nsAString& aScope, JSContext* aCx) {
--- a/dom/workers/ServiceWorkerManager.h +++ b/dom/workers/ServiceWorkerManager.h @@ -547,15 +547,17 @@ private: // Removes all service worker registrations for a given principal. void RemoveAllRegistrations(nsIPrincipal* aPrincipal); nsRefPtr<ServiceWorkerManagerChild> mActor; struct PendingOperation; nsTArray<PendingOperation> mPendingOperations; + + bool mShuttingDown; }; } // namespace workers } // namespace dom } // namespace mozilla #endif // mozilla_dom_workers_serviceworkermanager_h
--- a/dom/workers/ServiceWorkerScriptCache.cpp +++ b/dom/workers/ServiceWorkerScriptCache.cpp @@ -72,31 +72,32 @@ public: explicit CompareNetwork(CompareManager* aManager) : mManager(aManager) { MOZ_ASSERT(aManager); AssertIsOnMainThread(); } nsresult - Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL) + Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL, nsILoadGroup* aLoadGroup) { MOZ_ASSERT(aPrincipal); AssertIsOnMainThread(); nsCOMPtr<nsIURI> uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), aURL, nullptr, nullptr); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } rv = NS_NewChannel(getter_AddRefs(mChannel), uri, aPrincipal, nsILoadInfo::SEC_NORMAL, - nsIContentPolicy::TYPE_SCRIPT); // FIXME(nsm): TYPE_SERVICEWORKER + nsIContentPolicy::TYPE_SCRIPT, // FIXME(nsm): TYPE_SERVICEWORKER + aLoadGroup); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } nsLoadFlags flags; rv = mChannel->GetLoadFlags(&flags); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; @@ -275,34 +276,34 @@ public: , mCacheFinished(false) , mInCache(false) { AssertIsOnMainThread(); } nsresult Initialize(nsIPrincipal* aPrincipal, const nsAString& aURL, - const nsAString& aCacheName) + const nsAString& aCacheName, nsILoadGroup* aLoadGroup) { AssertIsOnMainThread(); MOZ_ASSERT(aPrincipal); mURL = aURL; // Always create a CacheStorage since we want to write the network entry to // the cache even if there isn't an existing one. ErrorResult result; mCacheStorage = CreateCacheStorage(aPrincipal, result, getter_AddRefs(mSandbox)); if (NS_WARN_IF(result.Failed())) { MOZ_ASSERT(!result.IsErrorWithMessage()); return result.StealNSResult(); } mCN = new CompareNetwork(this); - nsresult rv = mCN->Initialize(aPrincipal, aURL); + nsresult rv = mCN->Initialize(aPrincipal, aURL, aLoadGroup); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (!aCacheName.IsEmpty()) { mCC = new CompareCache(this); rv = mCC->Initialize(aPrincipal, aURL, aCacheName); if (NS_WARN_IF(NS_FAILED(rv))) { @@ -931,26 +932,27 @@ GenerateCacheName(nsAString& aName) id.ToProvidedString(chars); aName.AssignASCII(chars, NSID_LENGTH); return NS_OK; } nsresult Compare(nsIPrincipal* aPrincipal, const nsAString& aCacheName, - const nsAString& aURL, CompareCallback* aCallback) + const nsAString& aURL, CompareCallback* aCallback, + nsILoadGroup* aLoadGroup) { AssertIsOnMainThread(); MOZ_ASSERT(aPrincipal); MOZ_ASSERT(!aURL.IsEmpty()); MOZ_ASSERT(aCallback); nsRefPtr<CompareManager> cm = new CompareManager(aCallback); - nsresult rv = cm->Initialize(aPrincipal, aURL, aCacheName); + nsresult rv = cm->Initialize(aPrincipal, aURL, aCacheName, aLoadGroup); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } return NS_OK; } } // serviceWorkerScriptCache namespace
--- a/dom/workers/ServiceWorkerScriptCache.h +++ b/dom/workers/ServiceWorkerScriptCache.h @@ -39,17 +39,17 @@ public: const nsACString& aMaxScope) = 0; NS_IMETHOD_(MozExternalRefCountType) AddRef() = 0; NS_IMETHOD_(MozExternalRefCountType) Release() = 0; }; nsresult Compare(nsIPrincipal* aPrincipal, const nsAString& aCacheName, - const nsAString& aURL, CompareCallback* aCallback); + const nsAString& aURL, CompareCallback* aCallback, nsILoadGroup* aLoadGroup); } // serviceWorkerScriptCache namespace } // workers namespace } // dom namespace } // mozilla namespace #endif // mozilla_dom_workers_ServiceWorkerScriptCache_h
--- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -5957,21 +5957,23 @@ WorkerPrivate::AddFeature(JSContext* aCx MutexAutoLock lock(mMutex); if (mStatus >= Canceling) { return false; } } MOZ_ASSERT(!mFeatures.Contains(aFeature), "Already know about this one!"); + + if (mFeatures.IsEmpty() && !ModifyBusyCountFromWorker(aCx, true)) { + return false; + } + mFeatures.AppendElement(aFeature); - - return mFeatures.Length() == 1 ? - ModifyBusyCountFromWorker(aCx, true) : - true; + return true; } void WorkerPrivate::RemoveFeature(JSContext* aCx, WorkerFeature* aFeature) { AssertIsOnWorkerThread(); MOZ_ASSERT(mFeatures.Contains(aFeature), "Didn't know about this one!");
--- a/editor/libeditor/moz.build +++ b/editor/libeditor/moz.build @@ -65,9 +65,11 @@ LOCAL_INCLUDES += [ '/editor/txmgr', '/extensions/spellcheck/src', '/layout/generic', '/layout/style', '/layout/tables', '/layout/xul', ] +include('/ipc/chromium/chromium-config.mozbuild') + FINAL_LIBRARY = 'xul'
--- a/editor/libeditor/nsEditorEventListener.cpp +++ b/editor/libeditor/nsEditorEventListener.cpp @@ -54,16 +54,18 @@ #include "nsServiceManagerUtils.h" // for do_GetService #include "nsString.h" // for nsAutoString #include "nsQueryObject.h" // for do_QueryObject #ifdef HANDLE_NATIVE_TEXT_DIRECTION_SWITCH #include "nsContentUtils.h" // for nsContentUtils, etc #include "nsIBidiKeyboard.h" // for nsIBidiKeyboard #endif +#include "mozilla/dom/TabParent.h" + class nsPresContext; using namespace mozilla; using namespace mozilla::dom; static void DoCommandCallback(Command aCommand, void* aData) { @@ -980,16 +982,24 @@ nsEditorEventListener::CanDrop(nsIDOMDra nsresult rv = sourceNode->GetOwnerDocument(getter_AddRefs(sourceDoc)); NS_ENSURE_SUCCESS(rv, false); // If the source and the dest are not same document, allow to drop it always. if (domdoc != sourceDoc) { return true; } + // If the source node is a remote browser, treat this as coming from a + // different document and allow the drop. + nsCOMPtr<nsIContent> sourceContent = do_QueryInterface(sourceNode); + TabParent* tp = TabParent::GetFrom(sourceContent); + if (tp) { + return true; + } + nsRefPtr<Selection> selection = mEditor->GetSelection(); if (!selection) { return false; } // If selection is collapsed, allow to drop it always. if (selection->Collapsed()) { return true;
deleted file mode 100644 index ec288075e2874b7f8371930b7fdc8c4071fce40c..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@<O00001
deleted file mode 100644 --- a/embedding/tests/winEmbed/WebBrowserChrome.cpp +++ /dev/null @@ -1,591 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: Mozilla-sample-code 1.0 - * - * Copyright (c) 2002 Netscape Communications Corporation and - * other contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this Mozilla sample software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to permit - * persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Contributor(s): - * - * ***** END LICENSE BLOCK ***** */ - -// Local includes -#include "resource.h" -#include "winEmbed.h" -#include "WebBrowserChrome.h" - -// OS headers -#include <stdio.h> - -// Frozen APIs - -#include "nsStringAPI.h" -#include "nsIComponentManager.h" -#include "nsIDOMWindow.h" -#include "nsIInterfaceRequestor.h" -#include "nsIRequest.h" -#include "nsIURI.h" -#include "nsIWebProgress.h" -#include "nsCWebBrowser.h" - -// Glue APIs (not frozen, but safe to use because they are statically linked) -#include "nsComponentManagerUtils.h" - -// NON-FROZEN APIS! -#include "nsIWebNavigation.h" - -WebBrowserChrome::WebBrowserChrome() -{ - mNativeWindow = nullptr; - mSizeSet = false; -} - -WebBrowserChrome::~WebBrowserChrome() -{ - WebBrowserChromeUI::Destroyed(this); -} - -nsresult WebBrowserChrome::CreateBrowser(int32_t aX, int32_t aY, - int32_t aCX, int32_t aCY, - nsIWebBrowser **aBrowser) -{ - NS_ENSURE_ARG_POINTER(aBrowser); - *aBrowser = nullptr; - - mWebBrowser = do_CreateInstance(NS_WEBBROWSER_CONTRACTID); - - if (!mWebBrowser) - return NS_ERROR_FAILURE; - - (void)mWebBrowser->SetContainerWindow(static_cast<nsIWebBrowserChrome*>(this)); - - nsCOMPtr<nsIBaseWindow> browserBaseWindow = do_QueryInterface(mWebBrowser); - - mNativeWindow = WebBrowserChromeUI::CreateNativeWindow(static_cast<nsIWebBrowserChrome*>(this)); - - if (!mNativeWindow) - return NS_ERROR_FAILURE; - - browserBaseWindow->InitWindow( mNativeWindow, - nullptr, - aX, aY, aCX, aCY); - browserBaseWindow->Create(); - - nsCOMPtr<nsIWebProgressListener> listener(static_cast<nsIWebProgressListener*>(this)); - nsCOMPtr<nsIWeakReference> thisListener(do_GetWeakReference(listener)); - (void)mWebBrowser->AddWebBrowserListener(thisListener, - NS_GET_IID(nsIWebProgressListener)); - - // The window has been created. Now register for history notifications - mWebBrowser->AddWebBrowserListener(thisListener, NS_GET_IID(nsISHistoryListener)); - - if (mWebBrowser) - { - *aBrowser = mWebBrowser; - NS_ADDREF(*aBrowser); - return NS_OK; - } - return NS_ERROR_FAILURE; -} - -//***************************************************************************** -// WebBrowserChrome::nsISupports -//***************************************************************************** - -NS_IMPL_ADDREF(WebBrowserChrome) -NS_IMPL_RELEASE(WebBrowserChrome) - -NS_INTERFACE_MAP_BEGIN(WebBrowserChrome) - NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome) - NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) - NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome) - NS_INTERFACE_MAP_ENTRY(nsIEmbeddingSiteWindow) - NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener) // optional - NS_INTERFACE_MAP_ENTRY(nsISHistoryListener) - NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) - NS_INTERFACE_MAP_ENTRY(nsIObserver) - NS_INTERFACE_MAP_ENTRY(nsIContextMenuListener) - NS_INTERFACE_MAP_ENTRY(nsITooltipListener) -NS_INTERFACE_MAP_END - -//***************************************************************************** -// WebBrowserChrome::nsIInterfaceRequestor -//***************************************************************************** - -NS_IMETHODIMP WebBrowserChrome::GetInterface(const nsIID &aIID, void** aInstancePtr) -{ - NS_ENSURE_ARG_POINTER(aInstancePtr); - - *aInstancePtr = 0; - if (aIID.Equals(NS_GET_IID(nsIDOMWindow))) - { - if (mWebBrowser) - { - return mWebBrowser->GetContentDOMWindow((nsIDOMWindow **) aInstancePtr); - } - return NS_ERROR_NOT_INITIALIZED; - } - return QueryInterface(aIID, aInstancePtr); -} - -//***************************************************************************** -// WebBrowserChrome::nsIWebBrowserChrome -//***************************************************************************** - -NS_IMETHODIMP WebBrowserChrome::SetStatus(uint32_t aType, const char16_t* aStatus) -{ - WebBrowserChromeUI::UpdateStatusBarText(this, aStatus); - return NS_OK; -} - -NS_IMETHODIMP WebBrowserChrome::GetWebBrowser(nsIWebBrowser** aWebBrowser) -{ - NS_ENSURE_ARG_POINTER(aWebBrowser); - *aWebBrowser = mWebBrowser; - NS_IF_ADDREF(*aWebBrowser); - return NS_OK; -} - -NS_IMETHODIMP WebBrowserChrome::SetWebBrowser(nsIWebBrowser* aWebBrowser) -{ - mWebBrowser = aWebBrowser; - return NS_OK; -} - -NS_IMETHODIMP WebBrowserChrome::GetChromeFlags(uint32_t* aChromeMask) -{ - *aChromeMask = mChromeFlags; - return NS_OK; -} - -NS_IMETHODIMP WebBrowserChrome::SetChromeFlags(uint32_t aChromeMask) -{ - mChromeFlags = aChromeMask; - return NS_OK; -} - -NS_IMETHODIMP WebBrowserChrome::DestroyBrowserWindow(void) -{ - WebBrowserChromeUI::Destroy(this); - return NS_OK; -} - - -// IN: The desired browser client area dimensions. -NS_IMETHODIMP WebBrowserChrome::SizeBrowserTo(int32_t aWidth, int32_t aHeight) -{ - /* This isn't exactly correct: we're setting the whole window to - the size requested for the browser. At time of writing, though, - it's fine and useful for winEmbed's purposes. */ - WebBrowserChromeUI::SizeTo(this, aWidth, aHeight); - mSizeSet = true; - return NS_OK; -} - - -NS_IMETHODIMP WebBrowserChrome::ShowAsModal(void) -{ - if (mDependentParent) - AppCallbacks::EnableChromeWindow(mDependentParent, false); - - mContinueModalLoop = true; - AppCallbacks::RunEventLoop(mContinueModalLoop); - - if (mDependentParent) - AppCallbacks::EnableChromeWindow(mDependentParent, true); - - return NS_OK; -} - -NS_IMETHODIMP WebBrowserChrome::IsWindowModal(bool *_retval) -{ - *_retval = false; - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP WebBrowserChrome::ExitModalEventLoop(nsresult aStatus) -{ - mContinueModalLoop = false; - return NS_OK; -} - -//***************************************************************************** -// WebBrowserChrome::nsIWebBrowserChromeFocus -//***************************************************************************** - -NS_IMETHODIMP WebBrowserChrome::FocusNextElement() -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP WebBrowserChrome::FocusPrevElement() -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -//***************************************************************************** -// WebBrowserChrome::nsIWebProgressListener -//***************************************************************************** - -NS_IMETHODIMP WebBrowserChrome::OnProgressChange(nsIWebProgress *progress, nsIRequest *request, - int32_t curSelfProgress, int32_t maxSelfProgress, - int32_t curTotalProgress, int32_t maxTotalProgress) -{ - WebBrowserChromeUI::UpdateProgress(this, curTotalProgress, maxTotalProgress); - return NS_OK; -} - -NS_IMETHODIMP WebBrowserChrome::OnStateChange(nsIWebProgress *progress, nsIRequest *request, - uint32_t progressStateFlags, nsresult status) -{ - if ((progressStateFlags & STATE_START) && (progressStateFlags & STATE_IS_DOCUMENT)) - { - WebBrowserChromeUI::UpdateBusyState(this, true); - } - - if ((progressStateFlags & STATE_STOP) && (progressStateFlags & STATE_IS_DOCUMENT)) - { - WebBrowserChromeUI::UpdateBusyState(this, false); - WebBrowserChromeUI::UpdateProgress(this, 0, 100); - WebBrowserChromeUI::UpdateStatusBarText(this, nullptr); - ContentFinishedLoading(); - } - - return NS_OK; -} - - -NS_IMETHODIMP WebBrowserChrome::OnLocationChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, - nsIURI *location, - uint32_t aFlags) -{ - bool isSubFrameLoad = false; // Is this a subframe load - if (aWebProgress) { - nsCOMPtr<nsIDOMWindow> domWindow; - nsCOMPtr<nsIDOMWindow> topDomWindow; - aWebProgress->GetDOMWindow(getter_AddRefs(domWindow)); - if (domWindow) { // Get root domWindow - domWindow->GetTop(getter_AddRefs(topDomWindow)); - } - if (domWindow != topDomWindow) - isSubFrameLoad = true; - } - if (!isSubFrameLoad) - WebBrowserChromeUI::UpdateCurrentURI(this); - return NS_OK; -} - -NS_IMETHODIMP -WebBrowserChrome::OnStatusChange(nsIWebProgress* aWebProgress, - nsIRequest* aRequest, - nsresult aStatus, - const char16_t* aMessage) -{ - WebBrowserChromeUI::UpdateStatusBarText(this, aMessage); - return NS_OK; -} - - - -NS_IMETHODIMP -WebBrowserChrome::OnSecurityChange(nsIWebProgress *aWebProgress, - nsIRequest *aRequest, - uint32_t state) -{ - return NS_OK; -} - -//***************************************************************************** -// WebBrowserChrome::nsISHistoryListener -//***************************************************************************** - -NS_IMETHODIMP -WebBrowserChrome::OnHistoryNewEntry(nsIURI * aNewURI) -{ - return SendHistoryStatusMessage(aNewURI, "add"); -} - -NS_IMETHODIMP -WebBrowserChrome::OnHistoryGoBack(nsIURI * aBackURI, bool * aContinue) -{ - // For now, let the operation continue - *aContinue = true; - return SendHistoryStatusMessage(aBackURI, "back"); -} - - -NS_IMETHODIMP -WebBrowserChrome::OnHistoryGoForward(nsIURI * aForwardURI, bool * aContinue) -{ - // For now, let the operation continue - *aContinue = true; - return SendHistoryStatusMessage(aForwardURI, "forward"); -} - - -NS_IMETHODIMP -WebBrowserChrome::OnHistoryGotoIndex(int32_t aIndex, nsIURI * aGotoURI, bool * aContinue) -{ - // For now, let the operation continue - *aContinue = true; - return SendHistoryStatusMessage(aGotoURI, "goto", aIndex); -} - -NS_IMETHODIMP -WebBrowserChrome::OnHistoryReload(nsIURI * aURI, uint32_t aReloadFlags, bool * aContinue) -{ - // For now, let the operation continue - *aContinue = true; - return SendHistoryStatusMessage(aURI, "reload", 0 /* no info to pass here */, aReloadFlags); -} - -NS_IMETHODIMP -WebBrowserChrome::OnHistoryPurge(int32_t aNumEntries, bool *aContinue) -{ - // For now let the operation continue - *aContinue = false; - return SendHistoryStatusMessage(nullptr, "purge", aNumEntries); -} - -NS_IMETHODIMP -WebBrowserChrome::OnHistoryReplaceEntry(int32_t aIndex) -{ - return SendHistoryStatusMessage(nullptr, "replace", aIndex); -} - -static void -AppendIntToCString(int32_t info1, nsCString& aResult) -{ - char intstr[10]; - _snprintf(intstr, sizeof(intstr) - 1, "%i", info1); - intstr[sizeof(intstr) - 1] = '\0'; - aResult.Append(intstr); -} - -nsresult -WebBrowserChrome::SendHistoryStatusMessage(nsIURI * aURI, char * operation, int32_t info1, uint32_t aReloadFlags) -{ - nsCString uriSpec; - if (aURI) - { - aURI->GetSpec(uriSpec); - } - - nsCString status; - - if(!(strcmp(operation, "back"))) - { - status.AssignLiteral("Going back to url: "); - status.Append(uriSpec); - } - else if (!(strcmp(operation, "forward"))) - { - // Going forward. XXX Get string from a resource file - status.AssignLiteral("Going forward to url: "); - status.Append(uriSpec); - } - else if (!(strcmp(operation, "reload"))) - { - // Reloading. XXX Get string from a resource file - if (aReloadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY && - aReloadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE) - { - status.AssignLiteral("Reloading url, (bypassing proxy and cache): "); - } - else if (aReloadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY) - { - status.AssignLiteral("Reloading url, (bypassing proxy): "); - } - else if (aReloadFlags & nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE) - { - status.AssignLiteral("Reloading url, (bypassing cache): "); - } - else - { - status.AssignLiteral("Reloading url, (normal): "); - } - status.Append(uriSpec); - } - else if (!(strcmp(operation, "add"))) - { - status.Assign(uriSpec); - status.AppendLiteral(" added to session History"); - } - else if (!(strcmp(operation, "goto"))) - { - status.AssignLiteral("Going to HistoryIndex: "); - - AppendIntToCString(info1, status); - - status.AppendLiteral(" Url: "); - status.Append(uriSpec); - } - else if (!(strcmp(operation, "purge"))) - { - AppendIntToCString(info1, status); - status.AppendLiteral(" purged from Session History"); - } - else if (!(strcmp(operation, "replace"))) - { - status.AssignLiteral("Replacing HistoryIndex: "); - AppendIntToCString(info1, status); - } - - nsString wstatus; - NS_CStringToUTF16(status, NS_CSTRING_ENCODING_UTF8, wstatus); - WebBrowserChromeUI::UpdateStatusBarText(this, wstatus.get()); - - return NS_OK; -} - -void WebBrowserChrome::ContentFinishedLoading() -{ - // if it was a chrome window and no one has already specified a size, - // size to content - if (mWebBrowser && !mSizeSet && - (mChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) { - nsCOMPtr<nsIDOMWindow> contentWin; - mWebBrowser->GetContentDOMWindow(getter_AddRefs(contentWin)); - if (contentWin) - contentWin->SizeToContent(); - WebBrowserChromeUI::ShowWindow(this, true); - } -} - - -//***************************************************************************** -// WebBrowserChrome::nsIEmbeddingSiteWindow -//***************************************************************************** - -NS_IMETHODIMP WebBrowserChrome::SetDimensions(uint32_t aFlags, int32_t x, int32_t y, int32_t cx, int32_t cy) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -NS_IMETHODIMP WebBrowserChrome::GetDimensions(uint32_t aFlags, int32_t *x, int32_t *y, int32_t *cx, int32_t *cy) -{ - if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_POSITION) - { - *x = 0; - *y = 0; - } - if (aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_INNER || - aFlags & nsIEmbeddingSiteWindow::DIM_FLAGS_SIZE_OUTER) - { - *cx = 0; - *cy = 0; - } - return NS_ERROR_NOT_IMPLEMENTED; -} - -/* void setFocus (); */ -NS_IMETHODIMP WebBrowserChrome::SetFocus() -{ - WebBrowserChromeUI::SetFocus(this); - return NS_OK; -} - -/* void blur (); */ -NS_IMETHODIMP WebBrowserChrome::Blur() -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -/* attribute wstring title; */ -NS_IMETHODIMP WebBrowserChrome::GetTitle(char16_t * *aTitle) -{ - NS_ENSURE_ARG_POINTER(aTitle); - - *aTitle = nullptr; - - return NS_ERROR_NOT_IMPLEMENTED; -} -NS_IMETHODIMP WebBrowserChrome::SetTitle(const char16_t * aTitle) -{ - return NS_ERROR_NOT_IMPLEMENTED; -} - -/* attribute boolean visibility; */ -NS_IMETHODIMP WebBrowserChrome::GetVisibility(bool * aVisibility) -{ - NS_ENSURE_ARG_POINTER(aVisibility); - *aVisibility = true; - return NS_OK; -} -NS_IMETHODIMP WebBrowserChrome::SetVisibility(bool aVisibility) -{ - return NS_OK; -} - -/* attribute nativeSiteWindow siteWindow */ -NS_IMETHODIMP WebBrowserChrome::GetSiteWindow(void * *aSiteWindow) -{ - NS_ENSURE_ARG_POINTER(aSiteWindow); - - *aSiteWindow = mNativeWindow; - return NS_OK; -} - - -//***************************************************************************** -// WebBrowserChrome::nsIObserver -//***************************************************************************** - -NS_IMETHODIMP WebBrowserChrome::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData) -{ - nsresult rv = NS_OK; - if (strcmp(aTopic, "profile-change-teardown") == 0) - { - // A profile change means death for this window - WebBrowserChromeUI::Destroy(this); - } - return rv; -} - -//***************************************************************************** -// WebBrowserChrome::nsIContextMenuListener -//***************************************************************************** - -/* void OnShowContextMenu (in unsigned long aContextFlags, in nsIDOMEvent aEvent, in nsIDOMNode aNode); */ -NS_IMETHODIMP WebBrowserChrome::OnShowContextMenu(uint32_t aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode) -{ - WebBrowserChromeUI::ShowContextMenu(this, aContextFlags, aEvent, aNode); - return NS_OK; -} - -//***************************************************************************** -// WebBrowserChrome::nsITooltipListener -//***************************************************************************** - -/* void OnShowTooltip (in long aXCoords, in long aYCoords, in wstring aTipText); */ -NS_IMETHODIMP WebBrowserChrome::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText) -{ - WebBrowserChromeUI::ShowTooltip(this, aXCoords, aYCoords, aTipText); - return NS_OK; -} - -/* void OnHideTooltip (); */ -NS_IMETHODIMP WebBrowserChrome::OnHideTooltip() -{ - WebBrowserChromeUI::HideTooltip(this); - return NS_OK; -}
deleted file mode 100644 --- a/embedding/tests/winEmbed/WebBrowserChrome.h +++ /dev/null @@ -1,124 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: Mozilla-sample-code 1.0 - * - * Copyright (c) 2002 Netscape Communications Corporation and - * other contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this Mozilla sample software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to permit - * persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Contributor(s): - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef __WebBrowserChrome__ -#define __WebBrowserChrome__ - -// OS headers - -#include <windows.h> - -// FROZEN APIs - -#include "nsStringAPI.h" - -#include "nsIWebBrowserChrome.h" -#include "nsIWebBrowserChromeFocus.h" - -#include "nsIContextMenuListener.h" -#include "nsIEmbeddingSiteWindow.h" -#include "nsIInterfaceRequestor.h" -#include "nsIObserver.h" -#include "nsISHistoryListener.h" -#include "nsITooltipListener.h" -#include "nsIWebProgressListener.h" -#include "nsIWebBrowser.h" - -// GLUE APIs (not frozen, but safe because we're statically linking them) -#include "nsCOMPtr.h" -#include "nsIInterfaceRequestorUtils.h" -#include "nsWeakReference.h" - -class WebBrowserChromeUI -{ -public: - static HWND CreateNativeWindow(nsIWebBrowserChrome* chrome); - static void Destroy(nsIWebBrowserChrome* chrome); - static void Destroyed(nsIWebBrowserChrome* chrome); - static void SetFocus(nsIWebBrowserChrome *chrome); - static void UpdateStatusBarText(nsIWebBrowserChrome *aChrome, const char16_t* aStatusText); - static void UpdateCurrentURI(nsIWebBrowserChrome *aChrome); - static void UpdateBusyState(nsIWebBrowserChrome *aChrome, bool aBusy); - static void UpdateProgress(nsIWebBrowserChrome *aChrome, int32_t aCurrent, int32_t aMax); - static void GetResourceStringById(int32_t aID, char ** aReturn); - static void ShowContextMenu(nsIWebBrowserChrome *aChrome, uint32_t aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode); - static void ShowTooltip(nsIWebBrowserChrome *aChrome, int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText); - static void HideTooltip(nsIWebBrowserChrome *aChrome); - static void ShowWindow(nsIWebBrowserChrome *aChrome, bool aShow); - static void SizeTo(nsIWebBrowserChrome *aChrome, int32_t aWidth, int32_t aHeight); -}; - -class WebBrowserChrome : public nsIWebBrowserChrome, - public nsIWebBrowserChromeFocus, - public nsIWebProgressListener, - public nsIEmbeddingSiteWindow, - public nsIInterfaceRequestor, - public nsISHistoryListener, - public nsIObserver, - public nsIContextMenuListener, - public nsITooltipListener, - public nsSupportsWeakReference - -{ -public: - WebBrowserChrome(); - virtual ~WebBrowserChrome(); - - NS_DECL_ISUPPORTS - NS_DECL_NSIWEBBROWSERCHROME - NS_DECL_NSIWEBBROWSERCHROMEFOCUS - NS_DECL_NSIWEBPROGRESSLISTENER - NS_DECL_NSIEMBEDDINGSITEWINDOW - NS_DECL_NSIINTERFACEREQUESTOR - NS_DECL_NSISHISTORYLISTENER - NS_DECL_NSIOBSERVER - NS_DECL_NSICONTEXTMENULISTENER - NS_DECL_NSITOOLTIPLISTENER - - nsresult CreateBrowser(int32_t aX, int32_t aY, int32_t aCX, int32_t aCY, - nsIWebBrowser **aBrowser); - - void SetParent(nsIWebBrowserChrome *aParent) - { mDependentParent = aParent; } - -protected: - nsresult SendHistoryStatusMessage(nsIURI * aURI, char * operation, int32_t info1=0, uint32_t info2=0); - - void ContentFinishedLoading(); - - HWND mNativeWindow; - uint32_t mChromeFlags; - bool mContinueModalLoop; - bool mSizeSet; - - nsCOMPtr<nsIWebBrowser> mWebBrowser; - nsCOMPtr<nsIWebBrowserChrome> mDependentParent; // opener (for dependent windows only) -}; - -#endif /* __WebBrowserChrome__ */
deleted file mode 100644 --- a/embedding/tests/winEmbed/WindowCreator.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: Mozilla-sample-code 1.0 - * - * Copyright (c) 2002 Netscape Communications Corporation and - * other contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this Mozilla sample software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to permit - * persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Contributor(s): - * - * ***** END LICENSE BLOCK ***** */ - -#include "nsIWebBrowserChrome.h" -#include "WindowCreator.h" -#include "winEmbed.h" - -WindowCreator::WindowCreator() -{ -} - -WindowCreator::~WindowCreator() -{ -} - -NS_IMPL_ISUPPORTS(WindowCreator, nsIWindowCreator) - -NS_IMETHODIMP -WindowCreator::CreateChromeWindow(nsIWebBrowserChrome *parent, - uint32_t chromeFlags, - nsIWebBrowserChrome **_retval) -{ - NS_ENSURE_ARG_POINTER(_retval); - AppCallbacks::CreateBrowserWindow(int32_t(chromeFlags), parent, _retval); - return *_retval ? NS_OK : NS_ERROR_FAILURE; -}
deleted file mode 100644 --- a/embedding/tests/winEmbed/WindowCreator.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: Mozilla-sample-code 1.0 - * - * Copyright (c) 2002 Netscape Communications Corporation and - * other contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this Mozilla sample software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to permit - * persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Contributor(s): - * - * ***** END LICENSE BLOCK ***** */ - -#ifndef __WindowCreator_h_ -#define __WindowCreator_h_ - -#include "nsIWindowCreator.h" - -class WindowCreator : - public nsIWindowCreator -{ -public: - WindowCreator(); - virtual ~WindowCreator(); - - NS_DECL_ISUPPORTS - NS_DECL_NSIWINDOWCREATOR -}; - -#endif -
deleted file mode 100644 --- a/embedding/tests/winEmbed/moz.build +++ /dev/null @@ -1,44 +0,0 @@ -# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -GeckoProgram('winEmbed') - -SOURCES += [ - 'WebBrowserChrome.cpp', - 'WindowCreator.cpp', - 'winEmbed.cpp', -] - -XPI_NAME = 'winembed' - -RESFILE = 'winEmbed.res' - -if CONFIG['GNU_CC']: - # Get rid of console window - LDFLAGS += ['-mwindows'] -else: - # Control the default heap size. - # This is the heap returned by GetProcessHeap(). - # As we use the CRT heap, the default size is too large and wastes VM. - # - # The default heap size is 1MB on Win32. - # The heap will grow if need be. - # - # Set it to 256k. See bug 127069. - LDFLAGS += ['/HEAP:0x40000'] - -DISABLE_STL_WRAPPING = True - -USE_LIBS += [ - 'profdirserviceprovidersa_s', -] - -OS_LIBS += [ - 'ole32', - 'comdlg32', - 'shell32', - 'version', -]
deleted file mode 100644 --- a/embedding/tests/winEmbed/resource.h +++ /dev/null @@ -1,69 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Developer Studio generated include file. -// Used by winEmbed.rc -// -#define IDC_MYICON 2 -#define IDD_WINEMBED_DIALOG 102 -#define IDD_ABOUTBOX 103 -#define IDS_APP_TITLE 103 -#define IDM_ABOUT 104 -#define MOZ_OpenURI 104 -#define MOZ_GetURI 104 -#define IDM_EXIT 105 -#define IDS_HELLO 106 -#define IDI_WINEMBED 107 -#define IDS_ABOUT 107 -#define IDI_SMALL 108 -#define IDS_ABOUT_TITLE 108 -#define IDC_WINEMBED 109 -#define IDS_HIST_BACK 109 -#define IDS_HIST_FORWARD 110 -#define IDS_HIST_RELOAD_NORMAL 111 -#define IDS_HIST_RELOAD_BYPASSPROXY 112 -#define IDS_HIST_RELOAD_BYPASSCACHE 113 -#define IDS_HIST_ADDURL 114 -#define IDS_HIST_RELOAD_BYPASSPROXYANDCACHE 115 -#define IDS_HIST_PURGE 116 -#define IDS_HIST_GOTO 117 -#define IDS_HIST_URL 118 -#define IDR_MAINFRAME 128 -#define IDD_BROWSER 130 -#define IDD_BROWSER_NC 131 -#define IDD_CHOOSEPROFILE 132 -#define MOZ_EDIT_URI 1001 -#define IDC_GO 1003 -#define IDC_BROWSER 1004 -#define IDC_ADDRESS 1005 -#define IDC_STOP 1006 -#define IDC_STATUS 1007 -#define IDC_BACK 1008 -#define IDC_FORWARD 1009 -#define IDC_PROGRESS 1010 -#define IDC_RELOAD 1011 -#define IDC_PROFILELIST 1011 -#define MOZ_Open 32771 -#define MOZ_NewBrowser 32773 -#define MOZ_NewEditor 32774 -#define MOZ_Cut 32776 -#define MOZ_Copy 32777 -#define MOZ_Paste 32778 -#define MOZ_Delete 32779 -#define MOZ_SelectAll 32780 -#define MOZ_SelectNone 32781 -#define MOZ_GoBack 32782 -#define MOZ_GoForward 32783 -#define MOZ_About 32784 -#define ID_DEBUG_THISSPACEFORRENT 32786 -#define MOZ_SwitchProfile 32787 -#define IDC_STATIC -1 - -// Next default values for new objects -// -#ifdef APSTUDIO_INVOKED -#ifndef APSTUDIO_READONLY_SYMBOLS -#define _APS_NEXT_RESOURCE_VALUE 133 -#define _APS_NEXT_COMMAND_VALUE 32788 -#define _APS_NEXT_CONTROL_VALUE 1012 -#define _APS_NEXT_SYMED_VALUE 110 -#endif -#endif
deleted file mode 100644 index b276a959679bf59784dd4fcd071783a0e3b120a2..0000000000000000000000000000000000000000 GIT binary patch literal 0 Hc$@<O00001
deleted file mode 100644 --- a/embedding/tests/winEmbed/winEmbed.cpp +++ /dev/null @@ -1,1135 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: Mozilla-sample-code 1.0 - * - * Copyright (c) 2002 Netscape Communications Corporation and - * other contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this Mozilla sample software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to permit - * persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Contributor(s): - * Doug Turner <dougt@netscape.com> - * Adam Lock <adamlock@netscape.com> - * - * ***** END LICENSE BLOCK ***** */ - -// C RunTime Header Files -#include <stdio.h> -#include <stdlib.h> -#include <malloc.h> -#include <memory.h> -#include <tchar.h> - -// Win32 header files -#include <windows.h> -#include <commctrl.h> -#include <commdlg.h> - -// Mozilla Frozen APIs -#include "nsXULAppAPI.h" - -XRE_InitEmbedding2Type XRE_InitEmbedding2; -XRE_TermEmbeddingType XRE_TermEmbedding; - -#include "nsAppDirectoryServiceDefs.h" -#include "nsDirectoryServiceDefs.h" -#include "nsProfileDirServiceProvider.h" -#include "nsStringAPI.h" -#include "nsXPCOMGlue.h" - -#include "nsIClipboardCommands.h" -#include "nsIInterfaceRequestor.h" -#include "nsIObserverService.h" -#include "nsIObserver.h" -#include "nsIURI.h" -#include "nsIWebBrowserFocus.h" -#include "nsIWindowWatcher.h" - -// NON-FROZEN APIs! -#include "nsIBaseWindow.h" -#include "nsIWebNavigation.h" - -// Local header files -#include "winEmbed.h" -#include "WebBrowserChrome.h" -#include "WindowCreator.h" -#include "resource.h" - -#define MAX_LOADSTRING 100 - -const TCHAR *szWindowClass = _T("WINEMBED"); - -// Foward declarations of functions included in this code module: -static ATOM MyRegisterClass(HINSTANCE hInstance); -static LRESULT CALLBACK BrowserWndProc(HWND, UINT, WPARAM, LPARAM); -static INT_PTR CALLBACK BrowserDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam); - -static nsresult InitializeWindowCreator(); -static nsresult OpenWebPage(const char * url); -static nsresult ResizeEmbedding(nsIWebBrowserChrome* chrome); - -// Profile chooser stuff -static nsresult StartupProfile(); - -// Global variables -static UINT gDialogCount = 0; -static HINSTANCE ghInstanceApp = nullptr; -static char gFirstURL[1024]; - -// like strpbrk but finds the *last* char, not the first -static char* -ns_strrpbrk(char *string, const char *strCharSet) -{ - char *found = nullptr; - for (; *string; ++string) { - for (const char *search = strCharSet; *search; ++search) { - if (*search == *string) { - found = string; - // Since we're looking for the last char, we save "found" - // until we're at the end of the string. - } - } - } - - return found; -} - -// A list of URLs to populate the URL drop down list with -static const TCHAR *gDefaultURLs[] = -{ - _T("http://www.mozilla.org/"), - _T("http://www.netscape.com/"), - _T("http://browsertest.web.aol.com/tests/javascript/javascpt/index.htm"), - _T("http://127.0.0.1/"), - _T("http://www.yahoo.com/"), - _T("http://www.travelocity.com/"), - _T("http://www.disney.com/"), - _T("http://www.go.com/"), - _T("http://www.google.com/"), - _T("http://www.ebay.com/"), - _T("http://www.shockwave.com/"), - _T("http://www.slashdot.org/"), - _T("http://www.quicken.com/"), - _T("http://www.hotmail.com/"), - _T("http://www.cnn.com/"), - _T("http://www.javasoft.com/") -}; - -int main(int argc, char *argv[]) -{ - nsresult rv; - - printf("You are embedded, man!\n\n"); - printf("******************************************************************\n"); - printf("* *\n"); - printf("* IMPORTANT NOTE: *\n"); - printf("* *\n"); - printf("* WinEmbed is not supported!!! Do not raise bugs on it unless *\n"); - printf("* it is badly broken (e.g. crash on start/exit, build errors) *\n"); - printf("* or you have the patch to make it better! MFCEmbed is now our *\n"); - printf("* embedding test application on Win32 and all testing should *\n"); - printf("* be done on that. *\n"); - printf("* *\n"); - printf("******************************************************************\n"); - printf("\n\n"); - - // Sophisticated command-line parsing in action - char *szFirstURL = "http://www.mozilla.org/projects/embedding/"; - int argn; - for (argn = 1; argn < argc; argn++) - { - szFirstURL = argv[argn]; - } - strncpy(gFirstURL, szFirstURL, sizeof(gFirstURL) - 1); - - ghInstanceApp = GetModuleHandle(nullptr); - - // Initialize global strings - TCHAR szTitle[MAX_LOADSTRING]; - LoadString(ghInstanceApp, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); - MyRegisterClass(ghInstanceApp); - - char path[_MAX_PATH]; - GetModuleFileName(ghInstanceApp, path, sizeof(path)); - char* lastslash = ns_strrpbrk(path, "/\\"); - if (!lastslash) - return 7; - - strcpy(lastslash, "\\xulrunner\\xpcom.dll"); - - rv = XPCOMGlueStartup(path); - if (NS_FAILED(rv)) - return 3; - - strcpy(lastslash, "\\xulrunner\\xul.dll"); - - HINSTANCE xulModule = LoadLibraryEx(path, nullptr, 0); - if (!xulModule) - return 4; - - XRE_InitEmbedding2 = - (XRE_InitEmbedding2Type) GetProcAddress(xulModule, "XRE_InitEmbedding2"); - if (!XRE_InitEmbedding2) { - fprintf(stderr, "Error: %i\n", GetLastError()); - return 5; - } - - XRE_TermEmbedding = - (XRE_TermEmbeddingType) GetProcAddress(xulModule, "XRE_TermEmbedding"); - if (!XRE_TermEmbedding) { - fprintf(stderr, "Error: %i\n", GetLastError()); - return 5; - } - - int result = 0; - - // Scope all the XPCOM stuff - { - strcpy(lastslash, "\\xulrunner"); - - nsCOMPtr<nsIFile> xuldir; - rv = NS_NewNativeLocalFile(nsCString(path), false, - getter_AddRefs(xuldir)); - if (NS_FAILED(rv)) - return 6; - - *lastslash = '\0'; - - nsCOMPtr<nsIFile> appdir; - rv = NS_NewNativeLocalFile(nsCString(path), false, - getter_AddRefs(appdir)); - if (NS_FAILED(rv)) - return 8; - - rv = XRE_InitEmbedding2(xuldir, appdir, nullptr); - if (NS_FAILED(rv)) - return 9; - - if (NS_FAILED(StartupProfile())) { - result = 8; - } - else { - InitializeWindowCreator(); - - // Open the initial browser window - OpenWebPage(gFirstURL); - - // Main message loop. - // NOTE: We use a fake event and a timeout in order to process idle stuff for - // Mozilla every 1/10th of a second. - bool runCondition = true; - - result = AppCallbacks::RunEventLoop(runCondition); - } - } - XRE_TermEmbedding(); - - return result; -} - -/* InitializeWindowCreator creates and hands off an object with a callback - to a window creation function. This is how all new windows are opened, - except any created directly by the embedding app. */ -nsresult -InitializeWindowCreator() -{ - // create an nsWindowCreator and give it to the WindowWatcher service - nsCOMPtr<nsIWindowCreator> creator(new WindowCreator()); - if (!creator) - return NS_ERROR_OUT_OF_MEMORY; - - nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID)); - if (!wwatch) - return NS_ERROR_UNEXPECTED; - - return wwatch->SetWindowCreator(creator); -} - -//----------------------------------------------------------------------------- - -// -// FUNCTION: OpenWebPage() -// -// PURPOSE: Opens a new browser dialog and starts it loading to the -// specified url. -// -nsresult OpenWebPage(const char *url) -{ - nsresult rv; - - // Create the chrome object. Note that it leaves this function - // with an extra reference so that it can released correctly during - // destruction (via Win32UI::Destroy) - - nsCOMPtr<nsIWebBrowserChrome> chrome; - rv = AppCallbacks::CreateBrowserWindow(nsIWebBrowserChrome::CHROME_ALL, - nullptr, getter_AddRefs(chrome)); - if (NS_SUCCEEDED(rv)) - { - // Start loading a page - nsCOMPtr<nsIWebBrowser> newBrowser; - chrome->GetWebBrowser(getter_AddRefs(newBrowser)); - nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(newBrowser)); - - return webNav->LoadURI(NS_ConvertASCIItoUTF16(url).get(), - nsIWebNavigation::LOAD_FLAGS_NONE, - nullptr, - nullptr, - nullptr); - } - - return rv; -} - -// -// FUNCTION: GetBrowserFromChrome() -// -// PURPOSE: Returns the HWND for the webbrowser container associated -// with the specified chrome. -// -HWND GetBrowserFromChrome(nsIWebBrowserChrome *aChrome) -{ - if (!aChrome) - { - return nullptr; - } - nsCOMPtr<nsIEmbeddingSiteWindow> baseWindow = do_QueryInterface(aChrome); - HWND hwnd = nullptr; - baseWindow->GetSiteWindow((void **) & hwnd); - return hwnd; -} - - -// -// FUNCTION: GetBrowserDlgFromChrome() -// -// PURPOSE: Returns the HWND for the browser dialog associated with -// the specified chrome. -// -HWND GetBrowserDlgFromChrome(nsIWebBrowserChrome *aChrome) -{ - return GetParent(GetBrowserFromChrome(aChrome)); -} - - -// -// FUNCTION: ResizeEmbedding() -// -// PURPOSE: Resizes the webbrowser window to fit its container. -// -nsresult ResizeEmbedding(nsIWebBrowserChrome* chrome) -{ - if (!chrome) - return NS_ERROR_FAILURE; - - nsCOMPtr<nsIEmbeddingSiteWindow> embeddingSite = do_QueryInterface(chrome); - HWND hWnd; - embeddingSite->GetSiteWindow((void **) & hWnd); - - if (!hWnd) - return NS_ERROR_NULL_POINTER; - - RECT rect; - GetClientRect(hWnd, &rect); - - // Make sure the browser is visible and sized - nsCOMPtr<nsIWebBrowser> webBrowser; - chrome->GetWebBrowser(getter_AddRefs(webBrowser)); - nsCOMPtr<nsIBaseWindow> webBrowserAsWin = do_QueryInterface(webBrowser); - if (webBrowserAsWin) - { - webBrowserAsWin->SetPositionAndSize(rect.left, - rect.top, - rect.right - rect.left, - rect.bottom - rect.top, - true); - webBrowserAsWin->SetVisibility(true); - } - - return NS_OK; -} - - -// -// FUNCTION: MyRegisterClass() -// -// PURPOSE: Registers the window class. -// -// COMMENTS: -// -// This function and its usage is only necessary if you want this code -// to be compatible with Win32 systems prior to the 'RegisterClassEx' -// function that was added to Windows 95. It is important to call this function -// so that the application will get 'well formed' small icons associated -// with it. -// -ATOM MyRegisterClass(HINSTANCE hInstance) -{ - WNDCLASSEX wcex; - - memset(&wcex, 0, sizeof(wcex)); - wcex.cbSize = sizeof(WNDCLASSEX); - - wcex.style = CS_HREDRAW | CS_VREDRAW; - wcex.lpfnWndProc = (WNDPROC) BrowserWndProc; - wcex.cbClsExtra = 0; - wcex.cbWndExtra = 0; - wcex.hInstance = hInstance; - wcex.hIcon = LoadIcon(ghInstanceApp, (LPCTSTR)IDI_WINEMBED); - wcex.hCursor = LoadCursor(nullptr, IDC_ARROW); - wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); - wcex.lpszClassName = szWindowClass; - wcex.hIconSm = LoadIcon(ghInstanceApp, (LPCTSTR)IDI_SMALL); - - return RegisterClassEx(&wcex); -} - - -// -// FUNCTION: UpdateUI() -// -// PURPOSE: Refreshes the buttons and menu items in the browser dialog -// -void UpdateUI(nsIWebBrowserChrome *aChrome) -{ - HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); - nsCOMPtr<nsIWebBrowser> webBrowser; - nsCOMPtr<nsIWebNavigation> webNavigation; - aChrome->GetWebBrowser(getter_AddRefs(webBrowser)); - webNavigation = do_QueryInterface(webBrowser); - - bool canGoBack = false; - bool canGoForward = false; - if (webNavigation) - { - webNavigation->GetCanGoBack(&canGoBack); - webNavigation->GetCanGoForward(&canGoForward); - } - - bool canCutSelection = false; - bool canCopySelection = false; - bool canPaste = false; - - nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser); - if (clipCmds) - { - clipCmds->CanCutSelection(&canCutSelection); - clipCmds->CanCopySelection(&canCopySelection); - clipCmds->CanPaste(&canPaste); - } - - HMENU hmenu = GetMenu(hwndDlg); - if (hmenu) - { - EnableMenuItem(hmenu, MOZ_GoBack, MF_BYCOMMAND | - ((canGoBack) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); - EnableMenuItem(hmenu, MOZ_GoForward, MF_BYCOMMAND | - ((canGoForward) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); - - EnableMenuItem(hmenu, MOZ_Cut, MF_BYCOMMAND | - ((canCutSelection) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); - EnableMenuItem(hmenu, MOZ_Copy, MF_BYCOMMAND | - ((canCopySelection) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); - EnableMenuItem(hmenu, MOZ_Paste, MF_BYCOMMAND | - ((canPaste) ? MF_ENABLED : (MF_DISABLED | MF_GRAYED))); - } - - HWND button; - button = GetDlgItem(hwndDlg, IDC_BACK); - if (button) - EnableWindow(button, canGoBack); - button = GetDlgItem(hwndDlg, IDC_FORWARD); - if (button) - EnableWindow(button, canGoForward); -} - - -// -// FUNCTION: BrowserDlgProc() -// -// PURPOSE: Browser dialog windows message handler. -// -// COMMENTS: -// -// The code for handling buttons and menu actions is here. -// -INT_PTR CALLBACK BrowserDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) -{ - // Get the browser and other pointers since they are used a lot below - HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER); - nsIWebBrowserChrome *chrome = nullptr ; - if (hwndBrowser) - { - chrome = (nsIWebBrowserChrome *) GetWindowLongPtr(hwndBrowser, GWLP_USERDATA); - } - nsCOMPtr<nsIWebBrowser> webBrowser; - nsCOMPtr<nsIWebNavigation> webNavigation; - if (chrome) - { - chrome->GetWebBrowser(getter_AddRefs(webBrowser)); - webNavigation = do_QueryInterface(webBrowser); - } - - // Test the message - switch (uMsg) - { - case WM_INITDIALOG: - return TRUE; - - case WM_INITMENU: - UpdateUI(chrome); - return TRUE; - - case WM_SYSCOMMAND: - if (wParam == SC_CLOSE) - { - WebBrowserChromeUI::Destroy(chrome); - return TRUE; - } - break; - - case WM_DESTROY: - return TRUE; - - case WM_COMMAND: - if (!webBrowser) - { - return TRUE; - } - - // Test which command was selected - switch (LOWORD(wParam)) - { - case IDC_ADDRESS: - if (HIWORD(wParam) == CBN_EDITCHANGE || HIWORD(wParam) == CBN_SELCHANGE) - { - // User has changed the address field so enable the Go button - EnableWindow(GetDlgItem(hwndDlg, IDC_GO), TRUE); - } - break; - - case IDC_GO: - { - TCHAR szURL[2048]; - memset(szURL, 0, sizeof(szURL)); - GetDlgItemText(hwndDlg, IDC_ADDRESS, szURL, - sizeof(szURL) / sizeof(szURL[0]) - 1); - webNavigation->LoadURI( - NS_ConvertASCIItoUTF16(szURL).get(), - nsIWebNavigation::LOAD_FLAGS_NONE, - nullptr, - nullptr, - nullptr); - } - break; - - case IDC_STOP: - webNavigation->Stop(nsIWebNavigation::STOP_ALL); - UpdateUI(chrome); - break; - - case IDC_RELOAD: - webNavigation->Reload(nsIWebNavigation::LOAD_FLAGS_NONE); - break; - - case IDM_EXIT: - PostMessage(hwndDlg, WM_SYSCOMMAND, SC_CLOSE, 0); - break; - - // File menu commands - - case MOZ_NewBrowser: - OpenWebPage(gFirstURL); - break; - - // Edit menu commands - - case MOZ_Cut: - { - nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser); - clipCmds->CutSelection(); - } - break; - - case MOZ_Copy: - { - nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser); - clipCmds->CopySelection(); - } - break; - - case MOZ_Paste: - { - nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser); - clipCmds->Paste(); - } - break; - - case MOZ_SelectAll: - { - nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser); - clipCmds->SelectAll(); - } - break; - - case MOZ_SelectNone: - { - nsCOMPtr<nsIClipboardCommands> clipCmds = do_GetInterface(webBrowser); - clipCmds->SelectNone(); - } - break; - - // Go menu commands - case IDC_BACK: - case MOZ_GoBack: - webNavigation->GoBack(); - UpdateUI(chrome); - break; - - case IDC_FORWARD: - case MOZ_GoForward: - webNavigation->GoForward(); - UpdateUI(chrome); - break; - - // Help menu commands - case MOZ_About: - { - TCHAR szAboutTitle[MAX_LOADSTRING]; - TCHAR szAbout[MAX_LOADSTRING]; - LoadString(ghInstanceApp, IDS_ABOUT_TITLE, szAboutTitle, MAX_LOADSTRING); - LoadString(ghInstanceApp, IDS_ABOUT, szAbout, MAX_LOADSTRING); - MessageBox(nullptr, szAbout, szAboutTitle, MB_OK); - } - break; - } - - return TRUE; - - case WM_ACTIVATE: - { - nsCOMPtr<nsIWebBrowserFocus> focus(do_GetInterface(webBrowser)); - if(focus) - { - switch (wParam) - { - case WA_ACTIVE: - focus->Activate(); - break; - case WA_INACTIVE: - focus->Deactivate(); - break; - default: - break; - } - } - } - break; - - case WM_SIZE: - { - UINT newDlgWidth = LOWORD(lParam); - UINT newDlgHeight = HIWORD(lParam); - - // TODO Reposition the control bar - for the moment it's fixed size - - // Reposition the status area. Status bar - // gets any space that the fixed size progress bar doesn't use. - int progressWidth; - int statusWidth; - int statusHeight; - HWND hwndStatus = GetDlgItem(hwndDlg, IDC_STATUS); - if (hwndStatus) { - RECT rcStatus; - GetWindowRect(hwndStatus, &rcStatus); - statusHeight = rcStatus.bottom - rcStatus.top; - } else - statusHeight = 0; - - HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS); - if (hwndProgress) { - RECT rcProgress; - GetWindowRect(hwndProgress, &rcProgress); - progressWidth = rcProgress.right - rcProgress.left; - } else - progressWidth = 0; - statusWidth = newDlgWidth - progressWidth; - - if (hwndStatus) - SetWindowPos(hwndStatus, - HWND_TOP, - 0, newDlgHeight - statusHeight, - statusWidth, - statusHeight, - SWP_NOZORDER); - if (hwndProgress) - SetWindowPos(hwndProgress, - HWND_TOP, - statusWidth, newDlgHeight - statusHeight, - 0, 0, - SWP_NOSIZE | SWP_NOZORDER); - - // Resize the browser area (assuming the browse is - // sandwiched between the control bar and status area) - RECT rcBrowser; - POINT ptBrowser; - GetWindowRect(hwndBrowser, &rcBrowser); - ptBrowser.x = rcBrowser.left; - ptBrowser.y = rcBrowser.top; - ScreenToClient(hwndDlg, &ptBrowser); - int browserHeight = newDlgHeight - ptBrowser.y - statusHeight; - if (browserHeight < 1) - { - browserHeight = 1; - } - SetWindowPos(hwndBrowser, - HWND_TOP, - 0, 0, - newDlgWidth, - newDlgHeight - ptBrowser.y - statusHeight, - SWP_NOMOVE | SWP_NOZORDER); - } - return TRUE; - } - return FALSE; -} - - -// -// FUNCTION: BrowserWndProc(HWND, UINT, WRAPAM, LPARAM) -// -// PURPOSE: Processes messages for the browser container window. -// -LRESULT CALLBACK BrowserWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) -{ - nsIWebBrowserChrome *chrome = (nsIWebBrowserChrome *) GetWindowLongPtr(hWnd, GWLP_USERDATA); - switch (message) - { - case WM_SIZE: - // Resize the embedded browser - ResizeEmbedding(chrome); - return 0; - case WM_ERASEBKGND: - // Reduce flicker by not painting the non-visible background - return 1; - } - return DefWindowProc(hWnd, message, wParam, lParam); -} - -// -// FUNCTION: StartupProfile() -// -// PURPOSE: -// -nsresult StartupProfile() -{ - - nsCOMPtr<nsIFile> appDataDir; - nsresult rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR, getter_AddRefs(appDataDir)); - if (NS_FAILED(rv)) - return rv; - - appDataDir->AppendNative(nsCString("winembed")); - - nsCOMPtr<nsProfileDirServiceProvider> locProvider; - NS_NewProfileDirServiceProvider(true, getter_AddRefs(locProvider)); - if (!locProvider) - return NS_ERROR_FAILURE; - - rv = locProvider->Register(); - if (NS_FAILED(rv)) - return rv; - - return locProvider->SetProfileDir(appDataDir); - -} - - -/////////////////////////////////////////////////////////////////////////////// -// WebBrowserChromeUI - -// -// FUNCTION: CreateNativeWindow() -// -// PURPOSE: Creates a new browser dialog. -// -// COMMENTS: -// -// This function loads the browser dialog from a resource template -// and returns the HWND for the webbrowser container dialog item -// to the caller. -// -HWND WebBrowserChromeUI::CreateNativeWindow(nsIWebBrowserChrome* chrome) -{ - // Load the browser dialog from resource - HWND hwndDialog; - uint32_t chromeFlags; - - chrome->GetChromeFlags(&chromeFlags); - if ((chromeFlags & nsIWebBrowserChrome::CHROME_ALL) == nsIWebBrowserChrome::CHROME_ALL) - hwndDialog = CreateDialog(ghInstanceApp, - MAKEINTRESOURCE(IDD_BROWSER), - nullptr, - BrowserDlgProc); - else - hwndDialog = CreateDialog(ghInstanceApp, - MAKEINTRESOURCE(IDD_BROWSER_NC), - nullptr, - BrowserDlgProc); - if (!hwndDialog) - return nullptr; - - // Stick a menu onto it - if (chromeFlags & nsIWebBrowserChrome::CHROME_MENUBAR) { - HMENU hmenuDlg = LoadMenu(ghInstanceApp, MAKEINTRESOURCE(IDC_WINEMBED)); - SetMenu(hwndDialog, hmenuDlg); - } else - SetMenu(hwndDialog, 0); - - // Add some interesting URLs to the address drop down - HWND hwndAddress = GetDlgItem(hwndDialog, IDC_ADDRESS); - if (hwndAddress) { - for (int i = 0; i < sizeof(gDefaultURLs) / sizeof(gDefaultURLs[0]); i++) - { - SendMessage(hwndAddress, CB_ADDSTRING, 0, (LPARAM) gDefaultURLs[i]); - } - } - - // Fetch the browser window handle - HWND hwndBrowser = GetDlgItem(hwndDialog, IDC_BROWSER); - SetWindowLongPtr(hwndBrowser, GWLP_USERDATA, (LONG_PTR)chrome); // save the browser LONG_PTR. - SetWindowLongPtr(hwndBrowser, GWL_STYLE, GetWindowLongPtr(hwndBrowser, GWL_STYLE) | WS_CLIPCHILDREN); - - // Activate the window - PostMessage(hwndDialog, WM_ACTIVATE, WA_ACTIVE, 0); - - gDialogCount++; - - return hwndBrowser; -} - - -// -// FUNCTION: Destroy() -// -// PURPOSE: Destroy the window specified by the chrome -// -void WebBrowserChromeUI::Destroy(nsIWebBrowserChrome* chrome) -{ - nsCOMPtr<nsIWebBrowser> webBrowser; - nsCOMPtr<nsIWebNavigation> webNavigation; - - chrome->GetWebBrowser(getter_AddRefs(webBrowser)); - webNavigation = do_QueryInterface(webBrowser); - if (webNavigation) - webNavigation->Stop(nsIWebNavigation::STOP_ALL); - - chrome->ExitModalEventLoop(NS_OK); - - HWND hwndDlg = GetBrowserDlgFromChrome(chrome); - if (hwndDlg == nullptr) - return; - - // Explicitly destroy the embedded browser and then the chrome - - // First the browser - nsCOMPtr<nsIWebBrowser> browser = nullptr; - chrome->GetWebBrowser(getter_AddRefs(browser)); - nsCOMPtr<nsIBaseWindow> browserAsWin = do_QueryInterface(browser); - if (browserAsWin) - browserAsWin->Destroy(); - - // Now the chrome - chrome->SetWebBrowser(nullptr); - NS_RELEASE(chrome); -} - - -// -// FUNCTION: Called as the final act of a chrome object during its destructor -// -void WebBrowserChromeUI::Destroyed(nsIWebBrowserChrome* chrome) -{ - HWND hwndDlg = GetBrowserDlgFromChrome(chrome); - if (hwndDlg == nullptr) - { - return; - } - - // Clear the window user data - HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER); - SetWindowLongPtr(hwndBrowser, GWLP_USERDATA, 0); - DestroyWindow(hwndBrowser); - DestroyWindow(hwndDlg); - - --gDialogCount; - if (gDialogCount == 0) - { - // Quit when there are no more browser objects - PostQuitMessage(0); - } -} - - -// -// FUNCTION: Set the input focus onto the browser window -// -void WebBrowserChromeUI::SetFocus(nsIWebBrowserChrome *chrome) -{ - HWND hwndDlg = GetBrowserDlgFromChrome(chrome); - if (hwndDlg == nullptr) - { - return; - } - - HWND hwndBrowser = GetDlgItem(hwndDlg, IDC_BROWSER); - ::SetFocus(hwndBrowser); -} - -// -// FUNCTION: UpdateStatusBarText() -// -// PURPOSE: Set the status bar text. -// -void WebBrowserChromeUI::UpdateStatusBarText(nsIWebBrowserChrome *aChrome, const char16_t* aStatusText) -{ - HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); - nsCString status; - if (aStatusText) { - nsString wStatusText(aStatusText); - NS_UTF16ToCString(wStatusText, NS_CSTRING_ENCODING_NATIVE_FILESYSTEM, - status); - } - - SetDlgItemText(hwndDlg, IDC_STATUS, status.get()); -} - - -// -// FUNCTION: UpdateCurrentURI() -// -// PURPOSE: Updates the URL address field -// -void WebBrowserChromeUI::UpdateCurrentURI(nsIWebBrowserChrome *aChrome) -{ - nsCOMPtr<nsIWebBrowser> webBrowser; - nsCOMPtr<nsIWebNavigation> webNavigation; - aChrome->GetWebBrowser(getter_AddRefs(webBrowser)); - webNavigation = do_QueryInterface(webBrowser); - - nsCOMPtr<nsIURI> currentURI; - webNavigation->GetCurrentURI(getter_AddRefs(currentURI)); - if (currentURI) - { - nsCString uriString; - currentURI->GetAsciiSpec(uriString); - HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); - SetDlgItemText(hwndDlg, IDC_ADDRESS, uriString.get()); - } -} - - -// -// FUNCTION: UpdateBusyState() -// -// PURPOSE: Refreshes the stop/go buttons in the browser dialog -// -void WebBrowserChromeUI::UpdateBusyState(nsIWebBrowserChrome *aChrome, bool aBusy) -{ - HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); - HWND button; - button = GetDlgItem(hwndDlg, IDC_STOP); - if (button) - EnableWindow(button, aBusy); - button = GetDlgItem(hwndDlg, IDC_GO); - if (button) - EnableWindow(button, !aBusy); - UpdateUI(aChrome); -} - - -// -// FUNCTION: UpdateProgress() -// -// PURPOSE: Refreshes the progress bar in the browser dialog -// -void WebBrowserChromeUI::UpdateProgress(nsIWebBrowserChrome *aChrome, int32_t aCurrent, int32_t aMax) -{ - HWND hwndDlg = GetBrowserDlgFromChrome(aChrome); - HWND hwndProgress = GetDlgItem(hwndDlg, IDC_PROGRESS); - if (aCurrent < 0) - { - aCurrent = 0; - } - if (aCurrent > aMax) - { - aMax = aCurrent + 20; // What to do? - } - if (hwndProgress) - { - SendMessage(hwndProgress, PBM_SETRANGE, 0, MAKELPARAM(0, aMax)); - SendMessage(hwndProgress, PBM_SETPOS, aCurrent, 0); - } -} - -// -// FUNCTION: ShowContextMenu() -// -// PURPOSE: Display a context menu for the given node -// -void WebBrowserChromeUI::ShowContextMenu(nsIWebBrowserChrome *aChrome, uint32_t aContextFlags, nsIDOMEvent *aEvent, nsIDOMNode *aNode) -{ - // TODO code to test context flags and display a popup menu should go here -} - -// -// FUNCTION: ShowTooltip() -// -// PURPOSE: Show a tooltip -// -void WebBrowserChromeUI::ShowTooltip(nsIWebBrowserChrome *aChrome, int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText) -{ - // TODO code to show a tooltip should go here -} - -// -// FUNCTION: HideTooltip() -// -// PURPOSE: Hide the tooltip -// -void WebBrowserChromeUI::HideTooltip(nsIWebBrowserChrome *aChrome) -{ - // TODO code to hide a tooltip should go here -} - -void WebBrowserChromeUI::ShowWindow(nsIWebBrowserChrome *aChrome, bool aShow) -{ - HWND win = GetBrowserDlgFromChrome(aChrome); - ::ShowWindow(win, aShow ? SW_RESTORE : SW_HIDE); -} - -void WebBrowserChromeUI::SizeTo(nsIWebBrowserChrome *aChrome, int32_t aWidth, int32_t aHeight) -{ - HWND hchrome = GetBrowserDlgFromChrome(aChrome); - HWND hbrowser = GetBrowserFromChrome(aChrome); - RECT chromeRect, browserRect; - - ::GetWindowRect(hchrome, &chromeRect); - ::GetWindowRect(hbrowser, &browserRect); - - int32_t decoration_x = (browserRect.left - chromeRect.left) + - (chromeRect.right - browserRect.right); - int32_t decoration_y = (browserRect.top - chromeRect.top) + - (chromeRect.bottom - browserRect.bottom); - - ::MoveWindow(hchrome, chromeRect.left, chromeRect.top, - aWidth+decoration_x, - aHeight+decoration_y, TRUE); -} - -// -// FUNCTION: GetResourceStringByID() -// -// PURPOSE: Get the resource string for the ID -// -void WebBrowserChromeUI::GetResourceStringById(int32_t aID, char ** aReturn) -{ - char resBuf[MAX_LOADSTRING]; - int retval = LoadString( ghInstanceApp, aID, (LPTSTR)resBuf, sizeof(resBuf) ); - if (retval != 0) - { - size_t resLen = strlen(resBuf); - *aReturn = (char *)calloc(resLen+1, sizeof(char *)); - if (!*aReturn) return; - strncpy(*aReturn, resBuf, resLen); - } - return; -} - -//----------------------------------------------------------------------------- -// AppCallbacks -//----------------------------------------------------------------------------- - -nsresult AppCallbacks::CreateBrowserWindow(uint32_t aChromeFlags, - nsIWebBrowserChrome *aParent, - nsIWebBrowserChrome **aNewWindow) -{ - WebBrowserChrome * chrome = new WebBrowserChrome(); - if (!chrome) - return NS_ERROR_FAILURE; - - // the interface to return and one addref, which we assume will be - // immediately released - *aNewWindow = static_cast<nsIWebBrowserChrome*>(chrome); - // now an extra addref; the window owns itself (to be released by - // WebBrowserChromeUI::Destroy) - NS_ADDREF(*aNewWindow); - - chrome->SetChromeFlags(aChromeFlags); - chrome->SetParent(aParent); - - // Insert the browser - nsCOMPtr<nsIWebBrowser> newBrowser; - chrome->CreateBrowser(-1, -1, -1, -1, getter_AddRefs(newBrowser)); - if (!newBrowser) - return NS_ERROR_FAILURE; - - // Place it where we want it. - ResizeEmbedding(static_cast<nsIWebBrowserChrome*>(chrome)); - - // if opened as chrome, it'll be made visible after the chrome has loaded. - // otherwise, go ahead and show it now. - if (!(aChromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) - WebBrowserChromeUI::ShowWindow(*aNewWindow, true); - - return NS_OK; -} - -void AppCallbacks::EnableChromeWindow(nsIWebBrowserChrome *aWindow, - bool aEnabled) -{ - HWND hwnd = GetBrowserDlgFromChrome(aWindow); - ::EnableWindow(hwnd, aEnabled ? TRUE : FALSE); -} - -uint32_t AppCallbacks::RunEventLoop(bool &aRunCondition) -{ - MSG msg; - HANDLE hFakeEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); - - while (aRunCondition ) { - // Process pending messages - while (::PeekMessage(&msg, nullptr, 0, 0, PM_NOREMOVE)) { - if (!::GetMessage(&msg, nullptr, 0, 0)) { - // WM_QUIT - aRunCondition = false; - break; - } - - ::TranslateMessage(&msg); - ::DispatchMessage(&msg); - } - - // Do idle stuff - ::MsgWaitForMultipleObjects(1, &hFakeEvent, FALSE, 100, QS_ALLEVENTS); - } - ::CloseHandle(hFakeEvent); - return (uint32_t)msg.wParam; -}
deleted file mode 100644 --- a/embedding/tests/winEmbed/winEmbed.h +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: Mozilla-sample-code 1.0 - * - * Copyright (c) 2002 Netscape Communications Corporation and - * other contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this Mozilla sample software and associated documentation files - * (the "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to permit - * persons to whom the Software is furnished to do so, subject to the - * following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Contributor(s): - * - * ***** END LICENSE BLOCK ***** */ - -#include "nscore.h" - -class nsIWebBrowserChrome; - -namespace AppCallbacks { - nsresult CreateBrowserWindow(uint32_t aChromeFlags, - nsIWebBrowserChrome *aParent, - nsIWebBrowserChrome **aNewWindow); - - void EnableChromeWindow(nsIWebBrowserChrome *aWindow, bool aEnabled); - - uint32_t RunEventLoop(bool &aRunCondition); -}
deleted file mode 100644 --- a/embedding/tests/winEmbed/winEmbed.rc +++ /dev/null @@ -1,265 +0,0 @@ -// Microsoft Visual C++ generated resource script. -// -#include "resource.h" - -#define APSTUDIO_READONLY_SYMBOLS -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 2 resource. -// -#define APSTUDIO_HIDDEN_SYMBOLS -#include "windows.h" -#undef APSTUDIO_HIDDEN_SYMBOLS -#include "resource.h" - -///////////////////////////////////////////////////////////////////////////// -#undef APSTUDIO_READONLY_SYMBOLS - -///////////////////////////////////////////////////////////////////////////// -// English (U.S.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Icon -// - -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. -IDI_WINEMBED ICON "winEmbed.ICO" -IDI_SMALL ICON "SMALL.ICO" - -///////////////////////////////////////////////////////////////////////////// -// -// Menu -// - -IDC_WINEMBED MENU -BEGIN - POPUP "&File" - BEGIN - MENUITEM "New Browser...", MOZ_NewBrowser - MENUITEM "E&xit", IDM_EXIT - END - POPUP "&Edit" - BEGIN - MENUITEM "Cu&t", MOZ_Cut - MENUITEM "&Copy", MOZ_Copy - MENUITEM "&Paste", MOZ_Paste - MENUITEM SEPARATOR - MENUITEM "Select All", MOZ_SelectAll - MENUITEM "Select None", MOZ_SelectNone - END - POPUP "&Go" - BEGIN - MENUITEM "&Back", MOZ_GoBack - MENUITEM "&Forward", MOZ_GoForward - END - POPUP "&Debug" - BEGIN - MENUITEM "&This space for rent", ID_DEBUG_THISSPACEFORRENT - , GRAYED - END - POPUP "&Help" - BEGIN - MENUITEM "&About winEmbed...", MOZ_About - END -END - - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -2 TEXTINCLUDE -BEGIN - "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""windows.h""\r\n" - "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""resource.h""\r\n" - "\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -1 TEXTINCLUDE -BEGIN - "resource.h\0" -END - -#endif // APSTUDIO_INVOKED - - -///////////////////////////////////////////////////////////////////////////// -// -// String Table -// - -STRINGTABLE -BEGIN - IDS_APP_TITLE "winEmbed" - IDS_HELLO "Embedding Mozilla is so much fun!!" - IDS_ABOUT "winEmbed - Gecko embedding sample" - IDS_ABOUT_TITLE "About winEmbed" - IDS_HIST_BACK "Going Back to: " - IDS_HIST_FORWARD "Going Forward to: " - IDS_HIST_RELOAD_NORMAL "Reloading url, (normal) :" -END - -STRINGTABLE -BEGIN - IDS_HIST_RELOAD_BYPASSPROXY "Reloading url, (bypassing Proxy) :" - IDS_HIST_RELOAD_BYPASSCACHE "Reloading url, (bypassing cache) :" - IDS_HIST_ADDURL " added to Session History" - IDS_HIST_RELOAD_BYPASSPROXYANDCACHE - "Reloading url, (bypassing Proxy and cache) :" - IDS_HIST_PURGE "purged from session history" - IDS_HIST_GOTO "Going to history index : " - IDS_HIST_URL " URL : " -END - -#endif // English (U.S.) resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// English (U.K.) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_BROWSER DIALOG 0, 0, 400, 217 -STYLE DS_SETFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | - WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME -CAPTION "winEmbed sample - UNSUPPORTED" -MENU IDC_WINEMBED -FONT 8, "MS Sans Serif" -BEGIN - PUSHBUTTON "Back",IDC_BACK,1,1,21,13 - PUSHBUTTON "Forward",IDC_FORWARD,23,1,30,13 - PUSHBUTTON "Reload",IDC_RELOAD,57,1,28,13 - PUSHBUTTON "Stop",IDC_STOP,86,1,25,13 - LTEXT "Address:",IDC_STATIC,115,3,28,8 - COMBOBOX IDC_ADDRESS,145,1,193,52,CBS_DROPDOWN | CBS_AUTOHSCROLL | - WS_VSCROLL | WS_TABSTOP - DEFPUSHBUTTON "Go",IDC_GO,340,1,25,13 - CONTROL "Embedded Browser",IDC_BROWSER,"WINEMBED",WS_TABSTOP,0, - 16,400,192 - CONTROL "Status",IDC_STATUS,"Static",SS_LEFTNOWORDWRAP | - SS_SUNKEN | WS_GROUP,0,208,316,9 - CONTROL "Progress1",IDC_PROGRESS,"msctls_progress32",WS_BORDER, - 316,208,84,9 -END - -IDD_BROWSER_NC DIALOG 0, 0, 400, 217 -STYLE DS_SETFONT | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | - WS_CLIPCHILDREN | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME -CAPTION "winEmbed chromeless sample" -MENU IDC_WINEMBED -FONT 8, "MS Sans Serif" -BEGIN - CONTROL "Embedded Browser",IDC_BROWSER,"WINEMBED",WS_TABSTOP,0,0, - 400,217 -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_BROWSER, DIALOG - BEGIN - RIGHTMARGIN, 292 - BOTTOMMARGIN, 216 - END -END -#endif // APSTUDIO_INVOKED - -#endif // English (U.K.) resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// English (Ireland) resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENI) -#ifdef _WIN32 -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_EIRE -#pragma code_page(1252) -#endif //_WIN32 - -///////////////////////////////////////////////////////////////////////////// -// -// Dialog -// - -IDD_CHOOSEPROFILE DIALOG 0, 0, 186, 154 -STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | - WS_SYSMENU -CAPTION "Choose Profile" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "Available Profiles:",IDC_STATIC,7,7,56,8 - LISTBOX IDC_PROFILELIST,7,18,117,129,LBS_NOINTEGRALHEIGHT | - WS_VSCROLL | WS_TABSTOP - DEFPUSHBUTTON "Select",IDOK,129,18,50,14 - PUSHBUTTON "Cancel",IDCANCEL,129,36,50,14 -END - - -///////////////////////////////////////////////////////////////////////////// -// -// DESIGNINFO -// - -#ifdef APSTUDIO_INVOKED -GUIDELINES DESIGNINFO -BEGIN - IDD_CHOOSEPROFILE, DIALOG - BEGIN - LEFTMARGIN, 7 - RIGHTMARGIN, 179 - TOPMARGIN, 7 - BOTTOMMARGIN, 147 - END -END -#endif // APSTUDIO_INVOKED - -#endif // English (Ireland) resources -///////////////////////////////////////////////////////////////////////////// - - - -#ifndef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// Generated from the TEXTINCLUDE 3 resource. -// - - -///////////////////////////////////////////////////////////////////////////// -#endif // not APSTUDIO_INVOKED -
deleted file mode 100644 --- a/embedding/tests/winEmbed/winembed.dsp +++ /dev/null @@ -1,141 +0,0 @@ -# Microsoft Developer Studio Project File - Name="winembed" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 6.00 -# ** DO NOT EDIT ** - -# TARGTYPE "Win32 (x86) External Target" 0x0106 - -CFG=winembed - Win32 Debug -!MESSAGE This is not a valid makefile. To build this project using NMAKE, -!MESSAGE use the Export Makefile command and run -!MESSAGE -!MESSAGE NMAKE /f "winembed.mak". -!MESSAGE -!MESSAGE You can specify a configuration when running NMAKE -!MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE -!MESSAGE NMAKE /f "winembed.mak" CFG="winembed - Win32 Debug" -!MESSAGE -!MESSAGE Possible choices for configuration are: -!MESSAGE -!MESSAGE "winembed - Win32 Release" (based on "Win32 (x86) External Target") -!MESSAGE "winembed - Win32 Debug" (based on "Win32 (x86) External Target") -!MESSAGE - -# Begin Project -# PROP AllowPerConfigDependencies 0 -# PROP Scc_ProjName "" -# PROP Scc_LocalPath "" - -!IF "$(CFG)" == "winembed - Win32 Release" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 0 -# PROP BASE Output_Dir "Release" -# PROP BASE Intermediate_Dir "Release" -# PROP BASE Cmd_Line "NMAKE /f winembed.mak" -# PROP BASE Rebuild_Opt "/a" -# PROP BASE Target_File "winembed.exe" -# PROP BASE Bsc_Name "winembed.bsc" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 0 -# PROP Output_Dir "Release" -# PROP Intermediate_Dir "Release" -# PROP Cmd_Line "nmake /f makefile.win" -# PROP Rebuild_Opt "/a" -# PROP Target_File "win32_o.obj\winembed.exe" -# PROP Bsc_Name "" -# PROP Target_Dir "" - -!ELSEIF "$(CFG)" == "winembed - Win32 Debug" - -# PROP BASE Use_MFC 0 -# PROP BASE Use_Debug_Libraries 1 -# PROP BASE Output_Dir "Debug" -# PROP BASE Intermediate_Dir "Debug" -# PROP BASE Cmd_Line "NMAKE /f winembed.mak" -# PROP BASE Rebuild_Opt "/a" -# PROP BASE Target_File "winembed.exe" -# PROP BASE Bsc_Name "winembed.bsc" -# PROP BASE Target_Dir "" -# PROP Use_MFC 0 -# PROP Use_Debug_Libraries 1 -# PROP Output_Dir "Debug" -# PROP Intermediate_Dir "Debug" -# PROP Cmd_Line "nmake /f makefile.win" -# PROP Rebuild_Opt "/a" -# PROP Target_File "win32_d.obj\winembed.exe" -# PROP Bsc_Name "" -# PROP Target_Dir "" - -!ENDIF - -# Begin Target - -# Name "winembed - Win32 Release" -# Name "winembed - Win32 Debug" - -!IF "$(CFG)" == "winembed - Win32 Release" - -!ELSEIF "$(CFG)" == "winembed - Win32 Debug" - -!ENDIF - -# Begin Group "Source Files" - -# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" -# Begin Source File - -SOURCE=.\WebBrowserChrome.cpp -# End Source File -# Begin Source File - -SOURCE=.\WindowCreator.cpp -# End Source File -# Begin Source File - -SOURCE=.\winEmbed.cpp -# End Source File -# End Group -# Begin Group "Header Files" - -# PROP Default_Filter "h;hpp;hxx;hm;inl" -# Begin Source File - -SOURCE=.\resource.h -# End Source File -# Begin Source File - -SOURCE=.\StdAfx.h -# End Source File -# Begin Source File - -SOURCE=.\WebBrowserChrome.h -# End Source File -# Begin Source File - -SOURCE=.\WindowCreator.h -# End Source File -# Begin Source File - -SOURCE=.\winEmbed.h -# End Source File -# End Group -# Begin Group "Resource Files" - -# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" -# Begin Source File - -SOURCE=.\SMALL.ICO -# End Source File -# Begin Source File - -SOURCE=.\winEmbed.ICO -# End Source File -# Begin Source File - -SOURCE=.\winEmbed.rc -# End Source File -# End Group -# End Target -# End Project
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -1634,20 +1634,24 @@ nsEventStatus AsyncPanZoomController::On mY.StartTouch(aEvent.mLocalPanStartPoint.y, aEvent.mTime); if (GetAxisLockMode() == FREE) { SetState(PANNING); return nsEventStatus_eConsumeNoDefault; } float dx = aEvent.mPanDisplacement.x, dy = aEvent.mPanDisplacement.y; - double angle = atan2(dy, dx); // range [-pi, pi] - angle = fabs(angle); // range [0, pi] - - HandlePanning(angle); + + if (dx || dy) { + double angle = atan2(dy, dx); // range [-pi, pi] + angle = fabs(angle); // range [0, pi] + HandlePanning(angle); + } else { + SetState(PANNING); + } return nsEventStatus_eConsumeNoDefault; } nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, ScrollSource aSource, bool aFingersOnTouchpad) { APZC_LOG("%p got a pan-pan in state %d\n", this, mState); if (mState == SMOOTH_SCROLL) {
--- a/gfx/qcms/iccread.c +++ b/gfx/qcms/iccread.c @@ -600,22 +600,24 @@ static struct lutmABType *read_tag_lutmA lut = malloc(sizeof(struct lutmABType) + (clut_size) * sizeof(float)); if (!lut) return NULL; // we'll fill in the rest below memset(lut, 0, sizeof(struct lutmABType)); lut->clut_table = &lut->clut_table_data[0]; - for (i = 0; i < num_in_channels; i++) { - lut->num_grid_points[i] = read_u8(src, clut_offset + i); - if (lut->num_grid_points[i] == 0) { - invalid_source(src, "bad grid_points"); + if (clut_offset) { + for (i = 0; i < num_in_channels; i++) { + lut->num_grid_points[i] = read_u8(src, clut_offset + i); + if (lut->num_grid_points[i] == 0) { + invalid_source(src, "bad grid_points"); + } } - } + } // Reverse the processing of transformation elements for mBA type. lut->reversed = (type == LUT_MBA_TYPE); lut->num_in_channels = num_in_channels; lut->num_out_channels = num_out_channels; if (matrix_offset) {
--- a/intl/uconv/nsUCSupport.h +++ b/intl/uconv/nsUCSupport.h @@ -145,53 +145,16 @@ public: char16_t * aDest, int32_t * aDestLength); NS_IMETHOD Reset(); NS_IMETHOD GetMaxLength(const char *aSrc, int32_t aSrcLength, int32_t* aDestLength); }; //---------------------------------------------------------------------- -// Class nsTableDecoderSupport [declaration] - -/** - * Support class for a single-table-driven Unicode decoder. - * - * @created 15/Mar/1999 - * @author Catalin Rotaru [CATA] - */ -class nsTableDecoderSupport : public nsBufferDecoderSupport -{ -public: - - /** - * Class constructor. - */ - nsTableDecoderSupport(uScanClassID aScanClass, uShiftInTable * aShiftInTable, - uMappingTable * aMappingTable, uint32_t aMaxLengthFactor); - - /** - * Class destructor. - */ - virtual ~nsTableDecoderSupport(); - -protected: - - uScanClassID mScanClass; - uShiftInTable * mShiftInTable; - uMappingTable * mMappingTable; - - //-------------------------------------------------------------------- - // Subclassing of nsBufferDecoderSupport class [declaration] - - NS_IMETHOD ConvertNoBuff(const char * aSrc, int32_t * aSrcLength, - char16_t * aDest, int32_t * aDestLength); -}; - -//---------------------------------------------------------------------- // Class nsMultiTableDecoderSupport [declaration] /** * Support class for a multi-table-driven Unicode decoder. * * @created 24/Mar/1999 * @author Catalin Rotaru [CATA] */
--- a/intl/uconv/ucvcn/nsGBKToUnicode.cpp +++ b/intl/uconv/ucvcn/nsGBKToUnicode.cpp @@ -7,65 +7,31 @@ * * * @created 07/Sept/1999 * @author Yueheng Xu, Yueheng.Xu@intel.com */ #include "nsGBKToUnicode.h" #include "gbku.h" - -//------------------------------------------------------------ -// nsGB18030Unique2BytesToUnicode -//------------------------------------------------------------ -class nsGB18030Unique2BytesToUnicode : public nsTableDecoderSupport -{ -public: - nsGB18030Unique2BytesToUnicode(); - virtual ~nsGB18030Unique2BytesToUnicode() - { } -protected: -}; +#include "nsUnicodeDecodeHelper.h" static const uint16_t g_utGB18030Unique2Bytes[] = { #include "gb18030uniq2b.ut" }; -nsGB18030Unique2BytesToUnicode::nsGB18030Unique2BytesToUnicode() - : nsTableDecoderSupport(u2BytesCharset, nullptr, - (uMappingTable*) &g_utGB18030Unique2Bytes, 1) -{ -} - -//------------------------------------------------------------ -// nsGB18030Unique4BytesToUnicode -//------------------------------------------------------------ -class nsGB18030Unique4BytesToUnicode : public nsTableDecoderSupport -{ -public: - nsGB18030Unique4BytesToUnicode(); - virtual ~nsGB18030Unique4BytesToUnicode() - { } -protected: -}; static const uint16_t g_utGB18030Unique4Bytes[] = { #include "gb180304bytes.ut" }; -nsGB18030Unique4BytesToUnicode::nsGB18030Unique4BytesToUnicode() - : nsTableDecoderSupport(u4BytesGB18030Charset, nullptr, - (uMappingTable*) &g_utGB18030Unique4Bytes, 1) -{ -} - //---------------------------------------------------------------------- -// Class nsGBKToUnicode [implementation] +// Class nsGB18030ToUnicode [implementation] //---------------------------------------------------------------------- -// Subclassing of nsTablesDecoderSupport class [implementation] +// Subclassing of nsBufferDecoderSupport class [implementation] #define LEGAL_GBK_MULTIBYTE_FIRST_BYTE(c) \ (UINT8_IN_RANGE(0x81, (c), 0xFE)) #define FIRST_BYTE_IS_SURROGATE(c) \ (UINT8_IN_RANGE(0x90, (c), 0xFE)) #define LEGAL_GBK_2BYTE_SECOND_BYTE(c) \ (UINT8_IN_RANGE(0x40, (c), 0x7E)|| UINT8_IN_RANGE(0x80, (c), 0xFE)) #define LEGAL_GBK_4BYTE_SECOND_BYTE(c) \ @@ -202,24 +168,16 @@ NS_IMETHODIMP nsGB18030ToUnicode::Conver iDestlen++; aDest++; *aSrcLength = i+1; } *aDestLength = iDestlen; return rv; } -void nsGB18030ToUnicode::CreateExtensionDecoder() -{ - mExtensionDecoder = new nsGB18030Unique2BytesToUnicode(); -} -void nsGB18030ToUnicode::Create4BytesDecoder() -{ - m4BytesDecoder = new nsGB18030Unique4BytesToUnicode(); -} bool nsGB18030ToUnicode::DecodeToSurrogate(const char* aSrc, char16_t* aOut) { NS_ASSERTION(FIRST_BYTE_IS_SURROGATE(aSrc[0]), "illegal first byte"); NS_ASSERTION(LEGAL_GBK_4BYTE_SECOND_BYTE(aSrc[1]), "illegal second byte"); NS_ASSERTION(LEGAL_GBK_4BYTE_THIRD_BYTE(aSrc[2]), "illegal third byte"); NS_ASSERTION(LEGAL_GBK_4BYTE_FORTH_BYTE(aSrc[3]), "illegal forth byte"); if(! FIRST_BYTE_IS_SURROGATE(aSrc[0])) return false; @@ -245,48 +203,37 @@ bool nsGB18030ToUnicode::DecodeToSurroga *aOut++ = 0xD800 | (idx >> 10); *aOut = 0xDC00 | (0x000003FF & idx); return true; } bool nsGB18030ToUnicode::TryExtensionDecoder(const char* aSrc, char16_t* aOut) { - if(!mExtensionDecoder) - CreateExtensionDecoder(); - NS_ASSERTION(mExtensionDecoder, "cannot creqte 2 bytes unique converter"); - if(mExtensionDecoder) - { - nsresult res = mExtensionDecoder->Reset(); - NS_ASSERTION(NS_SUCCEEDED(res), "2 bytes unique conversoin reset failed"); - int32_t len = 2; - int32_t dstlen = 1; - res = mExtensionDecoder->Convert(aSrc,&len, aOut, &dstlen); - NS_ASSERTION(NS_FAILED(res) || ((len==2) && (dstlen == 1)), - "some strange conversion result"); - // if we failed, we then just use the 0xfffd - // therefore, we ignore the res here. - if(NS_SUCCEEDED(res)) - return true; - } - return false; + int32_t len = 2; + int32_t dstlen = 1; + nsresult res = + nsUnicodeDecodeHelper::ConvertByTable(aSrc, &len, aOut, &dstlen, + u2BytesCharset, nullptr, + (uMappingTable*) &g_utGB18030Unique2Bytes, + false); + NS_ASSERTION(NS_FAILED(res) || ((len==2) && (dstlen == 1)), + "some strange conversion result"); + // if we failed, we then just use the 0xfffd + // therefore, we ignore the res here. + return NS_SUCCEEDED(res); } bool nsGB18030ToUnicode::Try4BytesDecoder(const char* aSrc, char16_t* aOut) { - if(!m4BytesDecoder) - Create4BytesDecoder(); - if(m4BytesDecoder) - { - nsresult res = m4BytesDecoder->Reset(); - NS_ASSERTION(NS_SUCCEEDED(res), "4 bytes unique conversoin reset failed"); - int32_t len = 4; - int32_t dstlen = 1; - res = m4BytesDecoder->Convert(aSrc,&len, aOut, &dstlen); - NS_ASSERTION(NS_FAILED(res) || ((len==4) && (dstlen == 1)), - "some strange conversion result"); - // if we failed, we then just use the 0xfffd - // therefore, we ignore the res here. - if(NS_SUCCEEDED(res)) - return true; - } - return false; + int32_t len = 4; + int32_t dstlen = 1; + nsresult res = + nsUnicodeDecodeHelper::ConvertByTable(aSrc, &len, aOut, &dstlen, + u4BytesGB18030Charset, nullptr, + (uMappingTable*) &g_utGB18030Unique4Bytes, + false); + NS_ASSERTION(NS_FAILED(res) || ((len==4) && (dstlen == 1)), + "some strange conversion result"); + // if we failed, we then just use the 0xfffd + // therefore, we ignore the res here. + return NS_SUCCEEDED(res); }
--- a/intl/uconv/ucvcn/nsGBKToUnicode.h +++ b/intl/uconv/ucvcn/nsGBKToUnicode.h @@ -24,33 +24,27 @@ class nsGB18030ToUnicode : public nsBuff { public: /** * Class constructor. */ nsGB18030ToUnicode() : nsBufferDecoderSupport(1) { - mExtensionDecoder = nullptr; - m4BytesDecoder = nullptr; } protected: //-------------------------------------------------------------------- - // Subclassing of nsDecoderSupport class [declaration] + // Subclassing of nsBufferDecoderSupport class [declaration] NS_IMETHOD ConvertNoBuff(const char* aSrc, int32_t * aSrcLength, char16_t *aDest, int32_t * aDestLength); protected: nsGBKConvUtil mUtil; - nsCOMPtr<nsIUnicodeDecoder> mExtensionDecoder; - nsCOMPtr<nsIUnicodeDecoder> m4BytesDecoder; - void CreateExtensionDecoder(); - void Create4BytesDecoder(); bool TryExtensionDecoder(const char* aSrc, char16_t* aDest); bool Try4BytesDecoder(const char* aSrc, char16_t* aDest); bool DecodeToSurrogate(const char* aSrc, char16_t* aDest); }; #endif /* nsGBKToUnicode_h___ */
--- a/intl/uconv/util/nsUCSupport.cpp +++ b/intl/uconv/util/nsUCSupport.cpp @@ -194,49 +194,16 @@ NS_IMETHODIMP nsBufferDecoderSupport::Ge return NS_ERROR_OUT_OF_MEMORY; } *aDestLength = length.value(); return NS_OK; } //---------------------------------------------------------------------- -// Class nsTableDecoderSupport [implementation] - -nsTableDecoderSupport::nsTableDecoderSupport(uScanClassID aScanClass, - uShiftInTable* aShiftInTable, - uMappingTable* aMappingTable, - uint32_t aMaxLengthFactor) -: nsBufferDecoderSupport(aMaxLengthFactor) -{ - mScanClass = aScanClass; - mShiftInTable = aShiftInTable; - mMappingTable = aMappingTable; -} - -nsTableDecoderSupport::~nsTableDecoderSupport() -{ -} - -//---------------------------------------------------------------------- -// Subclassing of nsBufferDecoderSupport class [implementation] - -NS_IMETHODIMP nsTableDecoderSupport::ConvertNoBuff(const char* aSrc, - int32_t* aSrcLength, - char16_t* aDest, - int32_t* aDestLength) -{ - return nsUnicodeDecodeHelper::ConvertByTable(aSrc, aSrcLength, - aDest, aDestLength, - mScanClass, - mShiftInTable, mMappingTable, - mErrBehavior == kOnError_Signal); -} - -//---------------------------------------------------------------------- // Class nsMultiTableDecoderSupport [implementation] nsMultiTableDecoderSupport::nsMultiTableDecoderSupport( int32_t aTableCount, const uRange* aRangeArray, uScanClassID* aScanClassArray, uMappingTable** aMappingTable, uint32_t aMaxLengthFactor)
new file mode 100644 --- /dev/null +++ b/js/src/jit-test/tests/baseline/bug1153458.js @@ -0,0 +1,13 @@ +// |jit-test| baseline-eager; error: TypeError +try { + __defineGetter__("x", Iterator)() +} catch (e) {} +f = function() { + return (function() { + this.x + }) +}() +try { + f() +} catch (e) {} +f()
--- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -7661,74 +7661,78 @@ ICGetProp_CallScripted::Compiler::genera bool ICGetProp_CallNative::Compiler::generateStubCode(MacroAssembler& masm) { MOZ_ASSERT(engine_ == Engine::Baseline); Label failure; - AllocatableGeneralRegisterSet regs(availableGeneralRegs(0)); + AllocatableGeneralRegisterSet regs(availableGeneralRegs(1)); Register objReg = InvalidReg; MOZ_ASSERT(!(inputDefinitelyObject_ && outerClass_)); if (inputDefinitelyObject_) { objReg = R0.scratchReg(); } else { - regs.take(R0); // Guard input is an object and unbox. masm.branchTestObject(Assembler::NotEqual, R0, &failure); objReg = masm.extractObject(R0, ExtractTemp0); if (outerClass_) { ValueOperand val = regs.takeAnyValue(); Register tmp = regs.takeAny(); masm.branchTestObjClass(Assembler::NotEqual, objReg, tmp, outerClass_, &failure); masm.loadPtr(Address(objReg, ProxyDataOffset + offsetof(ProxyDataLayout, values)), tmp); masm.loadValue(Address(tmp, offsetof(ProxyValueArray, privateSlot)), val); - objReg = masm.extractObject(val, ExtractTemp0); + masm.movePtr(masm.extractObject(val, ExtractTemp0), objReg); regs.add(val); regs.add(tmp); } } - regs.takeUnchecked(objReg); Register scratch = regs.takeAnyExcluding(ICTailCallReg); // Shape guard. GuardReceiverObject(masm, ReceiverGuard(receiver_), objReg, scratch, ICGetProp_CallNative::offsetOfReceiverGuard(), &failure); if (receiver_ != holder_ ) { Register holderReg = regs.takeAny(); masm.loadPtr(Address(ICStubReg, ICGetProp_CallNative::offsetOfHolder()), holderReg); masm.loadPtr(Address(ICStubReg, ICGetProp_CallNative::offsetOfHolderShape()), scratch); masm.branchTestObjShape(Assembler::NotEqual, holderReg, scratch, &failure); regs.add(holderReg); } + // Box and push obj onto baseline frame stack for decompiler + if (inputDefinitelyObject_) + masm.tagValue(JSVAL_TYPE_OBJECT, objReg, R0); + EmitStowICValues(masm, 1); + if (inputDefinitelyObject_) + objReg = masm.extractObject(R0, ExtractTemp0); + // Push a stub frame so that we can perform a non-tail call. enterStubFrame(masm, scratch); // Load callee function. Register callee = regs.takeAny(); masm.loadPtr(Address(ICStubReg, ICGetProp_CallNative::offsetOfGetter()), callee); // Push args for vm call. masm.push(objReg); masm.push(callee); - if (!inputDefinitelyObject_) - regs.add(R0); - else - regs.add(objReg); + regs.add(R0); if (!callVM(DoCallNativeGetterInfo, masm)) return false; leaveStubFrame(masm); + EmitUnstowICValues(masm, 1, /* discard = */true); + // Enter type monitor IC to type-check result. EmitEnterTypeMonitorIC(masm); // Failure case - jump to next stub masm.bind(&failure); EmitStubGuardFailure(masm); return true; }
--- a/js/src/jit/JitSpewer.h +++ b/js/src/jit/JitSpewer.h @@ -92,16 +92,17 @@ namespace jit { enum JitSpewChannel { #define JITSPEW_CHANNEL(name) JitSpew_##name, JITSPEW_CHANNEL_LIST(JITSPEW_CHANNEL) #undef JITSPEW_CHANNEL JitSpew_Terminator }; class MIRGenerator; +class TempAllocator; // The JitSpewer is only available on debug builds. // None of the global functions have effect on non-debug builds. static const int NULL_ID = -1; #ifdef DEBUG // Class made to hold the MIR and LIR graphs of an AsmJS / Ion compilation.
--- a/js/src/jit/none/LIR-none.h +++ b/js/src/jit/none/LIR-none.h @@ -41,13 +41,14 @@ class LTableSwitchV : public LInstructio const LDefinition* tempPointer() { MOZ_CRASH(); } static const size_t InputValue = 0; }; class LGuardShape : public LInstruction {}; class LGuardObjectGroup : public LInstruction {}; class LMulI : public LInstruction {}; +class LRandom : public LInstructionHelper<1, 0, 5> {}; } // namespace jit } // namespace js #endif /* jit_none_LIR_none_h */
--- a/js/src/jit/none/Lowering-none.h +++ b/js/src/jit/none/Lowering-none.h @@ -80,17 +80,17 @@ class LIRGeneratorNone : public LIRGener LTableSwitch* newLTableSwitch(LAllocation, LDefinition, MTableSwitch*) { MOZ_CRASH(); } LTableSwitchV* newLTableSwitchV(MTableSwitch*) { MOZ_CRASH(); } void visitSimdSelect(MSimdSelect* ins) { MOZ_CRASH(); } void visitSimdSplatX4(MSimdSplatX4* ins) { MOZ_CRASH(); } void visitSimdValueX4(MSimdValueX4* lir) { MOZ_CRASH(); } void visitSubstr(MSubstr*) { MOZ_CRASH(); } void visitSimdBinaryArith(js::jit::MSimdBinaryArith*) { MOZ_CRASH(); } - + void visitRandom(MRandom* ) { MOZ_CRASH(); } }; typedef LIRGeneratorNone LIRGeneratorSpecific; } // namespace jit } // namespace js
--- a/js/src/jit/none/MacroAssembler-none.h +++ b/js/src/jit/none/MacroAssembler-none.h @@ -138,16 +138,21 @@ class Assembler : public AssemblerShared MOZ_CRASH(); } }; class Operand { public: Operand (const Address&) { MOZ_CRASH();} + Operand (const Register) { MOZ_CRASH();} + Operand (const FloatRegister) { MOZ_CRASH();} + Operand (Register, Imm32 ) { MOZ_CRASH(); } + Operand (Register, int32_t ) { MOZ_CRASH(); } + }; class MacroAssemblerNone : public Assembler { public: MacroAssemblerNone() { MOZ_CRASH(); }
--- a/js/src/tests/lib/jittests.py +++ b/js/src/tests/lib/jittests.py @@ -210,16 +210,18 @@ class Test: if options.can_test_also_noasmjs: test.test_also.append(['--no-asmjs']) elif name.startswith('test-also='): test.test_also.append([name[len('test-also='):]]) elif name.startswith('test-join='): test.test_join.append([name[len('test-join='):]]) elif name == 'ion-eager': test.jitflags.append('--ion-eager') + elif name == 'baseline-eager': + test.jitflags.append('--baseline-eager') elif name == 'dump-bytecode': test.jitflags.append('--dump-bytecode') elif name.startswith('--'): # // |jit-test| --ion-gvn=off; --no-sse4 test.jitflags.append(name) else: print('{}: warning: unrecognized |jit-test| attribute' ' {}'.format(path, part))
--- a/js/xpconnect/idl/nsIScriptError.idl +++ b/js/xpconnect/idl/nsIScriptError.idl @@ -7,17 +7,17 @@ * nsIConsoleMessage subclass for representing JavaScript errors and warnings. */ #include "nsISupports.idl" #include "nsIConsoleMessage.idl" %{C++ -#include "nsString.h" // for nsDependentCString +#include "nsStringGlue.h" // for nsDependentCString %} [scriptable, uuid(248b2c94-2736-4d29-bfdf-bc64a2e60d35)] interface nsIScriptError : nsIConsoleMessage { /** pseudo-flag for default case */ const unsigned long errorFlag = 0x0;
--- a/layout/base/moz.build +++ b/layout/base/moz.build @@ -72,17 +72,17 @@ EXPORTS += [ 'nsDisplayList.h', 'nsDisplayListInvalidation.h', 'nsFrameManager.h', 'nsFrameManagerBase.h', 'nsFrameTraversal.h', 'nsIFrameTraversal.h', 'nsILayoutDebugger.h', 'nsILayoutHistoryState.h', - 'nsIPercentHeightObserver.h', + 'nsIPercentBSizeObserver.h', 'nsIPresShell.h', 'nsIReflowCallback.h', 'nsLayoutUtils.h', 'nsPresArena.h', 'nsPresContext.h', 'nsPresState.h', 'nsRefreshDriver.h', 'nsStyleChangeList.h',
--- a/layout/base/nsBidiPresUtils.cpp +++ b/layout/base/nsBidiPresUtils.cpp @@ -729,41 +729,54 @@ nsBidiPresUtils::ResolveParagraph(nsBloc (void*)aBlockFrame, NS_ConvertUTF16toUTF8(aBpd->mBuffer).get(), frameCount, runCount); #ifdef REALLY_NOISY_BIDI printf(" block frame tree=:\n"); aBlockFrame->List(stdout, 0); #endif #endif #endif - if (runCount == 1 && frameCount == 1 && + bool isNonBidi = false; + + nsIFrame* frame0 = frameCount > 0 ? aBpd->FrameAt(0) : nullptr; + nsIFrame* frame1 = frameCount > 1 ? aBpd->FrameAt(1) : nullptr; + + // Non-bidi frames + if (runCount == 1 && (frameCount == 1 || frameCount == 2) && aBpd->mParagraphDepth == 0 && aBpd->GetDirection() == NSBIDI_LTR && - aBpd->GetParaLevel() == 0) { - // We have a single left-to-right frame in a left-to-right paragraph, + aBpd->GetParaLevel() == 0 && + frame0 != NS_BIDI_CONTROL_FRAME && + !frame0->Properties().Get(nsIFrame::EmbeddingLevelProperty()) && + !frame0->Properties().Get(nsIFrame::BaseLevelProperty())) { + // We have a left-to-right frame in a left-to-right paragraph, // without bidi isolation from the surrounding text. - // Make sure that the embedding level and base level frame properties aren't + // The embedding level and base level frame properties aren't // set (because if they are this frame used to have some other direction, - // so we can't do this optimization), and we're done. - nsIFrame* frame = aBpd->FrameAt(0); - if (frame != NS_BIDI_CONTROL_FRAME && - !frame->Properties().Get(nsIFrame::EmbeddingLevelProperty()) && - !frame->Properties().Get(nsIFrame::BaseLevelProperty())) { + // so we can't do this optimization) + // As long as this is the only frame, or it's followed by a linebreak, + // this is a non-bidi paragraph. + if (!frame1 || (frame1 != NS_BIDI_CONTROL_FRAME && + frame1->GetType() == nsGkAtoms::brFrame)) { + isNonBidi = true; + } + } + + if (isNonBidi) { #ifdef DEBUG #ifdef NOISY_BIDI - printf("early return for single direction frame %p\n", (void*)frame); + printf("early return for single direction frame %p\n", (void*)frame); #endif #endif - frame->AddStateBits(NS_FRAME_IS_BIDI); - return NS_OK; - } + return NS_OK; } nsIFrame* firstFrame = nullptr; nsIFrame* lastFrame = nullptr; + // Bidi frames for (; ;) { if (fragmentLength <= 0) { // Get the next frame from mLogicalFrames if (++frameIndex >= frameCount) { break; } frame = aBpd->FrameAt(frameIndex); if (frame == NS_BIDI_CONTROL_FRAME ||
--- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -110,19 +110,24 @@ AdjustCaretFrameForLineEnd(nsIFrame** aF NS_ASSERTION(r->GetType() == nsGkAtoms::textFrame, "Expected text frame"); *aOffset = (static_cast<nsTextFrame*>(r))->GetContentEnd(); return; } } } static bool -IsBidiUI() +IsKeyboardRTL() { - return Preferences::GetBool("bidi.browser.ui"); + bool isKeyboardRTL = false; + nsIBidiKeyboard* bidiKeyboard = nsContentUtils::GetBidiKeyboard(); + if (bidiKeyboard) { + bidiKeyboard->IsLangRTL(&isKeyboardRTL); + } + return isKeyboardRTL; } nsCaret::nsCaret() : mOverrideOffset(0) , mIsBlinkOn(false) , mBlinkCount(-1) , mVisible(false) , mReadOnly(false) @@ -473,28 +478,40 @@ nsCaret::SetCaretPosition(nsIDOMNode* aN { mOverrideContent = do_QueryInterface(aNode); mOverrideOffset = aOffset; ResetBlinking(); SchedulePaint(); } +bool +nsCaret::IsBidiUI() +{ + nsIFrame* frame = nullptr; + + if(Selection* selection = GetSelectionInternal()) { + int32_t contentOffset; + frame = GetFrameAndOffset(selection, mOverrideContent, mOverrideOffset, + &contentOffset); + } + + return (frame && frame->GetStateBits() & NS_FRAME_IS_BIDI) || + Preferences::GetBool("bidi.browser.ui"); +} + void nsCaret::CheckSelectionLanguageChange() { if (!IsBidiUI()) { return; } - bool isKeyboardRTL = false; - nsIBidiKeyboard* bidiKeyboard = nsContentUtils::GetBidiKeyboard(); - if (bidiKeyboard) { - bidiKeyboard->IsLangRTL(&isKeyboardRTL); - } + bool isKeyboardRTL = IsKeyboardRTL(); + // Call SelectionLanguageChange on every paint. Mostly it will be a noop // but it should be fast anyway. This guarantees we never paint the caret // at the wrong place. Selection* selection = GetSelectionInternal(); if (selection) { selection->SelectionLanguageChange(isKeyboardRTL); } } @@ -673,18 +690,19 @@ nsCaret::GetCaretFrameForNodeOffset(nsFr // // Direction Style from visibility->mDirection // ------------------ // NS_STYLE_DIRECTION_LTR : LTR or Default // NS_STYLE_DIRECTION_RTL if (theFrame->PresContext()->BidiEnabled()) { // If there has been a reflow, take the caret Bidi level to be the level of the current frame - if (aBidiLevel & BIDI_LEVEL_UNDEFINED) + if (aBidiLevel & BIDI_LEVEL_UNDEFINED) { aBidiLevel = NS_GET_EMBEDDING_LEVEL(theFrame); + } int32_t start; int32_t end; nsIFrame* frameBefore; nsIFrame* frameAfter; nsBidiLevel levelBefore; // Bidi level of the character before the caret nsBidiLevel levelAfter; // Bidi level of the character after the caret @@ -897,31 +915,32 @@ nsCaret::ComputeCaretRects(nsIFrame* aFr if (NS_STYLE_DIRECTION_RTL == vis->mDirection) { if (isVertical) { aCaretRect->y -= aCaretRect->height; } else { aCaretRect->x -= aCaretRect->width; } } - // Simon -- make a hook to draw to the left or right of the caret to show keyboard language direction aHookRect->SetEmpty(); - if (!IsBidiUI()) { + + Selection* selection = GetSelectionInternal(); + if (!selection || !selection->GetFrameSelection()) { return; } - bool isCaretRTL; - nsIBidiKeyboard* bidiKeyboard = nsContentUtils::GetBidiKeyboard(); - // if bidiKeyboard->IsLangRTL() fails, there is no way to tell the - // keyboard direction, or the user has no right-to-left keyboard - // installed, so we never draw the hook. - if (bidiKeyboard && NS_SUCCEEDED(bidiKeyboard->IsLangRTL(&isCaretRTL))) { - // If keyboard language is RTL, draw the hook on the left; if LTR, to the right + if (IsBidiUI() || IsKeyboardRTL()) { + // If caret level is RTL, draw the hook on the left; if LTR, to the right // The height of the hook rectangle is the same as the width of the caret // rectangle. + int caretBidiLevel = selection->GetFrameSelection()->GetCaretBidiLevel(); + if (caretBidiLevel & BIDI_LEVEL_UNDEFINED) { + caretBidiLevel = NS_GET_EMBEDDING_LEVEL(aFrame); + } + bool isCaretRTL = caretBidiLevel % 2; if (isVertical) { aHookRect->SetRect(aCaretRect->XMost() - bidiIndicatorSize, aCaretRect->y + (isCaretRTL ? bidiIndicatorSize * -1 : aCaretRect->height), aCaretRect->height, bidiIndicatorSize); } else { aHookRect->SetRect(aCaretRect->x + (isCaretRTL ? bidiIndicatorSize * -1 :
--- a/layout/base/nsCaret.h +++ b/layout/base/nsCaret.h @@ -153,16 +153,17 @@ class nsCaret final : public nsISelectio int32_t aFrameOffset, nscoord* aBidiIndicatorSize); size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; protected: static void CaretBlinkCallback(nsITimer *aTimer, void *aClosure); + bool IsBidiUI(); void CheckSelectionLanguageChange(); void ResetBlinking(); void StopBlinking(); mozilla::dom::Selection* GetSelectionInternal(); struct Metrics {
--- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -65,16 +65,17 @@ #include "UnitTransforms.h" #include "LayersLogging.h" #include "FrameLayerBuilder.h" #include "mozilla/EventStateManager.h" #include "RestyleManager.h" #include "nsCaret.h" #include "nsISelection.h" #include "nsDOMTokenList.h" +#include "mozilla/RuleNodeCacheConditions.h" // GetCurrentTime is defined in winbase.h as zero argument macro forwarding to // GetTickCount(). #ifdef GetCurrentTime #undef GetCurrentTime #endif using namespace mozilla; @@ -124,17 +125,17 @@ static void AddTransformFunctions(nsCSSV return; } for (const nsCSSValueList* curr = aList; curr; curr = curr->mNext) { const nsCSSValue& currElem = curr->mValue; NS_ASSERTION(currElem.GetUnit() == eCSSUnit_Function, "Stream should consist solely of functions!"); nsCSSValue::Array* array = currElem.GetArrayValue(); - bool canStoreInRuleTree = true; + RuleNodeCacheConditions conditions; switch (nsStyleTransformMatrix::TransformFunctionOf(array)) { case eCSSKeyword_rotatex: { CSSAngle theta = MakeCSSAngle(array->Item(1)); aFunctions.AppendElement(RotationX(theta)); break; } case eCSSKeyword_rotatey: @@ -196,62 +197,62 @@ static void AddTransformFunctions(nsCSSV double y = array->Item(2).GetFloatValue(); double z = array->Item(3).GetFloatValue(); aFunctions.AppendElement(Scale(x, y, z)); break; } case eCSSKeyword_translatex: { double x = nsStyleTransformMatrix::ProcessTranslatePart( - array->Item(1), aContext, aPresContext, canStoreInRuleTree, + array->Item(1), aContext, aPresContext, conditions, &aRefBox, &TransformReferenceBox::Width); aFunctions.AppendElement(Translation(x, 0, 0)); break; } case eCSSKeyword_translatey: { double y = nsStyleTransformMatrix::ProcessTranslatePart( - array->Item(1), aContext, aPresContext, canStoreInRuleTree, + array->Item(1), aContext, aPresContext, conditions, &aRefBox, &TransformReferenceBox::Height); aFunctions.AppendElement(Translation(0, y, 0)); break; } case eCSSKeyword_translatez: { double z = nsStyleTransformMatrix::ProcessTranslatePart( - array->Item(1), aContext, aPresContext, canStoreInRuleTree, + array->Item(1), aContext, aPresContext, conditions, nullptr); aFunctions.AppendElement(Translation(0, 0, z)); break; } case eCSSKeyword_translate: { double x = nsStyleTransformMatrix::ProcessTranslatePart( - array->Item(1), aContext, aPresContext, canStoreInRuleTree, + array->Item(1), aContext, aPresContext, conditions, &aRefBox, &TransformReferenceBox::Width); // translate(x) is shorthand for translate(x, 0) double y = 0; if (array->Count() == 3) { y = nsStyleTransformMatrix::ProcessTranslatePart( - array->Item(2), aContext, aPresContext, canStoreInRuleTree, + array->Item(2), aContext, aPresContext, conditions, &aRefBox, &TransformReferenceBox::Height); } aFunctions.AppendElement(Translation(x, y, 0)); break; } case eCSSKeyword_translate3d: { double x = nsStyleTransformMatrix::ProcessTranslatePart( - array->Item(1), aContext, aPresContext, canStoreInRuleTree, + array->Item(1), aContext, aPresContext, conditions, &aRefBox, &TransformReferenceBox::Width); double y = nsStyleTransformMatrix::ProcessTranslatePart( - array->Item(2), aContext, aPresContext, canStoreInRuleTree, + array->Item(2), aContext, aPresContext, conditions, &aRefBox, &TransformReferenceBox::Height); double z = nsStyleTransformMatrix::ProcessTranslatePart( - array->Item(3), aContext, aPresContext, canStoreInRuleTree, + array->Item(3), aContext, aPresContext, conditions, nullptr); aFunctions.AppendElement(Translation(x, y, z)); break; } case eCSSKeyword_skewx: { CSSAngle x = MakeCSSAngle(array->Item(1)); @@ -320,17 +321,17 @@ static void AddTransformFunctions(nsCSSV break; } case eCSSKeyword_interpolatematrix: { gfx3DMatrix matrix; nsStyleTransformMatrix::ProcessInterpolateMatrix(matrix, array, aContext, aPresContext, - canStoreInRuleTree, + conditions, aRefBox); aFunctions.AppendElement(TransformMatrix(gfx::ToMatrix4x4(matrix))); break; } case eCSSKeyword_perspective: { aFunctions.AppendElement(Perspective(array->Item(1).GetFloatValue())); break; @@ -4904,17 +4905,17 @@ nsDisplayTransform::GetResultingTransfor if (aBoundsOverride && (!frame || !(frame->GetStateBits() & NS_FRAME_SVG_LAYOUT))) { refBox.Init(aBoundsOverride->Size()); } else { refBox.Init(frame); } /* Get the matrix, then change its basis to factor in the origin. */ - bool dummy; + RuleNodeCacheConditions dummy; gfx3DMatrix result; // Call IsSVGTransformed() regardless of the value of // disp->mSpecifiedTransform, since we still need any transformFromSVGParent. Matrix svgTransform, transformFromSVGParent; bool hasSVGTransforms = frame && frame->IsSVGTransformed(&svgTransform, &transformFromSVGParent); bool hasTransformFromSVGParent = hasSVGTransforms && !transformFromSVGParent.IsIdentity();
rename from layout/base/nsIPercentHeightObserver.h rename to layout/base/nsIPercentBSizeObserver.h --- a/layout/base/nsIPercentHeightObserver.h +++ b/layout/base/nsIPercentBSizeObserver.h @@ -1,30 +1,31 @@ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#ifndef nsIPercentHeightObserver_h___ -#define nsIPercentHeightObserver_h___ +#ifndef nsIPercentBSizeObserver_h___ +#define nsIPercentBSizeObserver_h___ #include "nsQueryFrame.h" struct nsHTMLReflowState; /** - * This interface is supported by frames that need to provide computed height - * values to children during reflow which would otherwise not happen. Currently only - * table cells support this. + * This interface is supported by frames that need to provide computed bsize + * values to children during reflow which would otherwise not happen. Currently + * only table cells support this. */ -class nsIPercentHeightObserver +class nsIPercentBSizeObserver { public: - NS_DECL_QUERYFRAME_TARGET(nsIPercentHeightObserver) + NS_DECL_QUERYFRAME_TARGET(nsIPercentBSizeObserver) - // Notify the observer that aReflowState has no computed height, but it has a percent height - virtual void NotifyPercentHeight(const nsHTMLReflowState& aReflowState) = 0; + // Notify the observer that aReflowState has no computed bsize, + // but it has a percent bsize + virtual void NotifyPercentBSize(const nsHTMLReflowState& aReflowState) = 0; // Ask the observer if it should observe aReflowState.frame virtual bool NeedsToObserve(const nsHTMLReflowState& aReflowState) = 0; }; -#endif // nsIPercentHeightObserver_h___ +#endif // nsIPercentBSizeObserver_h___
--- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -94,16 +94,17 @@ #include "LayersLogging.h" #include "mozilla/Preferences.h" #include "nsFrameSelection.h" #include "FrameLayerBuilder.h" #include "mozilla/layers/APZCTreeManager.h" #include "mozilla/Telemetry.h" #include "mozilla/EventDispatcher.h" #include "mozilla/EventStateManager.h" +#include "mozilla/RuleNodeCacheConditions.h" #ifdef MOZ_XUL #include "nsXULPopupManager.h" #endif #include "GeckoProfiler.h" #include "nsAnimationManager.h" #include "nsTransitionManager.h" @@ -459,17 +460,17 @@ GetScaleForValue(const StyleAnimationVal nsCSSValueSharedList* list = aValue.GetCSSValueSharedListValue(); MOZ_ASSERT(list->mHead); if (list->mHead->mValue.GetUnit() == eCSSUnit_None) { // There is an animation, but no actual transform yet. return gfxSize(); } - bool dontCare; + RuleNodeCacheConditions dontCare; TransformReferenceBox refBox(aFrame); gfx3DMatrix transform = nsStyleTransformMatrix::ReadTransforms( list->mHead, aFrame->StyleContext(), aFrame->PresContext(), dontCare, refBox, aFrame->PresContext()->AppUnitsPerDevPixel()); gfxMatrix transform2d;
--- a/layout/base/nsPresArena.h +++ b/layout/base/nsPresArena.h @@ -27,16 +27,18 @@ public: ~nsPresArena(); enum ObjectID { nsLineBox_id = nsQueryFrame::NON_FRAME_MARKER, nsRuleNode_id, nsStyleContext_id, nsInheritedStyleData_id, nsResetStyleData_id, + nsConditionalResetStyleData_id, + nsConditionalResetStyleDataEntry_id, nsFrameList_id, CustomCounterStyle_id, DependentBuiltinCounterStyle_id, First_nsStyleStruct_id, DummyBeforeStyleStructs_id = First_nsStyleStruct_id - 1,
--- a/layout/base/tests/bug646382-1-ref.html +++ b/layout/base/tests/bug646382-1-ref.html @@ -1,17 +1,18 @@ <html class="reftest-wait"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> </head> <body onload="start()"> - <textarea onfocus="done()" style="-moz-appearance: none">س</textarea> + <textarea onfocus="done()" style="-moz-appearance: none">س‎</textarea> <script> var textarea = document.querySelector("textarea"); function start() { textarea.focus(); } function done() { + textarea.selectionStart = textarea.selectionEnd = 2; document.documentElement.removeAttribute("class"); } </script> </body> </html>
--- a/layout/base/tests/bug646382-2-ref.html +++ b/layout/base/tests/bug646382-2-ref.html @@ -1,14 +1,15 @@ <html class="reftest-wait"> <body onload="start()"> - <textarea dir="rtl" onfocus="done()" style="-moz-appearance: none">s</textarea> + <textarea dir="rtl" onfocus="done()" style="-moz-appearance: none">s‏</textarea> <script> var textarea = document.querySelector("textarea"); function start() { textarea.focus(); } function done() { + textarea.selectionStart = textarea.selectionEnd = 2; document.documentElement.removeAttribute("class"); } </script> </body> </html>
--- a/layout/generic/WritingModes.h +++ b/layout/generic/WritingModes.h @@ -467,16 +467,18 @@ public: /** * Check whether two modes are orthogonal to each other. */ bool IsOrthogonalTo(const WritingMode& aOther) const { return IsVertical() != aOther.IsVertical(); } + uint8_t GetBits() const { return mWritingMode; } + private: friend class LogicalPoint; friend class LogicalSize; friend class LogicalMargin; friend class LogicalRect; friend struct IPC::ParamTraits<WritingMode>; // IMENotification cannot store this class directly since this has some
--- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -48,17 +48,17 @@ #include "nsGkAtoms.h" #include "nsHtml5Atoms.h" #include "nsCSSAnonBoxes.h" #include "nsFrameTraversal.h" #include "nsRange.h" #include "nsITextControlFrame.h" #include "nsNameSpaceManager.h" -#include "nsIPercentHeightObserver.h" +#include "nsIPercentBSizeObserver.h" #include "nsStyleStructInlines.h" #include "FrameLayerBuilder.h" #include "nsBidiPresUtils.h" #include "RubyUtils.h" // For triple-click pref #include "imgIContainer.h" @@ -4444,25 +4444,26 @@ nsFrame::DidReflow(nsPresContext* nsSVGEffects::InvalidateDirectRenderingObservers(this, nsSVGEffects::INVALIDATE_REFLOW); if (nsDidReflowStatus::FINISHED == aStatus) { mState &= ~(NS_FRAME_IN_REFLOW | NS_FRAME_FIRST_REFLOW | NS_FRAME_IS_DIRTY | NS_FRAME_HAS_DIRTY_CHILDREN); } - // Notify the percent height observer if there is a percent height. + // Notify the percent bsize observer if there is a percent bsize. // The observer may be able to initiate another reflow with a computed - // height. This happens in the case where a table cell has no computed - // height but can fabricate one when the cell height is known. - if (aReflowState && aReflowState->mPercentHeightObserver && + // bsize. This happens in the case where a table cell has no computed + // bsize but can fabricate one when the cell bsize is known. + if (aReflowState && aReflowState->mPercentBSizeObserver && !GetPrevInFlow()) { - const nsStyleCoord &height = aReflowState->mStylePosition->mHeight; - if (height.HasPercent()) { - aReflowState->mPercentHeightObserver->NotifyPercentHeight(*aReflowState); + const nsStyleCoord &bsize = + aReflowState->mStylePosition->BSize(aReflowState->GetWritingMode()); + if (bsize.HasPercent()) { + aReflowState->mPercentBSizeObserver->NotifyPercentBSize(*aReflowState); } } aPresContext->ReflowedFrame(); } void nsFrame::FinishReflowWithAbsoluteFrames(nsPresContext* aPresContext, @@ -9737,18 +9738,18 @@ static void DisplayReflowEnterPrint(nsPr printf("c=%s,%s ", width, height); if (aFrame->GetStateBits() & NS_FRAME_IS_DIRTY) printf("dirty "); if (aFrame->GetStateBits() & NS_FRAME_HAS_DIRTY_CHILDREN) printf("dirty-children "); - if (aReflowState.mFlags.mSpecialHeightReflow) - printf("special-height "); + if (aReflowState.mFlags.mSpecialBSizeReflow) + printf("special-bsize "); if (aReflowState.IsHResize()) printf("h-resize "); if (aReflowState.IsVResize()) printf("v-resize "); nsIFrame* inFlow = aFrame->GetPrevInFlow();
--- a/layout/generic/nsFrameIdList.h +++ b/layout/generic/nsFrameIdList.h @@ -44,17 +44,17 @@ FRAME_ID(nsIComboboxControlFrame) FRAME_ID(nsIFormControlFrame) FRAME_ID(nsIFrame) FRAME_ID(nsIFrameFrame) FRAME_ID(nsIListControlFrame) FRAME_ID(nsIMathMLFrame) FRAME_ID(nsIMenuFrame) FRAME_ID(nsIObjectFrame) FRAME_ID(nsIPageSequenceFrame) -FRAME_ID(nsIPercentHeightObserver) +FRAME_ID(nsIPercentBSizeObserver) FRAME_ID(nsIRootBox) FRAME_ID(nsISVGChildFrame) FRAME_ID(nsISVGSVGFrame) FRAME_ID(nsIScrollableFrame) FRAME_ID(nsIScrollbarMediator) FRAME_ID(nsISelectControlFrame) FRAME_ID(nsIStatefulFrame) FRAME_ID(nsITableCellLayout)
--- a/layout/generic/nsFrameSelection.h +++ b/layout/generic/nsFrameSelection.h @@ -616,17 +616,19 @@ private: bool aContinueSelection, bool aMultipleSelection); void BidiLevelFromMove(nsIPresShell* aPresShell, nsIContent *aNode, uint32_t aContentOffset, nsSelectionAmount aAmount, CaretAssociateHint aHint); - void BidiLevelFromClick(nsIContent *aNewFocus, uint32_t aContentOffset); + void BidiLevelFromClick(nsIContent *aNewFocus, + uint32_t aContentOffset, + CaretAssociateHint aHint); nsPrevNextBidiLevels GetPrevNextBidiLevels(nsIContent *aNode, uint32_t aContentOffset, CaretAssociateHint aHint, bool aJumpLines) const; bool AdjustForMaintainedSelection(nsIContent *aContent, int32_t aOffset); // post and pop reasons for notifications. we may stack these later
--- a/layout/generic/nsFrameStateBits.h +++ b/layout/generic/nsFrameStateBits.h @@ -545,17 +545,17 @@ FRAME_STATE_BIT(Placeholder, 21, PLACEHO FRAME_STATE_BIT(Placeholder, 22, PLACEHOLDER_FOR_FIXEDPOS) FRAME_STATE_BIT(Placeholder, 23, PLACEHOLDER_FOR_POPUP) // == Frame state bits that apply to table cell frames ======================== FRAME_STATE_GROUP(TableCell, nsTableCellFrame) -FRAME_STATE_BIT(TableCell, 28, NS_TABLE_CELL_HAS_PCT_OVER_HEIGHT) +FRAME_STATE_BIT(TableCell, 28, NS_TABLE_CELL_HAS_PCT_OVER_BSIZE) FRAME_STATE_BIT(TableCell, 29, NS_TABLE_CELL_HAD_SPECIAL_REFLOW) FRAME_STATE_BIT(TableCell, 31, NS_TABLE_CELL_CONTENT_EMPTY) // == Frame state bits that apply to table column frames ====================== // Bits 28-31 on nsTableColFrames are used to store the column type. @@ -574,28 +574,28 @@ FRAME_STATE_GROUP(TableRowAndRowGroup, n FRAME_STATE_BIT(TableRowAndRowGroup, 28, NS_REPEATED_ROW_OR_ROWGROUP) // == Frame state bits that apply to table row frames ========================= FRAME_STATE_GROUP(TableRow, nsTableRowFrame) // Indicates whether this row has any cells that have -// non-auto-height and rowspan=1 -FRAME_STATE_BIT(TableRow, 29, NS_ROW_HAS_CELL_WITH_STYLE_HEIGHT) +// non-auto-bsize and rowspan=1 +FRAME_STATE_BIT(TableRow, 29, NS_ROW_HAS_CELL_WITH_STYLE_BSIZE) -FRAME_STATE_BIT(TableRow, 30, NS_TABLE_ROW_HAS_UNPAGINATED_HEIGHT) +FRAME_STATE_BIT(TableRow, 30, NS_TABLE_ROW_HAS_UNPAGINATED_BSIZE) // == Frame state bits that apply to table row group frames =================== FRAME_STATE_GROUP(TableRowGroup, nsTableRowGroupFrame) FRAME_STATE_BIT(TableRowGroup, 27, NS_ROWGROUP_HAS_ROW_CURSOR) -FRAME_STATE_BIT(TableRowGroup, 30, NS_ROWGROUP_HAS_STYLE_HEIGHT) +FRAME_STATE_BIT(TableRowGroup, 30, NS_ROWGROUP_HAS_STYLE_BSIZE) // thead or tfoot should be repeated on every printed page FRAME_STATE_BIT(TableRowGroup, 31, NS_ROWGROUP_REPEATABLE) FRAME_STATE_GROUP(Table, nsTableFrame) FRAME_STATE_BIT(Table, 28, NS_TABLE_PART_HAS_FIXED_BACKGROUND)
--- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -17,17 +17,17 @@ #include "nsIPresShell.h" #include "nsFontMetrics.h" #include "nsBlockFrame.h" #include "nsLineBox.h" #include "nsFlexContainerFrame.h" #include "nsImageFrame.h" #include "nsTableFrame.h" #include "nsTableCellFrame.h" -#include "nsIPercentHeightObserver.h" +#include "nsIPercentBSizeObserver.h" #include "nsLayoutUtils.h" #include "mozilla/Preferences.h" #include "nsFontInflationData.h" #include "StickyScrollContainer.h" #include "nsIFrameInlines.h" #include "CounterStyleManager.h" #include <algorithm> #include "mozilla/dom/HTMLInputElement.h" @@ -70,17 +70,17 @@ nsHTMLReflowState::nsHTMLReflowState(nsP MOZ_ASSERT(aPresContext == aFrame->PresContext(), "wrong pres context"); parentReflowState = nullptr; AvailableISize() = aAvailableSpace.ISize(mWritingMode); AvailableBSize() = aAvailableSpace.BSize(mWritingMode); mFloatManager = nullptr; mLineLayout = nullptr; memset(&mFlags, 0, sizeof(mFlags)); mDiscoveredClearance = nullptr; - mPercentHeightObserver = nullptr; + mPercentBSizeObserver = nullptr; if (aFlags & DUMMY_PARENT_REFLOW_STATE) { mFlags.mDummyParentReflowState = true; } if (!(aFlags & CALLER_WILL_INIT)) { Init(aPresContext); } @@ -174,26 +174,26 @@ nsHTMLReflowState::nsHTMLReflowState( , mBlockDelta(0) , mOrthogonalLimit(NS_UNCONSTRAINEDSIZE) , mReflowDepth(aParentReflowState.mReflowDepth + 1) , mFlags(aParentReflowState.mFlags) { MOZ_ASSERT(aPresContext, "no pres context"); MOZ_ASSERT(aFrame, "no frame"); MOZ_ASSERT(aPresContext == aFrame->PresContext(), "wrong pres context"); - NS_PRECONDITION(!mFlags.mSpecialHeightReflow || + NS_PRECONDITION(!mFlags.mSpecialBSizeReflow || !NS_SUBTREE_DIRTY(aFrame), - "frame should be clean when getting special height reflow"); + "frame should be clean when getting special bsize reflow"); parentReflowState = &aParentReflowState; // If the parent is dirty, then the child is as well. // XXX Are the other cases where the parent reflows a child a second // time, as a resize? - if (!mFlags.mSpecialHeightReflow) + if (!mFlags.mSpecialBSizeReflow) frame->AddStateBits(parentReflowState->frame->GetStateBits() & NS_FRAME_IS_DIRTY); AvailableISize() = aAvailableSpace.ISize(mWritingMode); AvailableBSize() = aAvailableSpace.BSize(mWritingMode); if (mWritingMode.IsOrthogonalTo(aParentReflowState.GetWritingMode())) { // If we're setting up for an orthogonal flow, and the parent reflow state @@ -218,19 +218,19 @@ nsHTMLReflowState::nsHTMLReflowState( CheckNextInFlowParenthood(aFrame, aParentReflowState.frame); mFlags.mAssumingHScrollbar = mFlags.mAssumingVScrollbar = false; mFlags.mHasClearance = false; mFlags.mIsColumnBalancing = false; mFlags.mIsFlexContainerMeasuringHeight = false; mFlags.mDummyParentReflowState = false; mDiscoveredClearance = nullptr; - mPercentHeightObserver = (aParentReflowState.mPercentHeightObserver && - aParentReflowState.mPercentHeightObserver->NeedsToObserve(*this)) - ? aParentReflowState.mPercentHeightObserver : nullptr; + mPercentBSizeObserver = (aParentReflowState.mPercentBSizeObserver && + aParentReflowState.mPercentBSizeObserver->NeedsToObserve(*this)) + ? aParentReflowState.mPercentBSizeObserver : nullptr; if ((aFlags & DUMMY_PARENT_REFLOW_STATE) || (parentReflowState->mFlags.mDummyParentReflowState && frame->GetType() == nsGkAtoms::tableFrame)) { mFlags.mDummyParentReflowState = true; } if (!(aFlags & CALLER_WILL_INIT)) { @@ -608,17 +608,17 @@ nsHTMLReflowState::InitResizeFlags(nsPre } SetIResize(!(frame->GetStateBits() & NS_FRAME_IS_DIRTY) && isIResize); // XXX Should we really need to null check mCBReflowState? (We do for // at least nsBoxFrame). if (IS_TABLE_CELL(aFrameType) && - (mFlags.mSpecialHeightReflow || + (mFlags.mSpecialBSizeReflow || (frame->FirstInFlow()->GetStateBits() & NS_TABLE_CELL_HAD_SPECIAL_REFLOW)) && (frame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_BSIZE)) { // Need to set the bit on the cell so that // mCBReflowState->IsBResize() is set correctly below when // reflowing descendant. SetBResize(true); } else if (mCBReflowState && !nsLayoutUtils::IsNonWrapperBlock(frame)) { @@ -657,36 +657,36 @@ nsHTMLReflowState::InitResizeFlags(nsPre "bad line-height value"); // line-height depends on block bsize frame->AddStateBits(NS_FRAME_CONTAINS_RELATIVE_BSIZE); // but only on containing blocks if this frame is not a suitable block dependsOnCBBSize |= !nsLayoutUtils::IsNonWrapperBlock(frame); } - // If we're the descendant of a table cell that performs special height + // If we're the descendant of a table cell that performs special bsize // reflows and we could be the child that requires them, always set // the block-axis resize in case this is the first pass before the - // special height reflow. However, don't do this if it actually is - // the special height reflow, since in that case it will already be + // special bsize reflow. However, don't do this if it actually is + // the special bsize reflow, since in that case it will already be // set correctly above if we need it set. if (!IsBResize() && mCBReflowState && (IS_TABLE_CELL(mCBReflowState->frame->GetType()) || mCBReflowState->mFlags.mHeightDependsOnAncestorCell) && - !mCBReflowState->mFlags.mSpecialHeightReflow && + !mCBReflowState->mFlags.mSpecialBSizeReflow && dependsOnCBBSize) { SetBResize(true); mFlags.mHeightDependsOnAncestorCell = true; } // Set NS_FRAME_CONTAINS_RELATIVE_BSIZE if it's needed. // It would be nice to check that |ComputedBSize != NS_AUTOHEIGHT| // &&ed with the percentage bsize check. However, this doesn't get - // along with table special height reflows, since a special height + // along with table special bsize reflows, since a special bsize // reflow (a quirk that makes such percentage height work on children // of table cells) can cause not just a single percentage height to // become fixed, but an entire descendant chain of percentage height // to become fixed. if (dependsOnCBBSize && mCBReflowState) { const nsHTMLReflowState *rs = this; bool hitCBReflowState = false; do {
--- a/layout/generic/nsHTMLReflowState.h +++ b/layout/generic/nsHTMLReflowState.h @@ -13,17 +13,17 @@ #include "nsIFrame.h" #include "mozilla/Assertions.h" #include <algorithm> class nsPresContext; class nsRenderingContext; class nsFloatManager; class nsLineLayout; -class nsIPercentHeightObserver; +class nsIPercentBSizeObserver; struct nsHypotheticalBox; /** * @return aValue clamped to [aMinValue, aMaxValue]. * * @note This function needs to handle aMinValue > aMaxValue. In that case, * aMinValue is returned. * @see http://www.w3.org/TR/CSS21/visudet.html#min-max-widths @@ -509,33 +509,33 @@ public: const nsStylePadding* mStylePadding; const nsStyleText* mStyleText; bool IsFloating() const; uint8_t GetDisplay() const; // a frame (e.g. nsTableCellFrame) which may need to generate a special - // reflow for percent height calculations - nsIPercentHeightObserver* mPercentHeightObserver; + // reflow for percent bsize calculations + nsIPercentBSizeObserver* mPercentBSizeObserver; // CSS margin collapsing sometimes requires us to reflow // optimistically assuming that margins collapse to see if clearance // is required. When we discover that clearance is required, we // store the frame in which clearance was discovered to the location // requested here. nsIFrame** mDiscoveredClearance; // This value keeps track of how deeply nested a given reflow state // is from the top of the frame tree. int16_t mReflowDepth; struct ReflowStateFlags { - uint16_t mSpecialHeightReflow:1; // used by tables to communicate special reflow (in process) to handle - // percent height frames inside cells which may not have computed heights + uint16_t mSpecialBSizeReflow:1; // used by tables to communicate special reflow (in process) to handle + // percent bsize frames inside cells which may not have computed bsizes uint16_t mNextInFlowUntouched:1; // nothing in the frame's next-in-flow (or its descendants) // is changing uint16_t mIsTopOfPage:1; // Is the current context at the top of a // page? When true, we force something // that's too tall for a page/column to // fit anyway to avoid infinite loops. uint16_t mHasClearance:1; // Block has clearance uint16_t mAssumingHScrollbar:1; // parent frame is an nsIScrollableFrame and it
--- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -729,31 +729,49 @@ public: */ void SetRect(mozilla::WritingMode aWritingMode, const mozilla::LogicalRect& aRect, nscoord aContainerWidth) { SetRect(aRect.GetPhysicalRect(aWritingMode, aContainerWidth)); } /** - * Set this frame's size from a logical size in its own writing direction + * Set this frame's size from a logical size in its own writing direction. + * This leaves the frame's logical position unchanged, which means its + * physical position may change (for right-to-left modes). */ void SetSize(const mozilla::LogicalSize& aSize) { SetSize(GetWritingMode(), aSize); } /* - * Set this frame's size from a logical size in a different writing direction + * Set this frame's size from a logical size in a different writing direction. + * This leaves the frame's logical position in the given mode unchanged, + * which means its physical position may change (for right-to-left modes). */ void SetSize(mozilla::WritingMode aWritingMode, - const mozilla::LogicalSize& aSize) { - SetSize(aSize.GetPhysicalSize(aWritingMode)); + const mozilla::LogicalSize& aSize) + { + if ((!aWritingMode.IsVertical() && !aWritingMode.IsBidiLTR()) || + aWritingMode.IsVerticalRL()) { + nscoord oldWidth = mRect.width; + SetSize(aSize.GetPhysicalSize(aWritingMode)); + mRect.x -= mRect.width - oldWidth; + } else { + SetSize(aSize.GetPhysicalSize(aWritingMode)); + } } + + /** + * Set this frame's physical size. This leaves the frame's physical position + * (topLeft) unchanged. + */ void SetSize(const nsSize& aSize) { SetRect(nsRect(mRect.TopLeft(), aSize)); } + void SetPosition(const nsPoint& aPt) { mRect.MoveTo(aPt); } void SetPosition(mozilla::WritingMode aWritingMode, const mozilla::LogicalPoint& aPt, nscoord aContainerWidth) { // We subtract mRect.width from the container width to account for // the fact that logical origins in RTL coordinate systems are at // the top right of the frame instead of the top left. mRect.MoveTo(aPt.GetPhysicalPoint(aWritingMode,
--- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -1426,22 +1426,23 @@ void nsFrameSelection::BidiLevelFromMove /** * BidiLevelFromClick is called when the caret is repositioned by clicking the mouse * * @param aNode is the content node * @param aContentOffset is the new caret position, as an offset into aNode */ void nsFrameSelection::BidiLevelFromClick(nsIContent *aNode, - uint32_t aContentOffset) + uint32_t aContentOffset, + CaretAssociateHint aHint) { nsIFrame* clickInFrame=nullptr; int32_t OffsetNotUsed; - clickInFrame = GetFrameForNodeOffset(aNode, aContentOffset, mHint, &OffsetNotUsed); + clickInFrame = GetFrameForNodeOffset(aNode, aContentOffset, aHint, &OffsetNotUsed); if (!clickInFrame) return; SetCaretBidiLevel(NS_GET_EMBEDDING_LEVEL(clickInFrame)); } bool @@ -1510,17 +1511,17 @@ nsFrameSelection::HandleClick(nsIContent if (!IsValidSelectionPoint(this, aNewFocus)) { mAncestorLimiter = nullptr; } } // Don't take focus when dragging off of a table if (!mDragSelectingCells) { - BidiLevelFromClick(aNewFocus, aContentOffset); + BidiLevelFromClick(aNewFocus, aContentOffset, aHint); PostReason(nsISelectionListener::MOUSEDOWN_REASON + nsISelectionListener::DRAG_REASON); if (aContinueSelection && AdjustForMaintainedSelection(aNewFocus, aContentOffset)) return NS_OK; //shift clicked to maintained selection. rejected. int8_t index = GetIndexFromSelectionType(nsISelectionController::SELECTION_NORMAL); AutoPrepareFocusRange prep(mDomSelections[index], aContinueSelection, aMultipleSelection); return TakeFocus(aNewFocus, aContentOffset, aContentEndOffset, aHint,
--- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -614,29 +614,30 @@ int32_t nsTextFrame::GetContentEnd() con struct FlowLengthProperty { int32_t mStartOffset; // The offset of the next fixed continuation after mStartOffset, or // of the end of the text if there is none int32_t mEndFlowOffset; }; int32_t nsTextFrame::GetInFlowContentLength() { - if (!(mState & NS_FRAME_IS_BIDI)) { + if (!(mState & NS_FRAME_IS_BIDI) && + !StyleText()->NewlineIsSignificant(this)) { return mContent->TextLength() - mContentOffset; } FlowLengthProperty* flowLength = static_cast<FlowLengthProperty*>(mContent->GetProperty(nsGkAtoms::flowlength)); /** * This frame must start inside the cached flow. If the flow starts at * mContentOffset but this frame is empty, logically it might be before the * start of the cached flow. */ - if (flowLength && + if (flowLength && !StyleText()->NewlineIsSignificant(this) && (flowLength->mStartOffset < mContentOffset || (flowLength->mStartOffset == mContentOffset && GetContentEnd() > mContentOffset)) && flowLength->mEndFlowOffset > mContentOffset) { #ifdef DEBUG NS_ASSERTION(flowLength->mEndFlowOffset >= GetContentEnd(), "frame crosses fixed continuation boundary"); #endif return flowLength->mEndFlowOffset - mContentOffset; @@ -4799,16 +4800,28 @@ LazyGetLineBaselineOffset(nsIFrame* aChi aChildFrame->Properties().Get(nsIFrame::LineBaselineOffset(), &offsetFound) ); } else { return offset; } } +static bool IsUnderlineRight(nsIFrame* aFrame) +{ + nsIAtom* langAtom = aFrame->StyleFont()->mLanguage; + if (!langAtom) { + return false; + } + nsAtomString langStr(langAtom); + return (StringBeginsWith(langStr, NS_LITERAL_STRING("ja")) || + StringBeginsWith(langStr, NS_LITERAL_STRING("ko"))) && + (langStr.Length() == 2 || langStr[2] == '-'); +} + void nsTextFrame::GetTextDecorations( nsPresContext* aPresContext, nsTextFrame::TextDecorationColorResolution aColorResolution, nsTextFrame::TextDecorations& aDecorations) { const nsCompatibility compatMode = aPresContext->CompatibilityMode(); @@ -4897,21 +4910,29 @@ nsTextFrame::GetTextDecorations( // override the fill paint of the decoration. color = aColorResolution == eResolvedColors ? nsLayoutUtils::GetColor(f, eCSSProperty_fill) : NS_SAME_AS_FOREGROUND_COLOR; } else { color = nsLayoutUtils::GetColor(f, eCSSProperty_text_decoration_color); } - if (textDecorations & NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE) { + bool swapUnderlineAndOverline = vertical && IsUnderlineRight(f); + const uint8_t kUnderline = + swapUnderlineAndOverline ? NS_STYLE_TEXT_DECORATION_LINE_OVERLINE : + NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE; + const uint8_t kOverline = + swapUnderlineAndOverline ? NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE : + NS_STYLE_TEXT_DECORATION_LINE_OVERLINE; + + if (textDecorations & kUnderline) { aDecorations.mUnderlines.AppendElement( nsTextFrame::LineDecoration(f, baselineOffset, color, style)); } - if (textDecorations & NS_STYLE_TEXT_DECORATION_LINE_OVERLINE) { + if (textDecorations & kOverline) { aDecorations.mOverlines.AppendElement( nsTextFrame::LineDecoration(f, baselineOffset, color, style)); } if (textDecorations & NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH) { aDecorations.mStrikes.AppendElement( nsTextFrame::LineDecoration(f, baselineOffset, color, style)); } } @@ -5255,17 +5276,17 @@ static void DrawSelectionDecorations(gfx const gfxRect& aDirtyRect, SelectionType aType, nsTextFrame* aFrame, nsTextPaintStyle& aTextPaintStyle, const TextRangeStyle &aRangeStyle, const gfxPoint& aPt, gfxFloat aICoordInFrame, gfxFloat aWidth, gfxFloat aAscent, const gfxFont::Metrics& aFontMetrics, nsTextFrame::DrawPathCallbacks* aCallbacks, - bool aVertical) + bool aVertical, uint8_t aDecoration) { gfxPoint pt(aPt); gfxSize size(aWidth, ComputeSelectionUnderlineHeight(aTextPaintStyle.PresContext(), aFontMetrics, aType)); gfxFloat descentLimit = ComputeDescentLimitForSelectionUnderline(aTextPaintStyle.PresContext(), aFrame, aFontMetrics); @@ -5333,18 +5354,20 @@ static void DrawSelectionDecorations(gfx break; default: NS_WARNING("Requested selection decorations when there aren't any"); return; } size.height *= relativeSize; PaintDecorationLine(aFrame, aContext, aDirtyRect, color, nullptr, pt, (aVertical ? (pt.y - aPt.y) : (pt.x - aPt.x)) + aICoordInFrame, - size, aAscent, aFontMetrics.underlineOffset, - NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, style, eSelectionDecoration, + size, aAscent, + aDecoration == NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE ? + aFontMetrics.underlineOffset : aFontMetrics.maxAscent, + aDecoration, style, eSelectionDecoration, aCallbacks, aVertical, descentLimit); } /** * This function encapsulates all knowledge of how selections affect foreground * and background colors. * @return true if the selection affects colors, false otherwise * @param aForeground the foreground color to use @@ -5799,16 +5822,20 @@ nsTextFrame::PaintTextSelectionDecoratio selectedChars[i] = sdptr; } } sdptr = sdptr->mNext; } gfxFont* firstFont = aProvider.GetFontGroup()->GetFirstValidFont(); bool verticalRun = mTextRun->IsVertical(); + bool rightUnderline = verticalRun && IsUnderlineRight(this); + const uint8_t kDecoration = + rightUnderline ? NS_STYLE_TEXT_DECORATION_LINE_OVERLINE : + NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE; bool useVerticalMetrics = verticalRun && mTextRun->UseCenterBaseline(); gfxFont::Metrics decorationMetrics(firstFont->GetMetrics(useVerticalMetrics ? gfxFont::eVertical : gfxFont::eHorizontal)); if (!useVerticalMetrics) { // The potential adjustment from using gfxFontGroup::GetUnderlineOffset // is only valid for horizontal font metrics. decorationMetrics.underlineOffset = @@ -5845,17 +5872,17 @@ nsTextFrame::PaintTextSelectionDecoratio pt.x = (aFramePt.x + iOffset - (mTextRun->IsRightToLeft() ? advance : 0)) / app; } gfxFloat width = Abs(advance) / app; gfxFloat xInFrame = pt.x - (aFramePt.x / app); DrawSelectionDecorations(aCtx, dirtyRect, aSelectionType, this, aTextPaintStyle, selectedStyle, pt, xInFrame, width, mAscent / app, decorationMetrics, - aCallbacks, verticalRun); + aCallbacks, verticalRun, kDecoration); } iterator.UpdateWithAdvance(advance); } } bool nsTextFrame::PaintTextWithSelection(gfxContext* aCtx, const gfxPoint& aFramePt,
--- a/layout/mathml/nsMathMLmtableFrame.cpp +++ b/layout/mathml/nsMathMLmtableFrame.cpp @@ -767,19 +767,17 @@ nsMathMLmtableOuterFrame::GetRowFrameAt( // if our inner table says that the index is valid, find the row now if (0 <= aRowIndex && aRowIndex <= rowCount) { nsIFrame* tableFrame = mFrames.FirstChild(); NS_ASSERTION(tableFrame && tableFrame->GetType() == nsGkAtoms::tableFrame, "should always have an inner table frame"); nsIFrame* rgFrame = tableFrame->GetFirstPrincipalChild(); if (!rgFrame || rgFrame->GetType() != nsGkAtoms::tableRowGroupFrame) return nullptr; - nsTableIterator rowIter(*rgFrame); - nsIFrame* rowFrame = rowIter.First(); - for ( ; rowFrame; rowFrame = rowIter.Next()) { + for (nsIFrame* rowFrame : rgFrame->PrincipalChildList()) { if (aRowIndex == 0) { DEBUG_VERIFY_THAT_FRAME_IS(rowFrame, TABLE_ROW); if (rowFrame->GetType() != nsGkAtoms::tableRowFrame) return nullptr; return rowFrame; } --aRowIndex;
--- a/layout/reftests/table-bordercollapse/border-collapse-rtl-ref.html +++ b/layout/reftests/table-bordercollapse/border-collapse-rtl-ref.html @@ -1,23 +1,23 @@ <!DOCTYPE html> <html> <head> <meta charset=utf-8> <style> table { margin: 10px; - border: 3px solid silver; + border: 8px solid silver; border-right-color: gray; border-bottom-color: gray; border-spacing: 5px; border-collapse: collapse; } td { - border: 5px solid black; + border: 4px solid black; width: 50px; height: 20px; text-align: center; } td.w1 { width: 80px; } td.w2 {
--- a/layout/reftests/table-bordercollapse/border-collapse-rtl.html +++ b/layout/reftests/table-bordercollapse/border-collapse-rtl.html @@ -1,23 +1,23 @@ <!DOCTYPE html> <html> <head> <meta charset=utf-8> <style> table { margin: 10px; - border: 3px solid silver; + border: 8px solid silver; border-right-color: gray; border-bottom-color: gray; border-spacing: 5px; border-collapse: collapse; } td { - border: 5px solid black; + border: 4px solid black; width: 50px; height: 20px; text-align: center; } td.w1 { width: 80px; } td.w2 {
new file mode 100644 --- /dev/null +++ b/layout/reftests/writing-mode/1175789-underline-overline-1-ref.html @@ -0,0 +1,91 @@ +<!DOCTYPE html> +<html> + <head> + <title>Bug 1175789 - underline and overline in various language</title> + <style type="text/css"> + body { + font-family: "Arial", "Helvetica", "sans-serif"; + } + div { + padding: .5em 1em; + line-height: 2em; + } + .underline { + text-decoration: underline; + } + .overline { + text-decoration: overline; + } + </style> + </head> + <body> + <dl> + <dt>lang="en-US"</dt> + <dd lang="en-US"> + <div style="writing-mode: vertical-rl;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + <div style="writing-mode: vertical-lr;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + </dd> + <dt>lang="ja"</dt> + <dd lang="en-US"> + <div style="writing-mode: vertical-rl;"> + <span class="overline">underline</span><br> + <span class="underline">overline</span> + </div> + <div style="writing-mode: vertical-lr;"> + <span class="overline">underline</span><br> + <span class="underline">overline</span> + </div> + </dd> + <dt>lang="ko"</dt> + <dd lang="en-US"> + <div style="writing-mode: vertical-rl;"> + <span class="overline">underline</span><br> + <span class="underline">overline</span> + </div> + <div style="writing-mode: vertical-lr;"> + <span class="overline">underline</span><br> + <span class="underline">overline</span> + </div> + </dd> + <dt>lang="ja-JP"</dt> + <dd lang="en-US"> + <div style="writing-mode: vertical-rl;"> + <span class="overline">underline</span><br> + <span class="underline">overline</span> + </div> + <div style="writing-mode: vertical-lr;"> + <span class="overline">underline</span><br> + <span class="underline">overline</span> + </div> + </dd> + <dt>lang="ko-KR"</dt> + <dd lang="en-US"> + <div style="writing-mode: vertical-rl;"> + <span class="overline">underline</span><br> + <span class="underline">overline</span> + </div> + <div style="writing-mode: vertical-lr;"> + <span class="overline">underline</span><br> + <span class="underline">overline</span> + </div> + </dd> + <dt>lang="zh"</dt> + <dd lang="en-US"> + <div style="writing-mode: vertical-rl;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + <div style="writing-mode: vertical-lr;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + </dd> + </dl> + </body> +</html>
new file mode 100644 --- /dev/null +++ b/layout/reftests/writing-mode/1175789-underline-overline-1.html @@ -0,0 +1,91 @@ +<!DOCTYPE html> +<html> + <head> + <title>Bug 1175789 - underline and overline in various language</title> + <style type="text/css"> + body { + font-family: "Arial", "Helvetica", "sans-serif"; + } + div { + padding: .5em 1em; + line-height: 2em; + } + .underline { + text-decoration: underline; + } + .overline { + text-decoration: overline; + } + </style> + </head> + <body> + <dl> + <dt>lang="en-US"</dt> + <dd lang="en-US"> + <div style="writing-mode: vertical-rl;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + <div style="writing-mode: vertical-lr;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + </dd> + <dt>lang="ja"</dt> + <dd lang="ja"> + <div style="writing-mode: vertical-rl;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + <div style="writing-mode: vertical-lr;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + </dd> + <dt>lang="ko"</dt> + <dd lang="ko"> + <div style="writing-mode: vertical-rl;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + <div style="writing-mode: vertical-lr;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + </dd> + <dt>lang="ja-JP"</dt> + <dd lang="ja-JP"> + <div style="writing-mode: vertical-rl;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + <div style="writing-mode: vertical-lr;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + </dd> + <dt>lang="ko-KR"</dt> + <dd lang="ko-KR"> + <div style="writing-mode: vertical-rl;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + <div style="writing-mode: vertical-lr;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + </dd> + <dt>lang="zh"</dt> + <dd lang="zh"> + <div style="writing-mode: vertical-rl;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + <div style="writing-mode: vertical-lr;"> + <span class="underline">underline</span><br> + <span class="overline">overline</span> + </div> + </dd> + </dl> + </body> +</html>
--- a/layout/reftests/writing-mode/reftest.list +++ b/layout/reftests/writing-mode/reftest.list @@ -144,11 +144,12 @@ fails == 1147834-relative-overconstraine == 1172774-percent-margin-2.html 1172774-percent-horizontal-ref.html == 1172774-percent-margin-3.html 1172774-percent-vertical-ref.html == 1172774-percent-margin-4.html 1172774-percent-vertical-ref.html == 1172774-percent-padding-1.html 1172774-percent-horizontal-ref.html == 1172774-percent-padding-2.html 1172774-percent-horizontal-ref.html == 1172774-percent-padding-3.html 1172774-percent-vertical-ref.html == 1172774-percent-padding-4.html 1172774-percent-vertical-ref.html == 1174450-intrinsic-sizing.html 1174450-intrinsic-sizing-ref.html +== 1175789-underline-overline-1.html 1175789-underline-overline-1-ref.html # Suite of tests from Gérard Talbot in bug 1079151 include abspos/reftest.list
new file mode 100644 --- /dev/null +++ b/layout/style/RuleNodeCacheConditions.cpp @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 et sw=2 tw=78: */ +/* 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/. */ + +/* + * an object that stores the result of determining whether a style struct that + * was computed can be cached in the rule tree, and if so, what the cache + * key is + */ + +#include "RuleNodeCacheConditions.h" + +#include "nsStyleContext.h" +#include "WritingModes.h" + +using namespace mozilla; + +bool +RuleNodeCacheConditions::Matches(nsStyleContext* aStyleContext) const +{ + MOZ_ASSERT(Cacheable()); + if ((mBits & eHaveFontSize) && + mFontSize != aStyleContext->StyleFont()->mFont.size) { + return false; + } + if ((mBits & eHaveWritingMode) && + (GetWritingMode() != WritingMode(aStyleContext).GetBits())) { + return false; + } + return true; +} + +#ifdef DEBUG +void +RuleNodeCacheConditions::List() const +{ + printf("{ "); + bool first = true; + if (mBits & eHaveFontSize) { + printf("FontSize(%d)", mFontSize); + first = false; + } + if (mBits & eHaveWritingMode) { + if (!first) { + printf(", "); + } + printf("WritingMode(0x%x)", GetWritingMode()); + } + printf(" }"); +} +#endif
new file mode 100644 --- /dev/null +++ b/layout/style/RuleNodeCacheConditions.h @@ -0,0 +1,120 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +/* + * an object that stores the result of determining whether a style struct that + * was computed can be cached in the rule tree, and if so, what the conditions + * it relies on are + */ + +#ifndef RuleNodeCacheConditions_h_ +#define RuleNodeCacheConditions_h_ + +#include "mozilla/Attributes.h" +#include "nsCoord.h" +#include "nsTArray.h" + +class nsStyleContext; + +namespace mozilla { + +class RuleNodeCacheConditions +{ +public: + RuleNodeCacheConditions() + : mFontSize(0), mBits(0) {} + RuleNodeCacheConditions(const RuleNodeCacheConditions& aOther) + : mFontSize(aOther.mFontSize), mBits(aOther.mBits) {} + RuleNodeCacheConditions& operator=(const RuleNodeCacheConditions& aOther) + { + mFontSize = aOther.mFontSize; + mBits = aOther.mBits; + return *this; + } + bool operator==(const RuleNodeCacheConditions& aOther) const + { + return mFontSize == aOther.mFontSize && + mBits == aOther.mBits; + } + bool operator!=(const RuleNodeCacheConditions& aOther) const + { + return !(*this == aOther); + } + + bool Matches(nsStyleContext* aStyleContext) const; + + void SetFontSizeDependency(nscoord aCoord) + { + MOZ_ASSERT(!(mBits & eHaveFontSize) || mFontSize == aCoord); + mFontSize = aCoord; + mBits |= eHaveFontSize; + } + + void SetWritingModeDependency(uint8_t aWritingMode) + { + MOZ_ASSERT(!(mBits & eHaveWritingMode) || GetWritingMode() == aWritingMode); + mBits |= (static_cast<uint64_t>(aWritingMode) << eWritingModeShift) | + eHaveWritingMode; + } + + void SetUncacheable() + { + mBits |= eUncacheable; + } + + bool Cacheable() const + { + return !(mBits & eUncacheable); + } + + bool CacheableWithDependencies() const + { + return !(mBits & eUncacheable) && + (mBits & eHaveBitsMask) != 0; + } + + bool CacheableWithoutDependencies() const + { + // We're not uncacheable and we have don't have a font-size or + // writing mode value. + return (mBits & eHaveBitsMask) == 0; + } + +#ifdef DEBUG + void List() const; +#endif + +private: + enum { + eUncacheable = 0x0001, + eHaveFontSize = 0x0002, + eHaveWritingMode = 0x0004, + eHaveBitsMask = 0x00ff, + eWritingModeMask = 0xff00, + eWritingModeShift = 8, + }; + + uint8_t GetWritingMode() const + { + return static_cast<uint8_t>( + (mBits & eWritingModeMask) >> eWritingModeShift); + } + + // The font size from which em units are derived. + nscoord mFontSize; + + // Values in mBits: + // bit 0: are we set to "uncacheable"? + // bit 1: do we have a font size value? + // bit 2: do we have a writing mode value? + // bits 2-7: unused + // bits 8-15: writing mode (uint8_t) + // bits 16-31: unused + uint32_t mBits; +}; + +} // namespace mozilla + +#endif // !defined(RuleNodeCacheConditions_h_)
--- a/layout/style/StyleAnimationValue.cpp +++ b/layout/style/StyleAnimationValue.cpp @@ -2,17 +2,17 @@ /* 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/. */ /* Utilities for animation of computed style values */ #include "mozilla/ArrayUtils.h" #include "mozilla/MathAlgorithms.h" - +#include "mozilla/RuleNodeCacheConditions.h" #include "mozilla/StyleAnimationValue.h" #include "nsStyleTransformMatrix.h" #include "nsCOMArray.h" #include "nsIStyleRule.h" #include "mozilla/css/StyleRule.h" #include "nsString.h" #include "nsStyleContext.h" #include "nsStyleSet.h" @@ -2585,17 +2585,17 @@ StyleAnimationValue::ComputeValue(nsCSSP // Force walk of rule tree nsStyleStructID sid = nsCSSProps::kSIDTable[aProperty]; tmpStyleContext->StyleData(sid); // If the rule node will have cached style data if the value is not // context-sensitive. So if there's nothing cached, it's not context // sensitive. *aIsContextSensitive = - !tmpStyleContext->RuleNode()->NodeHasCachedData(sid); + !tmpStyleContext->RuleNode()->NodeHasCachedUnconditionalData(sid); } // If we're not concerned whether the property is context sensitive then just // add the rule to a new temporary style context alongside the target // element's style context. // Also, if we previously discovered that this property IS context-sensitive // then we need to throw the temporary style context out since the property's // value may have been biased by the 'initial' values supplied. @@ -2863,41 +2863,41 @@ SetPositionValue(const nsStyleBackground * replaced with the equivalent in pixels, and any non-canonical calc() * expressions replaced with canonical ones. */ static void SubstitutePixelValues(nsStyleContext* aStyleContext, const nsCSSValue& aInput, nsCSSValue& aOutput) { if (aInput.IsCalcUnit()) { - bool canStoreInRuleTree = true; + RuleNodeCacheConditions conditions; nsRuleNode::ComputedCalc c = nsRuleNode::SpecifiedCalcToComputedCalc(aInput, aStyleContext, aStyleContext->PresContext(), - canStoreInRuleTree); + conditions); nsStyleCoord::CalcValue c2; c2.mLength = c.mLength; c2.mPercent = c.mPercent; c2.mHasPercent = true; // doesn't matter for transform translate SetCalcValue(&c2, aOutput); } else if (aInput.UnitHasArrayValue()) { const nsCSSValue::Array *inputArray = aInput.GetArrayValue(); nsRefPtr<nsCSSValue::Array> outputArray = nsCSSValue::Array::Create(inputArray->Count()); for (size_t i = 0, i_end = inputArray->Count(); i < i_end; ++i) { SubstitutePixelValues(aStyleContext, inputArray->Item(i), outputArray->Item(i)); } aOutput.SetArrayValue(outputArray, aInput.GetUnit()); } else if (aInput.IsLengthUnit() && aInput.GetUnit() != eCSSUnit_Pixel) { - bool canStoreInRuleTree = true; + RuleNodeCacheConditions conditions; nscoord len = nsRuleNode::CalcLength(aInput, aStyleContext, aStyleContext->PresContext(), - canStoreInRuleTree); + conditions); aOutput.SetFloatValue(nsPresContext::AppUnitsToFloatCSSPixels(len), eCSSUnit_Pixel); } else { aOutput = aInput; } } bool
--- a/layout/style/html.css +++ b/layout/style/html.css @@ -251,17 +251,16 @@ xmp, pre, plaintext { white-space: pre; margin-block-start: 1em; margin-block-end: 1em; } /* tables */ table { - writing-mode: horizontal-tb !important; /* XXX remove when bug 1077521 is fixed */ display: table; border-spacing: 2px; border-collapse: separate; /* XXXldb do we want this if we're border-collapse:collapse ? */ box-sizing: border-box; text-indent: 0; }
--- a/layout/style/moz.build +++ b/layout/style/moz.build @@ -80,16 +80,17 @@ EXPORTS += [ ] EXPORTS.mozilla += [ 'CSSStyleSheet.h', 'CSSVariableDeclarations.h', 'CSSVariableResolver.h', 'CSSVariableValues.h', 'IncrementalClearCOMRuleArray.h', + 'RuleNodeCacheConditions.h', 'StyleAnimationValue.h', ] EXPORTS.mozilla.dom += [ 'CSS.h', 'CSSLexer.h', 'CSSRuleList.h', 'CSSValue.h', @@ -158,16 +159,17 @@ UNIFIED_SOURCES += [ 'nsRuleNode.cpp', 'nsStyleContext.cpp', 'nsStyleCoord.cpp', 'nsStyleSet.cpp', 'nsStyleStruct.cpp', 'nsStyleTransformMatrix.cpp', 'nsStyleUtil.cpp', 'nsTransitionManager.cpp', + 'RuleNodeCacheConditions.cpp', 'StyleAnimationValue.cpp', 'StyleRule.cpp', 'SVGAttrAnimationRuleProcessor.cpp', ] # FontFaceSet.cpp needs to be built separately because it redefines LOG. # nsCSSRuleProcessor.cpp needs to be built separately because it uses plarena.h. SOURCES += [
--- a/layout/style/nsCSSDataBlock.cpp +++ b/layout/style/nsCSSDataBlock.cpp @@ -249,17 +249,18 @@ nsCSSCompressedDataBlock::MapRuleInfoInt nsCSSProperty iProp = PropertyAtIndex(i); if (nsCachedStyleData::GetBitForSID(nsCSSProps::kSIDTable[iProp]) & aRuleData->mSIDs) { if (nsCSSProps::PropHasFlags(iProp, CSS_PROPERTY_LOGICAL)) { EnsurePhysicalProperty(iProp, aRuleData); // We can't cache anything on the rule tree if we use any data from // the style context, since data cached in the rule tree could be // used with a style context with a different value. - aRuleData->mCanStoreInRuleTree = false; + uint8_t wm = WritingMode(aRuleData->mStyleContext).GetBits(); + aRuleData->mConditions.SetWritingModeDependency(wm); } nsCSSValue* target = aRuleData->ValueFor(iProp); if (target->GetUnit() == eCSSUnit_Null) { const nsCSSValue *val = ValueAtIndex(i); MapSinglePropertyInto(iProp, val, target, aRuleData); } } } @@ -688,17 +689,18 @@ nsCSSExpandedDataBlock::MapRuleInfoInto( MOZ_ASSERT(!nsCSSProps::IsShorthand(aPropID)); const nsCSSValue* src = PropertyAt(aPropID); MOZ_ASSERT(src->GetUnit() != eCSSUnit_Null); nsCSSProperty physicalProp = aPropID; if (nsCSSProps::PropHasFlags(aPropID, CSS_PROPERTY_LOGICAL)) { EnsurePhysicalProperty(physicalProp, aRuleData); - aRuleData->mCanStoreInRuleTree = false; + uint8_t wm = WritingMode(aRuleData->mStyleContext).GetBits(); + aRuleData->mConditions.SetWritingModeDependency(wm); } nsCSSValue* dest = aRuleData->ValueFor(physicalProp); MOZ_ASSERT(dest->GetUnit() == eCSSUnit_TokenStream && dest->GetTokenStreamValue()->mPropertyID == aPropID); MapSinglePropertyInto(physicalProp, src, dest, aRuleData); }
--- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -1260,17 +1260,17 @@ nsComputedDOMStyle::DoGetTransform() * the transform based on the size of the element. However, this poses a * problem, because only two of these values can be explicitly referenced * using the named transforms. Until a real solution is found, we'll just * use this approach. */ nsStyleTransformMatrix::TransformReferenceBox refBox(mInnerFrame, nsSize(0, 0)); - bool dummy; + RuleNodeCacheConditions dummy; gfx3DMatrix matrix = nsStyleTransformMatrix::ReadTransforms(display->mSpecifiedTransform->mHead, mStyleContextHolder, mStyleContextHolder->PresContext(), dummy, refBox, float(mozilla::AppUnitsPerCSSPixel()));
--- a/layout/style/nsRuleData.cpp +++ b/layout/style/nsRuleData.cpp @@ -23,17 +23,16 @@ nsRuleData::GetPoisonOffset() uintptr_t framePoisonValue = mozPoisonValue(); return size_t(framePoisonValue - uintptr_t(mValueStorage)) / sizeof(nsCSSValue); } nsRuleData::nsRuleData(uint32_t aSIDs, nsCSSValue* aValueStorage, nsPresContext* aContext, nsStyleContext* aStyleContext) : mSIDs(aSIDs), - mCanStoreInRuleTree(true), mPresContext(aContext), mStyleContext(aStyleContext), mValueStorage(aValueStorage) { #ifndef MOZ_VALGRIND size_t framePoisonOffset = GetPoisonOffset(); for (size_t i = 0; i < nsStyleStructID_Length; ++i) { mValueOffsets[i] = framePoisonOffset;
--- a/layout/style/nsRuleData.h +++ b/layout/style/nsRuleData.h @@ -7,30 +7,31 @@ * temporary (expanded) representation of property-value pairs used to * hold data from matched rules during style data computation. */ #ifndef nsRuleData_h_ #define nsRuleData_h_ #include "mozilla/CSSVariableDeclarations.h" +#include "mozilla/RuleNodeCacheConditions.h" #include "nsCSSProps.h" #include "nsCSSValue.h" #include "nsStyleStructFwd.h" class nsPresContext; class nsStyleContext; struct nsRuleData; typedef void (*nsPostResolveFunc)(void* aStyleStruct, nsRuleData* aData); struct nsRuleData { const uint32_t mSIDs; - bool mCanStoreInRuleTree; + mozilla::RuleNodeCacheConditions mConditions; bool mIsImportantRule; uint16_t mLevel; // an nsStyleSet::sheetType nsPresContext* const mPresContext; nsStyleContext* const mStyleContext; // We store nsCSSValues needed to compute the data for one or more // style structs (specified by the bitfield mSIDs). These are stored // in a single array allocation (which our caller allocates; see
--- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -43,16 +43,17 @@ #include "nsRenderingContext.h" #include "nsStyleUtil.h" #include "nsIDocument.h" #include "prtime.h" #include "CSSVariableResolver.h" #include "nsCSSParser.h" #include "CounterStyleManager.h" #include "nsCSSPropertySet.h" +#include "mozilla/RuleNodeCacheConditions.h" #if defined(_MSC_VER) || defined(__MINGW32__) #include <malloc.h> #ifdef _MSC_VER #define alloca _alloca #endif #endif #ifdef SOLARIS @@ -79,17 +80,17 @@ using namespace mozilla::dom; } /* Helper function to convert a CSS <position> specified value into its * computed-style form. */ static void ComputePositionValue(nsStyleContext* aStyleContext, const nsCSSValue& aValue, nsStyleBackground::Position& aComputedValue, - bool& aCanStoreInRuleTree); + RuleNodeCacheConditions& aConditions); /* * For storage of an |nsRuleNode|'s children in a PLDHashTable. */ struct ChildrenHashEntry : public PLDHashEntryHdr { // key is |mRuleNode->GetKey()| nsRuleNode *mRuleNode; @@ -222,49 +223,49 @@ nsRuleNode::EnsureInlineDisplay(uint8_t& static nscoord CalcLengthWith(const nsCSSValue& aValue, nscoord aFontSize, const nsStyleFont* aStyleFont, nsStyleContext* aStyleContext, nsPresContext* aPresContext, bool aUseProvidedRootEmSize, bool aUseUserFontSet, - bool& aCanStoreInRuleTree); + RuleNodeCacheConditions& aConditions); struct CalcLengthCalcOps : public css::BasicCoordCalcOps, public css::NumbersAlreadyNormalizedOps { // All of the parameters to CalcLengthWith except aValue. const nscoord mFontSize; const nsStyleFont* const mStyleFont; nsStyleContext* const mStyleContext; nsPresContext* const mPresContext; const bool mUseProvidedRootEmSize; const bool mUseUserFontSet; - bool& mCanStoreInRuleTree; + RuleNodeCacheConditions& mConditions; CalcLengthCalcOps(nscoord aFontSize, const nsStyleFont* aStyleFont, nsStyleContext* aStyleContext, nsPresContext* aPresContext, bool aUseProvidedRootEmSize, bool aUseUserFontSet, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) : mFontSize(aFontSize), mStyleFont(aStyleFont), mStyleContext(aStyleContext), mPresContext(aPresContext), mUseProvidedRootEmSize(aUseProvidedRootEmSize), mUseUserFontSet(aUseUserFontSet), - mCanStoreInRuleTree(aCanStoreInRuleTree) + mConditions(aConditions) { } result_type ComputeLeafValue(const nsCSSValue& aValue) { return CalcLengthWith(aValue, mFontSize, mStyleFont, mStyleContext, mPresContext, mUseProvidedRootEmSize, - mUseUserFontSet, mCanStoreInRuleTree); + mUseUserFontSet, mConditions); } }; static inline nscoord ScaleCoordRound(const nsCSSValue& aValue, float aFactor) { return NSToCoordRoundWithClamp(aValue.GetFloatValue() * aFactor); } @@ -360,17 +361,17 @@ static nscoord CalcLengthWith(const nsCS const nsStyleFont* aStyleFont, nsStyleContext* aStyleContext, nsPresContext* aPresContext, bool aUseProvidedRootEmSize, // aUseUserFontSet should always be true // except when called from // CalcLengthWithInitialFont. bool aUseUserFontSet, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) { NS_ASSERTION(aValue.IsLengthUnit() || aValue.IsCalcUnit(), "not a length or calc unit"); NS_ASSERTION(aStyleFont || aStyleContext, "Must have style data"); NS_ASSERTION(!aStyleFont || !aStyleContext, "Duplicate sources of data"); NS_ASSERTION(aPresContext, "Must have prescontext"); @@ -385,17 +386,17 @@ static nscoord CalcLengthWith(const nsCS // For properties for which lengths are the *only* units accepted in // calc(), we can handle calc() here and just compute a final // result. We ensure that we don't get to this code for other // properties by not calling CalcLength in those cases: SetCoord // only calls CalcLength for a calc when it is appropriate to do so. CalcLengthCalcOps ops(aFontSize, aStyleFont, aStyleContext, aPresContext, aUseProvidedRootEmSize, aUseUserFontSet, - aCanStoreInRuleTree); + aConditions); return css::ComputeCalc(aValue, ops); } switch (aValue.GetUnit()) { // nsPresContext::SetVisibleArea and // nsPresContext::MediaFeatureValuesChanged handle dynamic changes // of the basis for viewport units by rebuilding the rule tree and // style context tree. Not caching them in the rule tree wouldn't // be sufficient to handle these changes because we also need a way @@ -435,19 +436,19 @@ static nscoord CalcLengthWith(const nsCS // other things). And since the font size of the root element // changes rarely, we instead handle dynamic changes to the root // element's font size by rebuilding all style data in // nsCSSFrameConstructor::RestyleElement. case eCSSUnit_RootEM: { aPresContext->SetUsesRootEMUnits(true); nscoord rootFontSize; - // NOTE: Be very careful with |styleFont|, since we haven't set - // aCanStoreInRuleTree to false yet, so we don't want to introduce - // any dependencies on aStyleContext's data here. + // NOTE: Be very careful with |styleFont|, since we haven't added any + // conditions to aConditions or set it to uncacheable yet, so we don't + // want to introduce any dependencies on aStyleContext's data here. const nsStyleFont *styleFont = aStyleFont ? aStyleFont : aStyleContext->StyleFont(); if (aUseProvidedRootEmSize) { // We should use the provided aFontSize as the reference length to // scale. This only happens when we are calculating font-size or // an equivalent (scriptminsize or CalcLengthWithInitialFont) on // the root element, in which case aFontSize is already the @@ -489,115 +490,117 @@ static nscoord CalcLengthWith(const nsCS } default: // Fall through to the code for units that can't be stored in the // rule tree because they depend on font data. break; } // Common code for units that depend on the element's font data and // thus can't be stored in the rule tree: - aCanStoreInRuleTree = false; const nsStyleFont *styleFont = aStyleFont ? aStyleFont : aStyleContext->StyleFont(); if (aFontSize == -1) { // XXX Should this be styleFont->mSize instead to avoid taking minfontsize // prefs into account? aFontSize = styleFont->mFont.size; } switch (aValue.GetUnit()) { case eCSSUnit_EM: { // CSS2.1 specifies that this unit scales to the computed font // size, not the em-width in the font metrics, despite the name. + aConditions.SetFontSizeDependency(aFontSize); return ScaleCoordRound(aValue, float(aFontSize)); } case eCSSUnit_XHeight: { aPresContext->SetUsesExChUnits(true); nsRefPtr<nsFontMetrics> fm = GetMetricsFor(aPresContext, aStyleContext, styleFont, aFontSize, aUseUserFontSet); + aConditions.SetUncacheable(); return ScaleCoordRound(aValue, float(fm->XHeight())); } case eCSSUnit_Char: { aPresContext->SetUsesExChUnits(true); nsRefPtr<nsFontMetrics> fm = GetMetricsFor(aPresContext, aStyleContext, styleFont, aFontSize, aUseUserFontSet); gfxFloat zeroWidth = fm->GetThebesFontGroup()->GetFirstValidFont()-> GetMetrics(fm->Orientation()).zeroOrAveCharWidth; + aConditions.SetUncacheable(); return ScaleCoordRound(aValue, ceil(aPresContext->AppUnitsPerDevPixel() * zeroWidth)); } default: NS_NOTREACHED("unexpected unit"); break; } return 0; } /* static */ nscoord nsRuleNode::CalcLength(const nsCSSValue& aValue, nsStyleContext* aStyleContext, nsPresContext* aPresContext, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) { NS_ASSERTION(aStyleContext, "Must have style data"); return CalcLengthWith(aValue, -1, nullptr, aStyleContext, aPresContext, - false, true, aCanStoreInRuleTree); + false, true, aConditions); } /* Inline helper function to redirect requests to CalcLength. */ static inline nscoord CalcLength(const nsCSSValue& aValue, nsStyleContext* aStyleContext, nsPresContext* aPresContext, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) { return nsRuleNode::CalcLength(aValue, aStyleContext, - aPresContext, aCanStoreInRuleTree); + aPresContext, aConditions); } /* static */ nscoord nsRuleNode::CalcLengthWithInitialFont(nsPresContext* aPresContext, const nsCSSValue& aValue) { nsStyleFont defaultFont(aPresContext); // FIXME: best language? - bool canStoreInRuleTree; + RuleNodeCacheConditions conditions; return CalcLengthWith(aValue, -1, &defaultFont, nullptr, aPresContext, - true, false, canStoreInRuleTree); + true, false, conditions); } struct LengthPercentPairCalcOps : public css::NumbersAlreadyNormalizedOps { typedef nsRuleNode::ComputedCalc result_type; LengthPercentPairCalcOps(nsStyleContext* aContext, nsPresContext* aPresContext, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) : mContext(aContext), mPresContext(aPresContext), - mCanStoreInRuleTree(aCanStoreInRuleTree), + mConditions(aConditions), mHasPercent(false) {} nsStyleContext* mContext; nsPresContext* mPresContext; - bool& mCanStoreInRuleTree; + RuleNodeCacheConditions& mConditions; bool mHasPercent; result_type ComputeLeafValue(const nsCSSValue& aValue) { if (aValue.GetUnit() == eCSSUnit_Percent) { mHasPercent = true; return result_type(0, aValue.GetPercentValue()); } return result_type(CalcLength(aValue, mContext, mPresContext, - mCanStoreInRuleTree), + mConditions), 0.0f); } result_type MergeAdditive(nsCSSUnit aCalcFunction, result_type aValue1, result_type aValue2) { if (aCalcFunction == eCSSUnit_Calc_Plus) { @@ -636,39 +639,39 @@ struct LengthPercentPairCalcOps : public aValue1.mPercent * aValue2); } }; static void SpecifiedCalcToComputedCalc(const nsCSSValue& aValue, nsStyleCoord& aCoord, nsStyleContext* aStyleContext, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) { LengthPercentPairCalcOps ops(aStyleContext, aStyleContext->PresContext(), - aCanStoreInRuleTree); + aConditions); nsRuleNode::ComputedCalc vals = ComputeCalc(aValue, ops); nsStyleCoord::Calc* calcObj = new nsStyleCoord::Calc; calcObj->mLength = vals.mLength; calcObj->mPercent = vals.mPercent; calcObj->mHasPercent = ops.mHasPercent; aCoord.SetCalcValue(calcObj); } /* static */ nsRuleNode::ComputedCalc nsRuleNode::SpecifiedCalcToComputedCalc(const nsCSSValue& aValue, nsStyleContext* aStyleContext, nsPresContext* aPresContext, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) { LengthPercentPairCalcOps ops(aStyleContext, aPresContext, - aCanStoreInRuleTree); + aConditions); return ComputeCalc(aValue, ops); } // This is our public API for handling calc() expressions that involve // percentages. /* static */ nscoord nsRuleNode::ComputeComputedCalc(const nsStyleCoord& aValue, nscoord aPercentageBasis) @@ -762,28 +765,28 @@ GetFloatFromBoxPosition(int32_t aEnumVal #define SETCOORD_IA (SETCOORD_INTEGER | SETCOORD_AUTO) #define SETCOORD_LAE (SETCOORD_LENGTH | SETCOORD_AUTO | SETCOORD_ENUMERATED) // changes aCoord iff it returns true static bool SetCoord(const nsCSSValue& aValue, nsStyleCoord& aCoord, const nsStyleCoord& aParentCoord, int32_t aMask, nsStyleContext* aStyleContext, nsPresContext* aPresContext, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) { bool result = true; if (aValue.GetUnit() == eCSSUnit_Null) { result = false; } else if ((((aMask & SETCOORD_LENGTH) != 0) && aValue.IsLengthUnit()) || (((aMask & SETCOORD_CALC_LENGTH_ONLY) != 0) && aValue.IsCalcUnit())) { nscoord len = CalcLength(aValue, aStyleContext, aPresContext, - aCanStoreInRuleTree); + aConditions); if ((aMask & SETCOORD_CALC_CLAMP_NONNEGATIVE) && len < 0) { NS_ASSERTION(aValue.IsCalcUnit(), "parser should have ensured no nonnegative lengths"); len = 0; } aCoord.SetCoordValue(len); } else if (((aMask & SETCOORD_PERCENT) != 0) && @@ -806,34 +809,34 @@ static bool SetCoord(const nsCSSValue& a (aValue.GetUnit() == eCSSUnit_Auto)) { aCoord.SetAutoValue(); } else if ((((aMask & SETCOORD_INHERIT) != 0) && aValue.GetUnit() == eCSSUnit_Inherit) || (((aMask & SETCOORD_UNSET_INHERIT) != 0) && aValue.GetUnit() == eCSSUnit_Unset)) { aCoord = aParentCoord; // just inherit value from parent - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); } else if (((aMask & SETCOORD_NORMAL) != 0) && (aValue.GetUnit() == eCSSUnit_Normal)) { aCoord.SetNormalValue(); } else if (((aMask & SETCOORD_NONE) != 0) && (aValue.GetUnit() == eCSSUnit_None)) { aCoord.SetNoneValue(); } else if (((aMask & SETCOORD_FACTOR) != 0) && (aValue.GetUnit() == eCSSUnit_Number)) { aCoord.SetFactorValue(aValue.GetFloatValue()); } else if (((aMask & SETCOORD_STORE_CALC) != 0) && (aValue.IsCalcUnit())) { SpecifiedCalcToComputedCalc(aValue, aCoord, aStyleContext, - aCanStoreInRuleTree); + aConditions); } else if (aValue.GetUnit() == eCSSUnit_Initial || (aValue.GetUnit() == eCSSUnit_Unset && ((aMask & SETCOORD_UNSET_INITIAL) != 0))) { if ((aMask & SETCOORD_INITIAL_AUTO) != 0) { aCoord.SetAutoValue(); } else if ((aMask & SETCOORD_INITIAL_ZERO) != 0) { @@ -891,53 +894,53 @@ static inline bool SetAbsCoord(const nsC "does not handle SETCOORD_LENGTH, SETCOORD_INHERIT and " "SETCOORD_UNSET_*"); // The values of the following variables will never be used; so it does not // matter what to set. const nsStyleCoord dummyParentCoord; nsStyleContext* dummyStyleContext = nullptr; nsPresContext* dummyPresContext = nullptr; - bool dummyCanStoreInRuleTree = true; + RuleNodeCacheConditions dummyCacheKey; bool rv = SetCoord(aValue, aCoord, dummyParentCoord, aMask, dummyStyleContext, dummyPresContext, - dummyCanStoreInRuleTree); - MOZ_ASSERT(dummyCanStoreInRuleTree, - "SetCoord() should not modify dummyCanStoreInRuleTree."); + dummyCacheKey); + MOZ_ASSERT(dummyCacheKey.CacheableWithoutDependencies(), + "SetCoord() should not modify dummyCacheKey."); return rv; } /* Given a specified value that might be a pair value, call SetCoord twice, * either using each member of the pair, or using the unpaired value twice. */ static bool SetPairCoords(const nsCSSValue& aValue, nsStyleCoord& aCoordX, nsStyleCoord& aCoordY, const nsStyleCoord& aParentX, const nsStyleCoord& aParentY, int32_t aMask, nsStyleContext* aStyleContext, - nsPresContext* aPresContext, bool& aCanStoreInRuleTree) + nsPresContext* aPresContext, RuleNodeCacheConditions& aConditions) { const nsCSSValue& valX = aValue.GetUnit() == eCSSUnit_Pair ? aValue.GetPairValue().mXValue : aValue; const nsCSSValue& valY = aValue.GetUnit() == eCSSUnit_Pair ? aValue.GetPairValue().mYValue : aValue; bool cX = SetCoord(valX, aCoordX, aParentX, aMask, aStyleContext, - aPresContext, aCanStoreInRuleTree); + aPresContext, aConditions); mozilla::DebugOnly<bool> cY = SetCoord(valY, aCoordY, aParentY, aMask, - aStyleContext, aPresContext, aCanStoreInRuleTree); + aStyleContext, aPresContext, aConditions); MOZ_ASSERT(cX == cY, "changed one but not the other"); return cX; } static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor, nsPresContext* aPresContext, nsStyleContext *aContext, - nscolor& aResult, bool& aCanStoreInRuleTree) + nscolor& aResult, RuleNodeCacheConditions& aConditions) { bool result = false; nsCSSUnit unit = aValue.GetUnit(); if (aValue.IsNumericColorUnit()) { aResult = aValue.GetColorValue(); result = true; } @@ -978,17 +981,17 @@ static bool SetColor(const nsCSSValue& a if (aPresContext) { aResult = aPresContext->DefaultActiveLinkColor(); result = true; } break; case NS_COLOR_CURRENTCOLOR: // The data computed from this can't be shared in the rule tree // because they could be used on a node with a different color - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); if (aContext) { aResult = aContext->StyleColor()->mColor; result = true; } break; case NS_COLOR_MOZ_DEFAULT_COLOR: if (aPresContext) { aResult = aPresContext->DefaultColor(); @@ -1005,62 +1008,62 @@ static bool SetColor(const nsCSSValue& a NS_NOTREACHED("Should never have an unknown negative colorID."); break; } } } else if (eCSSUnit_Inherit == unit) { aResult = aParentColor; result = true; - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); } else if (eCSSUnit_Enumerated == unit && aValue.GetIntValue() == NS_STYLE_COLOR_INHERIT_FROM_BODY) { NS_ASSERTION(aPresContext->CompatibilityMode() == eCompatibility_NavQuirks, "Should only get this value in quirks mode"); // We just grab the color from the prescontext, and rely on the fact that // if the body color ever changes all its descendants will get new style // contexts (but NOT necessarily new rulenodes). aResult = aPresContext->BodyTextColor(); result = true; - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); } return result; } static void SetGradientCoord(const nsCSSValue& aValue, nsPresContext* aPresContext, nsStyleContext* aContext, nsStyleCoord& aResult, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) { // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT if (!SetCoord(aValue, aResult, nsStyleCoord(), SETCOORD_LPO | SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC, - aContext, aPresContext, aCanStoreInRuleTree)) { + aContext, aPresContext, aConditions)) { NS_NOTREACHED("unexpected unit for gradient anchor point"); aResult.SetNoneValue(); } } static void SetGradient(const nsCSSValue& aValue, nsPresContext* aPresContext, nsStyleContext* aContext, nsStyleGradient& aResult, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) { MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Gradient, "The given data is not a gradient"); const nsCSSValueGradient* gradient = aValue.GetGradientValue(); if (gradient->mIsExplicitSize) { SetCoord(gradient->GetRadiusX(), aResult.mRadiusX, nsStyleCoord(), SETCOORD_LP | SETCOORD_STORE_CALC, - aContext, aPresContext, aCanStoreInRuleTree); + aContext, aPresContext, aConditions); if (gradient->GetRadiusY().GetUnit() != eCSSUnit_None) { SetCoord(gradient->GetRadiusY(), aResult.mRadiusY, nsStyleCoord(), SETCOORD_LP | SETCOORD_STORE_CALC, - aContext, aPresContext, aCanStoreInRuleTree); + aContext, aPresContext, aConditions); aResult.mShape = NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL; } else { aResult.mRadiusY = aResult.mRadiusX; aResult.mShape = NS_STYLE_GRADIENT_SHAPE_CIRCULAR; } aResult.mSize = NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE; } else if (gradient->mIsRadial) { if (gradient->GetRadialShape().GetUnit() == eCSSUnit_Enumerated) { @@ -1085,52 +1088,52 @@ static void SetGradient(const nsCSSValue aResult.mShape = NS_STYLE_GRADIENT_SHAPE_LINEAR; aResult.mSize = NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER; } aResult.mLegacySyntax = gradient->mIsLegacySyntax; // bg-position SetGradientCoord(gradient->mBgPos.mXValue, aPresContext, aContext, - aResult.mBgPosX, aCanStoreInRuleTree); + aResult.mBgPosX, aConditions); SetGradientCoord(gradient->mBgPos.mYValue, aPresContext, aContext, - aResult.mBgPosY, aCanStoreInRuleTree); + aResult.mBgPosY, aConditions); aResult.mRepeating = gradient->mIsRepeating; // angle const nsStyleCoord dummyParentCoord; if (!SetCoord(gradient->mAngle, aResult.mAngle, dummyParentCoord, SETCOORD_ANGLE, - aContext, aPresContext, aCanStoreInRuleTree)) { + aContext, aPresContext, aConditions)) { NS_ASSERTION(gradient->mAngle.GetUnit() == eCSSUnit_None, "bad unit for gradient angle"); aResult.mAngle.SetNoneValue(); } // stops for (uint32_t i = 0; i < gradient->mStops.Length(); i++) { nsStyleGradientStop stop; const nsCSSValueGradientStop &valueStop = gradient->mStops[i]; if (!SetCoord(valueStop.mLocation, stop.mLocation, nsStyleCoord(), SETCOORD_LPO | SETCOORD_STORE_CALC, - aContext, aPresContext, aCanStoreInRuleTree)) { + aContext, aPresContext, aConditions)) { NS_NOTREACHED("unexpected unit for gradient stop location"); } stop.mIsInterpolationHint = valueStop.mIsInterpolationHint; // inherit is not a valid color for stops, so we pass in a dummy // parent color NS_ASSERTION(valueStop.mColor.GetUnit() != eCSSUnit_Inherit, "inherit is not a valid color for gradient stops"); if (!valueStop.mIsInterpolationHint) { SetColor(valueStop.mColor, NS_RGB(0, 0, 0), aPresContext, - aContext, stop.mColor, aCanStoreInRuleTree); + aContext, stop.mColor, aConditions); } else { // Always initialize to the same color so we don't need to worry // about comparisons. stop.mColor = NS_RGB(0, 0, 0); } aResult.mStops.AppendElement(stop); } @@ -1171,17 +1174,17 @@ static void SetStyleImageToImageRect(nsS cropRect.Set(side, coord); } aResult.SetCropRect(&cropRect); } static void SetStyleImage(nsStyleContext* aStyleContext, const nsCSSValue& aValue, nsStyleImage& aResult, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) { if (aValue.GetUnit() == eCSSUnit_Null) { return; } aResult.SetNull(); switch (aValue.GetUnit()) { @@ -1197,17 +1200,17 @@ static void SetStyleImage(nsStyleContext NS_NOTREACHED("-moz-image-rect() is the only expected function"); } break; case eCSSUnit_Gradient: { nsStyleGradient* gradient = new nsStyleGradient(); if (gradient) { SetGradient(aValue, aStyleContext->PresContext(), aStyleContext, - *gradient, aCanStoreInRuleTree); + *gradient, aConditions); aResult.SetGradientData(gradient); } break; } case eCSSUnit_Element: aResult.SetElementId(aValue.GetStringBufferValue()); break; case eCSSUnit_Initial: @@ -1237,32 +1240,32 @@ static void SetStyleImage(nsStyleContext #define SETDSC_UNSET_INHERIT 0x00400000 #define SETDSC_UNSET_INITIAL 0x00800000 // no caller cares whether aField was changed or not template <typename FieldT, typename T1, typename T2, typename T3, typename T4, typename T5> static void SetDiscrete(const nsCSSValue& aValue, FieldT & aField, - bool& aCanStoreInRuleTree, uint32_t aMask, + RuleNodeCacheConditions& aConditions, uint32_t aMask, FieldT aParentValue, T1 aInitialValue, T2 aAutoValue, T3 aNoneValue, T4 aNormalValue, T5 aSystemFontValue) { switch (aValue.GetUnit()) { case eCSSUnit_Null: return; // every caller of SetDiscrete provides inherit and initial // alternatives, so we don't require them to say so in the mask case eCSSUnit_Inherit: - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); aField = aParentValue; return; case eCSSUnit_Initial: aField = aInitialValue; return; // every caller provides one or other of these alternatives, @@ -1307,17 +1310,17 @@ SetDiscrete(const nsCSSValue& aValue, Fi if (aMask & SETDSC_SYSTEM_FONT) { aField = aSystemFontValue; return; } break; case eCSSUnit_Unset: if (aMask & SETDSC_UNSET_INHERIT) { - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); aField = aParentValue; return; } if (aMask & SETDSC_UNSET_INITIAL) { aField = aInitialValue; return; } break; @@ -1332,17 +1335,17 @@ SetDiscrete(const nsCSSValue& aValue, Fi // flags for SetFactor #define SETFCT_POSITIVE 0x01 // assert value is >= 0.0f #define SETFCT_OPACITY 0x02 // clamp value to [0.0f .. 1.0f] #define SETFCT_NONE 0x04 // allow _None (uses aInitialValue). #define SETFCT_UNSET_INHERIT 0x00400000 #define SETFCT_UNSET_INITIAL 0x00800000 static void -SetFactor(const nsCSSValue& aValue, float& aField, bool& aCanStoreInRuleTree, +SetFactor(const nsCSSValue& aValue, float& aField, RuleNodeCacheConditions& aConditions, float aParentValue, float aInitialValue, uint32_t aFlags = 0) { switch (aValue.GetUnit()) { case eCSSUnit_Null: return; case eCSSUnit_Number: aField = aValue.GetFloatValue(); @@ -1355,34 +1358,34 @@ SetFactor(const nsCSSValue& aValue, floa if (aField < 0.0f) aField = 0.0f; if (aField > 1.0f) aField = 1.0f; } return; case eCSSUnit_Inherit: - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); aField = aParentValue; return; case eCSSUnit_Initial: aField = aInitialValue; return; case eCSSUnit_None: if (aFlags & SETFCT_NONE) { aField = aInitialValue; return; } break; case eCSSUnit_Unset: if (aFlags & SETFCT_UNSET_INHERIT) { - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); aField = aParentValue; return; } if (aFlags & SETFCT_UNSET_INITIAL) { aField = aInitialValue; return; } break; @@ -2182,17 +2185,17 @@ nsRuleNode::ResolveVariableReferences(co // XXX Should pass in sheet here (see bug 952338). parser.ParsePropertyWithVariableReferences( tokenStream->mPropertyID, tokenStream->mShorthandPropertyID, tokenStream->mTokenStream, variables, aRuleData, tokenStream->mSheetURI, tokenStream->mBaseURI, tokenStream->mSheetPrincipal, nullptr, tokenStream->mLineNumber, tokenStream->mLineOffset); - aRuleData->mCanStoreInRuleTree = false; + aRuleData->mConditions.SetUncacheable(); anyTokenStreams = true; } return anyTokenStreams; } const void* nsRuleNode::WalkRuleTree(const nsStyleStructID aSID, @@ -2314,17 +2317,17 @@ nsRuleNode::WalkRuleTree(const nsStyleSt detail != eRuleFullMixed && detail != eRuleFullInherited), "can't have start struct and be fully specified"); bool isReset = nsCachedStyleData::IsReset(aSID); if (!highestNode) highestNode = rootNode; - if (!ruleData.mCanStoreInRuleTree) + if (!ruleData.mConditions.CacheableWithoutDependencies()) detail = eRulePartialMixed; // Treat as though some data is specified to avoid // the optimizations and force data computation. if (detail == eRuleNone && startStruct) { // We specified absolutely no rule information, but a parent rule in the tree // specified all the rule information. We set a bit along the branch from our // node in the tree to the node that specified the data that tells nodes on that // branch that they never need to examine their rules for this particular struct type @@ -2376,27 +2379,28 @@ nsRuleNode::WalkRuleTree(const nsStyleSt else // We are the root. In the case of fonts, the default values just // come from the pres context. return SetDefaultOnRoot(aSID, aContext); } typedef const void* (nsRuleNode::*ComputeFunc)(void*, const nsRuleData*, nsStyleContext*, nsRuleNode*, - RuleDetail, const bool); + RuleDetail, + const RuleNodeCacheConditions); static const ComputeFunc sComputeFuncs[] = { #define STYLE_STRUCT(name, checkdata_cb) &nsRuleNode::Compute##name##Data, #include "nsStyleStructList.h" #undef STYLE_STRUCT }; // We need to compute the data from the information that the rules specified. return (this->*sComputeFuncs[aSID])(startStruct, &ruleData, aContext, highestNode, detail, - ruleData.mCanStoreInRuleTree); + ruleData.mConditions); } const void* nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID, nsStyleContext* aContext) { switch (aSID) { case eStyleStruct_Font: { @@ -2575,46 +2579,46 @@ nsRuleNode::SetDefaultOnRoot(const nsSty NS_ASSERTION(aRuleDetail != eRuleFullInherited, \ "should not have bothered calling Compute*Data"); \ \ nsStyleContext* parentContext = aContext->GetParent(); \ \ nsStyle##type_* data_ = nullptr; \ mozilla::Maybe<nsStyle##type_> maybeFakeParentData; \ const nsStyle##type_* parentdata_ = nullptr; \ - bool canStoreInRuleTree = aCanStoreInRuleTree; \ + RuleNodeCacheConditions conditions = aConditions; \ \ - /* If |canStoreInRuleTree| might be true by the time we're done, we */ \ + /* If |conditions.Cacheable()| might be true by the time we're done, we */ \ /* can't call parentContext->Style##type_() since it could recur into */ \ /* setting the same struct on the same rule node, causing a leak. */ \ if (aRuleDetail != eRuleFullReset && \ (!aStartStruct || (aRuleDetail != eRulePartialReset && \ aRuleDetail != eRuleNone))) { \ if (parentContext) { \ parentdata_ = parentContext->Style##type_(); \ } else { \ maybeFakeParentData.emplace ctorargs_; \ parentdata_ = maybeFakeParentData.ptr(); \ } \ } \ if (eStyleStruct_##type_ == eStyleStruct_Variables) \ /* no need to copy construct an nsStyleVariables, as we will copy */ \ - /* inherited variables (and set canStoreInRuleTree to false) in */ \ + /* inherited variables (and call SetUncacheable()) in */ \ /* ComputeVariablesData */ \ data_ = new (mPresContext) nsStyle##type_ ctorargs_; \ else if (aStartStruct) \ /* We only need to compute the delta between this computed data and */ \ /* our computed data. */ \ data_ = new (mPresContext) \ nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \ else { \ if (aRuleDetail != eRuleFullMixed && aRuleDetail != eRuleFullReset) { \ /* No question. We will have to inherit. Go ahead and init */ \ /* with inherited vals from parent. */ \ - canStoreInRuleTree = false; \ + conditions.SetUncacheable(); \ if (parentdata_) \ data_ = new (mPresContext) nsStyle##type_(*parentdata_); \ else \ data_ = new (mPresContext) nsStyle##type_ ctorargs_; \ } \ else \ data_ = new (mPresContext) nsStyle##type_ ctorargs_; \ } \ @@ -2648,46 +2652,47 @@ nsRuleNode::SetDefaultOnRoot(const nsSty if (aStartStruct) \ /* We only need to compute the delta between this computed data and */ \ /* our computed data. */ \ data_ = new (mPresContext) \ nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \ else \ data_ = new (mPresContext) nsStyle##type_ ctorargs_; \ \ - /* If |canStoreInRuleTree| might be true by the time we're done, we */ \ + /* If |conditions.Cacheable()| might be true by the time we're done, we */ \ /* can't call parentContext->Style##type_() since it could recur into */ \ /* setting the same struct on the same rule node, causing a leak. */ \ mozilla::Maybe<nsStyle##type_> maybeFakeParentData; \ const nsStyle##type_* parentdata_ = data_; \ if (aRuleDetail != eRuleFullReset && \ aRuleDetail != eRulePartialReset && \ aRuleDetail != eRuleNone) { \ if (parentContext) { \ parentdata_ = parentContext->Style##type_(); \ } else { \ maybeFakeParentData.emplace ctorargs_; \ parentdata_ = maybeFakeParentData.ptr(); \ } \ } \ - bool canStoreInRuleTree = aCanStoreInRuleTree; + RuleNodeCacheConditions conditions = aConditions; /** * End an nsRuleNode::Compute*Data function for an inherited struct. * * @param type_ The nsStyle* type this function computes. * @param data_ Variable holding the result of this function. */ #define COMPUTE_END_INHERITED(type_, data_) \ - NS_POSTCONDITION(!canStoreInRuleTree || aRuleDetail == eRuleFullReset || \ + NS_POSTCONDITION(!conditions.CacheableWithoutDependencies() || \ + aRuleDetail == eRuleFullReset || \ (aStartStruct && aRuleDetail == eRulePartialReset), \ - "canStoreInRuleTree must be false for inherited structs " \ - "unless all properties have been specified with values " \ - "other than inherit"); \ - if (canStoreInRuleTree) { \ + "conditions.CacheableWithoutDependencies() must be false " \ + "for inherited structs unless all properties have been " \ + "specified with values other than inherit"); \ + if (conditions.CacheableWithoutDependencies()) { \ /* We were fully specified and can therefore be cached right on the */ \ /* rule node. */ \ if (!aHighestNode->mStyleData.mInheritedData) { \ aHighestNode->mStyleData.mInheritedData = \ new (mPresContext) nsInheritedStyleData; \ } \ NS_ASSERTION(!aHighestNode->mStyleData.mInheritedData-> \ mStyleStructs[eStyleStruct_##type_], \ @@ -2707,40 +2712,51 @@ nsRuleNode::SetDefaultOnRoot(const nsSty /** * End an nsRuleNode::Compute*Data function for a reset struct. * * @param type_ The nsStyle* type this function computes. * @param data_ Variable holding the result of this function. */ #define COMPUTE_END_RESET(type_, data_) \ - NS_POSTCONDITION(!canStoreInRuleTree || \ + NS_POSTCONDITION(!conditions.CacheableWithoutDependencies() || \ aRuleDetail == eRuleNone || \ aRuleDetail == eRulePartialReset || \ aRuleDetail == eRuleFullReset, \ - "canStoreInRuleTree must be false for reset structs " \ - "if any properties were specified as inherit"); \ - if (!canStoreInRuleTree) \ - /* We can't be cached in the rule node. We have to be put right */ \ - /* on the style context. */ \ - aContext->SetStyle(eStyleStruct_##type_, data_); \ - else { \ + "conditions.CacheableWithoutDependencies() must be false " \ + "for reset structs if any properties were specified as " \ + "inherit"); \ + if (conditions.CacheableWithoutDependencies()) { \ /* We were fully specified and can therefore be cached right on the */ \ /* rule node. */ \ if (!aHighestNode->mStyleData.mResetData) { \ aHighestNode->mStyleData.mResetData = \ - new (mPresContext) nsResetStyleData; \ + new (mPresContext) nsConditionalResetStyleData; \ } \ NS_ASSERTION(!aHighestNode->mStyleData.mResetData-> \ - mStyleStructs[eStyleStruct_##type_], \ + GetStyleData(eStyleStruct_##type_), \ "Going to leak style data"); \ aHighestNode->mStyleData.mResetData-> \ - mStyleStructs[eStyleStruct_##type_] = data_; \ + SetStyleData(eStyleStruct_##type_, data_); \ /* Propagate the bit down. */ \ PropagateDependentBit(eStyleStruct_##type_, aHighestNode, data_); \ + } else if (conditions.Cacheable()) { \ + if (!mStyleData.mResetData) { \ + mStyleData.mResetData = new (mPresContext) nsConditionalResetStyleData; \ + } \ + mStyleData.mResetData-> \ + SetStyleData(eStyleStruct_##type_, mPresContext, data_, conditions); \ + /* Tell the style context that it doesn't own the data */ \ + aContext-> \ + AddStyleBit(nsCachedStyleData::GetBitForSID(eStyleStruct_##type_)); \ + aContext->SetStyle(eStyleStruct_##type_, data_); \ + } else { \ + /* We can't be cached in the rule node. We have to be put right */ \ + /* on the style context. */ \ + aContext->SetStyle(eStyleStruct_##type_, data_); \ } \ \ return data_; // This function figures out how much scaling should be suppressed to // satisfy scriptminsize. This is our attempt to implement // http://www.w3.org/TR/MathML2/chapter3.html#id.3.3.4.2.2 // This is called after mScriptLevel, mScriptMinSize and mScriptSizeMultiplier @@ -3066,46 +3082,46 @@ nsRuleNode::FindNextLargerFontSize(nscoo struct SetFontSizeCalcOps : public css::BasicCoordCalcOps, public css::NumbersAlreadyNormalizedOps { // The parameters beyond aValue that we need for CalcLengthWith. const nscoord mParentSize; const nsStyleFont* const mParentFont; nsPresContext* const mPresContext; const bool mAtRoot; - bool& mCanStoreInRuleTree; + RuleNodeCacheConditions& mConditions; SetFontSizeCalcOps(nscoord aParentSize, const nsStyleFont* aParentFont, nsPresContext* aPresContext, bool aAtRoot, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) : mParentSize(aParentSize), mParentFont(aParentFont), mPresContext(aPresContext), mAtRoot(aAtRoot), - mCanStoreInRuleTree(aCanStoreInRuleTree) + mConditions(aConditions) { } result_type ComputeLeafValue(const nsCSSValue& aValue) { nscoord size; if (aValue.IsLengthUnit()) { // Note that font-based length units use the parent's size // unadjusted for scriptlevel changes. A scriptlevel change // between us and the parent is simply ignored. size = CalcLengthWith(aValue, mParentSize, mParentFont, nullptr, mPresContext, mAtRoot, - true, mCanStoreInRuleTree); + true, mConditions); if (!aValue.IsRelativeLengthUnit() && mParentFont->mAllowZoom) { size = nsStyleFont::ZoomText(mPresContext, size); } } else if (eCSSUnit_Percent == aValue.GetUnit()) { - mCanStoreInRuleTree = false; + mConditions.SetUncacheable(); // Note that % units use the parent's size unadjusted for scriptlevel // changes. A scriptlevel change between us and the parent is simply // ignored. // aValue.GetPercentValue() may be negative for, e.g., calc(-50%) size = NSCoordSaturatingMultiply(mParentSize, aValue.GetPercentValue()); } else { MOZ_ASSERT(false, "unexpected value"); size = mParentSize; @@ -3121,17 +3137,17 @@ nsRuleNode::SetFontSize(nsPresContext* a const nsStyleFont* aFont, const nsStyleFont* aParentFont, nscoord* aSize, const nsFont& aSystemFont, nscoord aParentSize, nscoord aScriptLevelAdjustedParentSize, bool aUsedStartStruct, bool aAtRoot, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) { // If false, means that *aSize has not been zoomed. If true, means that // *aSize has been zoomed iff aParentFont->mAllowZoom is true. bool sizeIsZoomedAccordingToParent = false; int32_t baseSize = (int32_t) aPresContext-> GetDefaultFont(aFont->mGenericID, aFont->mLanguage)->size; const nsCSSValue* sizeValue = aRuleData->ValueForFontSize(); @@ -3144,17 +3160,17 @@ nsRuleNode::SetFontSize(nsPresContext* a aPresContext, eFontSize_CSS); } else if (NS_STYLE_FONT_SIZE_XXXLARGE == value) { // <font size="7"> is not specified in CSS, so we don't use eFontSize_CSS. *aSize = CalcFontPointSize(value, baseSize, aPresContext); } else if (NS_STYLE_FONT_SIZE_LARGER == value || NS_STYLE_FONT_SIZE_SMALLER == value) { - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); // Un-zoom so we use the tables correctly. We'll then rezoom due // to the |zoom = true| above. // Note that relative units here use the parent's size unadjusted // for scriptlevel changes. A scriptlevel change between us and the parent // is simply ignored. nscoord parentSize = aParentSize; if (aParentFont->mAllowZoom) { @@ -3179,34 +3195,34 @@ nsRuleNode::SetFontSize(nsPresContext* a NS_NOTREACHED("unexpected value"); } } else if (sizeValue->IsLengthUnit() || sizeValue->GetUnit() == eCSSUnit_Percent || sizeValue->IsCalcUnit()) { SetFontSizeCalcOps ops(aParentSize, aParentFont, aPresContext, aAtRoot, - aCanStoreInRuleTree); + aConditions); *aSize = css::ComputeCalc(*sizeValue, ops); if (*aSize < 0) { MOZ_ASSERT(sizeValue->IsCalcUnit(), "negative lengths and percents should be rejected by parser"); *aSize = 0; } // The calc ops will always zoom its result according to the value // of aParentFont->mAllowZoom. sizeIsZoomedAccordingToParent = true; } else if (eCSSUnit_System_Font == sizeValue->GetUnit()) { // this becomes our cascading size *aSize = aSystemFont.size; } else if (eCSSUnit_Inherit == sizeValue->GetUnit() || eCSSUnit_Unset == sizeValue->GetUnit()) { - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); // We apply scriptlevel change for this case, because the default is // to inherit and we don't want explicit "inherit" to differ from the // default. *aSize = aScriptLevelAdjustedParentSize; sizeIsZoomedAccordingToParent = true; } else if (eCSSUnit_Initial == sizeValue->GetUnit()) { // The initial value is 'medium', which has magical sizing based on @@ -3218,17 +3234,17 @@ nsRuleNode::SetFontSize(nsPresContext* a // if aUsedStartStruct is true, then every single property in the // font struct is being set all at once. This means scriptlevel is not // going to have any influence on the font size; there is no need to // do anything here. if (!aUsedStartStruct && aParentSize != aScriptLevelAdjustedParentSize) { // There was no rule affecting the size but the size has been // affected by the parent's size via scriptlevel change. So we cannot // store the data in the rule tree. - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); *aSize = aScriptLevelAdjustedParentSize; sizeIsZoomedAccordingToParent = true; } else { return; } } // We want to zoom the cascaded size so that em-based measurements, @@ -3250,17 +3266,17 @@ static int8_t ClampTo8Bit(int32_t aValue return int8_t(aValue); } /* static */ void nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext, uint8_t aGenericFontID, const nsRuleData* aRuleData, const nsStyleFont* aParentFont, nsStyleFont* aFont, bool aUsedStartStruct, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) { bool atRoot = !aContext->GetParent(); // -x-text-zoom: none, inherit, initial bool allowZoom; const nsCSSValue* textZoomValue = aRuleData->ValueForTextZoom(); if (eCSSUnit_Null != textZoomValue->GetUnit()) { if (eCSSUnit_Inherit == textZoomValue->GetUnit()) { @@ -3397,17 +3413,17 @@ nsRuleNode::SetFont(nsPresContext* aPres } else if (eCSSUnit_System_Font == familyValue->GetUnit()) { aFont->mFont.fontlist = systemFont.fontlist; aFont->mFont.systemFont = true; aFont->mGenericID = kGenericFont_NONE; } else if (eCSSUnit_Inherit == familyValue->GetUnit() || eCSSUnit_Unset == familyValue->GetUnit()) { - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); aFont->mFont.fontlist = aParentFont->mFont.fontlist; aFont->mFont.systemFont = aParentFont->mFont.systemFont; aFont->mGenericID = aParentFont->mGenericID; } else if (eCSSUnit_Initial == familyValue->GetUnit()) { aFont->mFont.fontlist = defaultVariableFont->fontlist; aFont->mFont.systemFont = defaultVariableFont->systemFont; aFont->mGenericID = kGenericFont_NONE; @@ -3418,43 +3434,43 @@ nsRuleNode::SetFont(nsPresContext* aPres // to be careful not to touch it when we're called directly from // ComputeFontData, because we could have a start struct. if (aGenericFontID != kGenericFont_NONE) { aFont->mGenericID = aGenericFontID; } // -moz-math-variant: enum, inherit, initial SetDiscrete(*aRuleData->ValueForMathVariant(), aFont->mMathVariant, - aCanStoreInRuleTree, + aConditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, aParentFont->mMathVariant, NS_MATHML_MATHVARIANT_NONE, 0, 0, 0, 0); // -moz-math-display: enum, inherit, initial SetDiscrete(*aRuleData->ValueForMathDisplay(), aFont->mMathDisplay, - aCanStoreInRuleTree, + aConditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, aParentFont->mMathDisplay, NS_MATHML_DISPLAYSTYLE_INLINE, 0, 0, 0, 0); // font-smoothing: enum, inherit, initial SetDiscrete(*aRuleData->ValueForOsxFontSmoothing(), - aFont->mFont.smoothing, aCanStoreInRuleTree, + aFont->mFont.smoothing, aConditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, aParentFont->mFont.smoothing, defaultVariableFont->smoothing, 0, 0, 0, 0); // font-style: enum, inherit, initial, -moz-system-font if (aFont->mMathVariant != NS_MATHML_MATHVARIANT_NONE) { // -moz-math-variant overrides font-style aFont->mFont.style = NS_FONT_STYLE_NORMAL; } else { SetDiscrete(*aRuleData->ValueForFontStyle(), - aFont->mFont.style, aCanStoreInRuleTree, + aFont->mFont.style, aConditions, SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | SETDSC_UNSET_INHERIT, aParentFont->mFont.style, defaultVariableFont->style, 0, 0, 0, systemFont.style); } // font-weight: int, enum, inherit, initial, -moz-system-font // special handling for enum @@ -3465,50 +3481,50 @@ nsRuleNode::SetFont(nsPresContext* aPres } else if (eCSSUnit_Enumerated == weightValue->GetUnit()) { int32_t value = weightValue->GetIntValue(); switch (value) { case NS_STYLE_FONT_WEIGHT_NORMAL: case NS_STYLE_FONT_WEIGHT_BOLD: aFont->mFont.weight = value; break; case NS_STYLE_FONT_WEIGHT_BOLDER: { - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); int32_t inheritedValue = aParentFont->mFont.weight; if (inheritedValue <= 300) { aFont->mFont.weight = 400; } else if (inheritedValue <= 500) { aFont->mFont.weight = 700; } else { aFont->mFont.weight = 900; } break; } case NS_STYLE_FONT_WEIGHT_LIGHTER: { - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); int32_t inheritedValue = aParentFont->mFont.weight; if (inheritedValue < 600) { aFont->mFont.weight = 100; } else if (inheritedValue < 800) { aFont->mFont.weight = 400; } else { aFont->mFont.weight = 700; } break; } } } else - SetDiscrete(*weightValue, aFont->mFont.weight, aCanStoreInRuleTree, + SetDiscrete(*weightValue, aFont->mFont.weight, aConditions, SETDSC_INTEGER | SETDSC_SYSTEM_FONT | SETDSC_UNSET_INHERIT, aParentFont->mFont.weight, defaultVariableFont->weight, 0, 0, 0, systemFont.weight); // font-stretch: enum, inherit, initial, -moz-system-font SetDiscrete(*aRuleData->ValueForFontStretch(), - aFont->mFont.stretch, aCanStoreInRuleTree, + aFont->mFont.stretch, aConditions, SETDSC_SYSTEM_FONT | SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, aParentFont->mFont.stretch, defaultVariableFont->stretch, 0, 0, 0, systemFont.stretch); // Compute scriptlevel, scriptminsize and scriptsizemultiplier now so // they're available for font-size computation. @@ -3517,81 +3533,81 @@ nsRuleNode::SetFont(nsPresContext* aPres if (scriptMinSizeValue->IsLengthUnit()) { // scriptminsize in font units (em, ex) has to be interpreted relative // to the parent font, or the size definitions are circular and we // aFont->mScriptMinSize = CalcLengthWith(*scriptMinSizeValue, aParentFont->mSize, aParentFont, nullptr, aPresContext, atRoot, true, - aCanStoreInRuleTree); + aConditions); } // -moz-script-size-multiplier: factor, inherit, initial SetFactor(*aRuleData->ValueForScriptSizeMultiplier(), aFont->mScriptSizeMultiplier, - aCanStoreInRuleTree, aParentFont->mScriptSizeMultiplier, + aConditions, aParentFont->mScriptSizeMultiplier, NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER, SETFCT_POSITIVE | SETFCT_UNSET_INHERIT); // -moz-script-level: integer, number, inherit const nsCSSValue* scriptLevelValue = aRuleData->ValueForScriptLevel(); if (eCSSUnit_Integer == scriptLevelValue->GetUnit()) { // "relative" - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); aFont->mScriptLevel = ClampTo8Bit(aParentFont->mScriptLevel + scriptLevelValue->GetIntValue()); } else if (eCSSUnit_Number == scriptLevelValue->GetUnit()) { // "absolute" aFont->mScriptLevel = ClampTo8Bit(int32_t(scriptLevelValue->GetFloatValue())); } else if (eCSSUnit_Auto == scriptLevelValue->GetUnit()) { // auto - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); aFont->mScriptLevel = ClampTo8Bit(aParentFont->mScriptLevel + (aParentFont->mMathDisplay == NS_MATHML_DISPLAYSTYLE_INLINE ? 1 : 0)); } else if (eCSSUnit_Inherit == scriptLevelValue->GetUnit() || eCSSUnit_Unset == scriptLevelValue->GetUnit()) { - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); aFont->mScriptLevel = aParentFont->mScriptLevel; } else if (eCSSUnit_Initial == scriptLevelValue->GetUnit()) { aFont->mScriptLevel = 0; } // font-kerning: none, enum, inherit, initial, -moz-system-font SetDiscrete(*aRuleData->ValueForFontKerning(), - aFont->mFont.kerning, aCanStoreInRuleTree, + aFont->mFont.kerning, aConditions, SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | SETDSC_UNSET_INHERIT, aParentFont->mFont.kerning, defaultVariableFont->kerning, 0, 0, 0, systemFont.kerning); // font-synthesis: none, enum (bit field), inherit, initial, -moz-system-font SetDiscrete(*aRuleData->ValueForFontSynthesis(), - aFont->mFont.synthesis, aCanStoreInRuleTree, + aFont->mFont.synthesis, aConditions, SETDSC_NONE | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | SETDSC_UNSET_INHERIT, aParentFont->mFont.synthesis, defaultVariableFont->synthesis, 0, 0, 0, systemFont.synthesis); // font-variant-alternates: normal, enum (bit field) + functions, inherit, // initial, -moz-system-font const nsCSSValue* variantAlternatesValue = aRuleData->ValueForFontVariantAlternates(); int32_t variantAlternates = 0; switch (variantAlternatesValue->GetUnit()) { case eCSSUnit_Inherit: case eCSSUnit_Unset: aFont->mFont.CopyAlternates(aParentFont->mFont); - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); break; case eCSSUnit_Initial: case eCSSUnit_Normal: aFont->mFont.variantAlternates = 0; aFont->mFont.alternateValues.Clear(); aFont->mFont.featureValueLookup = nullptr; break; @@ -3617,57 +3633,57 @@ nsRuleNode::SetFont(nsPresContext* aPres break; default: break; } // font-variant-caps: normal, enum, inherit, initial, -moz-system-font SetDiscrete(*aRuleData->ValueForFontVariantCaps(), - aFont->mFont.variantCaps, aCanStoreInRuleTree, + aFont->mFont.variantCaps, aConditions, SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | SETDSC_UNSET_INHERIT, aParentFont->mFont.variantCaps, defaultVariableFont->variantCaps, 0, 0, 0, systemFont.variantCaps); // font-variant-east-asian: normal, enum (bit field), inherit, initial, // -moz-system-font SetDiscrete(*aRuleData->ValueForFontVariantEastAsian(), - aFont->mFont.variantEastAsian, aCanStoreInRuleTree, + aFont->mFont.variantEastAsian, aConditions, SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | SETDSC_UNSET_INHERIT, aParentFont->mFont.variantEastAsian, defaultVariableFont->variantEastAsian, 0, 0, 0, systemFont.variantEastAsian); // font-variant-ligatures: normal, none, enum (bit field), inherit, initial, // -moz-system-font SetDiscrete(*aRuleData->ValueForFontVariantLigatures(), - aFont->mFont.variantLigatures, aCanStoreInRuleTree, + aFont->mFont.variantLigatures, aConditions, SETDSC_NORMAL | SETDSC_NONE | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | SETDSC_UNSET_INHERIT, aParentFont->mFont.variantLigatures, defaultVariableFont->variantLigatures, 0, NS_FONT_VARIANT_LIGATURES_NONE, 0, systemFont.variantLigatures); // font-variant-numeric: normal, enum (bit field), inherit, initial, // -moz-system-font SetDiscrete(*aRuleData->ValueForFontVariantNumeric(), - aFont->mFont.variantNumeric, aCanStoreInRuleTree, + aFont->mFont.variantNumeric, aConditions, SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | SETDSC_UNSET_INHERIT, aParentFont->mFont.variantNumeric, defaultVariableFont->variantNumeric, 0, 0, 0, systemFont.variantNumeric); // font-variant-position: normal, enum, inherit, initial, // -moz-system-font SetDiscrete(*aRuleData->ValueForFontVariantPosition(), - aFont->mFont.variantPosition, aCanStoreInRuleTree, + aFont->mFont.variantPosition, aConditions, SETDSC_NORMAL | SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT | SETDSC_UNSET_INHERIT, aParentFont->mFont.variantPosition, defaultVariableFont->variantPosition, 0, 0, 0, systemFont.variantPosition); // font-feature-settings const nsCSSValue* featureSettingsValue = @@ -3679,17 +3695,17 @@ nsRuleNode::SetFont(nsPresContext* aPres case eCSSUnit_Normal: case eCSSUnit_Initial: aFont->mFont.fontFeatureSettings.Clear(); break; case eCSSUnit_Inherit: case eCSSUnit_Unset: - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); aFont->mFont.fontFeatureSettings = aParentFont->mFont.fontFeatureSettings; break; case eCSSUnit_System_Font: aFont->mFont.fontFeatureSettings = systemFont.fontFeatureSettings; break; case eCSSUnit_PairList: @@ -3703,17 +3719,17 @@ nsRuleNode::SetFont(nsPresContext* aPres break; } // font-language-override const nsCSSValue* languageOverrideValue = aRuleData->ValueForFontLanguageOverride(); if (eCSSUnit_Inherit == languageOverrideValue->GetUnit() || eCSSUnit_Unset == languageOverrideValue->GetUnit()) { - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); aFont->mFont.languageOverride = aParentFont->mFont.languageOverride; } else if (eCSSUnit_Normal == languageOverrideValue->GetUnit() || eCSSUnit_Initial == languageOverrideValue->GetUnit()) { aFont->mFont.languageOverride.Truncate(); } else if (eCSSUnit_System_Font == languageOverrideValue->GetUnit()) { aFont->mFont.languageOverride = systemFont.languageOverride; } else if (eCSSUnit_String == languageOverrideValue->GetUnit()) { languageOverrideValue->GetStringValue(aFont->mFont.languageOverride); @@ -3725,31 +3741,31 @@ nsRuleNode::SetFont(nsPresContext* aPres scriptLevelAdjustedParentSize = ComputeScriptLevelSize(aFont, aParentFont, aPresContext, &scriptLevelAdjustedUnconstrainedParentSize); NS_ASSERTION(!aUsedStartStruct || aFont->mScriptUnconstrainedSize == aFont->mSize, "If we have a start struct, we should have reset everything coming in here"); SetFontSize(aPresContext, aRuleData, aFont, aParentFont, &aFont->mSize, systemFont, aParentFont->mSize, scriptLevelAdjustedParentSize, - aUsedStartStruct, atRoot, aCanStoreInRuleTree); + aUsedStartStruct, atRoot, aConditions); if (aParentFont->mSize == aParentFont->mScriptUnconstrainedSize && scriptLevelAdjustedParentSize == scriptLevelAdjustedUnconstrainedParentSize) { // Fast path: we have not been affected by scriptminsize so we don't // need to call SetFontSize again to compute the // scriptminsize-unconstrained size. This is OK even if we have a // start struct, because if we have a start struct then 'font-size' // was specified and so scriptminsize has no effect. aFont->mScriptUnconstrainedSize = aFont->mSize; } else { SetFontSize(aPresContext, aRuleData, aFont, aParentFont, &aFont->mScriptUnconstrainedSize, systemFont, aParentFont->mScriptUnconstrainedSize, scriptLevelAdjustedUnconstrainedParentSize, - aUsedStartStruct, atRoot, aCanStoreInRuleTree); + aUsedStartStruct, atRoot, aConditions); } NS_ASSERTION(aFont->mScriptUnconstrainedSize <= aFont->mSize, "scriptminsize should never be making things bigger"); nscoord fontSize = aFont->mSize; // enforce the user' specified minimum font-size on the value that we expose // (but don't change font-size:0, since that would unhide hidden text) @@ -3766,17 +3782,17 @@ nsRuleNode::SetFont(nsPresContext* aPres aFont->mFont.size = fontSize; // font-size-adjust: number, none, inherit, initial, -moz-system-font const nsCSSValue* sizeAdjustValue = aRuleData->ValueForFontSizeAdjust(); if (eCSSUnit_System_Font == sizeAdjustValue->GetUnit()) { aFont->mFont.sizeAdjust = systemFont.sizeAdjust; } else SetFactor(*sizeAdjustValue, aFont->mFont.sizeAdjust, - aCanStoreInRuleTree, aParentFont->mFont.sizeAdjust, -1.0f, + aConditions, aParentFont->mFont.sizeAdjust, -1.0f, SETFCT_NONE | SETFCT_UNSET_INHERIT); } /* static */ void nsRuleNode::ComputeFontFeatures(const nsCSSValuePairList *aFeaturesList, nsTArray<gfxFontFeature>& aFeatureSettings) { aFeatureSettings.Clear(); @@ -3839,17 +3855,16 @@ nsRuleNode::SetGenericFont(nsPresContext aPresContext->GetDefaultFont(aGenericFontID, aFont->mLanguage); nsStyleFont parentFont(*defaultFont, aPresContext); if (higherContext) { const nsStyleFont* tmpFont = higherContext->StyleFont(); parentFont = *tmpFont; } *aFont = parentFont; - bool dummy; uint32_t fontBit = nsCachedStyleData::GetBitForSID(eStyleStruct_Font); // use placement new[] on the result of alloca() to allocate a // variable-sized stack array, including execution of constructors, // and use an RAII class to run the destructors too. size_t nprops = nsCSSProps::PropertyCountInStruct(eStyleStruct_Font); void* dataStorage = alloca(nprops * sizeof(nsCSSValue)); @@ -3883,16 +3898,17 @@ nsRuleNode::SetGenericFont(nsPresContext // Avoid unnecessary operations in SetFont(). But we care if it's // the final value that we're computing. if (i != 0) ruleData.ValueForFontFamily()->Reset(); ResolveVariableReferences(eStyleStruct_Font, &ruleData, aContext); + RuleNodeCacheConditions dummy; nsRuleNode::SetFont(aPresContext, context, aGenericFontID, &ruleData, &parentFont, aFont, false, dummy); parentFont = *aFont; } if (higherContext && contextPath.Length() > 1) { @@ -3904,17 +3920,17 @@ nsRuleNode::SetGenericFont(nsPresContext } const void* nsRuleNode::ComputeFontData(void* aStartStruct, const nsRuleData* aRuleData, nsStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail aRuleDetail, - const bool aCanStoreInRuleTree) + const RuleNodeCacheConditions aConditions) { COMPUTE_START_INHERITED(Font, (mPresContext), font, parentFont) // NOTE: The |aRuleDetail| passed in is a little bit conservative due // to the -moz-system-font property. We really don't need to consider // it here in determining whether to cache in the rule tree. However, // we do need to consider it in WalkRuleTree when deciding whether to // walk further up the tree. So this means that when the font struct @@ -3995,21 +4011,21 @@ nsRuleNode::ComputeFontData(void* aStart } } // Now compute our font struct if (generic == kGenericFont_NONE) { // continue the normal processing nsRuleNode::SetFont(mPresContext, aContext, generic, aRuleData, parentFont, font, - aStartStruct != nullptr, canStoreInRuleTree); + aStartStruct != nullptr, conditions); } else { // re-calculate the font as a generic font - canStoreInRuleTree = false; + conditions.SetUncacheable(); nsRuleNode::SetGenericFont(mPresContext, aContext, generic, font); } COMPUTE_END_INHERITED(Font, font) } template <typename T> @@ -4024,17 +4040,17 @@ inline uint32_t ListLength(const T* aLis } already_AddRefed<nsCSSShadowArray> nsRuleNode::GetShadowData(const nsCSSValueList* aList, nsStyleContext* aContext, bool aIsBoxShadow, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) { uint32_t arrayLength = ListLength(aList); MOZ_ASSERT(arrayLength > 0, "Non-null text-shadow list, yet we counted 0 items."); nsRefPtr<nsCSSShadowArray> shadowList = new(arrayLength) nsCSSShadowArray(arrayLength); @@ -4047,54 +4063,54 @@ nsRuleNode::GetShadowData(const nsCSSVal aList; aList = aList->mNext, ++item) { MOZ_ASSERT(aList->mValue.GetUnit() == eCSSUnit_Array, "expecting a plain array value"); nsCSSValue::Array *arr = aList->mValue.GetArrayValue(); // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT unitOK = SetCoord(arr->Item(0), tempCoord, nsStyleCoord(), SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY, - aContext, mPresContext, aCanStoreInRuleTree); + aContext, mPresContext, aConditions); NS_ASSERTION(unitOK, "unexpected unit"); item->mXOffset = tempCoord.GetCoordValue(); unitOK = SetCoord(arr->Item(1), tempCoord, nsStyleCoord(), SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY, - aContext, mPresContext, aCanStoreInRuleTree); + aContext, mPresContext, aConditions); NS_ASSERTION(unitOK, "unexpected unit"); item->mYOffset = tempCoord.GetCoordValue(); // Blur radius is optional in the current box-shadow spec if (arr->Item(2).GetUnit() != eCSSUnit_Null) { unitOK = SetCoord(arr->Item(2), tempCoord, nsStyleCoord(), SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY | SETCOORD_CALC_CLAMP_NONNEGATIVE, - aContext, mPresContext, aCanStoreInRuleTree); + aContext, mPresContext, aConditions); NS_ASSERTION(unitOK, "unexpected unit"); item->mRadius = tempCoord.GetCoordValue(); } else { item->mRadius = 0; } // Find the spread radius if (aIsBoxShadow && arr->Item(3).GetUnit() != eCSSUnit_Null) { unitOK = SetCoord(arr->Item(3), tempCoord, nsStyleCoord(), SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY, - aContext, mPresContext, aCanStoreInRuleTree); + aContext, mPresContext, aConditions); NS_ASSERTION(unitOK, "unexpected unit"); item->mSpread = tempCoord.GetCoordValue(); } else { item->mSpread = 0; } if (arr->Item(4).GetUnit() != eCSSUnit_Null) { item->mHasColor = true; // 2nd argument can be bogus since inherit is not a valid color unitOK = SetColor(arr->Item(4), 0, mPresContext, aContext, item->mColor, - aCanStoreInRuleTree); + aConditions); NS_ASSERTION(unitOK, "unexpected unit"); } if (aIsBoxShadow && arr->Item(5).GetUnit() == eCSSUnit_Enumerated) { NS_ASSERTION(arr->Item(5).GetIntValue() == NS_STYLE_BOX_SHADOW_INSET, "invalid keyword type for box shadow"); item->mInset = true; } else { @@ -4106,76 +4122,76 @@ nsRuleNode::GetShadowData(const nsCSSVal } const void* nsRuleNode::ComputeTextData(void* aStartStruct, const nsRuleData* aRuleData, nsStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail aRuleDetail, - const bool aCanStoreInRuleTree) + const RuleNodeCacheConditions aConditions) { COMPUTE_START_INHERITED(Text, (), text, parentText) // tab-size: integer, inherit SetDiscrete(*aRuleData->ValueForTabSize(), - text->mTabSize, canStoreInRuleTree, + text->mTabSize, conditions, SETDSC_INTEGER | SETDSC_UNSET_INHERIT, parentText->mTabSize, NS_STYLE_TABSIZE_INITIAL, 0, 0, 0, 0); // letter-spacing: normal, length, inherit SetCoord(*aRuleData->ValueForLetterSpacing(), text->mLetterSpacing, parentText->mLetterSpacing, SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL | SETCOORD_CALC_LENGTH_ONLY | SETCOORD_UNSET_INHERIT, - aContext, mPresContext, canStoreInRuleTree); + aContext, mPresContext, conditions); // text-shadow: none, list, inherit, initial const nsCSSValue* textShadowValue = aRuleData->ValueForTextShadow(); if (textShadowValue->GetUnit() != eCSSUnit_Null) { text->mTextShadow = nullptr; // Don't need to handle none/initial explicitly: The above assignment // takes care of that if (textShadowValue->GetUnit() == eCSSUnit_Inherit || textShadowValue->GetUnit() == eCSSUnit_Unset) { - canStoreInRuleTree = false; + conditions.SetUncacheable(); text->mTextShadow = parentText->mTextShadow; } else if (textShadowValue->GetUnit() == eCSSUnit_List || textShadowValue->GetUnit() == eCSSUnit_ListDep) { // List of arrays text->mTextShadow = GetShadowData(textShadowValue->GetListValue(), - aContext, false, canStoreInRuleTree); + aContext, false, conditions); } } // line-height: normal, number, length, percent, inherit const nsCSSValue* lineHeightValue = aRuleData->ValueForLineHeight(); if (eCSSUnit_Percent == lineHeightValue->GetUnit()) { - canStoreInRuleTree = false; + conditions.SetUncacheable(); // Use |mFont.size| to pick up minimum font size. text->mLineHeight.SetCoordValue( NSToCoordRound(float(aContext->StyleFont()->mFont.size) * lineHeightValue->GetPercentValue())); } else if (eCSSUnit_Initial == lineHeightValue->GetUnit() || eCSSUnit_System_Font == lineHeightValue->GetUnit()) { text->mLineHeight.SetNormalValue(); } else { SetCoord(*lineHeightValue, text->mLineHeight, parentText->mLineHeight, SETCOORD_LEH | SETCOORD_FACTOR | SETCOORD_NORMAL | SETCOORD_UNSET_INHERIT, - aContext, mPresContext, canStoreInRuleTree); + aContext, mPresContext, conditions); if (lineHeightValue->IsLengthUnit() && !lineHeightValue->IsRelativeLengthUnit()) { nscoord lh = nsStyleFont::ZoomText(mPresContext, text->mLineHeight.GetCoordValue()); - canStoreInRuleTree = false; + conditions.SetUncacheable(); const nsStyleFont *font = aContext->StyleFont(); nscoord minimumFontSize = mPresContext->MinFontSize(font->mLanguage); if (minimumFontSize > 0 && !mPresContext->IsChrome()) { if (font->mSize != 0) { lh = nscoord(float(lh) * float(font->mFont.size) / float(font->mSize)); } else { lh = minimumFontSize; @@ -4190,24 +4206,24 @@ nsRuleNode::ComputeTextData(void* aStart // NOTE: string is not implemented yet. const nsCSSValue* textAlignValue = aRuleData->ValueForTextAlign(); text->mTextAlignTrue = false; if (eCSSUnit_String == textAlignValue->GetUnit()) { NS_NOTYETIMPLEMENTED("align string"); } else if (eCSSUnit_Enumerated == textAlignValue->GetUnit() && NS_STYLE_TEXT_ALIGN_MOZ_CENTER_OR_INHERIT == textAlignValue->GetIntValue()) { - canStoreInRuleTree = false; + conditions.SetUncacheable(); uint8_t parentAlign = parentText->mTextAlign; text->mTextAlign = (NS_STYLE_TEXT_ALIGN_DEFAULT == parentAlign) ? NS_STYLE_TEXT_ALIGN_CENTER : parentAlign; } else if (eCSSUnit_Enumerated == textAlignValue->GetUnit() && NS_STYLE_TEXT_ALIGN_MATCH_PARENT == textAlignValue->GetIntValue()) { - canStoreInRuleTree = false; + conditions.SetUncacheable(); nsStyleContext* parent = aContext->GetParent(); if (parent) { uint8_t parentAlign = parentText->mTextAlign; uint8_t parentDirection = parent->StyleVisibility()->mDirection; switch (parentAlign) { case NS_STYLE_TEXT_ALIGN_DEFAULT: text->mTextAlign = parentDirection == NS_STYLE_DIRECTION_RTL ? NS_STYLE_TEXT_ALIGN_RIGHT : NS_STYLE_TEXT_ALIGN_LEFT; @@ -4234,17 +4250,17 @@ nsRuleNode::ComputeTextData(void* aStart } } else if (eCSSUnit_String == textAlignValue->GetUnit()) { NS_NOTYETIMPLEMENTED("align string"); } } else if (eCSSUnit_Inherit == textAlignValue->GetUnit() || eCSSUnit_Unset == textAlignValue->GetUnit()) { text->mTextAlignTrue = parentText->mTextAlignTrue; } - SetDiscrete(*textAlignValue, text->mTextAlign, canStoreInRuleTree, + SetDiscrete(*textAlignValue, text->mTextAlign, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentText->mTextAlign, NS_STYLE_TEXT_ALIGN_DEFAULT, 0, 0, 0, 0); } // text-align-last: enum, pair(enum), inherit, initial const nsCSSValue* textAlignLastValue = aRuleData->ValueForTextAlignLast(); text->mTextAlignLastTrue = false; @@ -4258,137 +4274,137 @@ nsRuleNode::ComputeTextData(void* aStart textAlignLastValue = &textAlignLastValuePair.mYValue; } } } else if (eCSSUnit_Inherit == textAlignLastValue->GetUnit() || eCSSUnit_Unset == textAlignLastValue->GetUnit()) { text->mTextAlignLastTrue = parentText->mTextAlignLastTrue; } SetDiscrete(*textAlignLastValue, text->mTextAlignLast, - canStoreInRuleTree, + conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentText->mTextAlignLast, NS_STYLE_TEXT_ALIGN_AUTO, 0, 0, 0, 0); // text-indent: length, percent, calc, inherit, initial SetCoord(*aRuleData->ValueForTextIndent(), text->mTextIndent, parentText->mTextIndent, SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC | SETCOORD_UNSET_INHERIT, - aContext, mPresContext, canStoreInRuleTree); + aContext, mPresContext, conditions); // text-transform: enum, inherit, initial - SetDiscrete(*aRuleData->ValueForTextTransform(), text->mTextTransform, canStoreInRuleTree, + SetDiscrete(*aRuleData->ValueForTextTransform(), text->mTextTransform, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentText->mTextTransform, NS_STYLE_TEXT_TRANSFORM_NONE, 0, 0, 0, 0); // white-space: enum, inherit, initial - SetDiscrete(*aRuleData->ValueForWhiteSpace(), text->mWhiteSpace, canStoreInRuleTree, + SetDiscrete(*aRuleData->ValueForWhiteSpace(), text->mWhiteSpace, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentText->mWhiteSpace, NS_STYLE_WHITESPACE_NORMAL, 0, 0, 0, 0); // word-break: enum, inherit, initial - SetDiscrete(*aRuleData->ValueForWordBreak(), text->mWordBreak, canStoreInRuleTree, + SetDiscrete(*aRuleData->ValueForWordBreak(), text->mWordBreak, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentText->mWordBreak, NS_STYLE_WORDBREAK_NORMAL, 0, 0, 0, 0); // word-spacing: normal, length, inherit nsStyleCoord tempCoord; const nsCSSValue* wordSpacingValue = aRuleData->ValueForWordSpacing(); if (SetCoord(*wordSpacingValue, tempCoord, nsStyleCoord(parentText->mWordSpacing, nsStyleCoord::CoordConstructor), SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL | SETCOORD_CALC_LENGTH_ONLY | SETCOORD_UNSET_INHERIT, - aContext, mPresContext, canStoreInRuleTree)) { + aContext, mPresContext, conditions)) { if (tempCoord.GetUnit() == eStyleUnit_Coord) { text->mWordSpacing = tempCoord.GetCoordValue(); } else if (tempCoord.GetUnit() == eStyleUnit_Normal) { text->mWordSpacing = 0; } else { NS_NOTREACHED("unexpected unit"); } } else { NS_ASSERTION(wordSpacingValue->GetUnit() == eCSSUnit_Null, "unexpected unit"); } // word-wrap: enum, inherit, initial - SetDiscrete(*aRuleData->ValueForWordWrap(), text->mWordWrap, canStoreInRuleTree, + SetDiscrete(*aRuleData->ValueForWordWrap(), text->mWordWrap, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentText->mWordWrap, NS_STYLE_WORDWRAP_NORMAL, 0, 0, 0, 0); // hyphens: enum, inherit, initial - SetDiscrete(*aRuleData->ValueForHyphens(), text->mHyphens, canStoreInRuleTree, + SetDiscrete(*aRuleData->ValueForHyphens(), text->mHyphens, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentText->mHyphens, NS_STYLE_HYPHENS_MANUAL, 0, 0, 0, 0); // ruby-align: enum, inherit, initial SetDiscrete(*aRuleData->ValueForRubyAlign(), - text->mRubyAlign, canStoreInRuleTree, + text->mRubyAlign, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentText->mRubyAlign, NS_STYLE_RUBY_ALIGN_SPACE_AROUND, 0, 0, 0, 0); // ruby-position: enum, inherit, initial SetDiscrete(*aRuleData->ValueForRubyPosition(), - text->mRubyPosition, canStoreInRuleTree, + text->mRubyPosition, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentText->mRubyPosition, NS_STYLE_RUBY_POSITION_OVER, 0, 0, 0, 0); // text-size-adjust: none, auto, inherit, initial SetDiscrete(*aRuleData->ValueForTextSizeAdjust(), text->mTextSizeAdjust, - canStoreInRuleTree, + conditions, SETDSC_NONE | SETDSC_AUTO | SETDSC_UNSET_INHERIT, parentText->mTextSizeAdjust, NS_STYLE_TEXT_SIZE_ADJUST_AUTO, // initial value NS_STYLE_TEXT_SIZE_ADJUST_AUTO, // auto value NS_STYLE_TEXT_SIZE_ADJUST_NONE, // none value 0, 0); // text-combine-upright: enum, inherit, initial SetDiscrete(*aRuleData->ValueForTextCombineUpright(), text->mTextCombineUpright, - canStoreInRuleTree, + conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentText->mTextCombineUpright, NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE, 0, 0, 0, 0); // -moz-text-discard: enum, inherit, initial SetDiscrete(*aRuleData->ValueForControlCharacterVisibility(), text->mControlCharacterVisibility, - canStoreInRuleTree, + conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentText->mControlCharacterVisibility, NS_STYLE_CONTROL_CHARACTER_VISIBILITY_HIDDEN, 0, 0, 0, 0); COMPUTE_END_INHERITED(Text, text) } const void* nsRuleNode::ComputeTextResetData(void* aStartStruct, const nsRuleData* aRuleData, nsStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail aRuleDetail, - const bool aCanStoreInRuleTree) + const RuleNodeCacheConditions aConditions) { COMPUTE_START_RESET(TextReset, (), text, parentText) // vertical-align: enum, length, percent, calc, inherit const nsCSSValue* verticalAlignValue = aRuleData->ValueForVerticalAlign(); if (!SetCoord(*verticalAlignValue, text->mVerticalAlign, parentText->mVerticalAlign, SETCOORD_LPH | SETCOORD_ENUMERATED | SETCOORD_STORE_CALC, - aContext, mPresContext, canStoreInRuleTree)) { + aContext, mPresContext, conditions)) { if (eCSSUnit_Initial == verticalAlignValue->GetUnit() || eCSSUnit_Unset == verticalAlignValue->GetUnit()) { text->mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE, eStyleUnit_Enumerated); } } // text-decoration-line: enum (bit field), inherit, initial @@ -4403,29 +4419,29 @@ nsRuleNode::ComputeTextResetData(void* a if (underlineLinks) { text->mTextDecorationLine |= NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE; } else { text->mTextDecorationLine &= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE; } } } else if (eCSSUnit_Inherit == decorationLineValue->GetUnit()) { - canStoreInRuleTree = false; + conditions.SetUncacheable(); text->mTextDecorationLine = parentText->mTextDecorationLine; } else if (eCSSUnit_Initial == decorationLineValue->GetUnit() || eCSSUnit_Unset == decorationLineValue->GetUnit()) { text->mTextDecorationLine = NS_STYLE_TEXT_DECORATION_LINE_NONE; } // text-decoration-color: color, string, enum, inherit, initial const nsCSSValue* decorationColorValue = aRuleData->ValueForTextDecorationColor(); nscolor decorationColor; if (eCSSUnit_Inherit == decorationColorValue->GetUnit()) { - canStoreInRuleTree = false; + conditions.SetUncacheable(); if (parentContext) { bool isForeground; parentText->GetDecorationColor(decorationColor, isForeground); if (isForeground) { text->SetDecorationColor(parentContext->StyleColor()->mColor); } else { text->SetDecorationColor(decorationColor); } @@ -4433,17 +4449,17 @@ nsRuleNode::ComputeTextResetData(void* a text->SetDecorationColorToForeground(); } } else if (eCSSUnit_EnumColor == decorationColorValue->GetUnit() && decorationColorValue->GetIntValue() == NS_COLOR_CURRENTCOLOR) { text->SetDecorationColorToForeground(); } else if (SetColor(*decorationColorValue, 0, mPresContext, aContext, - decorationColor, canStoreInRuleTree)) { + decorationColor, conditions)) { text->SetDecorationColor(decorationColor); } else if (eCSSUnit_Initial == decorationColorValue->GetUnit() || eCSSUnit_Unset == decorationColorValue->GetUnit() || eCSSUnit_Enumerated == decorationColorValue->GetUnit()) { MOZ_ASSERT(eCSSUnit_Enumerated != decorationColorValue->GetUnit() || decorationColorValue->GetIntValue() == NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR, @@ -4453,35 +4469,35 @@ nsRuleNode::ComputeTextResetData(void* a // text-decoration-style: enum, inherit, initial const nsCSSValue* decorationStyleValue = aRuleData->ValueForTextDecorationStyle(); if (eCSSUnit_Enumerated == decorationStyleValue->GetUnit()) { text->SetDecorationStyle(decorationStyleValue->GetIntValue()); } else if (eCSSUnit_Inherit == decorationStyleValue->GetUnit()) { text->SetDecorationStyle(parentText->GetDecorationStyle()); - canStoreInRuleTree = false; + conditions.SetUncacheable(); } else if (eCSSUnit_Initial == decorationStyleValue->GetUnit() || eCSSUnit_Unset == decorationStyleValue->GetUnit()) { text->SetDecorationStyle(NS_STYLE_TEXT_DECORATION_STYLE_SOLID); } // text-overflow: enum, string, pair(enum|string), inherit, initial const nsCSSValue* textOverflowValue = aRuleData->ValueForTextOverflow(); if (eCSSUnit_Initial == textOverflowValue->GetUnit() || eCSSUnit_Unset == textOverflowValue->GetUnit()) { text->mTextOverflow = nsStyleTextOverflow(); } else if (eCSSUnit_Inherit == textOverflowValue->GetUnit()) { - canStoreInRuleTree = false; + conditions.SetUncacheable(); text->mTextOverflow = parentText->mTextOverflow; } else if (eCSSUnit_Enumerated == textOverflowValue->GetUnit()) { // A single enumerated value. SetDiscrete(*textOverflowValue, text->mTextOverflow.mRight.mType, - canStoreInRuleTree, + conditions, SETDSC_ENUMERATED, parentText->mTextOverflow.mRight.mType, NS_STYLE_TEXT_OVERFLOW_CLIP, 0, 0, 0, 0); text->mTextOverflow.mRight.mString.Truncate(); text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_CLIP; text->mTextOverflow.mLeft.mString.Truncate(); text->mTextOverflow.mLogicalDirections = true; } else if (eCSSUnit_String == textOverflowValue->GetUnit()) { // A single string value. @@ -4494,68 +4510,68 @@ nsRuleNode::ComputeTextResetData(void* a // Two values were specified. text->mTextOverflow.mLogicalDirections = false; const nsCSSValuePair& textOverflowValuePair = textOverflowValue->GetPairValue(); const nsCSSValue *textOverflowLeftValue = &textOverflowValuePair.mXValue; if (eCSSUnit_Enumerated == textOverflowLeftValue->GetUnit()) { SetDiscrete(*textOverflowLeftValue, text->mTextOverflow.mLeft.mType, - canStoreInRuleTree, + conditions, SETDSC_ENUMERATED, parentText->mTextOverflow.mLeft.mType, NS_STYLE_TEXT_OVERFLOW_CLIP, 0, 0, 0, 0); text->mTextOverflow.mLeft.mString.Truncate(); } else if (eCSSUnit_String == textOverflowLeftValue->GetUnit()) { textOverflowLeftValue->GetStringValue(text->mTextOverflow.mLeft.mString); text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_STRING; } const nsCSSValue *textOverflowRightValue = &textOverflowValuePair.mYValue; if (eCSSUnit_Enumerated == textOverflowRightValue->GetUnit()) { SetDiscrete(*textOverflowRightValue, text->mTextOverflow.mRight.mType, - canStoreInRuleTree, + conditions, SETDSC_ENUMERATED, parentText->mTextOverflow.mRight.mType, NS_STYLE_TEXT_OVERFLOW_CLIP, 0, 0, 0, 0); text->mTextOverflow.mRight.mString.Truncate(); } else if (eCSSUnit_String == textOverflowRightValue->GetUnit()) { textOverflowRightValue->GetStringValue(text->mTextOverflow.mRight.mString); text->mTextOverflow.mRight.mType = NS_STYLE_TEXT_OVERFLOW_STRING; } } // unicode-bidi: enum, inherit, initial - SetDiscrete(*aRuleData->ValueForUnicodeBidi(), text->mUnicodeBidi, canStoreInRuleTree, + SetDiscrete(*aRuleData->ValueForUnicodeBidi(), text->mUnicodeBidi, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, parentText->mUnicodeBidi, NS_STYLE_UNICODE_BIDI_NORMAL, 0, 0, 0, 0); COMPUTE_END_RESET(TextReset, text) } const void* nsRuleNode::ComputeUserInterfaceData(void* aStartStruct, const nsRuleData* aRuleData, nsStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail aRuleDetail, - const bool aCanStoreInRuleTree) + const RuleNodeCacheConditions aConditions) { COMPUTE_START_INHERITED(UserInterface, (), ui, parentUI) // cursor: enum, url, inherit const nsCSSValue* cursorValue = aRuleData->ValueForCursor(); nsCSSUnit cursorUnit = cursorValue->GetUnit(); if (cursorUnit != eCSSUnit_Null) { delete [] ui->mCursorArray; ui->mCursorArray = nullptr; ui->mCursorArrayLength = 0; if (cursorUnit == eCSSUnit_Inherit || cursorUnit == eCSSUnit_Unset) { - canStoreInRuleTree = false; + conditions.SetUncacheable(); ui->mCursor = parentUI->mCursor; ui->CopyCursorArrayFrom(*parentUI); } else if (cursorUnit == eCSSUnit_Initial) { ui->mCursor = NS_STYLE_CURSOR_AUTO; } else { // The parser will never create a list that is *all* URL values -- @@ -4597,81 +4613,81 @@ nsRuleNode::ComputeUserInterfaceData(voi NS_ASSERTION(list->mValue.GetUnit() == eCSSUnit_Enumerated, "Unexpected fallback value at end of cursor list"); ui->mCursor = list->mValue.GetIntValue(); } } // user-input: enum, inherit, initial SetDiscrete(*aRuleData->ValueForUserInput(), - ui->mUserInput, canStoreInRuleTree, + ui->mUserInput, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentUI->mUserInput, NS_STYLE_USER_INPUT_AUTO, 0, 0, 0, 0); // user-modify: enum, inherit, initial SetDiscrete(*aRuleData->ValueForUserModify(), - ui->mUserModify, canStoreInRuleTree, + ui->mUserModify, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentUI->mUserModify, NS_STYLE_USER_MODIFY_READ_ONLY, 0, 0, 0, 0); // user-focus: enum, inherit, initial SetDiscrete(*aRuleData->ValueForUserFocus(), - ui->mUserFocus, canStoreInRuleTree, + ui->mUserFocus, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentUI->mUserFocus, NS_STYLE_USER_FOCUS_NONE, 0, 0, 0, 0); // -moz-window-dragging: enum, inherit, initial SetDiscrete(*aRuleData->ValueForWindowDragging(), - ui->mWindowDragging, canStoreInRuleTree, + ui->mWindowDragging, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT, parentUI->mWindowDragging, NS_STYLE_WINDOW_DRAGGING_NO_DRAG, 0, 0, 0, 0); COMPUTE_END_INHERITED(UserInterface, ui) } const void* nsRuleNode::ComputeUIResetData(void* aStartStruct, const nsRuleData* aRuleData, nsStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail aRuleDetail, - const bool aCanStoreInRuleTree) + const RuleNodeCacheConditions aConditions) { COMPUTE_START_RESET(UIReset, (), ui, parentUI) // user-select: enum, inherit, initial SetDiscrete(*aRuleData->ValueForUserSelect(), - ui->mUserSelect, canStoreInRuleTree, + ui->mUserSelect, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, parentUI->mUserSelect, NS_STYLE_USER_SELECT_AUTO, 0, 0, 0, 0); // ime-mode: enum, inherit, initial SetDiscrete(*aRuleData->ValueForImeMode(), - ui->mIMEMode, canStoreInRuleTree, + ui->mIMEMode, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, parentUI->mIMEMode, NS_STYLE_IME_MODE_AUTO, 0, 0, 0, 0); // force-broken-image-icons: integer, inherit, initial SetDiscrete(*aRuleData->ValueForForceBrokenImageIcon(), ui->mForceBrokenImageIcon, - canStoreInRuleTree, + conditions, SETDSC_INTEGER | SETDSC_UNSET_INITIAL, parentUI->mForceBrokenImageIcon, 0, 0, 0, 0, 0); // -moz-window-shadow: enum, inherit, initial SetDiscrete(*aRuleData->ValueForWindowShadow(), - ui->mWindowShadow, canStoreInRuleTree, + ui->mWindowShadow, conditions, SETDSC_ENUMERATED | SETDSC_UNSET_INITIAL, parentUI->mWindowShadow, NS_STYLE_WINDOW_SHADOW_DEFAULT, 0, 0, 0, 0); COMPUTE_END_RESET(UIReset, ui) } // Information about each transition or animation property that is @@ -4726,17 +4742,17 @@ struct TransitionPropData { static uint32_t CountTransitionProps(const TransitionPropInfo* aInfo, TransitionPropData* aData, size_t aLength, nsStyleDisplay* aDisplay, const nsStyleDisplay* aParentDisplay, const nsRuleData* aRuleData, - bool& aCanStoreInRuleTree) + RuleNodeCacheConditions& aConditions) { // The four transition properties or eight animation properties are // stored in nsCSSDisplay in a single array for all properties. The // number of transitions is equal to the number of items in the // longest property's value. Properties that have fewer values than // the longest are filled in by repeating the list. However, this // repetition does not extend the computed value of that particular // property (for purposes of inheritance, or, in our code, for when @@ -4785,17 +4801,17 @@ CountTransitionProps(const TransitionPro // that property are specified by the parent, but only those // that were explicitly specified // - otherwise, count the number of values specified in displayData // calculate number of elements if (data.unit == eCSSUnit_Inherit) { data.num = aParentDisplay->*(info.sdCount); - aCanStoreInRuleTree = false; + aConditions.SetUncacheable(); } else if (data.list) { data.num = ListLength(data.list); } else { data.num = aDisplay->*(info.sdCount); } if (data.num > numTransitions) numTransitions = data.num; } @@ -4847,17 +4863,17 @@ ComputeTimingFunction(const nsCSSValue& } const void* nsRuleNode::ComputeDisplayData(void* aStartStruct, const nsRuleData* aRuleData, nsStyleContext* aContext, nsRuleNode* aHighestNode, const RuleDetail aRuleDetail, - const bool aCanStoreInRuleTree) + const RuleNodeCacheConditions aConditions) { COMPUTE_START_RESET(Display, (), display, parentDisplay) // We may have ended up with aStartStruct's values of mDisplay and // mFloats, but those may not be correct if our style data overrides // its position or float properties. Reset to mOriginalDisplay and // mOriginalFloats; it if turns out we still need the display/floats // adjustments we'll do them below. @@ -4875,17 +4891,17 @@ nsRuleNode::ComputeDisplayData(void* aSt #define FOR_ALL_TRANSITION_PROPS(var_) \ for (uint32_t var_ = 0; var_ < 4; ++var_) // CSS Transitions uint32_t numTransitions = CountTransitionProps(transitionPropInfo, transitionPropData, ArrayLength(transitionPropData), display, parentDisplay, aRuleData, - canStoreInRuleTree); + conditions); display->mTransitions.SetLength(numTransitions); FOR_ALL_TRANSITION_PROPS(p) { const TransitionPropInfo& i = transitionPropInfo[p]; TransitionPropData& d = transitionPropData[p]; display->*(i.sdCount) = d.num; @@ -4898,18 +4914,18 @@ nsRuleNode::ComputeDisplayData(void* aSt if (i >= delay.num) { transition->SetDelay(display->mTransitions[i % delay.num].GetDelay()); } else if (delay.unit == eCSSUnit_Inherit) { // FIXME (Bug 522599) (for all transition properties): write a test that // detects when this was wrong for i >= delay.num if parent had // count for this property not equal to length MOZ_ASSERT(i < parentDisplay->mTransitionDelayCount, "delay.num computed incorrectly"); - MOZ_ASSERT(!canStoreInRuleTree, - "should have made canStoreInRuleTree false above"); + MOZ_ASSERT(!conditions.Cacheable(), + "should have made conditions.Cacheable() false above"); transition->SetDelay(parentDisplay->mTransitions[i].GetDelay()); } else if (delay.unit == eCSSUnit_Initial || delay.unit == eCSSUnit_Unset) { transition->SetDelay(0.0); } else if (delay.list) { switch (delay.list->mValue.GetUnit()) { case eCSSUnit_Seconds: transition->SetDelay(PR_MSEC_PER_SEC * @@ -4924,18 +4940,18 @@ nsRuleNode::ComputeDisplayData(void* aSt } if (i >= duration.num) { transition->SetDuration( display->mTransitions[i % duration.num].GetDuration()); } else if (duration.unit == eCSSUnit_Inherit) { MOZ_ASSERT(i < parentDisplay->mTransitionDurationCount, "duration.num computed incorrectly"); - MOZ_ASSERT(!canStoreInRuleTree, - "should have made canStoreInRuleTree false above"); + MOZ_ASSERT(!conditions.Cacheable(), + "should have made conditions.Cacheable() false above"); transition->SetDuration(parentDisplay->mTransitions[i].GetDuration()); } else if (duration.unit == eCSSUnit_Initial || duration.unit == eCSSUnit_Unset) { transition->SetDuration(0.0); } else if (duration.list) { switch (duration.list->mValue.GetUnit()) { case eCSSUnit_Seconds: transition->SetDuration(PR_MSEC_PER_SEC * @@ -4949,18 +4965,18 @@ nsRuleNode::ComputeDisplayData(void* aSt } } if (i >= property.num) { transition->CopyPropertyFrom(display->mTransitions[i % property.num]); } else if (property.unit == eCSSUnit_Inherit) { MOZ_ASSERT(i < parentDisplay->mTransitionPropertyCount, "property.num computed incorrectly"); - MOZ_ASSERT(!canStoreInRuleTree, - "should have made canStoreInRuleTree false above"); + MOZ_ASSERT(!conditions.Cacheable(), + "should have made conditions.Cacheable() false above"); transition->CopyPropertyFrom(parentDisplay->mTransitions[i]); } else if (property.unit == eCSSUnit_Initial || property.unit == eCSSUnit_Unset) { transition->SetProperty(eCSSPropertyExtra_all_properties); } else if (property.unit == eCSSUnit_None) { transition->SetProperty(eCSSPropertyExtra_no_properties); } else if (property.list) { const nsCSSValue &val = property.list->mValue; @@ -4984,18 +5000,18 @@ nsRuleNode::ComputeDisplayData(void* aSt } if (i >= timingFunction.num) { transition->SetTimingFunction( display->mTransitions[i % timingFunction.num].GetTimingFunction()); } else if (timingFunction.unit == eCSSUnit_Inherit) { MOZ_ASSERT(i < parentDisplay->mTransitionTimingFunctionCount, "timingFunction.num computed incorrectly"); - MOZ_ASSERT(!canStoreInRuleTree, - "should have made canStoreInRuleTree false above"); + MOZ_ASSERT(!conditions.Cacheable(), + "should have made conditions.Cacheable() false above"); transition->SetTimingFunction( parentDisplay->mTransitions[i].GetTimingFunction()); } else if (timingFunction.unit == eCSSUnit_Initial || timingFunction.unit == eCSSUnit_Unset) { transition->SetTimingFunction( nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)); } else if (timingFunction.list) { ComputeTimingFunction(timingFunction.list->mValue, @@ -5031,17 +5047,17 @@ nsRuleNode::ComputeDisplayData(void* aSt for (uint32_t var_ = 0; var_ < 8; ++var_) // CSS Animations. uint32_t numAnimations = CountTransitionProps(animationPropInfo, animationPropData, ArrayLength(animationPropData), display, parentDisplay, aRuleData, - canStoreInRuleTree); + conditions); display->mAnimations.SetLength(numAnimations); FOR_ALL_ANIMATION_PROPS(p) { const TransitionPropInfo& i = animationPropInfo[p]; TransitionPropData& d = animationPropData[p]; display->*(i.sdCount) = d.num; @@ -5054,18 +5070,18 @@ nsRuleNode::ComputeDisplayData(void* aSt if (i >= animDelay.num) { animation->SetDelay(display->mAnimations[i % animDelay.num].GetDelay()); } else if (animDelay.unit == eCSSUnit_Inherit) { // FIXME (Bug 522599) (for all animation properties): write a test that // detects when this was wrong for i >= animDelay.num if parent had // count for this property not equal to length MOZ_ASSERT(i < parentDisplay->mAnimationDelayCount, "animDelay.num computed incorrectly"); - MOZ_ASSERT(!canStoreInRuleTree, - "should have made canStoreInRuleTree false above"); + MOZ_ASSERT(!conditions.Cacheable(), + "should have made conditions.Cacheable() false above"); animation->SetDelay(parentDisplay->mAnimations[i].GetDelay()); } else if (animDelay.unit == eCSSUnit_Initial || animDelay.unit == eCSSUnit_Unset) { animation->SetDelay(0.0); } else if (animDelay.list) { switch (animDelay.list->mValue.GetUnit()) { case eCSSUnit_Seconds: animation->SetDelay(PR_MSEC_PER_SEC * @@ -5080,18 +5096,18 @@ nsRuleNode::ComputeDisplayData(void* aSt } if (i >= animDuration.num) { animation->SetDuration( display->mAnimations[i % animDuration.num].GetDuration()); } else if (animDuration.unit == eCSSUnit_Inherit) { MOZ_ASSERT(i < parentDisplay->mAnimationDurationCount, "animDuration.num computed incorrectly"); - MOZ_ASSERT(!canStoreInRuleTree, - "should have made canStoreInRuleTree false above"); + MOZ_ASSERT(!conditions.Cacheable(), + "should have made conditions.Cacheable() false above"); animation->SetDuration(parentDisplay->mAnimations[i].GetDuration()); } else if (animDuration.unit == eCSSUnit_Initial || animDuration.unit == eCSSUnit_Unset) { animation->SetDuration(0.0); } else if (animDuration.list) { switch (animDuration.list->mValue.GetUnit()) { case eCSSUnit_Seconds: animation->SetDuration(PR_MSEC_PER_SEC * @@ -5105,18 +5121,18 @@ nsRuleNode::ComputeDisplayData(void* aSt } } if (i >= animName.num) { animation->SetName(display->mAnimations[i % animName.num].GetName()); } else if (animName.unit == eCSSUnit_Inherit) { MOZ_ASSERT(i < parentDisplay->mAnimationNameCount, "animName.num computed incorrectly"); - MOZ_ASSERT(!canStoreInRuleTree, - "should have made canStoreInRuleTree false above"); + MOZ_ASSERT(!conditions.Cacheable(), + "should have made conditions.Cacheable() false above"); animation->SetName(parentDisplay->mAnimations[i].GetName()); } else if (animName.unit == eCSSUnit_Initial || animName.unit == eCSSUnit_Unset) { animation->SetName(EmptyString()); } else if (animName.list) { switch (animName.list->mValue.GetUnit()) { case eCSSUnit_Ident: { nsDependentString @@ -5134,90 +5150,90 @@ nsRuleNode::ComputeDisplayData(void* aSt } if (i >= animTimingFunction.num) { animation->SetTimingFunction( display->mAnimations[i % animTimingFunction.num].GetTimingFunction()); } else if (animTimingFunction.unit == eCSSUnit_Inherit) { MOZ_ASSERT(i < parentDisplay->mAnimationTimingFunctionCount, "animTimingFunction.num computed incorrectly"); - MOZ_ASSERT(!canStoreInRuleTree, - "should have made canStoreInRuleTree false above"); + MOZ_ASSERT(!conditions.Cacheable(), + "should have made conditions.Cacheable() false above"); animation->SetTimingFunction( parentDisplay->mAnimations[i].GetTimingFunction()); } else if (animTimingFunction.unit == eCSSUnit_Initial || animTimingFunction.unit == eCSSUnit_Unset) { animation->SetTimingFunction( nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)); } else if (animTimingFunction.list) { ComputeTimingFunction(animTimingFunction.list->mValue, animation->TimingFunctionSlot()); } if (i >= animDirection.num) { animation->SetDirection(display->mAnimations[i % animDirection.num].GetDirection()); } else if (animDirection.unit == eCSSUnit_Inherit) { MOZ_ASSERT(i < parentDisplay->mAnimationDirectionCount, "animDirection.num computed incorrectly"); - MOZ_ASSERT(!canStoreInRuleTree, - "should have made canStoreInRuleTree false above"); + MOZ_ASSERT(!conditions.Cacheable(), + "should have made conditions.Cac