From 4fcb9e782d755f03860b10cdb99fa37e2e966024 Mon Sep 17 00:00:00 2001 From: Simon Montagu Date: Sun, 30 Sep 2012 07:17:42 -0700 Subject: [PATCH 01/64] Change :dir selectors to :-moz-dir in css files. Bug 562169, r=dbaron --- browser/base/content/abouthome/aboutHome.css | 10 +++++----- browser/devtools/layoutview/view.css | 4 ++-- browser/themes/gnomestripe/aboutCertError.css | 6 +++--- browser/themes/gnomestripe/aboutPrivateBrowsing.css | 2 +- browser/themes/pinstripe/aboutCertError.css | 6 +++--- browser/themes/pinstripe/aboutPrivateBrowsing.css | 2 +- browser/themes/winstripe/aboutCertError.css | 6 +++--- browser/themes/winstripe/aboutPrivateBrowsing.css | 2 +- toolkit/themes/gnomestripe/global/netError.css | 4 ++-- .../themes/pinstripe/global/dirListing/dirListing.css | 4 ++-- toolkit/themes/pinstripe/global/netError.css | 4 ++-- toolkit/themes/winstripe/global/aboutSupport.css | 2 +- .../themes/winstripe/global/dirListing/dirListing.css | 4 ++-- toolkit/themes/winstripe/global/netError.css | 4 ++-- 14 files changed, 30 insertions(+), 30 deletions(-) diff --git a/browser/base/content/abouthome/aboutHome.css b/browser/base/content/abouthome/aboutHome.css index f877352896f1..c773738efa67 100644 --- a/browser/base/content/abouthome/aboutHome.css +++ b/browser/base/content/abouthome/aboutHome.css @@ -81,7 +81,7 @@ a { border-radius: 2.5px 0 0 2.5px; } -#searchText:dir(rtl) { +#searchText:-moz-dir(rtl) { border-radius: 0 2.5px 2.5px 0; } @@ -105,7 +105,7 @@ a { transition-duration: 150ms; } -#searchSubmit:dir(rtl) { +#searchSubmit:-moz-dir(rtl) { border-radius: 2.5px 0 0 2.5px; } @@ -147,8 +147,8 @@ a { -moz-padding-start: 79px; } -#defaultSnippet1:dir(rtl), -#defaultSnippet2:dir(rtl) { +#defaultSnippet1:-moz-dir(rtl), +#defaultSnippet2:-moz-dir(rtl) { background-position: right 30px center; } @@ -312,7 +312,7 @@ body[narrow] #restorePreviousSession { -moz-margin-end: 8px; } -#restorePreviousSession:dir(rtl)::before { +#restorePreviousSession:-moz-dir(rtl)::before { transform: scaleX(-1); } diff --git a/browser/devtools/layoutview/view.css b/browser/devtools/layoutview/view.css index fca0c0804e22..a8e9d2861b0f 100644 --- a/browser/devtools/layoutview/view.css +++ b/browser/devtools/layoutview/view.css @@ -22,7 +22,7 @@ body { vertical-align: top; } -#header:dir(rtl) { +#header:-moz-dir(rtl) { -moz-box-direction: reverse; } @@ -34,7 +34,7 @@ body { -moz-box-flex: 1; } -#element-size:dir(rtl) { +#element-size:-moz-dir(rtl) { -moz-box-pack: end; } diff --git a/browser/themes/gnomestripe/aboutCertError.css b/browser/themes/gnomestripe/aboutCertError.css index 9b4612916e1a..c7caf531e875 100644 --- a/browser/themes/gnomestripe/aboutCertError.css +++ b/browser/themes/gnomestripe/aboutCertError.css @@ -37,7 +37,7 @@ h2 { background-origin: content-box; } -#errorPageContainer:dir(rtl) { +#errorPageContainer:-moz-dir(rtl) { background-position: right 0; } @@ -59,7 +59,7 @@ h2 { cursor: pointer; } -.expander > button:dir(rtl) { +.expander > button:-moz-dir(rtl) { background-position: right center; } @@ -67,6 +67,6 @@ h2 { background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed.png"); } -.expander[collapsed] > button:dir(rtl) { +.expander[collapsed] > button:-moz-dir(rtl) { background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed-rtl.png"); } diff --git a/browser/themes/gnomestripe/aboutPrivateBrowsing.css b/browser/themes/gnomestripe/aboutPrivateBrowsing.css index fde7496a7b93..2bb39d295073 100644 --- a/browser/themes/gnomestripe/aboutPrivateBrowsing.css +++ b/browser/themes/gnomestripe/aboutPrivateBrowsing.css @@ -34,7 +34,7 @@ body.normal > #errorPageContainer { background: url("moz-icon://stock/gtk-dialog-info?size=menu") no-repeat top left; } -#moreInfo:dir(rtl) { +#moreInfo:-moz-dir(rtl) { background-position: top right; } diff --git a/browser/themes/pinstripe/aboutCertError.css b/browser/themes/pinstripe/aboutCertError.css index 9b4612916e1a..c7caf531e875 100644 --- a/browser/themes/pinstripe/aboutCertError.css +++ b/browser/themes/pinstripe/aboutCertError.css @@ -37,7 +37,7 @@ h2 { background-origin: content-box; } -#errorPageContainer:dir(rtl) { +#errorPageContainer:-moz-dir(rtl) { background-position: right 0; } @@ -59,7 +59,7 @@ h2 { cursor: pointer; } -.expander > button:dir(rtl) { +.expander > button:-moz-dir(rtl) { background-position: right center; } @@ -67,6 +67,6 @@ h2 { background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed.png"); } -.expander[collapsed] > button:dir(rtl) { +.expander[collapsed] > button:-moz-dir(rtl) { background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed-rtl.png"); } diff --git a/browser/themes/pinstripe/aboutPrivateBrowsing.css b/browser/themes/pinstripe/aboutPrivateBrowsing.css index 7dc446a8b0c1..b97093f4458b 100644 --- a/browser/themes/pinstripe/aboutPrivateBrowsing.css +++ b/browser/themes/pinstripe/aboutPrivateBrowsing.css @@ -34,7 +34,7 @@ body.normal > #errorPageContainer { background: url("chrome://global/skin/icons/information-16.png") no-repeat top left; } -#moreInfo:dir(rtl) { +#moreInfo:-moz-dir(rtl) { background-position: top right; } diff --git a/browser/themes/winstripe/aboutCertError.css b/browser/themes/winstripe/aboutCertError.css index 9b4612916e1a..c7caf531e875 100644 --- a/browser/themes/winstripe/aboutCertError.css +++ b/browser/themes/winstripe/aboutCertError.css @@ -37,7 +37,7 @@ h2 { background-origin: content-box; } -#errorPageContainer:dir(rtl) { +#errorPageContainer:-moz-dir(rtl) { background-position: right 0; } @@ -59,7 +59,7 @@ h2 { cursor: pointer; } -.expander > button:dir(rtl) { +.expander > button:-moz-dir(rtl) { background-position: right center; } @@ -67,6 +67,6 @@ h2 { background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed.png"); } -.expander[collapsed] > button:dir(rtl) { +.expander[collapsed] > button:-moz-dir(rtl) { background-image: url("chrome://browser/skin/aboutCertError_sectionCollapsed-rtl.png"); } diff --git a/browser/themes/winstripe/aboutPrivateBrowsing.css b/browser/themes/winstripe/aboutPrivateBrowsing.css index 77228d1c89cf..cd6026b8eab8 100644 --- a/browser/themes/winstripe/aboutPrivateBrowsing.css +++ b/browser/themes/winstripe/aboutPrivateBrowsing.css @@ -34,7 +34,7 @@ body.normal > #errorPageContainer { background: url("chrome://global/skin/icons/information-16.png") no-repeat top left; } -#moreInfo:dir(rtl) { +#moreInfo:-moz-dir(rtl) { background-position: top right; } diff --git a/toolkit/themes/gnomestripe/global/netError.css b/toolkit/themes/gnomestripe/global/netError.css index fac4138a20d1..77e3cea88381 100644 --- a/toolkit/themes/gnomestripe/global/netError.css +++ b/toolkit/themes/gnomestripe/global/netError.css @@ -58,7 +58,7 @@ ul { background-image: url("chrome://global/skin/icons/sslWarning.png"); } -#errorPageContainer:dir(rtl) { +#errorPageContainer:-moz-dir(rtl) { background-position: right 0; } @@ -99,7 +99,7 @@ ul { opacity: .4; } -#brand:dir(rtl) { +#brand:-moz-dir(rtl) { right: auto; left: 0; } diff --git a/toolkit/themes/pinstripe/global/dirListing/dirListing.css b/toolkit/themes/pinstripe/global/dirListing/dirListing.css index db2d49ccd7f0..d89752db13c4 100644 --- a/toolkit/themes/pinstripe/global/dirListing/dirListing.css +++ b/toolkit/themes/pinstripe/global/dirListing/dirListing.css @@ -45,7 +45,7 @@ p { float: left; } -#UI_goUp:dir(rtl) { +#UI_goUp:-moz-dir(rtl) { float: right; } @@ -54,7 +54,7 @@ p { float: right; } -#UI_showHidden:dir(rtl) { +#UI_showHidden:-moz-dir(rtl) { float: left; } diff --git a/toolkit/themes/pinstripe/global/netError.css b/toolkit/themes/pinstripe/global/netError.css index 9f37a3df8fa9..206f522116b4 100644 --- a/toolkit/themes/pinstripe/global/netError.css +++ b/toolkit/themes/pinstripe/global/netError.css @@ -59,7 +59,7 @@ ul { background-image: url("chrome://global/skin/icons/sslWarning.png"); } -#errorPageContainer:dir(rtl) { +#errorPageContainer:-moz-dir(rtl) { background-position: right 0; } @@ -100,7 +100,7 @@ ul { opacity: .4; } -#brand:dir(rtl) { +#brand:-moz-dir(rtl) { right: auto; left: 0; } diff --git a/toolkit/themes/winstripe/global/aboutSupport.css b/toolkit/themes/winstripe/global/aboutSupport.css index b9da92587cbe..38c9b82f9d3a 100644 --- a/toolkit/themes/winstripe/global/aboutSupport.css +++ b/toolkit/themes/winstripe/global/aboutSupport.css @@ -91,7 +91,7 @@ td { width: 30%; } -#reset-box:dir(rtl) { +#reset-box:-moz-dir(rtl) { float: left; } diff --git a/toolkit/themes/winstripe/global/dirListing/dirListing.css b/toolkit/themes/winstripe/global/dirListing/dirListing.css index 2052b67342ae..35dab890a87a 100644 --- a/toolkit/themes/winstripe/global/dirListing/dirListing.css +++ b/toolkit/themes/winstripe/global/dirListing/dirListing.css @@ -45,7 +45,7 @@ p { float: left; } -#UI_goUp:dir(rtl) { +#UI_goUp:-moz-dir(rtl) { float: right; } @@ -54,7 +54,7 @@ p { float: right; } -#UI_showHidden:dir(rtl) { +#UI_showHidden:-moz-dir(rtl) { float: left; } diff --git a/toolkit/themes/winstripe/global/netError.css b/toolkit/themes/winstripe/global/netError.css index b88aa68a2b28..5504a0e02e25 100644 --- a/toolkit/themes/winstripe/global/netError.css +++ b/toolkit/themes/winstripe/global/netError.css @@ -59,7 +59,7 @@ ul { background-image: url("chrome://global/skin/icons/sslWarning.png"); } -#errorPageContainer:dir(rtl) { +#errorPageContainer:-moz-dir(rtl) { background-position: right 0; } @@ -100,7 +100,7 @@ ul { opacity: .4; } -#brand:dir(rtl) { +#brand:-moz-dir(rtl) { right: auto; left: 0; } From 8b69632999d4614349a93b0e32a9260dcca8b6d4 Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Sun, 30 Sep 2012 14:47:48 +0100 Subject: [PATCH 02/64] Bug 795136 - 1/2 - Add events notifying the window if upload/download happen on the system. r=smaug sr=sicking --- content/base/src/nsGkAtomList.h | 2 + content/events/public/nsEventNameList.h | 8 ++ content/events/src/nsEventListenerManager.cpp | 31 ++++++- content/events/src/nsEventListenerManager.h | 1 + dom/base/nsGlobalWindow.cpp | 80 ++++++++++++++++++- dom/base/nsGlobalWindow.h | 8 ++ dom/base/nsPIDOMWindow.h | 16 +++- dom/interfaces/base/nsIDOMWindow.idl | 5 +- dom/tests/mochitest/general/Makefile.in | 1 + .../general/test_network_events.html | 68 ++++++++++++++++ widget/nsGUIEvent.h | 5 ++ 11 files changed, 220 insertions(+), 5 deletions(-) create mode 100644 dom/tests/mochitest/general/test_network_events.html diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index 10bf12943d7c..d1c2afa9e328 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -727,6 +727,8 @@ GK_ATOM(onmozpointerlockerror, "onmozpointerlockerror") GK_ATOM(onmoztimechange, "onmoztimechange") GK_ATOM(onMozMousePixelScroll, "onMozMousePixelScroll") GK_ATOM(onMozScrolledAreaChanged, "onMozScrolledAreaChanged") +GK_ATOM(onmoznetworkupload, "onmoznetworkupload") +GK_ATOM(onmoznetworkdownload, "onmoznetworkdownload") GK_ATOM(onnoupdate, "onnoupdate") GK_ATOM(onobsolete, "onobsolete") GK_ATOM(ononline, "ononline") diff --git a/content/events/public/nsEventNameList.h b/content/events/public/nsEventNameList.h index 88df83caf5ab..51487e098ef5 100644 --- a/content/events/public/nsEventNameList.h +++ b/content/events/public/nsEventNameList.h @@ -467,6 +467,14 @@ WINDOW_ONLY_EVENT(moztimechange, NS_MOZ_TIME_CHANGE_EVENT, EventNameType_None, NS_EVENT) +WINDOW_ONLY_EVENT(moznetworkupload, + NS_NETWORK_UPLOAD_EVENT, + EventNameType_None, + NS_EVENT) +WINDOW_ONLY_EVENT(moznetworkdownload, + NS_NETWORK_DOWNLOAD_EVENT, + EventNameType_None, + NS_EVENT) TOUCH_EVENT(touchstart, NS_TOUCH_START, diff --git a/content/events/src/nsEventListenerManager.cpp b/content/events/src/nsEventListenerManager.cpp index 110fb490c013..bab91e8d1baa 100644 --- a/content/events/src/nsEventListenerManager.cpp +++ b/content/events/src/nsEventListenerManager.cpp @@ -182,6 +182,18 @@ nsEventListenerManager::GetInnerWindowForTarget() return nullptr; } +already_AddRefed +nsEventListenerManager::GetTargetAsInnerWindow() const +{ + nsCOMPtr window = do_QueryInterface(mTarget); + if (!window) { + return nullptr; + } + + NS_ASSERTION(window->IsInnerWindow(), "Target should not be an outer window"); + return window.forget(); +} + void nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener, uint32_t aType, @@ -279,6 +291,16 @@ nsEventListenerManager::AddEventListener(nsIDOMEventListener *aListener, EnableDevice(NS_DEVICE_MOTION); } else if (aTypeAtom == nsGkAtoms::onmoztimechange) { EnableTimeChangeNotifications(); + } else if (aTypeAtom == nsGkAtoms::onmoznetworkupload) { + nsCOMPtr window = GetTargetAsInnerWindow(); + if (window) { + window->EnableNetworkEvent(NS_NETWORK_UPLOAD_EVENT); + } + } else if (aTypeAtom == nsGkAtoms::onmoznetworkdownload) { + nsCOMPtr window = GetTargetAsInnerWindow(); + if (window) { + window->EnableNetworkEvent(NS_NETWORK_DOWNLOAD_EVENT); + } } else if (aTypeAtom == nsGkAtoms::ontouchstart || aTypeAtom == nsGkAtoms::ontouchend || aTypeAtom == nsGkAtoms::ontouchmove || @@ -404,6 +426,8 @@ nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, uint32_t typeCount = 0; bool deviceType = IsDeviceType(aType); bool timeChangeEvent = (aType == NS_MOZ_TIME_CHANGE_EVENT); + bool networkEvent = (aType == NS_NETWORK_UPLOAD_EVENT || + aType == NS_NETWORK_DOWNLOAD_EVENT); for (uint32_t i = 0; i < count; ++i) { ls = &mListeners.ElementAt(i); @@ -417,7 +441,7 @@ nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, mNoListenerForEvent = NS_EVENT_TYPE_NULL; mNoListenerForEventAtom = nullptr; - if (!deviceType && !timeChangeEvent) { + if (!deviceType && !timeChangeEvent && !networkEvent) { return; } --typeCount; @@ -429,6 +453,11 @@ nsEventListenerManager::RemoveEventListener(nsIDOMEventListener *aListener, DisableDevice(aType); } else if (timeChangeEvent && typeCount == 0) { DisableTimeChangeNotifications(); + } else if (networkEvent && typeCount == 0) { + nsCOMPtr window = GetTargetAsInnerWindow(); + if (window) { + window->DisableNetworkEvent(aType); + } } } diff --git a/content/events/src/nsEventListenerManager.h b/content/events/src/nsEventListenerManager.h index 15c7a63dcb62..e6409a636e21 100644 --- a/content/events/src/nsEventListenerManager.h +++ b/content/events/src/nsEventListenerManager.h @@ -304,6 +304,7 @@ protected: const EventTypeData* GetTypeDataForIID(const nsIID& aIID); const EventTypeData* GetTypeDataForEventName(nsIAtom* aName); nsPIDOMWindow* GetInnerWindowForTarget(); + already_AddRefed GetTargetAsInnerWindow() const; uint32_t mMayHavePaintEventListener : 1; uint32_t mMayHaveMutationListeners : 1; diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 811a556df6d3..f14ff2b36681 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -222,6 +222,7 @@ #include "prrng.h" #include "nsSandboxFlags.h" #include "TimeChangeObserver.h" +#include "nsPISocketTransportService.h" #ifdef ANDROID #include @@ -416,6 +417,9 @@ static const char kPkcs11ContractID[] = NS_PKCS11_CONTRACTID; #endif static const char sPopStatePrefStr[] = "browser.history.allowPopState"; +#define NETWORK_UPLOAD_EVENT_NAME NS_LITERAL_STRING("moznetworkupload") +#define NETWORK_DOWNLOAD_EVENT_NAME NS_LITERAL_STRING("moznetworkdownload") + /** * An object implementing the window.URL property. */ @@ -686,7 +690,9 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow) mCallCleanUpAfterModalDialogCloses(false), mDialogAbuseCount(0), mStopAbuseDialogs(false), - mDialogsPermanentlyDisabled(false) + mDialogsPermanentlyDisabled(false), + mObservingNetworkUpload(false), + mObservingNetworkDownload(false) { nsLayoutStatics::AddRef(); @@ -990,6 +996,9 @@ nsGlobalWindow::CleanUp(bool aIgnoreModalDialog) os->RemoveObserver(mObserver, "dom-storage2-changed"); } + DisableNetworkEvent(NS_NETWORK_UPLOAD_EVENT); + DisableNetworkEvent(NS_NETWORK_DOWNLOAD_EVENT); + if (mIdleService) { mIdleService->RemoveIdleObserver(mObserver, MIN_IDLE_NOTIFICATION_TIME_S); } @@ -9050,6 +9059,23 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic, return NS_OK; } + if (!nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC) || + !nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC)) { + nsRefPtr event = new nsDOMEvent(nullptr, nullptr); + nsresult rv = event->InitEvent( + !nsCRT::strcmp(aTopic, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC) + ? NETWORK_UPLOAD_EVENT_NAME + : NETWORK_DOWNLOAD_EVENT_NAME, + false, false); + NS_ENSURE_SUCCESS(rv, rv); + + rv = event->SetTrusted(true); + NS_ENSURE_SUCCESS(rv, rv); + + bool dummy; + return DispatchEvent(event, &dummy); + } + NS_WARNING("unrecognized topic in nsGlobalWindow::Observe"); return NS_ERROR_FAILURE; } @@ -11102,6 +11128,58 @@ nsGlobalWindow::SetHasAudioAvailableEventListeners() } } +void +nsGlobalWindow::EnableNetworkEvent(uint32_t aType) +{ + if ((mObservingNetworkUpload && aType == NS_NETWORK_UPLOAD_EVENT) || + (mObservingNetworkDownload && aType == NS_NETWORK_DOWNLOAD_EVENT)) { + return; + } + + nsCOMPtr os = mozilla::services::GetObserverService(); + if (!os) { + NS_ERROR("ObserverService should be available!"); + return; + } + + switch (aType) { + case NS_NETWORK_UPLOAD_EVENT: + os->AddObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC, false); + mObservingNetworkUpload = true; + break; + case NS_NETWORK_DOWNLOAD_EVENT: + os->AddObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC, false); + mObservingNetworkDownload = true; + break; + } +} + +void +nsGlobalWindow::DisableNetworkEvent(uint32_t aType) +{ + if ((!mObservingNetworkUpload && aType == NS_NETWORK_UPLOAD_EVENT) || + (!mObservingNetworkDownload && aType == NS_NETWORK_DOWNLOAD_EVENT)) { + return; + } + + nsCOMPtr os = mozilla::services::GetObserverService(); + if (!os) { + NS_ERROR("ObserverService should be available!"); + return; + } + + switch (aType) { + case NS_NETWORK_UPLOAD_EVENT: + os->RemoveObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_UPLOAD_TOPIC); + mObservingNetworkUpload = false; + break; + case NS_NETWORK_DOWNLOAD_EVENT: + os->RemoveObserver(mObserver, NS_NETWORK_ACTIVITY_BLIP_DOWNLOAD_TOPIC); + mObservingNetworkDownload = false; + break; + } +} + #define EVENT(name_, id_, type_, struct_) \ NS_IMETHODIMP nsGlobalWindow::GetOn##name_(JSContext *cx, \ jsval *vp) { \ diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 1a7db4718125..811db13d7425 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -537,6 +537,9 @@ public: virtual void EnableTimeChangeNotifications(); virtual void DisableTimeChangeNotifications(); + virtual void EnableNetworkEvent(uint32_t aType); + virtual void DisableNetworkEvent(uint32_t aType); + virtual nsresult SetArguments(nsIArray *aArguments, nsIPrincipal *aOrigin); static bool DOMWindowDumpEnabled(); @@ -1084,6 +1087,11 @@ protected: // destroying this window). bool mDialogsPermanentlyDisabled; + // Temporary booleans to know if we are currently observing network blips. + // Will be hopefully removed after bug 795703. + bool mObservingNetworkUpload; + bool mObservingNetworkDownload; + nsRefPtr mURLProperty; nsTHashtable > mEventTargetObjects; diff --git a/dom/base/nsPIDOMWindow.h b/dom/base/nsPIDOMWindow.h index 96ae462f2bc5..ceeca57c45e8 100644 --- a/dom/base/nsPIDOMWindow.h +++ b/dom/base/nsPIDOMWindow.h @@ -48,8 +48,8 @@ class nsIArray; class nsPIWindowRoot; #define NS_PIDOMWINDOW_IID \ -{ 0x0c5763c6, 0x5e87, 0x4f6f, \ - { 0xa2, 0xef, 0xcf, 0x4d, 0xeb, 0xd1, 0xbc, 0xc3 } } +{ 0x54fd92bd, 0xda33, 0x4451, \ + { 0x8f, 0xb5, 0x11, 0x20, 0x5c, 0x03, 0xce, 0xaa } } class nsPIDOMWindow : public nsIDOMWindowInternal { @@ -574,6 +574,18 @@ public: virtual void EnableTimeChangeNotifications() = 0; virtual void DisableTimeChangeNotifications() = 0; + /** + * Tell the window that it should start to listen to the network event of the + * given aType. + */ + virtual void EnableNetworkEvent(uint32_t aType) = 0; + + /** + * Tell the window that it should stop to listen to the network event of the + * given aType. + */ + virtual void DisableNetworkEvent(uint32_t aType) = 0; + /** * Set a arguments for this window. This will be set on the window * right away (if there's an existing document) and it will also be diff --git a/dom/interfaces/base/nsIDOMWindow.idl b/dom/interfaces/base/nsIDOMWindow.idl index 3620cafecd80..5799a0490b4e 100644 --- a/dom/interfaces/base/nsIDOMWindow.idl +++ b/dom/interfaces/base/nsIDOMWindow.idl @@ -32,7 +32,7 @@ interface nsIDOMMozURLProperty : nsISupports * @see */ -[scriptable, uuid(AB4ED3B8-84F8-4585-B413-0996A7F96D20)] +[scriptable, uuid(25404a1b-6c73-4850-af95-69aa095c8ad0)] interface nsIDOMWindow : nsISupports { // the current browsing context @@ -501,6 +501,9 @@ interface nsIDOMWindow : nsISupports [implicit_jscontext] attribute jsval onmouseenter; [implicit_jscontext] attribute jsval onmouseleave; + + [implicit_jscontext] attribute jsval onmoznetworkupload; + [implicit_jscontext] attribute jsval onmoznetworkdownload; }; [scriptable, uuid(2146c906-57f7-486c-a1b4-8cdb57ef577f)] diff --git a/dom/tests/mochitest/general/Makefile.in b/dom/tests/mochitest/general/Makefile.in index e0cf3f2e23bd..ca851e2ee81d 100644 --- a/dom/tests/mochitest/general/Makefile.in +++ b/dom/tests/mochitest/general/Makefile.in @@ -46,6 +46,7 @@ MOCHITEST_FILES = \ file_moving_nodeList.html \ test_performance_now.html \ test_interfaces.html \ + test_network_events.html \ $(NULL) MOCHITEST_CHROME_FILES = \ diff --git a/dom/tests/mochitest/general/test_network_events.html b/dom/tests/mochitest/general/test_network_events.html new file mode 100644 index 000000000000..eefbb06d9586 --- /dev/null +++ b/dom/tests/mochitest/general/test_network_events.html @@ -0,0 +1,68 @@ + + + + + + Test for moznetworkupload and moznetworkdownload + + + + +Mozilla Bug 795136 +

+
+ +
+
+
+
+ + diff --git a/widget/nsGUIEvent.h b/widget/nsGUIEvent.h index 0c4e39275e62..ad09db94ffaf 100644 --- a/widget/nsGUIEvent.h +++ b/widget/nsGUIEvent.h @@ -469,6 +469,11 @@ class nsHashKey; //System time is changed #define NS_MOZ_TIME_CHANGE_EVENT 5500 +// Network packet events. +#define NS_NETWORK_EVENT_START 5600 +#define NS_NETWORK_UPLOAD_EVENT (NS_NETWORK_EVENT_START + 1) +#define NS_NETWORK_DOWNLOAD_EVENT (NS_NETWORK_EVENT_START + 2) + /** * Return status for event processors, nsEventStatus, is defined in * nsEvent.h. From 701371086e0e8cc450b27898de68ec10fb62358a Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Sun, 30 Sep 2012 14:48:40 +0100 Subject: [PATCH 03/64] Bug 795136 - 2/2 - Add 'network-events' permission to access network-{upload,download} events. r=sicking --- dom/apps/src/PermissionsTable.jsm | 5 +++++ dom/base/nsGlobalWindow.cpp | 15 +++++++++++++++ .../mochitest/general/test_network_events.html | 4 ++++ extensions/cookie/Permission.txt | 5 +++++ 4 files changed, 29 insertions(+) diff --git a/dom/apps/src/PermissionsTable.jsm b/dom/apps/src/PermissionsTable.jsm index 9dac9257c585..8b47cd509709 100644 --- a/dom/apps/src/PermissionsTable.jsm +++ b/dom/apps/src/PermissionsTable.jsm @@ -62,6 +62,11 @@ const PermissionsTable = { "resource-lock": { privileged: ALLOW_ACTION, certified: ALLOW_ACTION }, + "network-events": { + app: DENY_ACTION, + privileged: DENY_ACTION, + certified: ALLOW_ACTION + }, contacts: { app: DENY_ACTION, privileged: PROMPT_ACTION, diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index f14ff2b36681..2bbb755cea76 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -11136,6 +11136,21 @@ nsGlobalWindow::EnableNetworkEvent(uint32_t aType) return; } + nsCOMPtr permMgr = + do_GetService(NS_PERMISSIONMANAGER_CONTRACTID); + if (!permMgr) { + NS_ERROR("No PermissionManager available!"); + return; + } + + uint32_t permission = nsIPermissionManager::DENY_ACTION; + permMgr->TestExactPermissionFromPrincipal(GetPrincipal(), "network-events", + &permission); + + if (permission != nsIPermissionManager::ALLOW_ACTION) { + return; + } + nsCOMPtr os = mozilla::services::GetObserverService(); if (!os) { NS_ERROR("ObserverService should be available!"); diff --git a/dom/tests/mochitest/general/test_network_events.html b/dom/tests/mochitest/general/test_network_events.html index eefbb06d9586..ef8853f64d44 100644 --- a/dom/tests/mochitest/general/test_network_events.html +++ b/dom/tests/mochitest/general/test_network_events.html @@ -22,6 +22,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=795136 SimpleTest.waitForExplicitFinish(); +SpecialPowers.addPermission("network-events", true, document); + var gNetworkUpload = false; var gNetworkDownload = false; @@ -33,6 +35,8 @@ function finish() { removeEventListener('moznetworkupload', uploadHandler); removeEventListener('moznetworkdownload', downloadHandler); + SpecialPowers.removePermission("network-events", document); + SimpleTest.finish(); } diff --git a/extensions/cookie/Permission.txt b/extensions/cookie/Permission.txt index 341dec0d8a31..adc878ea79ec 100644 --- a/extensions/cookie/Permission.txt +++ b/extensions/cookie/Permission.txt @@ -90,6 +90,11 @@ systemclock Time/Clock API, 714358 Set current time. Timezone will go in the Settings API. +network-events +{} +Network Events, 795136 +Receive events when a packet is downloaded or uploaded from the device. + network-http {} old name: systemXHR From 4d37eb758f8a57b2c33c947c3285c10b20ac202c Mon Sep 17 00:00:00 2001 From: Mounir Lamouri Date: Sun, 30 Sep 2012 16:07:51 +0100 Subject: [PATCH 04/64] Bug 795136 - 3/2 - Disabling tests until bug 795711 is fixed. r=me --- build/automation.py.in | 3 +++ dom/tests/mochitest/general/Makefile.in | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/build/automation.py.in b/build/automation.py.in index 569ddc67c81e..2b8a05ded742 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -449,6 +449,9 @@ user_pref("extensions.getAddons.search.url", "http://%(server)s/extensions-dummy // Make enablePrivilege continue to work for test code. :-( user_pref("security.enablePrivilege.enable_for_tests", true); + +// Get network events. +user_pref("network.activity.blipIntervalMilliseconds", 250); """ % { "server" : self.webServer + ":" + str(self.httpPort) } prefs.append(part) diff --git a/dom/tests/mochitest/general/Makefile.in b/dom/tests/mochitest/general/Makefile.in index ca851e2ee81d..00fefa807745 100644 --- a/dom/tests/mochitest/general/Makefile.in +++ b/dom/tests/mochitest/general/Makefile.in @@ -46,9 +46,11 @@ MOCHITEST_FILES = \ file_moving_nodeList.html \ test_performance_now.html \ test_interfaces.html \ - test_network_events.html \ $(NULL) +# Disable this test until bug 795711 is fixed. +# test_network_events.html \ + MOCHITEST_CHROME_FILES = \ test_innerScreen.xul \ test_offsets.xul \ From ef2beecd2b0538fdf4d98c922e25b3e2620d4db8 Mon Sep 17 00:00:00 2001 From: Brad Lassey Date: Sat, 29 Sep 2012 08:03:54 -0400 Subject: [PATCH 05/64] bug 792825 - Crash in js::gc::MarkObjectRange on CyanogenMod 10, back out changeset 9a02263d7206 r=mossop --- toolkit/mozapps/extensions/AddonManager.jsm | 56 ----------- .../extensions/test/xpcshell/test_shutdown.js | 98 ++++++++----------- .../test/xpcshell/test_updatecheck.js | 1 - 3 files changed, 40 insertions(+), 115 deletions(-) diff --git a/toolkit/mozapps/extensions/AddonManager.jsm b/toolkit/mozapps/extensions/AddonManager.jsm index 2dceb4b85215..ceda1d4b50dc 100644 --- a/toolkit/mozapps/extensions/AddonManager.jsm +++ b/toolkit/mozapps/extensions/AddonManager.jsm @@ -1932,26 +1932,14 @@ var AddonManagerInternal = { }, get addonTypes() { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - return this.typesProxy; }, get autoUpdateDefault() { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - return gAutoUpdateDefault; }, set autoUpdateDefault(aValue) { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - aValue = !!aValue; if (aValue != gAutoUpdateDefault) Services.prefs.setBoolPref(PREF_EM_AUTOUPDATE_DEFAULT, aValue); @@ -1959,18 +1947,10 @@ var AddonManagerInternal = { }, get checkCompatibility() { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - return gCheckCompatibility; }, set checkCompatibility(aValue) { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - aValue = !!aValue; if (aValue != gCheckCompatibility) { if (!aValue) @@ -1982,18 +1962,10 @@ var AddonManagerInternal = { }, get strictCompatibility() { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - return gStrictCompatibility; }, set strictCompatibility(aValue) { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - aValue = !!aValue; if (aValue != gStrictCompatibility) Services.prefs.setBoolPref(PREF_EM_STRICT_COMPATIBILITY, aValue); @@ -2001,26 +1973,14 @@ var AddonManagerInternal = { }, get checkUpdateSecurityDefault() { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - return gCheckUpdateSecurityDefault; }, get checkUpdateSecurity() { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - return gCheckUpdateSecurity; }, set checkUpdateSecurity(aValue) { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - aValue = !!aValue; if (aValue != gCheckUpdateSecurity) { if (aValue != gCheckUpdateSecurityDefault) @@ -2032,18 +1992,10 @@ var AddonManagerInternal = { }, get updateEnabled() { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - return gUpdateEnabled; }, set updateEnabled(aValue) { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - aValue = !!aValue; if (aValue != gUpdateEnabled) Services.prefs.setBoolPref(PREF_EM_UPDATE_ENABLED, aValue); @@ -2051,10 +2003,6 @@ var AddonManagerInternal = { }, get hotfixID() { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - return gHotfixID; }, }; @@ -2392,10 +2340,6 @@ var AddonManager = { * @return true if the addon should auto-update, false otherwise. */ shouldAutoUpdate: function AM_shouldAutoUpdate(aAddon) { - if (!gStarted) - throw Components.Exception("AddonManager is not initialized", - Cr.NS_ERROR_NOT_INITIALIZED); - if (!aAddon || typeof aAddon != "object") throw Components.Exception("aAddon must be specified", Cr.NS_ERROR_INVALID_ARG); diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js b/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js index 5859b9d648ac..60d74b4d8831 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_shutdown.js @@ -4,75 +4,57 @@ // Verify that API functions fail if the Add-ons Manager isn't initialised. -const IGNORE = { - funcs: ["escapeAddonURI", "getStartupChanges", "addTypeListener", - "removeTypeListener", "addAddonListener", "removeAddonListener", - "addInstallListener", "removeInstallListener", "addManagerListener", - "removeManagerListener"], - getters: ["__AddonManagerInternal__"], - setters: [] -}; +const IGNORE = ["escapeAddonURI", "shouldAutoUpdate", "getStartupChanges", + "addTypeListener", "removeTypeListener", + "addAddonListener", "removeAddonListener", + "addInstallListener", "removeInstallListener", + "addManagerListener", "removeManagerListener"]; -const IGNORE_PRIVATE = { - funcs: ["AddonAuthor", "AddonCompatibilityOverride", "AddonScreenshot", - "AddonType", "startup", "shutdown", "registerProvider", - "unregisterProvider", "addStartupChange", "removeStartupChange"], - getters: [], - setters: [] -}; +const IGNORE_PRIVATE = ["AddonAuthor", "AddonCompatibilityOverride", + "AddonScreenshot", "AddonType", "startup", "shutdown", + "registerProvider", "unregisterProvider", + "addStartupChange", "removeStartupChange"]; +function test_functions() { + for (let prop in AddonManager) { + if (typeof AddonManager[prop] != "function") + continue; + if (IGNORE.indexOf(prop) != -1) + continue; -function test_functions(aObjName, aIgnore) { - let obj = this[aObjName]; - for (let prop in obj) { - let desc = Object.getOwnPropertyDescriptor(obj, prop); + try { + do_print("AddonManager." + prop); + AddonManager[prop](); + do_throw(prop + " did not throw an exception"); + } + catch (e) { + if (e.result != Components.results.NS_ERROR_NOT_INITIALIZED) + do_throw(prop + " threw an unexpected exception: " + e); + } + } - if (typeof desc.value == "function") { - if (aIgnore.funcs.indexOf(prop) != -1) - continue; + for (let prop in AddonManagerPrivate) { + if (typeof AddonManagerPrivate[prop] != "function") + continue; + if (IGNORE_PRIVATE.indexOf(prop) != -1) + continue; - try { - do_print(aObjName + "." + prop + "()"); - obj[prop](); - do_throw(prop + " did not throw an exception"); - } - catch (e) { - if (e.result != Components.results.NS_ERROR_NOT_INITIALIZED) - do_throw(prop + " threw an unexpected exception: " + e); - } - } else { - if (typeof desc.get == "function" && aIgnore.getters.indexOf(prop) == -1) { - do_print(aObjName + "." + prop + " getter"); - try { - let temp = obj[prop]; - do_throw(prop + " did not throw an exception"); - } - catch (e) { - if (e.result != Components.results.NS_ERROR_NOT_INITIALIZED) - do_throw(prop + " threw an unexpected exception: " + e); - } - } - if (typeof desc.set == "function" && aIgnore.setters.indexOf(prop) == -1) { - do_print(aObjName + "." + prop + " setter"); - try { - obj[prop] = "i am the walrus"; - do_throw(prop + " did not throw an exception"); - } - catch (e) { - if (e.result != Components.results.NS_ERROR_NOT_INITIALIZED) - do_throw(prop + " threw an unexpected exception: " + e); - } - } + try { + do_print("AddonManagerPrivate." + prop); + AddonManagerPrivate[prop](); + do_throw(prop + " did not throw an exception"); + } + catch (e) { + if (e.result != Components.results.NS_ERROR_NOT_INITIALIZED) + do_throw(prop + " threw an unexpected exception: " + e); } } } function run_test() { createAppInfo("xpcshell@tests.mozilla.org", "XPCShell", "1", "1.9.2"); - test_functions("AddonManager", IGNORE); - test_functions("AddonManagerPrivate", IGNORE_PRIVATE); + test_functions(); startupManager(); shutdownManager(); - test_functions("AddonManager", IGNORE); - test_functions("AddonManagerPrivate", IGNORE_PRIVATE); + test_functions(); } diff --git a/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js b/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js index 6d45833ad7c0..8b7dc4cfbdfb 100644 --- a/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js +++ b/toolkit/mozapps/extensions/test/xpcshell/test_updatecheck.js @@ -18,7 +18,6 @@ function run_test() { testserver.start(4444); do_test_pending(); - startupManager(); run_test_1(); } From dfa819730079d345b01d6c3f73b8effc302ec7a9 Mon Sep 17 00:00:00 2001 From: Eddy Bruel Date: Sun, 30 Sep 2012 17:51:26 +0200 Subject: [PATCH 06/64] Bug 787856 - Use static JSObject::getProto in proxy code; r=wmccloskey --- js/src/jsproxy.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index dc784e0b8540..306c8cc6d5c5 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -1603,7 +1603,9 @@ ScriptedDirectProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy return false; if (desc->obj) return true; - JSObject *proto = proxy->getProto(); + RootedObject proto(cx); + if (!JSObject::getProto(cx, proxy, &proto)) + return false; if (!proto) { JS_ASSERT(!desc->obj); return true; @@ -3125,14 +3127,16 @@ proxy(JSContext *cx, unsigned argc, jsval *vp) "Proxy", "1", "s"); return false; } - JSObject *target = NonNullObject(cx, args[0]); + RootedObject target(cx, NonNullObject(cx, args[0])); if (!target) return false; - JSObject *handler = NonNullObject(cx, args[1]); + RootedObject handler(cx, NonNullObject(cx, args[1])); if (!handler) return false; - JSObject *proto = target->getProto(); - JSObject *fun = target->isCallable() ? target : NULL; + RootedObject proto(cx); + if (!JSObject::getProto(cx, target, &proto)) + return false; + RootedObject fun(cx, target->isCallable() ? target : (JSObject *) NULL); JSObject *proxy = NewProxyObject(cx, &ScriptedDirectProxyHandler::singleton, ObjectValue(*target), proto, proto->getParent(), fun, fun); From 5a65bc3488989fa514b7c4fff39bf0cfaffeec22 Mon Sep 17 00:00:00 2001 From: Eddy Bruel Date: Sun, 30 Sep 2012 18:01:13 +0200 Subject: [PATCH 07/64] Bug 789897 - Implement the preventExtensions trap for proxies; r=jorendorff --- .../testDirectProxyPreventExtensions1.js | 6 ++ .../testDirectProxyPreventExtensions2.js | 17 +++++ .../testDirectProxyPreventExtensions3.js | 13 ++++ .../testDirectProxyPreventExtensions4.js | 13 ++++ .../testDirectProxyPreventExtensions5.js | 12 ++++ js/src/js.msg | 2 + js/src/jsapi.cpp | 2 +- js/src/jsobj.h | 3 + js/src/jsproxy.cpp | 68 +++++++++++++++++++ js/src/jsproxy.h | 7 ++ js/src/jsscope.cpp | 43 +++++++++++- js/src/jsscope.h | 1 + js/src/vm/CommonPropertyNames.h | 1 + js/src/vm/ObjectImpl-inl.h | 6 -- js/src/vm/ObjectImpl.cpp | 2 +- js/src/vm/ObjectImpl.h | 2 - 16 files changed, 187 insertions(+), 11 deletions(-) create mode 100644 js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions1.js create mode 100644 js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions2.js create mode 100644 js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions3.js create mode 100644 js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions4.js create mode 100644 js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions5.js diff --git a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions1.js b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions1.js new file mode 100644 index 000000000000..f668719c6540 --- /dev/null +++ b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions1.js @@ -0,0 +1,6 @@ +// Forward to the target if the trap is not defined +target = {}; +var proxy = new Proxy(target, {}); +Object.preventExtensions(proxy); +assertEq(Object.isExtensible(target), false); +assertEq(Object.isExtensible(proxy), false); diff --git a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions2.js b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions2.js new file mode 100644 index 000000000000..cc6db477b600 --- /dev/null +++ b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions2.js @@ -0,0 +1,17 @@ +/* + * Call the trap with the handler as the this value, and the target as the first + * argument + */ +var target = {}; +var called = false; +var handler = { + preventExtensions: function (target1) { + assertEq(this, handler); + assertEq(target1, target); + called = true; + Object.preventExtensions(target); + return true; + } +}; +Object.preventExtensions(new Proxy(target, handler)); +assertEq(called, true); diff --git a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions3.js b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions3.js new file mode 100644 index 000000000000..e04e1073fad9 --- /dev/null +++ b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions3.js @@ -0,0 +1,13 @@ +load(libdir + "asserts.js"); + +/* + * Throw a TypeError if the trap reports that the proxy has been made + * non-extensible, while the target is still extensible + */ +assertThrowsInstanceOf(function () { + Object.preventExtensions(new Proxy({}, { + preventExtensions: function (target) { + return true; + } + })); +}, TypeError); diff --git a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions4.js b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions4.js new file mode 100644 index 000000000000..4333464ba294 --- /dev/null +++ b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions4.js @@ -0,0 +1,13 @@ +load(libdir + "asserts.js"); + +/* + * Throw a TypeError if the trap reports that the proxy cannot be made + * non-extensible + */ +assertThrowsInstanceOf(function () { + Object.preventExtensions(new Proxy({}, { + preventExtensions: function (target) { + return false; + } + })); +}, TypeError); diff --git a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions5.js b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions5.js new file mode 100644 index 000000000000..d0b618fc123e --- /dev/null +++ b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions5.js @@ -0,0 +1,12 @@ +// Reflect side-effects from the trap +target = {}; +var proxy = new Proxy(target, { + preventExtensions: function (target) { + Object.preventExtensions(target); + return true; + } +}); +Object.preventExtensions(proxy); +assertEq(Object.isExtensible(target), false); +assertEq(Object.isExtensible(proxy), false); + diff --git a/js/src/js.msg b/js/src/js.msg index 92d4519c6f96..8128405d81ed 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -375,3 +375,5 @@ MSG_DEF(JSMSG_MUST_REPORT_UNDEFINED, 321, 0, JSEXN_TYPEERR, "proxy must report MSG_DEF(JSMSG_CANT_SET_NW_NC, 322, 0, JSEXN_TYPEERR, "proxy can't successfully set a non-writable, non-configurable property") MSG_DEF(JSMSG_CANT_SET_WO_SETTER, 323, 0, JSEXN_TYPEERR, "proxy can't succesfully set an accessor property without a setter") MSG_DEF(JSMSG_DEBUG_BAD_REFERENT, 324, 2, JSEXN_TYPEERR, "{0} does not refer to {1}") +MSG_DEF(JSMSG_CANT_REPORT_NON_EXT, 325, 0, JSEXN_TYPEERR, "proxy can't report extensible object as non-extensible") +MSG_DEF(JSMSG_CANT_MAKE_NON_EXT, 326, 0, JSEXN_TYPEERR, "can't prevent extensions on object") diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 1b4845ed7168..f78861756e70 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -3482,7 +3482,7 @@ JS_DeepFreezeObject(JSContext *cx, JSObject *objArg) assertSameCompartment(cx, obj); /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */ - if (!obj->isExtensible()) + if (obj->isExtensible()) return true; if (!JSObject::freeze(cx, obj)) diff --git a/js/src/jsobj.h b/js/src/jsobj.h index bf14f7f2cad6..752b62f3328a 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -548,6 +548,9 @@ struct JSObject : public js::ObjectImpl static inline unsigned getSealedOrFrozenAttributes(unsigned attrs, ImmutabilityType it); public: + friend class js::BaseProxyHandler; + + bool isExtensible() const; bool preventExtensions(JSContext *cx); /* ES5 15.2.3.8: non-extensible, all props non-configurable */ diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 306c8cc6d5c5..ae8f98e86919 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -412,6 +412,12 @@ IndirectProxyHandler::defineProperty(JSContext *cx, JSObject *proxy, jsid id_, JS_DefinePropertyById(cx, obj, id, v, desc->getter, desc->setter, desc->attrs); } +bool +IndirectProxyHandler::preventExtensions(JSContext *cx, JSObject *proxy) +{ + return GetProxyTargetObject(proxy)->preventExtensions(cx); +} + bool IndirectProxyHandler::getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) @@ -442,6 +448,12 @@ IndirectProxyHandler::enumerate(JSContext *cx, JSObject *proxy, return GetPropertyNames(cx, target, 0, &props); } +bool +IndirectProxyHandler::isExtensible(JSObject *proxy) +{ + return GetProxyTargetObject(proxy)->isExtensible(); +} + bool IndirectProxyHandler::call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp) @@ -1031,6 +1043,7 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler { PropertyDescriptor *desc) MOZ_OVERRIDE; virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool preventExtensions(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE; virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props); virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) MOZ_OVERRIDE; virtual bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props) MOZ_OVERRIDE; @@ -1654,6 +1667,47 @@ ScriptedDirectProxyHandler::defineProperty(JSContext *cx, JSObject *proxy_, jsid return TrapDefineOwnProperty(cx, proxy, id, &v); } +bool +ScriptedDirectProxyHandler::preventExtensions(JSContext *cx, JSObject *proxy_) +{ + RootedObject proxy(cx, proxy_); + + // step a + RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); + + // step b + RootedObject target(cx, GetProxyTargetObject(proxy)); + + // step c + RootedValue trap(cx); + if (!JSObject::getProperty(cx, handler, handler, cx->names().preventExtensions, &trap)) + return false; + + // step d + if (trap.isUndefined()) + return DirectProxyHandler::preventExtensions(cx, proxy_); + + // step e + Value argv[] = { + ObjectValue(*target) + }; + RootedValue trapResult(cx); + if (!Invoke(cx, ObjectValue(*handler), trap, 1, argv, trapResult.address())) + return false; + + // steps f-h + if (ToBoolean(trapResult)) { + if (target->isExtensible()) { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_REPORT_NON_EXT); + return false; + } + return true; + } else { + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_MAKE_NON_EXT); + return false; + } +} + bool ScriptedDirectProxyHandler::getOwnPropertyNames(JSContext *cx, JSObject *proxy_, AutoIdVector &props) @@ -2286,6 +2340,14 @@ Proxy::defineProperty(JSContext *cx, JSObject *proxy_, jsid id_, const Value &v) Proxy::defineProperty(cx, proxy, id, &desc); } +bool +Proxy::preventExtensions(JSContext *cx, JSObject *proxy_) +{ + JS_CHECK_RECURSION(cx, return false); + RootedObject proxy(cx, proxy_); + return GetProxyHandler(proxy)->preventExtensions(cx, proxy); +} + bool Proxy::getOwnPropertyNames(JSContext *cx, JSObject *proxy_, AutoIdVector &props) { @@ -2453,6 +2515,12 @@ Proxy::iterate(JSContext *cx, HandleObject proxy_, unsigned flags, MutableHandle return EnumeratedIdVectorToIterator(cx, proxy, flags, props, vp); } +bool +Proxy::isExtensible(JSObject *proxy) +{ + return GetProxyHandler(proxy)->isExtensible(proxy); +} + bool Proxy::call(JSContext *cx, JSObject *proxy_, unsigned argc, Value *vp) { diff --git a/js/src/jsproxy.h b/js/src/jsproxy.h index 93a40005f881..cbd451158166 100644 --- a/js/src/jsproxy.h +++ b/js/src/jsproxy.h @@ -49,6 +49,7 @@ class JS_FRIEND_API(Wrapper); class JS_FRIEND_API(BaseProxyHandler) { void *mFamily; bool mHasPrototype; + protected: // Subclasses may set this in their constructor. void setHasPrototype(bool hasPrototype) { mHasPrototype = hasPrototype; } @@ -91,6 +92,7 @@ class JS_FRIEND_API(BaseProxyHandler) { PropertyDescriptor *desc) = 0; virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, PropertyDescriptor *desc) = 0; + virtual bool preventExtensions(JSContext *cx, JSObject *proxy); virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 0; virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) = 0; @@ -109,6 +111,7 @@ class JS_FRIEND_API(BaseProxyHandler) { Value *vp); /* Spidermonkey extensions. */ + virtual bool isExtensible(JSObject *proxy); virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp); virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc, Value *argv, Value *rval); virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args); @@ -148,6 +151,7 @@ class JS_PUBLIC_API(IndirectProxyHandler) : public BaseProxyHandler { PropertyDescriptor *desc) MOZ_OVERRIDE; virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool preventExtensions(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE; virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) MOZ_OVERRIDE; virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, @@ -156,6 +160,7 @@ class JS_PUBLIC_API(IndirectProxyHandler) : public BaseProxyHandler { AutoIdVector &props) MOZ_OVERRIDE; /* Spidermonkey extensions. */ + virtual bool isExtensible(JSObject *proxy); virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp) MOZ_OVERRIDE; virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc, @@ -218,6 +223,7 @@ class Proxy { Value *vp); static bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, PropertyDescriptor *desc); static bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, const Value &v); + static bool preventExtensions(JSContext *cx, JSObject *proxy); static bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props); static bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp); static bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props); @@ -234,6 +240,7 @@ class Proxy { static bool iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleValue vp); /* Spidermonkey extensions. */ + static bool isExtensible(JSObject *proxy); static bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp); static bool construct(JSContext *cx, JSObject *proxy, unsigned argc, Value *argv, Value *rval); static bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args); diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 48e22fff8339..96864ae1daa7 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -1028,12 +1028,21 @@ Shape::setObjectParent(JSContext *cx, JSObject *parent, TaggedProto proto, Shape return replaceLastProperty(cx, base, proto, last); } +bool +JSObject::isExtensible() const +{ + if (isProxy()) + return Proxy::isExtensible(const_cast(this)); + return !lastProperty()->hasObjectFlag(js::BaseShape::NOT_EXTENSIBLE); +} + bool JSObject::preventExtensions(JSContext *cx) { JS_ASSERT(isExtensible()); - RootedObject self(cx, this); + if (self->isProxy()) + return Proxy::preventExtensions(cx, self); /* * Force lazy properties to be resolved by iterating over the objects' own @@ -1049,6 +1058,38 @@ JSObject::preventExtensions(JSContext *cx) return self->setFlag(cx, BaseShape::NOT_EXTENSIBLE, GENERATE_SHAPE); } +/* + * Per spec, preventExtensions should be a fundamental trap. We don't want to + * force consumers of BaseProxyHandler (i.e. DOM bindings) to implement yet + * another fundamental trap, however, so we provide a default implementation + * here. We cannot simply forward the operation to the target object, since + * BaseProxyHandler is not guaranteed to have one. Instead, we use the proxy's + * shape tree (as we would for normal objects) to store a flag indicating that + * the proxy is not extensible. + */ +bool +BaseProxyHandler::isExtensible(JSObject *proxy) +{ + return !proxy->lastProperty()->hasObjectFlag(js::BaseShape::NOT_EXTENSIBLE); +} + +bool +BaseProxyHandler::preventExtensions(JSContext *cx, JSObject *proxy_) +{ + JS_ASSERT(isExtensible()); + RootedObject proxy(cx, proxy_); + + /* + * Force lazy properties to be resolved by iterating over the objects' own + * properties. + */ + AutoIdVector props(cx); + if (!js::GetPropertyNames(cx, proxy, JSITER_HIDDEN | JSITER_OWNONLY, &props)) + return false; + JS_ASSERT(!proxy->isDenseArray()); + return proxy_->setFlag(cx, BaseShape::NOT_EXTENSIBLE, JSObject::GENERATE_SHAPE); +} + bool JSObject::setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag_, GenerateShape generateShape) { diff --git a/js/src/jsscope.h b/js/src/jsscope.h index d869196e55cd..a7ec511634ca 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -15,6 +15,7 @@ #endif #include "jsobj.h" +#include "jsproxy.h" #include "jspropertytree.h" #include "jstypes.h" diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h index bfeb290c7d52..6714a05ef281 100644 --- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -106,6 +106,7 @@ macro(of, of, "of") \ macro(parseFloat, parseFloat, "parseFloat") \ macro(parseInt, parseInt, "parseInt") \ + macro(preventExtensions, preventExtensions, "preventExtensions") \ macro(propertyIsEnumerable, propertyIsEnumerable, "propertyIsEnumerable") \ macro(proto, proto, "__proto__") \ macro(return, return_, "return") \ diff --git a/js/src/vm/ObjectImpl-inl.h b/js/src/vm/ObjectImpl-inl.h index f2265d2fcd81..b30da6f6d76c 100644 --- a/js/src/vm/ObjectImpl-inl.h +++ b/js/src/vm/ObjectImpl-inl.h @@ -100,12 +100,6 @@ js::ObjectImpl::nativeContainsNoAllocation(Shape &shape) return nativeLookupNoAllocation(shape.propid()) == &shape; } -inline bool -js::ObjectImpl::isExtensible() const -{ - return !lastProperty()->hasObjectFlag(BaseShape::NOT_EXTENSIBLE); -} - inline bool js::ObjectImpl::isDenseArray() const { diff --git a/js/src/vm/ObjectImpl.cpp b/js/src/vm/ObjectImpl.cpp index 5a5e57bbd19d..9eb0251b1d8f 100644 --- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -414,7 +414,7 @@ DenseElementsHeader::defineElement(JSContext *cx, Handle obj, uint3 * If the element doesn't exist, we can only add it if the object is * extensible. */ - if (!obj->isExtensible()) { + if (!obj->asObjectPtr()->isExtensible()) { *succeeded = false; if (!shouldThrow) return true; diff --git a/js/src/vm/ObjectImpl.h b/js/src/vm/ObjectImpl.h index 56ab79a1b19b..b7bc0081a251 100644 --- a/js/src/vm/ObjectImpl.h +++ b/js/src/vm/ObjectImpl.h @@ -1016,8 +1016,6 @@ class ObjectImpl : public gc::Cell return type_->proto; } - inline bool isExtensible() const; - /* * XXX Once the property/element split of bug 586842 is complete, these * methods should move back to JSObject. From b86af95695705d67ad5c78b04684febff41c3eba Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Sun, 30 Sep 2012 12:12:47 -0400 Subject: [PATCH 08/64] Backout 12465a1211e0 (bug 789897) for landing without addressing all review comments. --- .../testDirectProxyPreventExtensions1.js | 6 -- .../testDirectProxyPreventExtensions2.js | 17 ----- .../testDirectProxyPreventExtensions3.js | 13 ---- .../testDirectProxyPreventExtensions4.js | 13 ---- .../testDirectProxyPreventExtensions5.js | 12 ---- js/src/js.msg | 2 - js/src/jsapi.cpp | 2 +- js/src/jsobj.h | 3 - js/src/jsproxy.cpp | 68 ------------------- js/src/jsproxy.h | 7 -- js/src/jsscope.cpp | 43 +----------- js/src/jsscope.h | 1 - js/src/vm/CommonPropertyNames.h | 1 - js/src/vm/ObjectImpl-inl.h | 6 ++ js/src/vm/ObjectImpl.cpp | 2 +- js/src/vm/ObjectImpl.h | 2 + 16 files changed, 11 insertions(+), 187 deletions(-) delete mode 100644 js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions1.js delete mode 100644 js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions2.js delete mode 100644 js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions3.js delete mode 100644 js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions4.js delete mode 100644 js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions5.js diff --git a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions1.js b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions1.js deleted file mode 100644 index f668719c6540..000000000000 --- a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions1.js +++ /dev/null @@ -1,6 +0,0 @@ -// Forward to the target if the trap is not defined -target = {}; -var proxy = new Proxy(target, {}); -Object.preventExtensions(proxy); -assertEq(Object.isExtensible(target), false); -assertEq(Object.isExtensible(proxy), false); diff --git a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions2.js b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions2.js deleted file mode 100644 index cc6db477b600..000000000000 --- a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions2.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Call the trap with the handler as the this value, and the target as the first - * argument - */ -var target = {}; -var called = false; -var handler = { - preventExtensions: function (target1) { - assertEq(this, handler); - assertEq(target1, target); - called = true; - Object.preventExtensions(target); - return true; - } -}; -Object.preventExtensions(new Proxy(target, handler)); -assertEq(called, true); diff --git a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions3.js b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions3.js deleted file mode 100644 index e04e1073fad9..000000000000 --- a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions3.js +++ /dev/null @@ -1,13 +0,0 @@ -load(libdir + "asserts.js"); - -/* - * Throw a TypeError if the trap reports that the proxy has been made - * non-extensible, while the target is still extensible - */ -assertThrowsInstanceOf(function () { - Object.preventExtensions(new Proxy({}, { - preventExtensions: function (target) { - return true; - } - })); -}, TypeError); diff --git a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions4.js b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions4.js deleted file mode 100644 index 4333464ba294..000000000000 --- a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions4.js +++ /dev/null @@ -1,13 +0,0 @@ -load(libdir + "asserts.js"); - -/* - * Throw a TypeError if the trap reports that the proxy cannot be made - * non-extensible - */ -assertThrowsInstanceOf(function () { - Object.preventExtensions(new Proxy({}, { - preventExtensions: function (target) { - return false; - } - })); -}, TypeError); diff --git a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions5.js b/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions5.js deleted file mode 100644 index d0b618fc123e..000000000000 --- a/js/src/jit-test/tests/proxy/testDirectProxyPreventExtensions5.js +++ /dev/null @@ -1,12 +0,0 @@ -// Reflect side-effects from the trap -target = {}; -var proxy = new Proxy(target, { - preventExtensions: function (target) { - Object.preventExtensions(target); - return true; - } -}); -Object.preventExtensions(proxy); -assertEq(Object.isExtensible(target), false); -assertEq(Object.isExtensible(proxy), false); - diff --git a/js/src/js.msg b/js/src/js.msg index 8128405d81ed..92d4519c6f96 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -375,5 +375,3 @@ MSG_DEF(JSMSG_MUST_REPORT_UNDEFINED, 321, 0, JSEXN_TYPEERR, "proxy must report MSG_DEF(JSMSG_CANT_SET_NW_NC, 322, 0, JSEXN_TYPEERR, "proxy can't successfully set a non-writable, non-configurable property") MSG_DEF(JSMSG_CANT_SET_WO_SETTER, 323, 0, JSEXN_TYPEERR, "proxy can't succesfully set an accessor property without a setter") MSG_DEF(JSMSG_DEBUG_BAD_REFERENT, 324, 2, JSEXN_TYPEERR, "{0} does not refer to {1}") -MSG_DEF(JSMSG_CANT_REPORT_NON_EXT, 325, 0, JSEXN_TYPEERR, "proxy can't report extensible object as non-extensible") -MSG_DEF(JSMSG_CANT_MAKE_NON_EXT, 326, 0, JSEXN_TYPEERR, "can't prevent extensions on object") diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index f78861756e70..1b4845ed7168 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -3482,7 +3482,7 @@ JS_DeepFreezeObject(JSContext *cx, JSObject *objArg) assertSameCompartment(cx, obj); /* Assume that non-extensible objects are already deep-frozen, to avoid divergence. */ - if (obj->isExtensible()) + if (!obj->isExtensible()) return true; if (!JSObject::freeze(cx, obj)) diff --git a/js/src/jsobj.h b/js/src/jsobj.h index 752b62f3328a..bf14f7f2cad6 100644 --- a/js/src/jsobj.h +++ b/js/src/jsobj.h @@ -548,9 +548,6 @@ struct JSObject : public js::ObjectImpl static inline unsigned getSealedOrFrozenAttributes(unsigned attrs, ImmutabilityType it); public: - friend class js::BaseProxyHandler; - - bool isExtensible() const; bool preventExtensions(JSContext *cx); /* ES5 15.2.3.8: non-extensible, all props non-configurable */ diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index ae8f98e86919..306c8cc6d5c5 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -412,12 +412,6 @@ IndirectProxyHandler::defineProperty(JSContext *cx, JSObject *proxy, jsid id_, JS_DefinePropertyById(cx, obj, id, v, desc->getter, desc->setter, desc->attrs); } -bool -IndirectProxyHandler::preventExtensions(JSContext *cx, JSObject *proxy) -{ - return GetProxyTargetObject(proxy)->preventExtensions(cx); -} - bool IndirectProxyHandler::getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) @@ -448,12 +442,6 @@ IndirectProxyHandler::enumerate(JSContext *cx, JSObject *proxy, return GetPropertyNames(cx, target, 0, &props); } -bool -IndirectProxyHandler::isExtensible(JSObject *proxy) -{ - return GetProxyTargetObject(proxy)->isExtensible(); -} - bool IndirectProxyHandler::call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp) @@ -1043,7 +1031,6 @@ class ScriptedDirectProxyHandler : public DirectProxyHandler { PropertyDescriptor *desc) MOZ_OVERRIDE; virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, PropertyDescriptor *desc) MOZ_OVERRIDE; - virtual bool preventExtensions(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE; virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props); virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) MOZ_OVERRIDE; virtual bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props) MOZ_OVERRIDE; @@ -1667,47 +1654,6 @@ ScriptedDirectProxyHandler::defineProperty(JSContext *cx, JSObject *proxy_, jsid return TrapDefineOwnProperty(cx, proxy, id, &v); } -bool -ScriptedDirectProxyHandler::preventExtensions(JSContext *cx, JSObject *proxy_) -{ - RootedObject proxy(cx, proxy_); - - // step a - RootedObject handler(cx, GetDirectProxyHandlerObject(proxy)); - - // step b - RootedObject target(cx, GetProxyTargetObject(proxy)); - - // step c - RootedValue trap(cx); - if (!JSObject::getProperty(cx, handler, handler, cx->names().preventExtensions, &trap)) - return false; - - // step d - if (trap.isUndefined()) - return DirectProxyHandler::preventExtensions(cx, proxy_); - - // step e - Value argv[] = { - ObjectValue(*target) - }; - RootedValue trapResult(cx); - if (!Invoke(cx, ObjectValue(*handler), trap, 1, argv, trapResult.address())) - return false; - - // steps f-h - if (ToBoolean(trapResult)) { - if (target->isExtensible()) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_REPORT_NON_EXT); - return false; - } - return true; - } else { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_CANT_MAKE_NON_EXT); - return false; - } -} - bool ScriptedDirectProxyHandler::getOwnPropertyNames(JSContext *cx, JSObject *proxy_, AutoIdVector &props) @@ -2340,14 +2286,6 @@ Proxy::defineProperty(JSContext *cx, JSObject *proxy_, jsid id_, const Value &v) Proxy::defineProperty(cx, proxy, id, &desc); } -bool -Proxy::preventExtensions(JSContext *cx, JSObject *proxy_) -{ - JS_CHECK_RECURSION(cx, return false); - RootedObject proxy(cx, proxy_); - return GetProxyHandler(proxy)->preventExtensions(cx, proxy); -} - bool Proxy::getOwnPropertyNames(JSContext *cx, JSObject *proxy_, AutoIdVector &props) { @@ -2515,12 +2453,6 @@ Proxy::iterate(JSContext *cx, HandleObject proxy_, unsigned flags, MutableHandle return EnumeratedIdVectorToIterator(cx, proxy, flags, props, vp); } -bool -Proxy::isExtensible(JSObject *proxy) -{ - return GetProxyHandler(proxy)->isExtensible(proxy); -} - bool Proxy::call(JSContext *cx, JSObject *proxy_, unsigned argc, Value *vp) { diff --git a/js/src/jsproxy.h b/js/src/jsproxy.h index cbd451158166..93a40005f881 100644 --- a/js/src/jsproxy.h +++ b/js/src/jsproxy.h @@ -49,7 +49,6 @@ class JS_FRIEND_API(Wrapper); class JS_FRIEND_API(BaseProxyHandler) { void *mFamily; bool mHasPrototype; - protected: // Subclasses may set this in their constructor. void setHasPrototype(bool hasPrototype) { mHasPrototype = hasPrototype; } @@ -92,7 +91,6 @@ class JS_FRIEND_API(BaseProxyHandler) { PropertyDescriptor *desc) = 0; virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, PropertyDescriptor *desc) = 0; - virtual bool preventExtensions(JSContext *cx, JSObject *proxy); virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) = 0; virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) = 0; @@ -111,7 +109,6 @@ class JS_FRIEND_API(BaseProxyHandler) { Value *vp); /* Spidermonkey extensions. */ - virtual bool isExtensible(JSObject *proxy); virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp); virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc, Value *argv, Value *rval); virtual bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args); @@ -151,7 +148,6 @@ class JS_PUBLIC_API(IndirectProxyHandler) : public BaseProxyHandler { PropertyDescriptor *desc) MOZ_OVERRIDE; virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, PropertyDescriptor *desc) MOZ_OVERRIDE; - virtual bool preventExtensions(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE; virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props) MOZ_OVERRIDE; virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, @@ -160,7 +156,6 @@ class JS_PUBLIC_API(IndirectProxyHandler) : public BaseProxyHandler { AutoIdVector &props) MOZ_OVERRIDE; /* Spidermonkey extensions. */ - virtual bool isExtensible(JSObject *proxy); virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp) MOZ_OVERRIDE; virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc, @@ -223,7 +218,6 @@ class Proxy { Value *vp); static bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, PropertyDescriptor *desc); static bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, const Value &v); - static bool preventExtensions(JSContext *cx, JSObject *proxy); static bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, AutoIdVector &props); static bool delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp); static bool enumerate(JSContext *cx, JSObject *proxy, AutoIdVector &props); @@ -240,7 +234,6 @@ class Proxy { static bool iterate(JSContext *cx, HandleObject proxy, unsigned flags, MutableHandleValue vp); /* Spidermonkey extensions. */ - static bool isExtensible(JSObject *proxy); static bool call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp); static bool construct(JSContext *cx, JSObject *proxy, unsigned argc, Value *argv, Value *rval); static bool nativeCall(JSContext *cx, IsAcceptableThis test, NativeImpl impl, CallArgs args); diff --git a/js/src/jsscope.cpp b/js/src/jsscope.cpp index 96864ae1daa7..48e22fff8339 100644 --- a/js/src/jsscope.cpp +++ b/js/src/jsscope.cpp @@ -1028,21 +1028,12 @@ Shape::setObjectParent(JSContext *cx, JSObject *parent, TaggedProto proto, Shape return replaceLastProperty(cx, base, proto, last); } -bool -JSObject::isExtensible() const -{ - if (isProxy()) - return Proxy::isExtensible(const_cast(this)); - return !lastProperty()->hasObjectFlag(js::BaseShape::NOT_EXTENSIBLE); -} - bool JSObject::preventExtensions(JSContext *cx) { JS_ASSERT(isExtensible()); + RootedObject self(cx, this); - if (self->isProxy()) - return Proxy::preventExtensions(cx, self); /* * Force lazy properties to be resolved by iterating over the objects' own @@ -1058,38 +1049,6 @@ JSObject::preventExtensions(JSContext *cx) return self->setFlag(cx, BaseShape::NOT_EXTENSIBLE, GENERATE_SHAPE); } -/* - * Per spec, preventExtensions should be a fundamental trap. We don't want to - * force consumers of BaseProxyHandler (i.e. DOM bindings) to implement yet - * another fundamental trap, however, so we provide a default implementation - * here. We cannot simply forward the operation to the target object, since - * BaseProxyHandler is not guaranteed to have one. Instead, we use the proxy's - * shape tree (as we would for normal objects) to store a flag indicating that - * the proxy is not extensible. - */ -bool -BaseProxyHandler::isExtensible(JSObject *proxy) -{ - return !proxy->lastProperty()->hasObjectFlag(js::BaseShape::NOT_EXTENSIBLE); -} - -bool -BaseProxyHandler::preventExtensions(JSContext *cx, JSObject *proxy_) -{ - JS_ASSERT(isExtensible()); - RootedObject proxy(cx, proxy_); - - /* - * Force lazy properties to be resolved by iterating over the objects' own - * properties. - */ - AutoIdVector props(cx); - if (!js::GetPropertyNames(cx, proxy, JSITER_HIDDEN | JSITER_OWNONLY, &props)) - return false; - JS_ASSERT(!proxy->isDenseArray()); - return proxy_->setFlag(cx, BaseShape::NOT_EXTENSIBLE, JSObject::GENERATE_SHAPE); -} - bool JSObject::setFlag(JSContext *cx, /*BaseShape::Flag*/ uint32_t flag_, GenerateShape generateShape) { diff --git a/js/src/jsscope.h b/js/src/jsscope.h index a7ec511634ca..d869196e55cd 100644 --- a/js/src/jsscope.h +++ b/js/src/jsscope.h @@ -15,7 +15,6 @@ #endif #include "jsobj.h" -#include "jsproxy.h" #include "jspropertytree.h" #include "jstypes.h" diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h index 6714a05ef281..bfeb290c7d52 100644 --- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -106,7 +106,6 @@ macro(of, of, "of") \ macro(parseFloat, parseFloat, "parseFloat") \ macro(parseInt, parseInt, "parseInt") \ - macro(preventExtensions, preventExtensions, "preventExtensions") \ macro(propertyIsEnumerable, propertyIsEnumerable, "propertyIsEnumerable") \ macro(proto, proto, "__proto__") \ macro(return, return_, "return") \ diff --git a/js/src/vm/ObjectImpl-inl.h b/js/src/vm/ObjectImpl-inl.h index b30da6f6d76c..f2265d2fcd81 100644 --- a/js/src/vm/ObjectImpl-inl.h +++ b/js/src/vm/ObjectImpl-inl.h @@ -100,6 +100,12 @@ js::ObjectImpl::nativeContainsNoAllocation(Shape &shape) return nativeLookupNoAllocation(shape.propid()) == &shape; } +inline bool +js::ObjectImpl::isExtensible() const +{ + return !lastProperty()->hasObjectFlag(BaseShape::NOT_EXTENSIBLE); +} + inline bool js::ObjectImpl::isDenseArray() const { diff --git a/js/src/vm/ObjectImpl.cpp b/js/src/vm/ObjectImpl.cpp index 9eb0251b1d8f..5a5e57bbd19d 100644 --- a/js/src/vm/ObjectImpl.cpp +++ b/js/src/vm/ObjectImpl.cpp @@ -414,7 +414,7 @@ DenseElementsHeader::defineElement(JSContext *cx, Handle obj, uint3 * If the element doesn't exist, we can only add it if the object is * extensible. */ - if (!obj->asObjectPtr()->isExtensible()) { + if (!obj->isExtensible()) { *succeeded = false; if (!shouldThrow) return true; diff --git a/js/src/vm/ObjectImpl.h b/js/src/vm/ObjectImpl.h index b7bc0081a251..56ab79a1b19b 100644 --- a/js/src/vm/ObjectImpl.h +++ b/js/src/vm/ObjectImpl.h @@ -1016,6 +1016,8 @@ class ObjectImpl : public gc::Cell return type_->proto; } + inline bool isExtensible() const; + /* * XXX Once the property/element split of bug 586842 is complete, these * methods should move back to JSObject. From 43e58e33c8bef46741cdab490169c65bf7cfd066 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Sun, 30 Sep 2012 09:40:24 -0700 Subject: [PATCH 09/64] Bug 760331: Coalesce data for inline style across nodes. r=bz This patch enables sharing of an nsAttrValue's MiscContainer between nodes for style rules. MiscContainers of type eCSSStyleRule are now refcounted (with some clever struct packing to ensure that the amount of memory allocated for MiscContainer remains unchanged on 32 and 64 bit). This infrastructure can be used to share most MiscContainer types in the future if we find advantages to sharing other types than just eCSSStyleRuley. A cache mapping strings to MiscContainers has been added to nsHTMLCSSStyleSheet. MiscContainers can be shared between nsAttrValues when one nsAttrValue is SetTo another nsAttrValue or when there is a cache hit in this cache. This patch also adds the ability to tell a style rule that it belongs to an nsHTMLCSSStyleSheet, with appropriate accessor functions to separate that from the existing case of belonging to an nsCSSStyleSheet. The primary use case is to reduce memory use for pages that have lots of inline style attributes with the same value. This can happen easily with large pages that are automatically generated. An (admittedly pathological) testcase in Bug 686975 sees over 250 MB of memory savings with this change. Reusing the same MiscContainer for multiple nodes saves the overhead of maintaining separate copies of the string containing the serialized value of the style attribute and of creating separate style rules for each node. Eliminating duplicate style rules enables further savings in layout through style context sharing. The testcase sees the amount of memory used by style contexts go from over 250 MB to 10 KB. Because the cache is based on the text value of the style attribute, it will not handle attributes that have different text values but are parsed into identical style rules. We also do not attempt to share MiscContainers when the node's base URI differs from the document URI. The effect of these limitations is expected to be low. --- content/base/src/Makefile.in | 1 + content/base/src/nsAttrValue.cpp | 541 +++++++++++------- content/base/src/nsAttrValue.h | 202 +------ content/base/src/nsAttrValueInlines.h | 216 +++++++ content/base/src/nsContentUtils.cpp | 1 + content/base/src/nsGenericElement.cpp | 1 + content/base/src/nsStyledElement.cpp | 18 +- content/html/content/src/nsFormSubmission.cpp | 1 + .../html/content/src/nsGenericHTMLElement.cpp | 1 + content/html/content/src/nsHTMLBRElement.cpp | 1 + .../html/content/src/nsHTMLBodyElement.cpp | 3 +- .../html/content/src/nsHTMLButtonElement.cpp | 2 + .../html/content/src/nsHTMLCanvasElement.cpp | 1 + .../html/content/src/nsHTMLFontElement.cpp | 1 + content/html/content/src/nsHTMLHRElement.cpp | 1 + .../html/content/src/nsHTMLIFrameElement.cpp | 1 + .../html/content/src/nsHTMLInputElement.cpp | 1 + content/html/content/src/nsHTMLLIElement.cpp | 1 + .../html/content/src/nsHTMLMediaElement.cpp | 1 + .../html/content/src/nsHTMLMenuElement.cpp | 2 +- .../content/src/nsHTMLMenuItemElement.cpp | 1 + .../html/content/src/nsHTMLMeterElement.cpp | 1 + .../html/content/src/nsHTMLOListElement.cpp | 1 + .../html/content/src/nsHTMLObjectElement.cpp | 1 + content/html/content/src/nsHTMLPreElement.cpp | 1 + .../content/src/nsHTMLProgressElement.cpp | 1 + .../html/content/src/nsHTMLSharedElement.cpp | 1 + .../content/src/nsHTMLTableCaptionElement.cpp | 1 + .../content/src/nsHTMLTableCellElement.cpp | 1 + .../content/src/nsHTMLTableColElement.cpp | 1 + .../html/content/src/nsHTMLTableElement.cpp | 1 + .../content/src/nsHTMLTableRowElement.cpp | 1 + .../content/src/nsHTMLTableSectionElement.cpp | 1 + .../content/src/nsHTMLTextAreaElement.cpp | 1 + .../html/content/src/nsTextEditorState.cpp | 1 + content/smil/nsSMILAnimationFunction.cpp | 1 + content/smil/nsSMILTimedElement.cpp | 1 + content/svg/content/src/DOMSVGTransform.cpp | 1 + .../src/SVGAnimatedPreserveAspectRatio.cpp | 1 + .../src/SVGMotionSMILAnimationFunction.cpp | 1 + content/svg/content/src/nsSVGAngle.cpp | 1 + content/svg/content/src/nsSVGLength2.cpp | 1 + content/svg/content/src/nsSVGViewBox.cpp | 1 + content/xul/content/src/nsXULElement.cpp | 1 + dom/base/nsFocusManager.cpp | 1 - dom/bindings/Makefile.in | 1 - dom/media/MediaManager.cpp | 4 +- layout/forms/nsLegendFrame.cpp | 1 + layout/forms/nsTextControlFrame.cpp | 1 + layout/generic/nsBlockFrame.cpp | 1 + layout/generic/nsBulletFrame.cpp | 1 + layout/generic/nsFrameSetFrame.cpp | 1 + layout/generic/nsSubDocumentFrame.cpp | 1 + layout/style/Rule.h | 13 +- layout/style/StyleRule.cpp | 17 +- layout/style/nsCSSRuleProcessor.cpp | 1 + layout/style/nsCSSRules.cpp | 79 ++- layout/style/nsHTMLCSSStyleSheet.cpp | 53 ++ layout/style/nsHTMLCSSStyleSheet.h | 8 + layout/tables/nsTableCellFrame.cpp | 1 + 60 files changed, 781 insertions(+), 424 deletions(-) create mode 100644 content/base/src/nsAttrValueInlines.h diff --git a/content/base/src/Makefile.in b/content/base/src/Makefile.in index 8bfcc6b8e24c..674b8a8e295e 100644 --- a/content/base/src/Makefile.in +++ b/content/base/src/Makefile.in @@ -35,6 +35,7 @@ EXPORTS = \ nsFrameMessageManager.h \ nsAttrAndChildArray.h \ nsAttrValue.h \ + nsAttrValueInlines.h \ nsCrossSiteListenerProxy.h \ nsDOMAttributeMap.h \ nsGenericElement.h \ diff --git a/content/base/src/nsAttrValue.cpp b/content/base/src/nsAttrValue.cpp index cf36d09ed3c6..2a22fc54fa96 100644 --- a/content/base/src/nsAttrValue.cpp +++ b/content/base/src/nsAttrValue.cpp @@ -9,6 +9,7 @@ */ #include "nsAttrValue.h" +#include "nsAttrValueInlines.h" #include "nsIAtom.h" #include "nsUnicharUtils.h" #include "mozilla/css/StyleRule.h" @@ -17,12 +18,101 @@ #include "nsReadableUtils.h" #include "prprf.h" #include "mozilla/HashFunctions.h" +#include "nsHTMLCSSStyleSheet.h" +#include "nsCSSParser.h" +#include "nsStyledElement.h" using namespace mozilla; #define MISC_STR_PTR(_cont) \ reinterpret_cast((_cont)->mStringBits & NS_ATTRVALUE_POINTERVALUE_MASK) +bool +MiscContainer::GetString(nsDependentString& aString) const +{ + void* ptr = MISC_STR_PTR(this); + + if (!ptr) { + return false; + } + + if (static_cast(mStringBits & + NS_ATTRVALUE_BASETYPE_MASK) == + nsAttrValue::eStringBase) { + nsStringBuffer* buffer = static_cast(ptr); + if (!buffer) { + return false; + } + + aString.Rebind(reinterpret_cast(buffer->Data()), + buffer->StorageSize() / sizeof(PRUnichar) - 1); + return true; + } + + nsIAtom* atom = static_cast(ptr); + if (!atom) { + return false; + } + + aString.Rebind(atom->GetUTF16String(), atom->GetLength()); + return true; +} + +void +MiscContainer::Cache() +{ + // Not implemented for anything else yet. + MOZ_ASSERT(mType == nsAttrValue::eCSSStyleRule); + MOZ_ASSERT(IsRefCounted()); + MOZ_ASSERT(mValue.mRefCount > 0); + MOZ_ASSERT(!mValue.mCached); + + css::StyleRule* rule = mValue.mCSSStyleRule; + nsHTMLCSSStyleSheet* sheet = rule->GetHTMLCSSStyleSheet(); + if (!sheet) { + return; + } + + nsDependentString str; + bool gotString = GetString(str); + if (!gotString) { + return; + } + + sheet->CacheStyleAttr(str, this); + mValue.mCached = 1; + + // This has to be immutable once it goes into the cache. + css::Declaration* decl = rule->GetDeclaration(); + if (decl) { + decl->SetImmutable(); + } +} + +void +MiscContainer::Evict() +{ + // Not implemented for anything else yet. + MOZ_ASSERT(mType == nsAttrValue::eCSSStyleRule); + MOZ_ASSERT(IsRefCounted()); + MOZ_ASSERT(mValue.mRefCount == 0); + + if (!mValue.mCached) { + return; + } + + css::StyleRule* rule = mValue.mCSSStyleRule; + nsHTMLCSSStyleSheet* sheet = rule->GetHTMLCSSStyleSheet(); + MOZ_ASSERT(sheet); + + nsDependentString str; + DebugOnly gotString = GetString(str); + MOZ_ASSERT(gotString); + + sheet->EvictStyleAttr(str, this); + mValue.mCached = 0; +} + nsTArray* nsAttrValue::sEnumTableArray = nullptr; nsAttrValue::nsAttrValue() @@ -119,8 +209,13 @@ nsAttrValue::Reset() } case eOtherBase: { - EnsureEmptyMiscContainer(); - delete GetMiscContainer(); + MiscContainer* cont = GetMiscContainer(); + if (cont->IsRefCounted() && cont->mValue.mRefCount > 1) { + NS_RELEASE(cont); + break; + } + + delete ClearMiscContainer(); break; } @@ -179,51 +274,54 @@ nsAttrValue::SetTo(const nsAttrValue& aOther) } MiscContainer* otherCont = aOther.GetMiscContainer(); - if (!EnsureEmptyMiscContainer()) { + if (otherCont->IsRefCounted()) { + delete ClearMiscContainer(); + NS_ADDREF(otherCont); + SetPtrValueAndType(otherCont, eOtherBase); return; } - MiscContainer* cont = GetMiscContainer(); + MiscContainer* cont = EnsureEmptyMiscContainer(); switch (otherCont->mType) { case eInteger: { - cont->mInteger = otherCont->mInteger; + cont->mValue.mInteger = otherCont->mValue.mInteger; break; } case eEnum: { - cont->mEnumValue = otherCont->mEnumValue; + cont->mValue.mEnumValue = otherCont->mValue.mEnumValue; break; } case ePercent: { - cont->mPercent = otherCont->mPercent; + cont->mValue.mPercent = otherCont->mValue.mPercent; break; } case eColor: { - cont->mColor = otherCont->mColor; + cont->mValue.mColor = otherCont->mValue.mColor; break; } case eCSSStyleRule: { - NS_ADDREF(cont->mCSSStyleRule = otherCont->mCSSStyleRule); + MOZ_NOT_REACHED("These should be refcounted!"); break; } case eURL: { - NS_ADDREF(cont->mURL = otherCont->mURL); + NS_ADDREF(cont->mValue.mURL = otherCont->mValue.mURL); break; } case eImage: { - NS_ADDREF(cont->mImage = otherCont->mImage); + NS_ADDREF(cont->mValue.mImage = otherCont->mValue.mImage); break; } case eAtomArray: { if (!EnsureEmptyAtomArray() || - !GetAtomArrayValue()->AppendElements(*otherCont->mAtomArray)) { + !GetAtomArrayValue()->AppendElements(*otherCont->mValue.mAtomArray)) { Reset(); return; } @@ -236,8 +334,9 @@ nsAttrValue::SetTo(const nsAttrValue& aOther) } case eIntMarginValue: { - if (otherCont->mIntMargin) - cont->mIntMargin = new nsIntMargin(*otherCont->mIntMargin); + if (otherCont->mValue.mIntMargin) + cont->mValue.mIntMargin = + new nsIntMargin(*otherCont->mValue.mIntMargin); break; } default: @@ -245,7 +344,7 @@ nsAttrValue::SetTo(const nsAttrValue& aOther) if (IsSVGType(otherCont->mType)) { // All SVG types are just pointers to classes and will therefore have // the same size so it doesn't really matter which one we assign - cont->mSVGAngle = otherCont->mSVGAngle; + cont->mValue.mSVGAngle = otherCont->mValue.mSVGAngle; } else { NS_NOTREACHED("unknown type stored in MiscContainer"); } @@ -305,44 +404,39 @@ nsAttrValue::SetTo(int32_t aInt, const nsAString* aSerialized) void nsAttrValue::SetTo(double aValue, const nsAString* aSerialized) { - if (EnsureEmptyMiscContainer()) { - MiscContainer* cont = GetMiscContainer(); - cont->mDoubleValue = aValue; - cont->mType = eDoubleValue; - SetMiscAtomOrString(aSerialized); - } + MiscContainer* cont = EnsureEmptyMiscContainer(); + cont->mDoubleValue = aValue; + cont->mType = eDoubleValue; + SetMiscAtomOrString(aSerialized); } void nsAttrValue::SetTo(css::StyleRule* aValue, const nsAString* aSerialized) { - if (EnsureEmptyMiscContainer()) { - MiscContainer* cont = GetMiscContainer(); - NS_ADDREF(cont->mCSSStyleRule = aValue); - cont->mType = eCSSStyleRule; - SetMiscAtomOrString(aSerialized); - } + MiscContainer* cont = EnsureEmptyMiscContainer(); + MOZ_ASSERT(cont->mValue.mRefCount == 0); + NS_ADDREF(cont->mValue.mCSSStyleRule = aValue); + cont->mType = eCSSStyleRule; + NS_ADDREF(cont); + SetMiscAtomOrString(aSerialized); + MOZ_ASSERT(cont->mValue.mRefCount == 1); } void nsAttrValue::SetTo(css::URLValue* aValue, const nsAString* aSerialized) { - if (EnsureEmptyMiscContainer()) { - MiscContainer* cont = GetMiscContainer(); - NS_ADDREF(cont->mURL = aValue); - cont->mType = eURL; - SetMiscAtomOrString(aSerialized); - } + MiscContainer* cont = EnsureEmptyMiscContainer(); + NS_ADDREF(cont->mValue.mURL = aValue); + cont->mType = eURL; + SetMiscAtomOrString(aSerialized); } void nsAttrValue::SetTo(const nsIntMargin& aValue) { - if (EnsureEmptyMiscContainer()) { - MiscContainer* cont = GetMiscContainer(); - cont->mIntMargin = new nsIntMargin(aValue); - cont->mType = eIntMarginValue; - } + MiscContainer* cont = EnsureEmptyMiscContainer(); + cont->mValue.mIntMargin = new nsIntMargin(aValue); + cont->mType = eIntMarginValue; } void @@ -481,20 +575,11 @@ nsAttrValue::ToString(nsAString& aResult) const MiscContainer* cont = nullptr; if (BaseType() == eOtherBase) { cont = GetMiscContainer(); - void* ptr = MISC_STR_PTR(cont); - if (ptr) { - if (static_cast(cont->mStringBits & NS_ATTRVALUE_BASETYPE_MASK) == - eStringBase) { - nsStringBuffer* str = static_cast(ptr); - if (str) { - str->ToString(str->StorageSize()/sizeof(PRUnichar) - 1, aResult); - return; - } - } else { - nsIAtom *atom = static_cast(ptr); - atom->ToString(aResult); - return; - } + + nsDependentString str; + if (cont->GetString(str)) { + aResult = str; + return; } } @@ -541,7 +626,7 @@ nsAttrValue::ToString(nsAString& aResult) const case ePercent: { nsAutoString intStr; - intStr.AppendInt(cont ? cont->mPercent : GetIntInternal()); + intStr.AppendInt(cont ? cont->mValue.mPercent : GetIntInternal()); aResult = intStr + NS_LITERAL_STRING("%"); break; @@ -550,7 +635,8 @@ nsAttrValue::ToString(nsAString& aResult) const { aResult.Truncate(); MiscContainer *container = GetMiscContainer(); - css::Declaration *decl = container->mCSSStyleRule->GetDeclaration(); + css::Declaration *decl = + container->mValue.mCSSStyleRule->GetDeclaration(); if (decl) { decl->ToString(aResult); } @@ -566,69 +652,74 @@ nsAttrValue::ToString(nsAString& aResult) const } case eSVGAngle: { - SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGAngle, aResult); + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGAngle, + aResult); break; } case eSVGIntegerPair: { - SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGIntegerPair, + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGIntegerPair, aResult); break; } case eSVGLength: { - SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGLength, aResult); + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGLength, + aResult); break; } case eSVGLengthList: { - SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGLengthList, + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGLengthList, aResult); break; } case eSVGNumberList: { - SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGNumberList, + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGNumberList, aResult); break; } case eSVGNumberPair: { - SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGNumberPair, + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGNumberPair, aResult); break; } case eSVGPathData: { - SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGPathData, aResult); + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGPathData, + aResult); break; } case eSVGPointList: { - SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGPointList, aResult); + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGPointList, + aResult); break; } case eSVGPreserveAspectRatio: { - SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGPreserveAspectRatio, + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGPreserveAspectRatio, aResult); break; } case eSVGStringList: { - SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGStringList, + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGStringList, aResult); break; } case eSVGTransformList: { - SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGTransformList, + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGTransformList, aResult); break; } case eSVGViewBox: { - SVGAttrValueWrapper::ToString(GetMiscContainer()->mSVGViewBox, aResult); + SVGAttrValueWrapper::ToString(GetMiscContainer()->mValue.mSVGViewBox, + aResult); break; } default: @@ -679,7 +770,7 @@ nsAttrValue::GetColorValue(nscolor& aColor) const return false; } - aColor = GetMiscContainer()->mColor; + aColor = GetMiscContainer()->mValue.mColor; return true; } @@ -690,7 +781,7 @@ nsAttrValue::GetEnumString(nsAString& aResult, bool aRealTag) const uint32_t allEnumBits = (BaseType() == eIntegerBase) ? static_cast(GetIntInternal()) - : GetMiscContainer()->mEnumValue; + : GetMiscContainer()->mValue.mEnumValue; int16_t val = allEnumBits >> NS_ATTRVALUE_ENUMTABLEINDEX_BITS; const EnumTable* table = sEnumTableArray-> ElementAt(allEnumBits & NS_ATTRVALUE_ENUMTABLEINDEX_MASK); @@ -777,23 +868,23 @@ nsAttrValue::HashValue() const switch (cont->mType) { case eInteger: { - return cont->mInteger; + return cont->mValue.mInteger; } case eEnum: { - return cont->mEnumValue; + return cont->mValue.mEnumValue; } case ePercent: { - return cont->mPercent; + return cont->mValue.mPercent; } case eColor: { - return cont->mColor; + return cont->mValue.mColor; } case eCSSStyleRule: { - return NS_PTR_TO_INT32(cont->mCSSStyleRule); + return NS_PTR_TO_INT32(cont->mValue.mCSSStyleRule); } // Intentionally identical, so that loading the image does not change the // hash code. @@ -807,8 +898,8 @@ nsAttrValue::HashValue() const case eAtomArray: { uint32_t hash = 0; - uint32_t count = cont->mAtomArray->Length(); - for (nsCOMPtr *cur = cont->mAtomArray->Elements(), + uint32_t count = cont->mValue.mAtomArray->Length(); + for (nsCOMPtr *cur = cont->mValue.mAtomArray->Elements(), *end = cur + count; cur != end; ++cur) { hash = AddToHash(hash, cur->get()); @@ -822,13 +913,13 @@ nsAttrValue::HashValue() const } case eIntMarginValue: { - return NS_PTR_TO_INT32(cont->mIntMargin); + return NS_PTR_TO_INT32(cont->mValue.mIntMargin); } default: { if (IsSVGType(cont->mType)) { // All SVG types are just pointers to classes so we can treat them alike - return NS_PTR_TO_INT32(cont->mSVGAngle); + return NS_PTR_TO_INT32(cont->mValue.mSVGAngle); } NS_NOTREACHED("unknown type stored in MiscContainer"); return 0; @@ -861,6 +952,10 @@ nsAttrValue::Equals(const nsAttrValue& aOther) const MiscContainer* thisCont = GetMiscContainer(); MiscContainer* otherCont = aOther.GetMiscContainer(); + if (thisCont == otherCont) { + return true; + } + if (thisCont->mType != otherCont->mType) { return false; } @@ -870,50 +965,50 @@ nsAttrValue::Equals(const nsAttrValue& aOther) const switch (thisCont->mType) { case eInteger: { - if (thisCont->mInteger == otherCont->mInteger) { + if (thisCont->mValue.mInteger == otherCont->mValue.mInteger) { needsStringComparison = true; } break; } case eEnum: { - if (thisCont->mEnumValue == otherCont->mEnumValue) { + if (thisCont->mValue.mEnumValue == otherCont->mValue.mEnumValue) { needsStringComparison = true; } break; } case ePercent: { - if (thisCont->mPercent == otherCont->mPercent) { + if (thisCont->mValue.mPercent == otherCont->mValue.mPercent) { needsStringComparison = true; } break; } case eColor: { - if (thisCont->mColor == otherCont->mColor) { + if (thisCont->mValue.mColor == otherCont->mValue.mColor) { needsStringComparison = true; } break; } case eCSSStyleRule: { - return thisCont->mCSSStyleRule == otherCont->mCSSStyleRule; + return thisCont->mValue.mCSSStyleRule == otherCont->mValue.mCSSStyleRule; } case eURL: { - return thisCont->mURL == otherCont->mURL; + return thisCont->mValue.mURL == otherCont->mValue.mURL; } case eImage: { - return thisCont->mImage == otherCont->mImage; + return thisCont->mValue.mImage == otherCont->mValue.mImage; } case eAtomArray: { // For classlists we could be insensitive to order, however // classlists are never mapped attributes so they are never compared. - if (!(*thisCont->mAtomArray == *otherCont->mAtomArray)) { + if (!(*thisCont->mValue.mAtomArray == *otherCont->mValue.mAtomArray)) { return false; } @@ -926,7 +1021,7 @@ nsAttrValue::Equals(const nsAttrValue& aOther) const } case eIntMarginValue: { - return thisCont->mIntMargin == otherCont->mIntMargin; + return thisCont->mValue.mIntMargin == otherCont->mValue.mIntMargin; } default: { @@ -1243,33 +1338,31 @@ nsAttrValue::SetIntValueAndType(int32_t aValue, ValueType aType, { if (aStringValue || aValue > NS_ATTRVALUE_INTEGERTYPE_MAXVALUE || aValue < NS_ATTRVALUE_INTEGERTYPE_MINVALUE) { - if (EnsureEmptyMiscContainer()) { - MiscContainer* cont = GetMiscContainer(); - switch (aType) { - case eInteger: - { - cont->mInteger = aValue; - break; - } - case ePercent: - { - cont->mPercent = aValue; - break; - } - case eEnum: - { - cont->mEnumValue = aValue; - break; - } - default: - { - NS_NOTREACHED("unknown integer type"); - break; - } + MiscContainer* cont = EnsureEmptyMiscContainer(); + switch (aType) { + case eInteger: + { + cont->mValue.mInteger = aValue; + break; + } + case ePercent: + { + cont->mValue.mPercent = aValue; + break; + } + case eEnum: + { + cont->mValue.mEnumValue = aValue; + break; + } + default: + { + NS_NOTREACHED("unknown integer type"); + break; } - cont->mType = aType; - SetMiscAtomOrString(aStringValue); } + cont->mType = aType; + SetMiscAtomOrString(aStringValue); } else { NS_ASSERTION(!mBits, "Reset before calling SetIntValueAndType!"); mBits = (aValue * NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER) | aType; @@ -1438,13 +1531,8 @@ nsAttrValue::SetColorValue(nscolor aColor, const nsAString& aString) return; } - if (!EnsureEmptyMiscContainer()) { - buf->Release(); - return; - } - - MiscContainer* cont = GetMiscContainer(); - cont->mColor = aColor; + MiscContainer* cont = EnsureEmptyMiscContainer(); + cont->mValue.mColor = aColor; cont->mType = eColor; // Save the literal string we were passed for round-tripping. @@ -1505,17 +1593,14 @@ bool nsAttrValue::ParseDoubleValue(const nsAString& aString) if (NS_FAILED(ec)) { return false; } - if (EnsureEmptyMiscContainer()) { - MiscContainer* cont = GetMiscContainer(); - cont->mDoubleValue = val; - cont->mType = eDoubleValue; - nsAutoString serializedFloat; - serializedFloat.AppendFloat(val); - SetMiscAtomOrString(serializedFloat.Equals(aString) ? nullptr : &aString); - return true; - } - return false; + MiscContainer* cont = EnsureEmptyMiscContainer(); + cont->mDoubleValue = val; + cont->mType = eDoubleValue; + nsAutoString serializedFloat; + serializedFloat.AppendFloat(val); + SetMiscAtomOrString(serializedFloat.Equals(aString) ? nullptr : &aString); + return true; } bool @@ -1527,15 +1612,11 @@ nsAttrValue::ParseIntMarginValue(const nsAString& aString) if (!nsContentUtils::ParseIntMarginValue(aString, margins)) return false; - if (EnsureEmptyMiscContainer()) { - MiscContainer* cont = GetMiscContainer(); - cont->mIntMargin = new nsIntMargin(margins); - cont->mType = eIntMarginValue; - SetMiscAtomOrString(&aString); - return true; - } - - return false; + MiscContainer* cont = EnsureEmptyMiscContainer(); + cont->mValue.mIntMargin = new nsIntMargin(margins); + cont->mType = eIntMarginValue; + SetMiscAtomOrString(&aString); + return true; } void @@ -1553,17 +1634,65 @@ nsAttrValue::LoadImage(nsIDocument* aDocument) #endif MiscContainer* cont = GetMiscContainer(); - mozilla::css::URLValue* url = cont->mURL; + mozilla::css::URLValue* url = cont->mValue.mURL; mozilla::css::ImageValue* image = new css::ImageValue(url->GetURI(), url->mString, url->mReferrer, url->mOriginPrincipal, aDocument); NS_ADDREF(image); - cont->mImage = image; + cont->mValue.mImage = image; NS_RELEASE(url); cont->mType = eImage; } +bool +nsAttrValue::ParseStyleAttribute(const nsAString& aString, + nsStyledElementNotElementCSSInlineStyle* aElement) +{ + nsIDocument* ownerDoc = aElement->OwnerDoc(); + nsHTMLCSSStyleSheet* sheet = ownerDoc->GetInlineStyleSheet(); + nsCOMPtr baseURI = aElement->GetBaseURI(); + nsIURI* docURI = ownerDoc->GetDocumentURI(); + + NS_ASSERTION(aElement->NodePrincipal() == ownerDoc->NodePrincipal(), + "This is unexpected"); + + // If the (immutable) document URI does not match the element's base URI + // (the common case is that they do match) do not cache the rule. This is + // because the results of the CSS parser are dependent on these URIs, and we + // do not want to have to account for the URIs in the hash lookup. + bool cachingAllowed = sheet && baseURI == docURI; + if (cachingAllowed) { + MiscContainer* cont = sheet->LookupStyleAttr(aString); + if (cont) { + // Set our MiscContainer to the cached one. + NS_ADDREF(cont); + SetPtrValueAndType(cont, eOtherBase); + return true; + } + } + + css::Loader* cssLoader = ownerDoc->CSSLoader(); + nsCSSParser cssParser(cssLoader); + + nsRefPtr rule; + cssParser.ParseStyleAttribute(aString, docURI, baseURI, + aElement->NodePrincipal(), + getter_AddRefs(rule)); + if (rule) { + rule->SetHTMLCSSStyleSheet(sheet); + SetTo(rule, &aString); + if (cachingAllowed) { + MiscContainer* cont = GetMiscContainer(); + cont->Cache(); + } + + return true; + } + + return false; +} + void nsAttrValue::SetMiscAtomOrString(const nsAString* aValue) { @@ -1615,71 +1744,90 @@ void nsAttrValue::SetSVGType(ValueType aType, const void* aValue, const nsAString* aSerialized) { NS_ABORT_IF_FALSE(IsSVGType(aType), "Not an SVG type"); - if (EnsureEmptyMiscContainer()) { - MiscContainer* cont = GetMiscContainer(); - // All SVG types are just pointers to classes so just setting any of them - // will do. We'll lose type-safety but the signature of the calling - // function should ensure we don't get anything unexpected, and once we - // stick aValue in a union we lose type information anyway. - cont->mSVGAngle = static_cast(aValue); - cont->mType = aType; - SetMiscAtomOrString(aSerialized); - } + + MiscContainer* cont = EnsureEmptyMiscContainer(); + // All SVG types are just pointers to classes so just setting any of them + // will do. We'll lose type-safety but the signature of the calling + // function should ensure we don't get anything unexpected, and once we + // stick aValue in a union we lose type information anyway. + cont->mValue.mSVGAngle = static_cast(aValue); + cont->mType = aType; + SetMiscAtomOrString(aSerialized); } -bool -nsAttrValue::EnsureEmptyMiscContainer() +MiscContainer* +nsAttrValue::ClearMiscContainer() { - MiscContainer* cont; + MiscContainer* cont = nullptr; if (BaseType() == eOtherBase) { - ResetMiscAtomOrString(); cont = GetMiscContainer(); - switch (cont->mType) { - case eCSSStyleRule: - { - NS_RELEASE(cont->mCSSStyleRule); - break; - } - case eURL: - { - NS_RELEASE(cont->mURL); - break; - } - case eImage: - { - NS_RELEASE(cont->mImage); - break; - } - case eAtomArray: - { - delete cont->mAtomArray; - break; - } - case eIntMarginValue: - { - delete cont->mIntMargin; - break; - } - default: - { - break; + if (cont->IsRefCounted() && cont->mValue.mRefCount > 1) { + // This MiscContainer is shared, we need a new one. + NS_RELEASE(cont); + + cont = new MiscContainer; + SetPtrValueAndType(cont, eOtherBase); + } + else { + switch (cont->mType) { + case eCSSStyleRule: + { + MOZ_ASSERT(cont->mValue.mRefCount == 1); + cont->Release(); + cont->Evict(); + NS_RELEASE(cont->mValue.mCSSStyleRule); + break; + } + case eURL: + { + NS_RELEASE(cont->mValue.mURL); + break; + } + case eImage: + { + NS_RELEASE(cont->mValue.mImage); + break; + } + case eAtomArray: + { + delete cont->mValue.mAtomArray; + break; + } + case eIntMarginValue: + { + delete cont->mValue.mIntMargin; + break; + } + default: + { + break; + } } } + ResetMiscAtomOrString(); } else { ResetIfSet(); + } + return cont; +} + +MiscContainer* +nsAttrValue::EnsureEmptyMiscContainer() +{ + MiscContainer* cont = ClearMiscContainer(); + if (cont) { + MOZ_ASSERT(BaseType() == eOtherBase); + ResetMiscAtomOrString(); + cont = GetMiscContainer(); + } + else { cont = new MiscContainer; - NS_ENSURE_TRUE(cont, false); - SetPtrValueAndType(cont, eOtherBase); } - cont->mType = eColor; - cont->mStringBits = 0; - cont->mColor = 0; - - return true; + return cont; } bool @@ -1691,19 +1839,14 @@ nsAttrValue::EnsureEmptyAtomArray() return true; } - if (!EnsureEmptyMiscContainer()) { - // should already be reset - return false; - } - AtomArray* array = new AtomArray; if (!array) { Reset(); return false; } - MiscContainer* cont = GetMiscContainer(); - cont->mAtomArray = array; + MiscContainer* cont = EnsureEmptyMiscContainer(); + cont->mValue.mAtomArray = array; cont->mType = eAtomArray; return true; @@ -1834,13 +1977,13 @@ nsAttrValue::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const n += str ? str->SizeOfIncludingThisIfUnshared(aMallocSizeOf) : 0; } - if (Type() == eCSSStyleRule && container->mCSSStyleRule) { + if (Type() == eCSSStyleRule && container->mValue.mCSSStyleRule) { // TODO: mCSSStyleRule might be owned by another object which would // make us count them twice, bug 677493. //n += container->mCSSStyleRule->SizeOfIncludingThis(aMallocSizeOf); - } else if (Type() == eAtomArray && container->mAtomArray) { + } else if (Type() == eAtomArray && container->mValue.mAtomArray) { // Don't measure each nsIAtom, they are measured separatly. - n += container->mAtomArray->SizeOfIncludingThis(aMallocSizeOf); + n += container->mValue.mAtomArray->SizeOfIncludingThis(aMallocSizeOf); } break; } diff --git a/content/base/src/nsAttrValue.h b/content/base/src/nsAttrValue.h index 86ae9ebdcb64..30a7179afc24 100644 --- a/content/base/src/nsAttrValue.h +++ b/content/base/src/nsAttrValue.h @@ -26,6 +26,8 @@ class nsIAtom; class nsIDocument; template class nsTArray; struct nsTArrayDefaultAllocator; +class nsStyledElementNotElementCSSInlineStyle; +struct MiscContainer; namespace mozilla { namespace css { @@ -66,22 +68,10 @@ public: }; class nsAttrValue { + friend struct MiscContainer; public: typedef nsTArray< nsCOMPtr > AtomArray; - nsAttrValue(); - nsAttrValue(const nsAttrValue& aOther); - explicit nsAttrValue(const nsAString& aValue); - explicit nsAttrValue(nsIAtom* aValue); - nsAttrValue(mozilla::css::StyleRule* aValue, const nsAString* aSerialized); - explicit nsAttrValue(const nsIntMargin& aValue); - ~nsAttrValue(); - - inline const nsAttrValue& operator=(const nsAttrValue& aOther); - - static nsresult Init(); - static void Shutdown(); - // This has to be the same as in ValueBaseType enum ValueType { eString = 0x00, // 00 @@ -115,6 +105,19 @@ public: ,eSVGTypesEnd = 0x34 }; + nsAttrValue(); + nsAttrValue(const nsAttrValue& aOther); + explicit nsAttrValue(const nsAString& aValue); + explicit nsAttrValue(nsIAtom* aValue); + nsAttrValue(mozilla::css::StyleRule* aValue, const nsAString* aSerialized); + explicit nsAttrValue(const nsIntMargin& aValue); + ~nsAttrValue(); + + inline const nsAttrValue& operator=(const nsAttrValue& aOther); + + static nsresult Init(); + static void Shutdown(); + ValueType Type() const; void Reset(); @@ -357,6 +360,15 @@ public: */ void LoadImage(nsIDocument* aDocument); + /** + * Parse a string into a CSS style rule. + * + * @param aString the style attribute value to be parsed. + * @param aElement the element the attribute is set on. + */ + bool ParseStyleAttribute(const nsAString& aString, + nsStyledElementNotElementCSSInlineStyle* aElement); + size_t SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const; private: @@ -368,40 +380,6 @@ private: eIntegerBase = 0x03 // 11 }; - struct MiscContainer - { - ValueType mType; - // mStringBits points to either nsIAtom* or nsStringBuffer* and is used when - // mType isn't mCSSStyleRule. - // Note eStringBase and eAtomBase is used also to handle the type of - // mStringBits. - PtrBits mStringBits; - union { - int32_t mInteger; - nscolor mColor; - uint32_t mEnumValue; - int32_t mPercent; - mozilla::css::StyleRule* mCSSStyleRule; - mozilla::css::URLValue* mURL; - mozilla::css::ImageValue* mImage; - AtomArray* mAtomArray; - double mDoubleValue; - nsIntMargin* mIntMargin; - const nsSVGAngle* mSVGAngle; - const nsSVGIntegerPair* mSVGIntegerPair; - const nsSVGLength2* mSVGLength; - const mozilla::SVGLengthList* mSVGLengthList; - const mozilla::SVGNumberList* mSVGNumberList; - const nsSVGNumberPair* mSVGNumberPair; - const mozilla::SVGPathData* mSVGPathData; - const mozilla::SVGPointList* mSVGPointList; - const mozilla::SVGAnimatedPreserveAspectRatio* mSVGPreserveAspectRatio; - const mozilla::SVGStringList* mSVGStringList; - const mozilla::SVGTransformList* mSVGTransformList; - const nsSVGViewBox* mSVGViewBox; - }; - }; - inline ValueBaseType BaseType() const; inline bool IsSVGType(ValueType aType) const; @@ -428,7 +406,12 @@ private: inline MiscContainer* GetMiscContainer() const; inline int32_t GetIntInternal() const; - bool EnsureEmptyMiscContainer(); + // Clears the current MiscContainer. This will return null if there is no + // existing container. + MiscContainer* ClearMiscContainer(); + // Like ClearMiscContainer, except allocates a new container if one does not + // exist already. + MiscContainer* EnsureEmptyMiscContainer(); bool EnsureEmptyAtomArray(); nsStringBuffer* GetStringBuffer(const nsAString& aValue) const; // aStrict is set true if stringifying the return value equals with @@ -448,10 +431,6 @@ private: PtrBits mBits; }; -/** - * Implementation of inline methods - */ - inline const nsAttrValue& nsAttrValue::operator=(const nsAttrValue& aOther) { @@ -466,112 +445,12 @@ nsAttrValue::GetAtomValue() const return reinterpret_cast(GetPtr()); } -inline int32_t -nsAttrValue::GetIntegerValue() const -{ - NS_PRECONDITION(Type() == eInteger, "wrong type"); - return (BaseType() == eIntegerBase) - ? GetIntInternal() - : GetMiscContainer()->mInteger; -} - -inline int16_t -nsAttrValue::GetEnumValue() const -{ - NS_PRECONDITION(Type() == eEnum, "wrong type"); - // We don't need to worry about sign extension here since we're - // returning an int16_t which will cut away the top bits. - return static_cast(( - (BaseType() == eIntegerBase) - ? static_cast(GetIntInternal()) - : GetMiscContainer()->mEnumValue) - >> NS_ATTRVALUE_ENUMTABLEINDEX_BITS); -} - -inline float -nsAttrValue::GetPercentValue() const -{ - NS_PRECONDITION(Type() == ePercent, "wrong type"); - return ((BaseType() == eIntegerBase) - ? GetIntInternal() - : GetMiscContainer()->mPercent) - / 100.0f; -} - -inline nsAttrValue::AtomArray* -nsAttrValue::GetAtomArrayValue() const -{ - NS_PRECONDITION(Type() == eAtomArray, "wrong type"); - return GetMiscContainer()->mAtomArray; -} - -inline mozilla::css::StyleRule* -nsAttrValue::GetCSSStyleRuleValue() const -{ - NS_PRECONDITION(Type() == eCSSStyleRule, "wrong type"); - return GetMiscContainer()->mCSSStyleRule; -} - -inline mozilla::css::URLValue* -nsAttrValue::GetURLValue() const -{ - NS_PRECONDITION(Type() == eURL, "wrong type"); - return GetMiscContainer()->mURL; -} - -inline mozilla::css::ImageValue* -nsAttrValue::GetImageValue() const -{ - NS_PRECONDITION(Type() == eImage, "wrong type"); - return GetMiscContainer()->mImage; -} - -inline double -nsAttrValue::GetDoubleValue() const -{ - NS_PRECONDITION(Type() == eDoubleValue, "wrong type"); - return GetMiscContainer()->mDoubleValue; -} - -inline bool -nsAttrValue::GetIntMarginValue(nsIntMargin& aMargin) const -{ - NS_PRECONDITION(Type() == eIntMarginValue, "wrong type"); - nsIntMargin* m = GetMiscContainer()->mIntMargin; - if (!m) - return false; - aMargin = *m; - return true; -} - inline nsAttrValue::ValueBaseType nsAttrValue::BaseType() const { return static_cast(mBits & NS_ATTRVALUE_BASETYPE_MASK); } -inline bool -nsAttrValue::IsSVGType(ValueType aType) const -{ - return aType >= eSVGTypesBegin && aType <= eSVGTypesEnd; -} - -inline void -nsAttrValue::SetPtrValueAndType(void* aValue, ValueBaseType aType) -{ - NS_ASSERTION(!(NS_PTR_TO_INT32(aValue) & ~NS_ATTRVALUE_POINTERVALUE_MASK), - "pointer not properly aligned, this will crash"); - mBits = reinterpret_cast(aValue) | aType; -} - -inline void -nsAttrValue::ResetIfSet() -{ - if (mBits) { - Reset(); - } -} - inline void* nsAttrValue::GetPtr() const { @@ -580,25 +459,6 @@ nsAttrValue::GetPtr() const return reinterpret_cast(mBits & NS_ATTRVALUE_POINTERVALUE_MASK); } -inline nsAttrValue::MiscContainer* -nsAttrValue::GetMiscContainer() const -{ - NS_ASSERTION(BaseType() == eOtherBase, "wrong type"); - return static_cast(GetPtr()); -} - -inline int32_t -nsAttrValue::GetIntInternal() const -{ - NS_ASSERTION(BaseType() == eIntegerBase, - "getting integer from non-integer"); - // Make sure we get a signed value. - // Lets hope the optimizer optimizes this into a shift. Unfortunatly signed - // bitshift right is implementaion dependant. - return static_cast(mBits & ~NS_ATTRVALUE_INTEGERTYPE_MASK) / - NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER; -} - inline bool nsAttrValue::IsEmptyString() const { diff --git a/content/base/src/nsAttrValueInlines.h b/content/base/src/nsAttrValueInlines.h new file mode 100644 index 000000000000..160db93efc29 --- /dev/null +++ b/content/base/src/nsAttrValueInlines.h @@ -0,0 +1,216 @@ +/* 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 nsAttrValueInlines_h__ +#define nsAttrValueInlines_h__ + +struct MiscContainer +{ + typedef nsAttrValue::ValueType ValueType; + + ValueType mType; + // mStringBits points to either nsIAtom* or nsStringBuffer* and is used when + // mType isn't mCSSStyleRule. + // Note eStringBase and eAtomBase is used also to handle the type of + // mStringBits. + PtrBits mStringBits; + union { + struct { + union { + int32_t mInteger; + nscolor mColor; + uint32_t mEnumValue; + int32_t mPercent; + mozilla::css::StyleRule* mCSSStyleRule; + mozilla::css::URLValue* mURL; + mozilla::css::ImageValue* mImage; + nsAttrValue::AtomArray* mAtomArray; + nsIntMargin* mIntMargin; + const nsSVGAngle* mSVGAngle; + const nsSVGIntegerPair* mSVGIntegerPair; + const nsSVGLength2* mSVGLength; + const mozilla::SVGLengthList* mSVGLengthList; + const mozilla::SVGNumberList* mSVGNumberList; + const nsSVGNumberPair* mSVGNumberPair; + const mozilla::SVGPathData* mSVGPathData; + const mozilla::SVGPointList* mSVGPointList; + const mozilla::SVGAnimatedPreserveAspectRatio* mSVGPreserveAspectRatio; + const mozilla::SVGStringList* mSVGStringList; + const mozilla::SVGTransformList* mSVGTransformList; + const nsSVGViewBox* mSVGViewBox; + }; + uint32_t mRefCount : 31; + uint32_t mCached : 1; + } mValue; + double mDoubleValue; + }; + + MiscContainer() + : mType(nsAttrValue::eColor), + mStringBits(0) + { + MOZ_COUNT_CTOR(MiscContainer); + mValue.mColor = 0; + mValue.mRefCount = 0; + mValue.mCached = 0; + } + + ~MiscContainer() + { + if (IsRefCounted()) { + MOZ_ASSERT(mValue.mRefCount == 0); + MOZ_ASSERT(!mValue.mCached); + } + MOZ_COUNT_DTOR(MiscContainer); + } + + bool GetString(nsDependentString& aString) const; + + inline bool IsRefCounted() const + { + // Nothing stops us from refcounting (and sharing) other types of + // MiscContainer (except eDoubleValue types) but there's no compelling + // reason to + return mType == nsAttrValue::eCSSStyleRule; + } + + inline int32_t AddRef() { + MOZ_ASSERT(IsRefCounted()); + return ++mValue.mRefCount; + } + + inline int32_t Release() { + MOZ_ASSERT(IsRefCounted()); + return --mValue.mRefCount; + } + + void Cache(); + void Evict(); +}; + + +/** + * Implementation of inline methods + */ + +inline int32_t +nsAttrValue::GetIntegerValue() const +{ + NS_PRECONDITION(Type() == eInteger, "wrong type"); + return (BaseType() == eIntegerBase) + ? GetIntInternal() + : GetMiscContainer()->mValue.mInteger; +} + +inline int16_t +nsAttrValue::GetEnumValue() const +{ + NS_PRECONDITION(Type() == eEnum, "wrong type"); + // We don't need to worry about sign extension here since we're + // returning an int16_t which will cut away the top bits. + return static_cast(( + (BaseType() == eIntegerBase) + ? static_cast(GetIntInternal()) + : GetMiscContainer()->mValue.mEnumValue) + >> NS_ATTRVALUE_ENUMTABLEINDEX_BITS); +} + +inline float +nsAttrValue::GetPercentValue() const +{ + NS_PRECONDITION(Type() == ePercent, "wrong type"); + return ((BaseType() == eIntegerBase) + ? GetIntInternal() + : GetMiscContainer()->mValue.mPercent) + / 100.0f; +} + +inline nsAttrValue::AtomArray* +nsAttrValue::GetAtomArrayValue() const +{ + NS_PRECONDITION(Type() == eAtomArray, "wrong type"); + return GetMiscContainer()->mValue.mAtomArray; +} + +inline mozilla::css::StyleRule* +nsAttrValue::GetCSSStyleRuleValue() const +{ + NS_PRECONDITION(Type() == eCSSStyleRule, "wrong type"); + return GetMiscContainer()->mValue.mCSSStyleRule; +} + +inline mozilla::css::URLValue* +nsAttrValue::GetURLValue() const +{ + NS_PRECONDITION(Type() == eURL, "wrong type"); + return GetMiscContainer()->mValue.mURL; +} + +inline mozilla::css::ImageValue* +nsAttrValue::GetImageValue() const +{ + NS_PRECONDITION(Type() == eImage, "wrong type"); + return GetMiscContainer()->mValue.mImage; +} + +inline double +nsAttrValue::GetDoubleValue() const +{ + NS_PRECONDITION(Type() == eDoubleValue, "wrong type"); + return GetMiscContainer()->mDoubleValue; +} + +inline bool +nsAttrValue::GetIntMarginValue(nsIntMargin& aMargin) const +{ + NS_PRECONDITION(Type() == eIntMarginValue, "wrong type"); + nsIntMargin* m = GetMiscContainer()->mValue.mIntMargin; + if (!m) + return false; + aMargin = *m; + return true; +} + +inline bool +nsAttrValue::IsSVGType(ValueType aType) const +{ + return aType >= eSVGTypesBegin && aType <= eSVGTypesEnd; +} + +inline void +nsAttrValue::SetPtrValueAndType(void* aValue, ValueBaseType aType) +{ + NS_ASSERTION(!(NS_PTR_TO_INT32(aValue) & ~NS_ATTRVALUE_POINTERVALUE_MASK), + "pointer not properly aligned, this will crash"); + mBits = reinterpret_cast(aValue) | aType; +} + +inline void +nsAttrValue::ResetIfSet() +{ + if (mBits) { + Reset(); + } +} + +inline MiscContainer* +nsAttrValue::GetMiscContainer() const +{ + NS_ASSERTION(BaseType() == eOtherBase, "wrong type"); + return static_cast(GetPtr()); +} + +inline int32_t +nsAttrValue::GetIntInternal() const +{ + NS_ASSERTION(BaseType() == eIntegerBase, + "getting integer from non-integer"); + // Make sure we get a signed value. + // Lets hope the optimizer optimizes this into a shift. Unfortunatly signed + // bitshift right is implementaion dependant. + return static_cast(mBits & ~NS_ATTRVALUE_INTEGERTYPE_MASK) / + NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER; +} + +#endif diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index c8c4b6cfb34c..f01b5b5a6218 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -99,6 +99,7 @@ static NS_DEFINE_CID(kXTFServiceCID, NS_XTFSERVICE_CID); #include "nsDOMJSUtils.h" #include "nsGenericHTMLElement.h" #include "nsAttrValue.h" +#include "nsAttrValueInlines.h" #include "nsReferencedElement.h" #include "nsIDragService.h" #include "nsIChannelEventSink.h" diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 0b068a2b9346..68e21eafa76f 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -54,6 +54,7 @@ #include "mozilla/dom/DirectionalityUtils.h" #include "nsDocument.h" #include "nsAttrValueOrString.h" +#include "nsAttrValueInlines.h" #ifdef MOZ_XUL #include "nsXULElement.h" #endif /* MOZ_XUL */ diff --git a/content/base/src/nsStyledElement.cpp b/content/base/src/nsStyledElement.cpp index d78c9c094338..9b8f13417232 100644 --- a/content/base/src/nsStyledElement.cpp +++ b/content/base/src/nsStyledElement.cpp @@ -7,6 +7,7 @@ #include "nsStyledElement.h" #include "nsGkAtoms.h" #include "nsAttrValue.h" +#include "nsAttrValueInlines.h" #include "nsGenericElement.h" #include "nsMutationEvent.h" #include "nsDOMCSSDeclaration.h" @@ -251,21 +252,8 @@ nsStyledElementNotElementCSSInlineStyle::ParseStyleAttribute(const nsAString& aV } } - if (isCSS) { - css::Loader* cssLoader = doc->CSSLoader(); - nsCSSParser cssParser(cssLoader); - - nsCOMPtr baseURI = GetBaseURI(); - - nsRefPtr rule; - cssParser.ParseStyleAttribute(aValue, doc->GetDocumentURI(), - baseURI, - NodePrincipal(), - getter_AddRefs(rule)); - if (rule) { - aResult.SetTo(rule, &aValue); - return; - } + if (isCSS && aResult.ParseStyleAttribute(aValue, this)) { + return; } } diff --git a/content/html/content/src/nsFormSubmission.cpp b/content/html/content/src/nsFormSubmission.cpp index d4fc46333da1..11d62f0651ef 100644 --- a/content/html/content/src/nsFormSubmission.cpp +++ b/content/html/content/src/nsFormSubmission.cpp @@ -17,6 +17,7 @@ #include "nsIDOMHTMLFormElement.h" #include "nsError.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsISaveAsCharset.h" #include "nsIFile.h" #include "nsIDOMFile.h" diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 8d90df65f5b5..3be2dcffa898 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -8,6 +8,7 @@ #include "nscore.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsCOMPtr.h" #include "nsIAtom.h" #include "nsIContentViewer.h" diff --git a/content/html/content/src/nsHTMLBRElement.cpp b/content/html/content/src/nsHTMLBRElement.cpp index ae2273591bf5..e9c410352446 100644 --- a/content/html/content/src/nsHTMLBRElement.cpp +++ b/content/html/content/src/nsHTMLBRElement.cpp @@ -8,6 +8,7 @@ #include "nsIDOMHTMLBRElement.h" #include "nsIDOMEventTarget.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsMappedAttributes.h" diff --git a/content/html/content/src/nsHTMLBodyElement.cpp b/content/html/content/src/nsHTMLBodyElement.cpp index 95bb9937e519..fd85ac9a8162 100644 --- a/content/html/content/src/nsHTMLBodyElement.cpp +++ b/content/html/content/src/nsHTMLBodyElement.cpp @@ -9,6 +9,7 @@ #include "nsCOMPtr.h" #include "nsIDOMHTMLBodyElement.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsPresContext.h" @@ -21,7 +22,7 @@ #include "nsIDocShell.h" #include "nsIEditorDocShell.h" #include "nsRuleWalker.h" -#include "jsapi.h" +#include "jspubtd.h" //---------------------------------------------------------------------- diff --git a/content/html/content/src/nsHTMLButtonElement.cpp b/content/html/content/src/nsHTMLButtonElement.cpp index ee3f2a5e071f..3811d9a324e4 100644 --- a/content/html/content/src/nsHTMLButtonElement.cpp +++ b/content/html/content/src/nsHTMLButtonElement.cpp @@ -2,10 +2,12 @@ /* 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 "nsIDOMHTMLButtonElement.h" #include "nsIDOMHTMLFormElement.h" #include "nsIDOMEventTarget.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsIPresShell.h" #include "nsStyleConsts.h" diff --git a/content/html/content/src/nsHTMLCanvasElement.cpp b/content/html/content/src/nsHTMLCanvasElement.cpp index e37015241983..304bb39e2041 100644 --- a/content/html/content/src/nsHTMLCanvasElement.cpp +++ b/content/html/content/src/nsHTMLCanvasElement.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsHTMLCanvasElement.h" +#include "nsAttrValueInlines.h" #include "mozilla/Base64.h" #include "mozilla/CheckedInt.h" diff --git a/content/html/content/src/nsHTMLFontElement.cpp b/content/html/content/src/nsHTMLFontElement.cpp index f678d66b0c81..3a2491006d84 100644 --- a/content/html/content/src/nsHTMLFontElement.cpp +++ b/content/html/content/src/nsHTMLFontElement.cpp @@ -9,6 +9,7 @@ #include "nsIDOMHTMLFontElement.h" #include "nsIDOMEventTarget.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsPresContext.h" diff --git a/content/html/content/src/nsHTMLHRElement.cpp b/content/html/content/src/nsHTMLHRElement.cpp index b7e9480b5686..5b124ca3eed5 100644 --- a/content/html/content/src/nsHTMLHRElement.cpp +++ b/content/html/content/src/nsHTMLHRElement.cpp @@ -13,6 +13,7 @@ #include "nsStyleConsts.h" #include "nsPresContext.h" #include "nsMappedAttributes.h" +#include "nsAttrValueInlines.h" #include "nsRuleData.h" #include "nsCSSProps.h" diff --git a/content/html/content/src/nsHTMLIFrameElement.cpp b/content/html/content/src/nsHTMLIFrameElement.cpp index d8f711709ed4..54a0d9a4d016 100644 --- a/content/html/content/src/nsHTMLIFrameElement.cpp +++ b/content/html/content/src/nsHTMLIFrameElement.cpp @@ -8,6 +8,7 @@ #include "nsHTMLIFrameElement.h" #include "nsIDOMSVGDocument.h" #include "nsMappedAttributes.h" +#include "nsAttrValueInlines.h" #include "nsError.h" #include "nsRuleData.h" #include "nsStyleConsts.h" diff --git a/content/html/content/src/nsHTMLInputElement.cpp b/content/html/content/src/nsHTMLInputElement.cpp index eaae6297658d..2e8bdfe7c5fb 100644 --- a/content/html/content/src/nsHTMLInputElement.cpp +++ b/content/html/content/src/nsHTMLInputElement.cpp @@ -6,6 +6,7 @@ #include "mozilla/Util.h" #include "nsHTMLInputElement.h" +#include "nsAttrValueInlines.h" #include "nsIDOMHTMLInputElement.h" #include "nsITextControlElement.h" diff --git a/content/html/content/src/nsHTMLLIElement.cpp b/content/html/content/src/nsHTMLLIElement.cpp index 193e58d8233e..365902cc7dbc 100644 --- a/content/html/content/src/nsHTMLLIElement.cpp +++ b/content/html/content/src/nsHTMLLIElement.cpp @@ -8,6 +8,7 @@ #include "nsIDOMHTMLLIElement.h" #include "nsIDOMEventTarget.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsMappedAttributes.h" diff --git a/content/html/content/src/nsHTMLMediaElement.cpp b/content/html/content/src/nsHTMLMediaElement.cpp index 7895b536fb6a..aeb9617c7b20 100644 --- a/content/html/content/src/nsHTMLMediaElement.cpp +++ b/content/html/content/src/nsHTMLMediaElement.cpp @@ -12,6 +12,7 @@ #include "nsHTMLMediaElement.h" #include "nsTimeRanges.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsPresContext.h" #include "nsIPresShell.h" #include "nsGkAtoms.h" diff --git a/content/html/content/src/nsHTMLMenuElement.cpp b/content/html/content/src/nsHTMLMenuElement.cpp index 9734471304f6..9fc215c280be 100644 --- a/content/html/content/src/nsHTMLMenuElement.cpp +++ b/content/html/content/src/nsHTMLMenuElement.cpp @@ -4,7 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsHTMLMenuElement.h" - +#include "nsAttrValueInlines.h" #include "nsIDOMHTMLMenuItemElement.h" #include "nsXULContextMenuBuilder.h" #include "nsGUIEvent.h" diff --git a/content/html/content/src/nsHTMLMenuItemElement.cpp b/content/html/content/src/nsHTMLMenuItemElement.cpp index f132976f7237..8e2349780342 100644 --- a/content/html/content/src/nsHTMLMenuItemElement.cpp +++ b/content/html/content/src/nsHTMLMenuItemElement.cpp @@ -6,6 +6,7 @@ #include "nsGUIEvent.h" #include "nsEventDispatcher.h" #include "nsHTMLMenuItemElement.h" +#include "nsAttrValueInlines.h" #include "nsContentUtils.h" using namespace mozilla::dom; diff --git a/content/html/content/src/nsHTMLMeterElement.cpp b/content/html/content/src/nsHTMLMeterElement.cpp index 2446863551d1..ff49435922ac 100644 --- a/content/html/content/src/nsHTMLMeterElement.cpp +++ b/content/html/content/src/nsHTMLMeterElement.cpp @@ -6,6 +6,7 @@ #include "nsIDOMHTMLMeterElement.h" #include "nsGenericHTMLElement.h" #include "nsAttrValue.h" +#include "nsAttrValueInlines.h" #include "nsEventStateManager.h" #include "nsAlgorithm.h" diff --git a/content/html/content/src/nsHTMLOListElement.cpp b/content/html/content/src/nsHTMLOListElement.cpp index 7b27514eaf9f..3cab8f7cb440 100644 --- a/content/html/content/src/nsHTMLOListElement.cpp +++ b/content/html/content/src/nsHTMLOListElement.cpp @@ -10,6 +10,7 @@ #include "nsIDOMHTMLUListElement.h" #include "nsIDOMEventTarget.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsMappedAttributes.h" diff --git a/content/html/content/src/nsHTMLObjectElement.cpp b/content/html/content/src/nsHTMLObjectElement.cpp index 2fffea25456a..f7f9bb649f53 100644 --- a/content/html/content/src/nsHTMLObjectElement.cpp +++ b/content/html/content/src/nsHTMLObjectElement.cpp @@ -8,6 +8,7 @@ #include "nsAutoPtr.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsObjectLoadingContent.h" #include "nsGkAtoms.h" #include "nsError.h" diff --git a/content/html/content/src/nsHTMLPreElement.cpp b/content/html/content/src/nsHTMLPreElement.cpp index ebec88a556f1..b38ef0ee1808 100644 --- a/content/html/content/src/nsHTMLPreElement.cpp +++ b/content/html/content/src/nsHTMLPreElement.cpp @@ -8,6 +8,7 @@ #include "nsIDOMHTMLPreElement.h" #include "nsIDOMEventTarget.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsMappedAttributes.h" diff --git a/content/html/content/src/nsHTMLProgressElement.cpp b/content/html/content/src/nsHTMLProgressElement.cpp index aa51ff7bd98d..071232722692 100644 --- a/content/html/content/src/nsHTMLProgressElement.cpp +++ b/content/html/content/src/nsHTMLProgressElement.cpp @@ -6,6 +6,7 @@ #include "nsIDOMHTMLProgressElement.h" #include "nsGenericHTMLElement.h" #include "nsAttrValue.h" +#include "nsAttrValueInlines.h" #include "nsEventStateManager.h" diff --git a/content/html/content/src/nsHTMLSharedElement.cpp b/content/html/content/src/nsHTMLSharedElement.cpp index 53e724084443..e2cfda9e0496 100644 --- a/content/html/content/src/nsHTMLSharedElement.cpp +++ b/content/html/content/src/nsHTMLSharedElement.cpp @@ -12,6 +12,7 @@ #include "nsIDOMHTMLHeadElement.h" #include "nsIDOMHTMLHtmlElement.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" diff --git a/content/html/content/src/nsHTMLTableCaptionElement.cpp b/content/html/content/src/nsHTMLTableCaptionElement.cpp index 2112db742347..572e9f6c630b 100644 --- a/content/html/content/src/nsHTMLTableCaptionElement.cpp +++ b/content/html/content/src/nsHTMLTableCaptionElement.cpp @@ -8,6 +8,7 @@ #include "nsIDOMHTMLTableCaptionElem.h" #include "nsIDOMEventTarget.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsMappedAttributes.h" diff --git a/content/html/content/src/nsHTMLTableCellElement.cpp b/content/html/content/src/nsHTMLTableCellElement.cpp index 477b397099da..9ce90ca6dc30 100644 --- a/content/html/content/src/nsHTMLTableCellElement.cpp +++ b/content/html/content/src/nsHTMLTableCellElement.cpp @@ -12,6 +12,7 @@ #include "nsIDOMEventTarget.h" #include "nsMappedAttributes.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsPresContext.h" diff --git a/content/html/content/src/nsHTMLTableColElement.cpp b/content/html/content/src/nsHTMLTableColElement.cpp index caaa3f8e4df4..13436ec6107e 100644 --- a/content/html/content/src/nsHTMLTableColElement.cpp +++ b/content/html/content/src/nsHTMLTableColElement.cpp @@ -9,6 +9,7 @@ #include "nsIDOMEventTarget.h" #include "nsMappedAttributes.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsRuleData.h" diff --git a/content/html/content/src/nsHTMLTableElement.cpp b/content/html/content/src/nsHTMLTableElement.cpp index ac5a6f0ce4af..0b6fc68d5ba2 100644 --- a/content/html/content/src/nsHTMLTableElement.cpp +++ b/content/html/content/src/nsHTMLTableElement.cpp @@ -13,6 +13,7 @@ #include "nsError.h" #include "nsContentList.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsPresContext.h" diff --git a/content/html/content/src/nsHTMLTableRowElement.cpp b/content/html/content/src/nsHTMLTableRowElement.cpp index 673344084a32..c362621b7a45 100644 --- a/content/html/content/src/nsHTMLTableRowElement.cpp +++ b/content/html/content/src/nsHTMLTableRowElement.cpp @@ -13,6 +13,7 @@ #include "nsError.h" #include "nsMappedAttributes.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsContentList.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" diff --git a/content/html/content/src/nsHTMLTableSectionElement.cpp b/content/html/content/src/nsHTMLTableSectionElement.cpp index 8c6f232a2f0f..e42cae49bfaf 100644 --- a/content/html/content/src/nsHTMLTableSectionElement.cpp +++ b/content/html/content/src/nsHTMLTableSectionElement.cpp @@ -9,6 +9,7 @@ #include "nsIDOMEventTarget.h" #include "nsMappedAttributes.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsHTMLParts.h" #include "nsStyleConsts.h" diff --git a/content/html/content/src/nsHTMLTextAreaElement.cpp b/content/html/content/src/nsHTMLTextAreaElement.cpp index 205a91701862..a3bfdddbe3b6 100644 --- a/content/html/content/src/nsHTMLTextAreaElement.cpp +++ b/content/html/content/src/nsHTMLTextAreaElement.cpp @@ -21,6 +21,7 @@ #include "nsFormSubmission.h" #include "nsIDOMEventTarget.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" #include "nsPresContext.h" diff --git a/content/html/content/src/nsTextEditorState.cpp b/content/html/content/src/nsTextEditorState.cpp index 4587701e36d0..d8e3e8eeb542 100644 --- a/content/html/content/src/nsTextEditorState.cpp +++ b/content/html/content/src/nsTextEditorState.cpp @@ -24,6 +24,7 @@ #include "nsITransactionManager.h" #include "nsIControllerContext.h" #include "nsAttrValue.h" +#include "nsAttrValueInlines.h" #include "nsGenericHTMLElement.h" #include "nsIDOMEventListener.h" #include "EditActionListener.h" diff --git a/content/smil/nsSMILAnimationFunction.cpp b/content/smil/nsSMILAnimationFunction.cpp index 7bd2c1decd68..ad57fa82e0ec 100644 --- a/content/smil/nsSMILAnimationFunction.cpp +++ b/content/smil/nsSMILAnimationFunction.cpp @@ -9,6 +9,7 @@ #include "nsSMILNullType.h" #include "nsISMILAnimationElement.h" #include "nsSMILTimedElement.h" +#include "nsAttrValueInlines.h" #include "nsGkAtoms.h" #include "nsCOMPtr.h" #include "nsCOMArray.h" diff --git a/content/smil/nsSMILTimedElement.cpp b/content/smil/nsSMILTimedElement.cpp index c69e707f0127..442f6696662e 100644 --- a/content/smil/nsSMILTimedElement.cpp +++ b/content/smil/nsSMILTimedElement.cpp @@ -4,6 +4,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "nsSMILTimedElement.h" +#include "nsAttrValueInlines.h" #include "nsSMILAnimationFunction.h" #include "nsSMILTimeValue.h" #include "nsSMILTimeValueSpec.h" diff --git a/content/svg/content/src/DOMSVGTransform.cpp b/content/svg/content/src/DOMSVGTransform.cpp index d016324c88af..86520ff3ad8c 100644 --- a/content/svg/content/src/DOMSVGTransform.cpp +++ b/content/svg/content/src/DOMSVGTransform.cpp @@ -10,6 +10,7 @@ #include "nsError.h" #include #include "nsContentUtils.h" +#include "nsAttrValueInlines.h" namespace mozilla { diff --git a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp index 03f29a4044da..3905700335b4 100644 --- a/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp +++ b/content/svg/content/src/SVGAnimatedPreserveAspectRatio.cpp @@ -9,6 +9,7 @@ #include "nsWhitespaceTokenizer.h" #include "nsSMILValue.h" #include "SMILEnumType.h" +#include "nsAttrValueInlines.h" using namespace mozilla; diff --git a/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp b/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp index 725ab59f976a..b91030c4f8c3 100644 --- a/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp +++ b/content/svg/content/src/SVGMotionSMILAnimationFunction.cpp @@ -12,6 +12,7 @@ #include "nsSVGPathDataParser.h" #include "nsSVGPathElement.h" // for nsSVGPathList #include "nsSVGMpathElement.h" +#include "nsAttrValueInlines.h" namespace mozilla { diff --git a/content/svg/content/src/nsSVGAngle.cpp b/content/svg/content/src/nsSVGAngle.cpp index c7f921453dd7..e04fbf3c8f2c 100644 --- a/content/svg/content/src/nsSVGAngle.cpp +++ b/content/svg/content/src/nsSVGAngle.cpp @@ -13,6 +13,7 @@ #include "nsContentUtils.h" // NS_ENSURE_FINITE #include "nsSMILValue.h" #include "SVGOrientSMILType.h" +#include "nsAttrValueInlines.h" #include "mozilla/Attributes.h" using namespace mozilla; diff --git a/content/svg/content/src/nsSVGLength2.cpp b/content/svg/content/src/nsSVGLength2.cpp index 80019cf2ae32..56d543463e03 100644 --- a/content/svg/content/src/nsSVGLength2.cpp +++ b/content/svg/content/src/nsSVGLength2.cpp @@ -15,6 +15,7 @@ #include "nsContentUtils.h" // NS_ENSURE_FINITE #include "nsSMILValue.h" #include "nsSMILFloatType.h" +#include "nsAttrValueInlines.h" using namespace mozilla; diff --git a/content/svg/content/src/nsSVGViewBox.cpp b/content/svg/content/src/nsSVGViewBox.cpp index 93d38c320f1f..b03be04ee642 100644 --- a/content/svg/content/src/nsSVGViewBox.cpp +++ b/content/svg/content/src/nsSVGViewBox.cpp @@ -11,6 +11,7 @@ #include "nsSMILValue.h" #include "SVGContentUtils.h" #include "SVGViewBoxSMILType.h" +#include "nsAttrValueInlines.h" #define NUM_VIEWBOX_COMPONENTS 4 using namespace mozilla; diff --git a/content/xul/content/src/nsXULElement.cpp b/content/xul/content/src/nsXULElement.cpp index e0a198fe21d8..260e0ec358d8 100644 --- a/content/xul/content/src/nsXULElement.cpp +++ b/content/xul/content/src/nsXULElement.cpp @@ -87,6 +87,7 @@ #include "rdf.h" #include "nsIControllers.h" #include "nsAttrValueOrString.h" +#include "nsAttrValueInlines.h" #include "mozilla/Attributes.h" // The XUL doc interface diff --git a/dom/base/nsFocusManager.cpp b/dom/base/nsFocusManager.cpp index c7e0ef50f13d..29c7a497910d 100644 --- a/dom/base/nsFocusManager.cpp +++ b/dom/base/nsFocusManager.cpp @@ -24,7 +24,6 @@ #include "nsIDOMDocument.h" #include "nsIDOMRange.h" #include "nsIHTMLDocument.h" -#include "nsGenericHTMLElement.h" #include "nsIDocShell.h" #include "nsIEditorDocShell.h" #include "nsIDocShellTreeItem.h" diff --git a/dom/bindings/Makefile.in b/dom/bindings/Makefile.in index 69fe4be4e9b0..1dd733774c64 100644 --- a/dom/bindings/Makefile.in +++ b/dom/bindings/Makefile.in @@ -6,7 +6,6 @@ DEPTH = @DEPTH@ topsrcdir = @top_srcdir@ srcdir = @srcdir@ VPATH = @srcdir@ -FAIL_ON_WARNINGS := 1 MODULE = dom LIBRARY_NAME = dombindings_s diff --git a/dom/media/MediaManager.cpp b/dom/media/MediaManager.cpp index a37dbcf852ea..0350192f5c78 100644 --- a/dom/media/MediaManager.cpp +++ b/dom/media/MediaManager.cpp @@ -475,7 +475,7 @@ public: { NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread"); - uint32_t audioCount, videoCount, total, i; + uint32_t audioCount, videoCount, i; MediaManager* manager = MediaManager::Get(); nsTArray > videoSources; @@ -486,8 +486,6 @@ public: manager->GetBackend()->EnumerateAudioDevices(&audioSources); audioCount = videoSources.Length(); - total = videoCount + audioCount; - nsTArray > *devices = new nsTArray >; diff --git a/layout/forms/nsLegendFrame.cpp b/layout/forms/nsLegendFrame.cpp index 0dac02dcb143..6abe1ed0a0c4 100644 --- a/layout/forms/nsLegendFrame.cpp +++ b/layout/forms/nsLegendFrame.cpp @@ -7,6 +7,7 @@ #include "nsIContent.h" #include "nsIAtom.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsHTMLParts.h" #include "nsGkAtoms.h" #include "nsStyleConsts.h" diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index 984a5a15d138..b31402be8ca1 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -70,6 +70,7 @@ #include "nsTextEditRules.h" #include "nsPresState.h" #include "nsContentList.h" +#include "nsAttrValueInlines.h" #include "mozilla/Selection.h" diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index b7986540c96c..fe35f45b7243 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -28,6 +28,7 @@ #include "nsGkAtoms.h" #include "nsIDOMEvent.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "prprf.h" #include "nsStyleChangeList.h" #include "nsFrameSelection.h" diff --git a/layout/generic/nsBulletFrame.cpp b/layout/generic/nsBulletFrame.cpp index 6d4fd9ef2f12..68b2dafbfc0f 100644 --- a/layout/generic/nsBulletFrame.cpp +++ b/layout/generic/nsBulletFrame.cpp @@ -11,6 +11,7 @@ #include "nsHTMLParts.h" #include "nsContainerFrame.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsPresContext.h" #include "nsIPresShell.h" #include "nsIDocument.h" diff --git a/layout/generic/nsFrameSetFrame.cpp b/layout/generic/nsFrameSetFrame.cpp index 49746e728d90..d476a2201187 100644 --- a/layout/generic/nsFrameSetFrame.cpp +++ b/layout/generic/nsFrameSetFrame.cpp @@ -8,6 +8,7 @@ #include "nsCOMPtr.h" #include "nsFrameSetFrame.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsLeafFrame.h" #include "nsContainerFrame.h" #include "nsPresContext.h" diff --git a/layout/generic/nsSubDocumentFrame.cpp b/layout/generic/nsSubDocumentFrame.cpp index 47815a653165..a76fe5d8eb17 100644 --- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -13,6 +13,7 @@ #include "nsSubDocumentFrame.h" #include "nsCOMPtr.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsIDocShell.h" #include "nsIDocShellLoadInfo.h" #include "nsIDocShellTreeItem.h" diff --git a/layout/style/Rule.h b/layout/style/Rule.h index a0bf02f93f87..99d35b0f5079 100644 --- a/layout/style/Rule.h +++ b/layout/style/Rule.h @@ -16,6 +16,7 @@ class nsIStyleSheet; class nsIDocument; struct nsRuleData; template struct already_AddRefed; +class nsHTMLCSSStyleSheet; namespace mozilla { namespace css { @@ -31,7 +32,7 @@ virtual nsIDOMCSSRule* GetDOMRule(); class Rule : public nsIStyleRule { protected: Rule() - : mSheet(nullptr), + : mSheet(0), mParentRule(nullptr) { } @@ -75,7 +76,8 @@ public: virtual int32_t GetType() const = 0; - nsCSSStyleSheet* GetStyleSheet() const { return mSheet; } + nsCSSStyleSheet* GetStyleSheet() const; + nsHTMLCSSStyleSheet* GetHTMLCSSStyleSheet() const; // Return the document the rule lives in, if any nsIDocument* GetDocument() const @@ -85,6 +87,9 @@ public: } virtual void SetStyleSheet(nsCSSStyleSheet* aSheet); + // This does not need to be virtual, because GroupRule and MediaRule are not + // used for inline style. + void SetHTMLCSSStyleSheet(nsHTMLCSSStyleSheet* aSheet); void SetParentRule(GroupRule* aRule) { // We don't reference count this up reference. The group rule @@ -117,7 +122,9 @@ public: void* aData); protected: - nsCSSStyleSheet* mSheet; + // This is either an nsCSSStyleSheet* or a nsHTMLStyleSheet*. The former + // if the low bit is 0, the latter if the low bit is 1. + uintptr_t mSheet; GroupRule* mParentRule; }; diff --git a/layout/style/StyleRule.cpp b/layout/style/StyleRule.cpp index e36e88ea36fc..6807247d895e 100644 --- a/layout/style/StyleRule.cpp +++ b/layout/style/StyleRule.cpp @@ -1394,7 +1394,7 @@ StyleRule::Clone() const /* virtual */ nsIDOMCSSRule* StyleRule::GetDOMRule() { - if (!mSheet) { + if (!GetStyleSheet()) { // inline style rules aren't supposed to have a DOM rule object, only // a declaration. return nullptr; @@ -1418,14 +1418,15 @@ StyleRule::DeclarationChanged(Declaration* aDecl, NS_ADDREF(clone); // for return if (aHandleContainer) { + nsCSSStyleSheet* sheet = GetStyleSheet(); if (mParentRule) { - if (mSheet) { - mSheet->ReplaceRuleInGroup(mParentRule, this, clone); + if (sheet) { + sheet->ReplaceRuleInGroup(mParentRule, this, clone); } else { mParentRule->ReplaceStyleRule(this, clone); } - } else if (mSheet) { - mSheet->ReplaceStyleRule(this, clone); + } else if (sheet) { + sheet->ReplaceStyleRule(this, clone); } } @@ -1449,7 +1450,7 @@ StyleRule::List(FILE* out, int32_t aIndent) const nsAutoString buffer; if (mSelector) - mSelector->ToString(buffer, mSheet); + mSelector->ToString(buffer, GetStyleSheet()); buffer.AppendLiteral(" "); fputs(NS_LossyConvertUTF16toASCII(buffer).get(), out); @@ -1467,7 +1468,7 @@ void StyleRule::GetCssText(nsAString& aCssText) { if (mSelector) { - mSelector->ToString(aCssText, mSheet); + mSelector->ToString(aCssText, GetStyleSheet()); aCssText.Append(PRUnichar(' ')); } aCssText.Append(PRUnichar('{')); @@ -1492,7 +1493,7 @@ void StyleRule::GetSelectorText(nsAString& aSelectorText) { if (mSelector) - mSelector->ToString(aSelectorText, mSheet); + mSelector->ToString(aSelectorText, GetStyleSheet()); else aSelectorText.Truncate(); } diff --git a/layout/style/nsCSSRuleProcessor.cpp b/layout/style/nsCSSRuleProcessor.cpp index cdbfaea3f19e..286840f91d09 100644 --- a/layout/style/nsCSSRuleProcessor.cpp +++ b/layout/style/nsCSSRuleProcessor.cpp @@ -42,6 +42,7 @@ #include "nsStyleUtil.h" #include "nsQuickSort.h" #include "nsAttrValue.h" +#include "nsAttrValueInlines.h" #include "nsAttrName.h" #include "nsServiceManagerUtils.h" #include "nsTArray.h" diff --git a/layout/style/nsCSSRules.cpp b/layout/style/nsCSSRules.cpp index 3076124ddd19..430db883e544 100644 --- a/layout/style/nsCSSRules.cpp +++ b/layout/style/nsCSSRules.cpp @@ -58,13 +58,43 @@ namespace css { NS_IMPL_ADDREF(Rule) NS_IMPL_RELEASE(Rule) +nsCSSStyleSheet* +Rule::GetStyleSheet() const +{ + if (!(mSheet & 0x1)) { + return reinterpret_cast(mSheet); + } + + return nullptr; +} + +nsHTMLCSSStyleSheet* +Rule::GetHTMLCSSStyleSheet() const +{ + if (mSheet & 0x1) { + return reinterpret_cast(mSheet & ~uintptr_t(0x1)); + } + + return nullptr; +} + /* virtual */ void Rule::SetStyleSheet(nsCSSStyleSheet* aSheet) { // We don't reference count this up reference. The style sheet // will tell us when it's going away or when we're detached from // it. - mSheet = aSheet; + mSheet = reinterpret_cast(aSheet); +} + +void +Rule::SetHTMLCSSStyleSheet(nsHTMLCSSStyleSheet* aSheet) +{ + // We don't reference count this up reference. The style sheet + // will tell us when it's going away or when we're detached from + // it. + mSheet = reinterpret_cast(aSheet); + mSheet |= 0x1; } nsresult @@ -83,7 +113,7 @@ Rule::GetParentStyleSheet(nsIDOMCSSStyleSheet** aSheet) { NS_ENSURE_ARG_POINTER(aSheet); - NS_IF_ADDREF(*aSheet = mSheet); + NS_IF_ADDREF(*aSheet = GetStyleSheet()); return NS_OK; } @@ -571,10 +601,11 @@ void GroupRule::AppendStyleRule(Rule* aRule) { mRules.AppendObject(aRule); - aRule->SetStyleSheet(mSheet); + nsCSSStyleSheet* sheet = GetStyleSheet(); + aRule->SetStyleSheet(sheet); aRule->SetParentRule(this); - if (mSheet) { - mSheet->SetModifiedByChildRule(); + if (sheet) { + sheet->SetModifiedByChildRule(); } } @@ -612,7 +643,7 @@ nsresult GroupRule::InsertStyleRulesAt(uint32_t aIndex, nsCOMArray& aRules) { - aRules.EnumerateForwards(SetStyleSheetReference, mSheet); + aRules.EnumerateForwards(SetStyleSheetReference, GetStyleSheet()); aRules.EnumerateForwards(SetParentRuleReference, this); if (! mRules.InsertObjectsAt(aRules, aIndex)) { return NS_ERROR_FAILURE; @@ -626,7 +657,7 @@ GroupRule::ReplaceStyleRule(Rule* aOld, Rule* aNew) int32_t index = mRules.IndexOf(aOld); NS_ENSURE_TRUE(index != -1, NS_ERROR_UNEXPECTED); mRules.ReplaceObjectAt(aNew, index); - aNew->SetStyleSheet(mSheet); + aNew->SetStyleSheet(GetStyleSheet()); aNew->SetParentRule(this); aOld->SetStyleSheet(nullptr); aOld->SetParentRule(nullptr); @@ -671,7 +702,8 @@ GroupRule::GetCssRules(nsIDOMCSSRuleList* *aRuleList) nsresult GroupRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retval) { - NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); + nsCSSStyleSheet* sheet = GetStyleSheet(); + NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE); if (aIndex > uint32_t(mRules.Count())) return NS_ERROR_DOM_INDEX_SIZE_ERR; @@ -679,13 +711,14 @@ GroupRule::InsertRule(const nsAString & aRule, uint32_t aIndex, uint32_t* _retva NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX, "Too many style rules!"); - return mSheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval); + return sheet->InsertRuleIntoGroup(aRule, this, aIndex, _retval); } nsresult GroupRule::DeleteRule(uint32_t aIndex) { - NS_ENSURE_TRUE(mSheet, NS_ERROR_FAILURE); + nsCSSStyleSheet* sheet = GetStyleSheet(); + NS_ENSURE_TRUE(sheet, NS_ERROR_FAILURE); if (aIndex >= uint32_t(mRules.Count())) return NS_ERROR_DOM_INDEX_SIZE_ERR; @@ -693,7 +726,7 @@ GroupRule::DeleteRule(uint32_t aIndex) NS_ASSERTION(uint32_t(mRules.Count()) <= INT32_MAX, "Too many style rules!"); - return mSheet->DeleteRuleFromGroup(this, aIndex); + return sheet->DeleteRuleFromGroup(this, aIndex); } /* virtual */ size_t @@ -722,7 +755,7 @@ MediaRule::MediaRule(const MediaRule& aCopy) aCopy.mMedia->Clone(getter_AddRefs(mMedia)); if (mMedia) { // XXXldb This doesn't really make sense. - mMedia->SetStyleSheet(aCopy.mSheet); + mMedia->SetStyleSheet(aCopy.GetStyleSheet()); } } } @@ -796,7 +829,7 @@ MediaRule::SetMedia(nsMediaList* aMedia) { mMedia = aMedia; if (aMedia) - mMedia->SetStyleSheet(mSheet); + mMedia->SetStyleSheet(GetStyleSheet()); return NS_OK; } @@ -2000,8 +2033,9 @@ nsCSSKeyframeRule::SetKeyText(const nsAString& aKeyText) // for now, we don't do anything if the parse fails } - if (mSheet) { - mSheet->SetModifiedByChildRule(); + nsCSSStyleSheet* sheet = GetStyleSheet(); + if (sheet) { + sheet->SetModifiedByChildRule(); } return NS_OK; @@ -2026,8 +2060,9 @@ nsCSSKeyframeRule::ChangeDeclaration(css::Declaration* aDeclaration) mDeclaration = aDeclaration; } - if (mSheet) { - mSheet->SetModifiedByChildRule(); + nsCSSStyleSheet* sheet = GetStyleSheet(); + if (sheet) { + sheet->SetModifiedByChildRule(); } } @@ -2150,8 +2185,9 @@ nsCSSKeyframesRule::SetName(const nsAString& aName) { mName = aName; - if (mSheet) { - mSheet->SetModifiedByChildRule(); + nsCSSStyleSheet* sheet = GetStyleSheet(); + if (sheet) { + sheet->SetModifiedByChildRule(); } return NS_OK; @@ -2212,8 +2248,9 @@ nsCSSKeyframesRule::DeleteRule(const nsAString& aKey) uint32_t index = FindRuleIndexForKey(aKey); if (index != RULE_NOT_FOUND) { mRules.RemoveObjectAt(index); - if (mSheet) { - mSheet->SetModifiedByChildRule(); + nsCSSStyleSheet* sheet = GetStyleSheet(); + if (sheet) { + sheet->SetModifiedByChildRule(); } } return NS_OK; diff --git a/layout/style/nsHTMLCSSStyleSheet.cpp b/layout/style/nsHTMLCSSStyleSheet.cpp index 2fdde7744e16..fa2414498d26 100644 --- a/layout/style/nsHTMLCSSStyleSheet.cpp +++ b/layout/style/nsHTMLCSSStyleSheet.cpp @@ -22,15 +22,41 @@ #include "nsRuleData.h" #include "nsRuleProcessorData.h" #include "mozilla/dom/Element.h" +#include "nsAttrValue.h" +#include "nsAttrValueInlines.h" using namespace mozilla::dom; namespace css = mozilla::css; +namespace { + +PLDHashOperator +ClearAttrCache(const nsAString& aKey, MiscContainer*& aValue, void*) +{ + // Ideally we'd just call MiscContainer::Evict, but we can't do that since + // we're iterating the hashtable. + MOZ_ASSERT(aValue->mType == nsAttrValue::eCSSStyleRule); + + aValue->mValue.mCSSStyleRule->SetHTMLCSSStyleSheet(nullptr); + aValue->mValue.mCached = 0; + + return PL_DHASH_REMOVE; +} + +} // anonymous namespace + nsHTMLCSSStyleSheet::nsHTMLCSSStyleSheet() : mDocument(nullptr) { } +nsHTMLCSSStyleSheet::~nsHTMLCSSStyleSheet() +{ + // We may go away before all of our cached style attributes do, + // so clean up any that are left. + mCachedStyleAttrs.Enumerate(ClearAttrCache, nullptr); +} + NS_IMPL_ISUPPORTS2(nsHTMLCSSStyleSheet, nsIStyleSheet, nsIStyleRuleProcessor) @@ -94,6 +120,7 @@ nsHTMLCSSStyleSheet::Init(nsIURI* aURL, nsIDocument* aDocument) mDocument = aDocument; // not refcounted! mURL = aURL; + mCachedStyleAttrs.Init(); return NS_OK; } @@ -141,6 +168,32 @@ nsHTMLCSSStyleSheet::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf); } +void +nsHTMLCSSStyleSheet::CacheStyleAttr(const nsAString& aSerialized, + MiscContainer* aValue) +{ + mCachedStyleAttrs.Put(aSerialized, aValue); +} + +void +nsHTMLCSSStyleSheet::EvictStyleAttr(const nsAString& aSerialized, + MiscContainer* aValue) +{ +#ifdef DEBUG + { + NS_ASSERTION(aValue = mCachedStyleAttrs.Get(aSerialized), + "Cached value does not match?!"); + } +#endif + mCachedStyleAttrs.Remove(aSerialized); +} + +MiscContainer* +nsHTMLCSSStyleSheet::LookupStyleAttr(const nsAString& aSerialized) +{ + return mCachedStyleAttrs.Get(aSerialized); +} + void nsHTMLCSSStyleSheet::Reset(nsIURI* aURL) { diff --git a/layout/style/nsHTMLCSSStyleSheet.h b/layout/style/nsHTMLCSSStyleSheet.h index 9260eec6df17..246f1c895114 100644 --- a/layout/style/nsHTMLCSSStyleSheet.h +++ b/layout/style/nsHTMLCSSStyleSheet.h @@ -15,10 +15,13 @@ #include "nsIStyleSheet.h" #include "nsIStyleRuleProcessor.h" +struct MiscContainer; + class nsHTMLCSSStyleSheet MOZ_FINAL : public nsIStyleSheet, public nsIStyleRuleProcessor { public: nsHTMLCSSStyleSheet(); + ~nsHTMLCSSStyleSheet(); NS_DECL_ISUPPORTS @@ -59,6 +62,10 @@ public: virtual NS_MUST_OVERRIDE size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const MOZ_OVERRIDE; + void CacheStyleAttr(const nsAString& aSerialized, MiscContainer* aValue); + void EvictStyleAttr(const nsAString& aSerialized, MiscContainer* aValue); + MiscContainer* LookupStyleAttr(const nsAString& aSerialized); + private: nsHTMLCSSStyleSheet(const nsHTMLCSSStyleSheet& aCopy) MOZ_DELETE; nsHTMLCSSStyleSheet& operator=(const nsHTMLCSSStyleSheet& aCopy) MOZ_DELETE; @@ -66,6 +73,7 @@ private: protected: nsCOMPtr mURL; nsIDocument* mDocument; + nsDataHashtable mCachedStyleAttrs; }; #endif /* !defined(nsHTMLCSSStyleSheet_h_) */ diff --git a/layout/tables/nsTableCellFrame.cpp b/layout/tables/nsTableCellFrame.cpp index fc9f6ffac07c..75aba45a29c1 100644 --- a/layout/tables/nsTableCellFrame.cpp +++ b/layout/tables/nsTableCellFrame.cpp @@ -14,6 +14,7 @@ #include "nsCSSRendering.h" #include "nsIContent.h" #include "nsGenericHTMLElement.h" +#include "nsAttrValueInlines.h" #include "nsHTMLParts.h" #include "nsGkAtoms.h" #include "nsIPresShell.h" From 4bb2f6dc8a6daa916e3befb534dce43c543c3b43 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Sun, 30 Sep 2012 09:43:47 -0700 Subject: [PATCH 10/64] Bug 795128: Add memory reporting for attribute maps and nodes. r=smaug --- content/base/public/FragmentOrElement.h | 2 ++ content/base/src/FragmentOrElement.cpp | 36 +++++++++++++++++++++++-- content/base/src/nsDOMAttributeMap.cpp | 20 ++++++++++++++ content/base/src/nsDOMAttributeMap.h | 2 ++ 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/content/base/public/FragmentOrElement.h b/content/base/public/FragmentOrElement.h index 18f6b10b0e78..37d2bbf3159e 100644 --- a/content/base/public/FragmentOrElement.h +++ b/content/base/public/FragmentOrElement.h @@ -348,6 +348,8 @@ public: void Traverse(nsCycleCollectionTraversalCallback &cb, bool aIsXUL); void Unlink(bool aIsXUL); + size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const; + /** * The .style attribute (an interface that forwards to the actual * style rules) diff --git a/content/base/src/FragmentOrElement.cpp b/content/base/src/FragmentOrElement.cpp index 8c7f4dc45b39..ef4dfb466e48 100644 --- a/content/base/src/FragmentOrElement.cpp +++ b/content/base/src/FragmentOrElement.cpp @@ -598,6 +598,30 @@ FragmentOrElement::nsDOMSlots::Unlink(bool aIsXUL) } } +size_t +FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const +{ + size_t n = aMallocSizeOf(this); + + if (mAttributeMap) { + n += mAttributeMap->SizeOfIncludingThis(aMallocSizeOf); + } + + // Measurement of the following members may be added later if DMD finds it is + // worthwhile: + // - Superclass members (nsINode::nsSlots) + // - mStyle + // - mDataSet + // - mSMILOverrideStyle + // - mSMILOverrideStyleRule + // - mChildrenList + // - mClassList + + // The following members are not measured: + // - mBindingParent / mControllers: because they're non-owning + return n; +} + FragmentOrElement::FragmentOrElement(already_AddRefed aNodeInfo) : nsIContent(aNodeInfo) { @@ -1938,6 +1962,14 @@ FragmentOrElement::FireNodeRemovedForChildren() size_t FragmentOrElement::SizeOfExcludingThis(nsMallocSizeOfFun aMallocSizeOf) const { - return nsIContent::SizeOfExcludingThis(aMallocSizeOf) + - mAttrsAndChildren.SizeOfExcludingThis(aMallocSizeOf); + size_t n = 0; + n += nsIContent::SizeOfExcludingThis(aMallocSizeOf); + n += mAttrsAndChildren.SizeOfExcludingThis(aMallocSizeOf); + + nsDOMSlots* slots = GetExistingDOMSlots(); + if (slots) { + n += slots->SizeOfIncludingThis(aMallocSizeOf); + } + + return n; } diff --git a/content/base/src/nsDOMAttributeMap.cpp b/content/base/src/nsDOMAttributeMap.cpp index 7caea2f36aea..629b6de6411b 100644 --- a/content/base/src/nsDOMAttributeMap.cpp +++ b/content/base/src/nsDOMAttributeMap.cpp @@ -501,3 +501,23 @@ nsDOMAttributeMap::Enumerate(AttrCache::EnumReadFunction aFunc, { return mAttributeCache.EnumerateRead(aFunc, aUserArg); } + +size_t +AttrCacheSizeEnumerator(const nsAttrKey& aKey, + const nsRefPtr& aValue, + nsMallocSizeOfFun aMallocSizeOf, + void* aUserArg) +{ + return aMallocSizeOf(aValue.get()); +} + +size_t +nsDOMAttributeMap::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const +{ + size_t n = aMallocSizeOf(this); + n += mAttributeCache.SizeOfExcludingThis(AttrCacheSizeEnumerator, + aMallocSizeOf); + + // NB: mContent is non-owning and thus not counted. + return n; +} diff --git a/content/base/src/nsDOMAttributeMap.h b/content/base/src/nsDOMAttributeMap.h index ee4dcba3673b..b4c200b172f3 100644 --- a/content/base/src/nsDOMAttributeMap.h +++ b/content/base/src/nsDOMAttributeMap.h @@ -159,6 +159,8 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS(nsDOMAttributeMap) + size_t SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const; + private: Element *mContent; // Weak reference From 35610fce7c3d8498efd9354fe8fd584dabe38d91 Mon Sep 17 00:00:00 2001 From: Kyle Huey Date: Sun, 30 Sep 2012 09:45:05 -0700 Subject: [PATCH 11/64] Bug 792625: Fix xpcshell to accept non-ASCII command line arguments on Windows. r=bsmedberg --- js/xpconnect/shell/Makefile.in | 11 +++++++++++ js/xpconnect/shell/xpcshell.cpp | 7 +++++++ toolkit/xre/nsWindowsWMain.cpp | 10 ++++++++++ 3 files changed, 28 insertions(+) diff --git a/js/xpconnect/shell/Makefile.in b/js/xpconnect/shell/Makefile.in index 2a7a8c913245..9b11780c5a85 100644 --- a/js/xpconnect/shell/Makefile.in +++ b/js/xpconnect/shell/Makefile.in @@ -16,6 +16,10 @@ SDK_BINARY = $(PROGRAM) CPPSRCS = xpcshell.cpp +LOCAL_INCLUDES += \ + -I$(topsrcdir)/toolkit/xre \ + $(NULL) + ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) CMMSRCS += xpcshellMacUtils.mm endif @@ -63,6 +67,13 @@ ifeq ($(OS_TEST),ia64) LIBS += $(JEMALLOC_LIBS) endif include $(topsrcdir)/config/config.mk + +ifdef _MSC_VER +# Always enter a Windows program through wmain, whether or not we're +# a console application. +WIN32_EXE_LDFLAGS += -ENTRY:wmainCRTStartup +endif + include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/config/rules.mk diff --git a/js/xpconnect/shell/xpcshell.cpp b/js/xpconnect/shell/xpcshell.cpp index 4d7d31e7a153..900c8a223994 100644 --- a/js/xpconnect/shell/xpcshell.cpp +++ b/js/xpconnect/shell/xpcshell.cpp @@ -51,6 +51,13 @@ #ifdef XP_WIN #include #include + +// we want a wmain entry point +#define XRE_DONT_PROTECT_DLL_LOAD +#define XRE_WANT_ENVIRON +#include "nsWindowsWMain.cpp" +#define snprintf _snprintf +#define strcasecmp _stricmp #endif #ifdef ANDROID diff --git a/toolkit/xre/nsWindowsWMain.cpp b/toolkit/xre/nsWindowsWMain.cpp index 3a2e39514b11..17660e28ef59 100644 --- a/toolkit/xre/nsWindowsWMain.cpp +++ b/toolkit/xre/nsWindowsWMain.cpp @@ -42,7 +42,11 @@ int main(int argc, char **argv) #define main NS_internal_main +#ifndef XRE_WANT_ENVIRON int main(int argc, char **argv); +#else +int main(int argc, char **argv, char **envp); +#endif static char* AllocConvertUTF16toUTF8(const WCHAR *arg) @@ -97,7 +101,13 @@ int wmain(int argc, WCHAR **argv) } for (int i = 0; i < argc; i++) deleteUs[i] = argvConverted[i]; +#ifndef XRE_WANT_ENVIRON int result = main(argc, argvConverted); +#else + // Force creation of the multibyte _environ variable. + getenv("PATH"); + int result = main(argc, argvConverted, _environ); +#endif delete[] argvConverted; FreeAllocStrings(argc, deleteUs); From f391946e844b5e69f58c21f7959579204fa821a7 Mon Sep 17 00:00:00 2001 From: "Gordon P. Hemsley" Date: Thu, 20 Sep 2012 18:10:09 -0400 Subject: [PATCH 12/64] Bug 792575 - Change Hawaiian [haw] langGroup to 'x-western'. r=jfkthame --- intl/locale/src/langGroups.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intl/locale/src/langGroups.properties b/intl/locale/src/langGroups.properties index 05ce6cca0681..0d0d12b39398 100644 --- a/intl/locale/src/langGroups.properties +++ b/intl/locale/src/langGroups.properties @@ -70,7 +70,7 @@ gn=x-western #ha=x-western : Latin and Ajami scripts gu=x-gujr gv=x-western -haw=x-unicode +haw=x-western he=he hi=x-devanagari hil=x-western From 15e9437300f38192b3a093be233af3a43d4c6864 Mon Sep 17 00:00:00 2001 From: Frank Yan Date: Sat, 29 Sep 2012 21:56:40 -0700 Subject: [PATCH 13/64] Bug 781327 - Use 2x images for HiDPI browser UI. r=dolske --- browser/themes/pinstripe/Geolocation-16.png | Bin 416 -> 312 bytes .../themes/pinstripe/Geolocation-16@2x.png | Bin 0 -> 666 bytes .../themes/pinstripe/Geolocation-64@2x.png | Bin 0 -> 26989 bytes browser/themes/pinstripe/Search@2x.png | Bin 0 -> 545 bytes browser/themes/pinstripe/Secure-Glyph@2x.png | Bin 0 -> 1423 bytes browser/themes/pinstripe/Toolbar-lion@2x.png | Bin 0 -> 17375 bytes .../themes/pinstripe/actionicon-tab@2x.png | Bin 0 -> 1371 bytes browser/themes/pinstripe/browser.css | 710 ++++++++++++++++++ .../themes/pinstripe/devtools/debugger.css | 8 + .../themes/pinstripe/downloads/downloads.css | 11 + .../pinstripe/identity-icons-generic@2x.png | Bin 0 -> 1235 bytes .../pinstripe/identity-icons-https-ev@2x.png | Bin 0 -> 1162 bytes .../pinstripe/identity-icons-https@2x.png | Bin 0 -> 1077 bytes browser/themes/pinstripe/identity.png | Bin 10051 -> 13607 bytes browser/themes/pinstripe/identity@2x.png | Bin 0 -> 33250 bytes browser/themes/pinstripe/jar.mn | 39 + .../pinstripe/keyhole-circle-lion@2x.png | Bin 0 -> 5642 bytes browser/themes/pinstripe/newtab/controls.png | Bin 4180 -> 4671 bytes .../themes/pinstripe/newtab/controls@2x.png | Bin 0 -> 15928 bytes browser/themes/pinstripe/newtab/newTab.css | 14 + .../themes/pinstripe/page-livemarks@2x.png | Bin 0 -> 1167 bytes .../pinstripe/panel-expander-closed@2x.png | Bin 0 -> 362 bytes .../pinstripe/panel-expander-open@2x.png | Bin 0 -> 356 bytes .../pinstripe/places/bookmarksToolbar.png | Bin 405 -> 524 bytes .../pinstripe/places/bookmarksToolbar@2x.png | Bin 0 -> 1179 bytes .../pinstripe/places/editBookmarkOverlay.css | 18 + .../pinstripe/places/folderDropArrow.png | Bin 161 -> 201 bytes .../pinstripe/places/folderDropArrow@2x.png | Bin 0 -> 443 bytes browser/themes/pinstripe/places/history.png | Bin 559 -> 843 bytes .../themes/pinstripe/places/history@2x.png | Bin 0 -> 1872 bytes browser/themes/pinstripe/places/organizer.css | 10 + browser/themes/pinstripe/places/query@2x.png | Bin 0 -> 1055 bytes .../themes/pinstripe/places/star-icons@2x.png | Bin 0 -> 4458 bytes browser/themes/pinstripe/places/tag@2x.png | Bin 0 -> 1593 bytes .../pinstripe/places/unfiledBookmarks.png | Bin 719 -> 586 bytes .../pinstripe/places/unfiledBookmarks@2x.png | Bin 0 -> 1289 bytes .../preferences/aboutPermissions.css | 12 + .../themes/pinstripe/reload-stop-go@2x.png | Bin 0 -> 1850 bytes .../pinstripe/searchbar-dropmarker@2x.png | Bin 0 -> 189 bytes browser/themes/pinstripe/searchbar.css | 16 + .../alltabs-box-bkgnd-icon-lion@2x.png | Bin 0 -> 1350 bytes .../pinstripe/tabbrowser/connecting@2x.png | Bin 0 -> 30143 bytes .../pinstripe/tabbrowser/loading@2x.png | Bin 0 -> 40165 bytes .../themes/pinstripe/tabbrowser/newtab@2x.png | Bin 0 -> 1742 bytes .../tabbrowser/tab-arrow-left@2x.png | Bin 0 -> 2768 bytes .../tabbrowser/tab-arrow-right@2x.png | Bin 0 -> 2732 bytes .../tabbrowser/tab-top-hover-active@2x.png | Bin 0 -> 891 bytes .../tabbrowser/tab-top-normal-active@2x.png | Bin 0 -> 968 bytes .../tabbrowser/tab-top-selected-active@2x.png | Bin 0 -> 1098 bytes .../toolbarbutton-dropmarker-lion@2x.png | Bin 0 -> 286 bytes browser/themes/pinstripe/urlbar-arrow@2x.png | Bin 0 -> 362 bytes .../urlbar-history-dropmarker@2x.png | Bin 0 -> 807 bytes .../pinstripe/urlbar-popup-blocked@2x.png | Bin 0 -> 769 bytes browser/themes/pinstripe/webapps-16@2x.png | Bin 0 -> 481 bytes toolkit/themes/pinstripe/global/findBar.css | 19 + .../themes/pinstripe/global/icons/chevron.png | Bin 401 -> 251 bytes .../pinstripe/global/icons/chevron@2x.png | Bin 0 -> 462 bytes .../pinstripe/global/icons/close@2x.png | Bin 0 -> 1788 bytes toolkit/themes/pinstripe/global/jar.mn | 3 + .../themes/pinstripe/global/notification.css | 19 + .../pinstripe/global/tree/folder@2x.png | Bin 0 -> 589 bytes toolkit/themes/pinstripe/mozapps/jar.mn | 1 + .../mozapps/places/defaultFavicon@2x.png | Bin 0 -> 477 bytes 63 files changed, 880 insertions(+) create mode 100755 browser/themes/pinstripe/Geolocation-16@2x.png create mode 100644 browser/themes/pinstripe/Geolocation-64@2x.png create mode 100755 browser/themes/pinstripe/Search@2x.png create mode 100644 browser/themes/pinstripe/Secure-Glyph@2x.png create mode 100755 browser/themes/pinstripe/Toolbar-lion@2x.png create mode 100644 browser/themes/pinstripe/actionicon-tab@2x.png create mode 100755 browser/themes/pinstripe/identity-icons-generic@2x.png create mode 100755 browser/themes/pinstripe/identity-icons-https-ev@2x.png create mode 100755 browser/themes/pinstripe/identity-icons-https@2x.png create mode 100755 browser/themes/pinstripe/identity@2x.png create mode 100755 browser/themes/pinstripe/keyhole-circle-lion@2x.png create mode 100755 browser/themes/pinstripe/newtab/controls@2x.png create mode 100755 browser/themes/pinstripe/page-livemarks@2x.png create mode 100644 browser/themes/pinstripe/panel-expander-closed@2x.png create mode 100644 browser/themes/pinstripe/panel-expander-open@2x.png create mode 100755 browser/themes/pinstripe/places/bookmarksToolbar@2x.png create mode 100644 browser/themes/pinstripe/places/folderDropArrow@2x.png create mode 100755 browser/themes/pinstripe/places/history@2x.png create mode 100755 browser/themes/pinstripe/places/query@2x.png create mode 100755 browser/themes/pinstripe/places/star-icons@2x.png create mode 100755 browser/themes/pinstripe/places/tag@2x.png create mode 100755 browser/themes/pinstripe/places/unfiledBookmarks@2x.png create mode 100755 browser/themes/pinstripe/reload-stop-go@2x.png create mode 100755 browser/themes/pinstripe/searchbar-dropmarker@2x.png create mode 100755 browser/themes/pinstripe/tabbrowser/alltabs-box-bkgnd-icon-lion@2x.png create mode 100644 browser/themes/pinstripe/tabbrowser/connecting@2x.png create mode 100644 browser/themes/pinstripe/tabbrowser/loading@2x.png create mode 100755 browser/themes/pinstripe/tabbrowser/newtab@2x.png create mode 100755 browser/themes/pinstripe/tabbrowser/tab-arrow-left@2x.png create mode 100755 browser/themes/pinstripe/tabbrowser/tab-arrow-right@2x.png create mode 100755 browser/themes/pinstripe/tabbrowser/tab-top-hover-active@2x.png create mode 100755 browser/themes/pinstripe/tabbrowser/tab-top-normal-active@2x.png create mode 100755 browser/themes/pinstripe/tabbrowser/tab-top-selected-active@2x.png create mode 100755 browser/themes/pinstripe/toolbarbutton-dropmarker-lion@2x.png create mode 100755 browser/themes/pinstripe/urlbar-arrow@2x.png create mode 100755 browser/themes/pinstripe/urlbar-history-dropmarker@2x.png create mode 100755 browser/themes/pinstripe/urlbar-popup-blocked@2x.png create mode 100755 browser/themes/pinstripe/webapps-16@2x.png create mode 100644 toolkit/themes/pinstripe/global/icons/chevron@2x.png create mode 100755 toolkit/themes/pinstripe/global/icons/close@2x.png create mode 100755 toolkit/themes/pinstripe/global/tree/folder@2x.png create mode 100644 toolkit/themes/pinstripe/mozapps/places/defaultFavicon@2x.png diff --git a/browser/themes/pinstripe/Geolocation-16.png b/browser/themes/pinstripe/Geolocation-16.png index a40cc1bb9ab74689fc3b7fdcffb3c9258387e4f4..54ef8f8eae7221735fe774a2d6cfc4c68c1e342e 100644 GIT binary patch delta 296 zcmV+@0oVSZ1GoZ^8Gi-<001BJ|6u?C0RKruK~#9!rOQF8f?yQI@v{kMxffkTJYPF# z7g~s!h=@qJt`}kGE^^#`=Yunlj|M@5A6yRqi(wePg6s9_3#p(#GDr7`Lcho5a#{PK zg^V6#-n~#l5TNgSNJ1}~Dbi*FZL^w08_;!~v!N$V6cEG&5`U;!^aHeQ>zv6bCai1) zE3w*&fTn4jJB@@7jrsxVx^~R7BY5_2I-sg5$2>cNXaA-H%CdBBG!i~E>IW!_!a0*s zOjy|pRwA_(0ePM~8+y`20YOY4ftp1>!0~v5B=n-0B5fwnHmOOp0f)n3Eun>s9%SCV u&@VxNEX#Z$ogwH(CO2)N-y==aulxgfsrhYt7Waq%0000K~yMHZBff=!cY`ED;M=05u+w*^DxqQ z@qvK`#kdHzf=j=|{|E%~4gCN?$WH`>f*^G32LuX%3xVlEW4kD`IK!ObJQxDq@MILc zQdCaMX(=jrPe!KSOK~qG4YVOcMjH(XNpb%$BMcJF;k& z&N2BW>uUwu{(oiE zkdC%4&c!mtR~+r7wT@0sPKqj_f{$q64u69?G{UVCvMQoTD8&WZu!7pSKnnGusi+cr=3VFy|Y}kYkRV628EkX4n#>{r&w%b(nL81j=EK zatz@E%&9}rV{jB*7rF`s>f;0c6IU+VMG9$eZ%?>@MKYA29?Ve>C1fst32AqCw~RI{ z@)jDfs@rIzteu^m3M}#)2{d3y=(b2j+uPgcut*JhAvL#kuC1-D1}riOy^u+_)zIeV z<~^(cJ(Cr1uZ@k34y*t@lNHd>`uchYR)C(#3g~EUZS5XbfS$<;xYz3HY6BLTfL_R? z+iGZKW#t?esX;HK=C;nYyu4h2MSdZH1}q8P7O7}yX{n4hEK-FAtm-x%P}bt&qHqa| zWGF#Bn4=y_$Xxys(!#=mkfIBVe8mv-1ap*+4!T^ni!n&^^Yf4DFy{;jl*1h57{Ys) z^A3XI@CceP=Nrm>e4vESFsF&v5Tv=exmb!8%*jwi0tMzMNJ2J)IW45|reZ;a za%4Eg1k9NTw;wPsbdLKy&CJZ?NzsH2NHcWGiyz)F>gdAy)I~jXDUYV7r~hXR7kGdb z^aqz1gL=`_)KpO=RPhPdXrUXla2;;dkW~@?02aAW9_}4~KL7v#07*qoM6N<$f;@aM A9smFU literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/Geolocation-64@2x.png b/browser/themes/pinstripe/Geolocation-64@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..411db1a5a455401d5df6a5fd3bca39bd3b3bca77 GIT binary patch literal 26989 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 literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/Search@2x.png b/browser/themes/pinstripe/Search@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..a12c4133f83c46a2ac4ed3ffd516d69413a64958 GIT binary patch literal 545 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 literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/browser.css b/browser/themes/pinstripe/browser.css index 27bcca30d1b0..4e2b9aed1e96 100644 --- a/browser/themes/pinstripe/browser.css +++ b/browser/themes/pinstripe/browser.css @@ -121,6 +121,16 @@ toolbarbutton.chevron:-moz-locale-dir(rtl) > .toolbarbutton-icon { transform: scaleX(-1); } +@media (min-resolution: 2dppx) { + toolbarbutton.chevron { + list-style-image: url("chrome://global/skin/icons/chevron@2x.png"); + } + + toolbarbutton.chevron > .toolbarbutton-icon { + width: 13px; + } +} + /* ----- BOOKMARK BUTTONS ----- */ toolbarbutton.bookmark-item { @@ -140,6 +150,17 @@ toolbarbutton.bookmark-item { -moz-margin-end: -2px; } +@media (min-resolution: 2dppx) { + .bookmark-item > .toolbarbutton-menu-dropmarker { + list-style-image: url("chrome://browser/skin/places/folderDropArrow@2x.png"); + -moz-image-region: rect(0, 14px, 10px, 0); + } + + .bookmark-item > .toolbarbutton-menu-dropmarker > .dropmarker-icon { + width: 7px; + } +} + .bookmark-item > .toolbarbutton-text { display: -moz-box !important; /* prevent [mode="icons"] from hiding the label */ margin: 0 !important; @@ -161,6 +182,13 @@ toolbarbutton.bookmark-item[open="true"] { -moz-image-region: rect(5px, 7px, 10px, 0); } +@media (min-resolution: 2dppx) { + .bookmark-item:hover > .toolbarbutton-menu-dropmarker, + .bookmark-item[open="true"] > .toolbarbutton-menu-dropmarker { + -moz-image-region: rect(10px, 14px, 20px, 0); + } +} + toolbarbutton.bookmark-item:active:hover, toolbarbutton.bookmark-item[open="true"] { box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.4), 0 1px rgba(255, 255, 255, 0.4); @@ -220,6 +248,40 @@ toolbarbutton.bookmark-item > menupopup { list-style-image: url("chrome://global/skin/tree/folder.png"); } +@media (min-resolution: 2dppx) { + .bookmark-item[container] { + list-style-image: url("chrome://global/skin/tree/folder@2x.png"); + } + + .bookmark-item[container][livemark] { + list-style-image: url("chrome://browser/skin/page-livemarks@2x.png"); + } + + .bookmark-item[container][livemark] .bookmark-item { + list-style-image: url("chrome://browser/skin/places/livemark-item.png"); + } + + .bookmark-item[container][query] { + list-style-image: url("chrome://browser/skin/places/query@2x.png"); + } + + .bookmark-item[query][tagContainer] { + list-style-image: url("chrome://browser/skin/places/tag@2x.png"); + } + + .bookmark-item[query][dayContainer] { + list-style-image: url("chrome://browser/skin/places/history@2x.png"); + } + + .bookmark-item[query][hostContainer] { + list-style-image: url("chrome://global/skin/tree/folder@2x.png"); + } + + .bookmark-item[query][hostContainer][open] { + list-style-image: url("chrome://global/skin/tree/folder@2x.png"); + } +} + /* Workaround for native menubar inheritance */ .openintabs-menuitem, .openlivemarksite-menuitem, @@ -246,6 +308,21 @@ toolbarbutton.bookmark-item > menupopup { list-style-image: url("chrome://browser/skin/places/bookmarksToolbar.png") !important; } +@media (min-resolution: 2dppx) { + #wrapper-personal-bookmarks[place="palette"] > .toolbarpaletteitem-box { + background-image: url("chrome://browser/skin/places/bookmarksToolbar@2x.png"); + background-size: 16px; + } + + .bookmarks-toolbar-customize { + list-style-image: url("chrome://browser/skin/places/bookmarksToolbar@2x.png") !important; + } + + .bookmarks-toolbar-customize > .toolbarbutton-icon { + width: 16px; + } +} + /* ----- BOOKMARK MENUS ----- */ .bookmark-item > .menu-iconic-left > .menu-iconic-icon { @@ -262,6 +339,17 @@ toolbarbutton.bookmark-item > menupopup { list-style-image: url("chrome://browser/skin/places/unfiledBookmarks.png"); } +@media (min-resolution: 2dppx) { + #bookmarksToolbarFolderMenu, + #BMB_bookmarksToolbar { + list-style-image: url("chrome://browser/skin/places/bookmarksToolbar@2x.png"); + } + + #BMB_unsortedBookmarks { + list-style-image: url("chrome://browser/skin/places/unfiledBookmarks@2x.png"); + } +} + /* ----- PRIMARY TOOLBAR BUTTONS ----- */ .toolbarbutton-1:not([type="menu-button"]), @@ -310,6 +398,18 @@ toolbarbutton.bookmark-item > menupopup { list-style-image: url("chrome://browser/skin/Toolbar.png"); } +@media (min-resolution: 2dppx) { + /* Whitelist built-in buttons, instead of .toolbarbutton-1, + to avoid potentially breaking add-on toolbar buttons. */ + :-moz-any(@primaryToolbarButtons@):not(#tabview-button) { + list-style-image: url("chrome://browser/skin/Toolbar@2x.png"); + } + + :-moz-any(@primaryToolbarButtons@):not(#tabview-button) > .toolbarbutton-icon { + width: 20px; + } +} + toolbar:not([mode="icons"]) .toolbarbutton-1:not([type="menu-button"]), toolbar:not([mode="icons"]) .toolbarbutton-1 > .toolbarbutton-menubutton-button, toolbar:not([mode="icons"]) .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker, @@ -371,6 +471,18 @@ toolbar:not([mode="icons"]) #restore-button { list-style-image: url(chrome://browser/skin/toolbarbutton-dropmarker.png); } +@media (min-resolution: 2dppx) { + .toolbarbutton-1 > .toolbarbutton-menu-dropmarker, + .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker { + list-style-image: url(chrome://browser/skin/toolbarbutton-dropmarker@2x.png); + } + + .toolbarbutton-1 > .toolbarbutton-menu-dropmarker > .dropmarker-icon, + .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon { + width: 7px; + } +} + .toolbarbutton-1 > .toolbarbutton-menu-dropmarker { -moz-margin-end: 1px; } @@ -448,6 +560,14 @@ toolbar[mode="icons"] #back-button:-moz-locale-dir(rtl):-moz-lwtheme { -moz-image-region: rect(0, 40px, 20px, 20px); } +@media (min-resolution: 2dppx) { + #back-button, + #forward-button:-moz-locale-dir(rtl), + toolbar[mode="icons"] #back-button:-moz-locale-dir(rtl):-moz-lwtheme { + -moz-image-region: rect(0, 80px, 40px, 40px); + } +} + #forward-button, #back-button:-moz-locale-dir(rtl), #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button:-moz-locale-dir(rtl), @@ -455,6 +575,15 @@ toolbar[mode="icons"] #forward-button:-moz-locale-dir(rtl):-moz-lwtheme { -moz-image-region: rect(0, 60px, 20px, 40px); } +@media (min-resolution: 2dppx) { + #forward-button, + #back-button:-moz-locale-dir(rtl), + #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button:-moz-locale-dir(rtl), + toolbar[mode="icons"] #forward-button:-moz-locale-dir(rtl):-moz-lwtheme { + -moz-image-region: rect(0, 120px, 40px, 80px); + } +} + #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:-moz-locale-dir(rtl), #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button:-moz-locale-dir(rtl), toolbar[mode="icons"] #back-button:-moz-locale-dir(rtl):-moz-lwtheme, @@ -474,6 +603,12 @@ toolbar[mode="icons"] #forward-button:-moz-locale-dir(rtl):-moz-lwtheme { border-radius: 10000px; } +@media (min-resolution: 2dppx) { + #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button { + -moz-image-region: rect(0, 40px, 40px, 0); + } +} + #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not(:-moz-lwtheme) { height: 31px; padding: 4px 5px 5px 3px; @@ -482,6 +617,13 @@ toolbar[mode="icons"] #forward-button:-moz-locale-dir(rtl):-moz-lwtheme { border-radius: 0; } +@media (min-resolution: 2dppx) { + #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not(:-moz-lwtheme) { + background-image: url(chrome://browser/skin/keyhole-circle@2x.png); + background-size: 90px; + } +} + #navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:-moz-window-inactive:not(:-moz-lwtheme) { background-position: -60px 0; } @@ -612,12 +754,24 @@ toolbar[mode="icons"] #forward-button:-moz-lwtheme { -moz-image-region: rect(0, 80px, 20px, 60px); } +@media (min-resolution: 2dppx) { + #reload-button { + -moz-image-region: rect(0, 160px, 40px, 120px); + } +} + /* stop button */ #stop-button { -moz-image-region: rect(0, 100px, 20px, 80px); } +@media (min-resolution: 2dppx) { + #stop-button { + -moz-image-region: rect(0, 200px, 40px, 160px); + } +} + /* home button */ #home-button { @@ -639,6 +793,12 @@ toolbar[mode="icons"] #forward-button:-moz-lwtheme { -moz-margin-end: 3px; } +@media (min-resolution: 2dppx) { + #home-button:not(.bookmark-item) { + -moz-image-region: rect(0, 240px, 40px, 200px); + } +} + /* tabview button */ #tabview-button, @@ -692,6 +852,12 @@ toolbar[mode="icons"] #forward-button:-moz-lwtheme { -moz-image-region: rect(0, 140px, 20px, 120px); } +@media (min-resolution: 2dppx) { + #downloads-button { + -moz-image-region: rect(0, 280px, 40px, 240px); + } +} + /* history sidebar button */ #history-button { @@ -702,6 +868,16 @@ toolbar[mode="icons"] #forward-button:-moz-lwtheme { -moz-image-region: rect(20px, 160px, 40px, 140px); } +@media (min-resolution: 2dppx) { + #history-button { + -moz-image-region: rect(0, 320px, 40px, 280px); + } + + #history-button[checked="true"] { + -moz-image-region: rect(40px, 320px, 80px, 280px); + } +} + /* bookmark sidebar & menu buttons */ #bookmarks-button, @@ -718,6 +894,26 @@ toolbar[mode="icons"] #forward-button:-moz-lwtheme { list-style-image: url("chrome://browser/skin/Toolbar.png"); } +@media (min-resolution: 2dppx) { + #bookmarks-button, + #bookmarks-menu-button { + -moz-image-region: rect(0, 360px, 40px, 320px); + } + + #bookmarks-button[checked="true"] { + -moz-image-region: rect(40px, 360px, 80px, 320px); + } + + #bookmarks-menu-button.bookmark-item { + -moz-image-region: rect(4px, 356px, 36px, 324px); + list-style-image: url("chrome://browser/skin/Toolbar@2x.png"); + } + + #bookmarks-menu-button.bookmark-item > .toolbarbutton-icon { + width: 16px; + } +} + #bookmarks-menu-button.toolbarbutton-1 { -moz-box-orient: horizontal; } @@ -728,42 +924,84 @@ toolbar[mode="icons"] #forward-button:-moz-lwtheme { -moz-image-region: rect(0, 200px, 20px, 180px); } +@media (min-resolution: 2dppx) { + #print-button { + -moz-image-region: rect(0, 400px, 40px, 360px); + } +} + /* toolbar new tab button */ #new-tab-button { -moz-image-region: rect(0, 220px, 20px, 200px); } +@media (min-resolution: 2dppx) { + #new-tab-button { + -moz-image-region: rect(0, 440px, 40px, 400px); + } +} + /* new window button */ #new-window-button { -moz-image-region: rect(0, 240px, 20px, 220px); } +@media (min-resolution: 2dppx) { + #new-window-button { + -moz-image-region: rect(0, 480px, 40px, 440px); + } +} + /* cut button */ #cut-button { -moz-image-region: rect(0, 260px, 20px, 240px); } +@media (min-resolution: 2dppx) { + #cut-button { + -moz-image-region: rect(0, 520px, 40px, 480px); + } +} + /* copy button */ #copy-button { -moz-image-region: rect(0, 280px, 20px, 260px); } +@media (min-resolution: 2dppx) { + #copy-button { + -moz-image-region: rect(0, 560px, 40px, 520px); + } +} + /* paste button */ #paste-button { -moz-image-region: rect(0, 300px, 20px, 280px); } +@media (min-resolution: 2dppx) { + #paste-button { + -moz-image-region: rect(0, 600px, 40px, 560px); + } +} + /* alltabs button */ #alltabs-button { -moz-image-region: rect(0, 380px, 20px, 360px); } +@media (min-resolution: 2dppx) { + #alltabs-button { + -moz-image-region: rect(0, 760px, 40px, 720px); + } +} + /* fullscreen button */ #fullscreen-button { @@ -775,6 +1013,17 @@ toolbar[mode="icons"] #forward-button:-moz-lwtheme { -moz-image-region: rect(0, 360px, 20px, 340px); } +@media (min-resolution: 2dppx) { + #fullscreen-button { + -moz-image-region: rect(0, 680px, 40px, 640px); + } + + #fullscreen-button[checked="true"], + #restore-button { + -moz-image-region: rect(0, 720px, 40px, 680px); + } +} + /* zoom controls */ #zoom-controls { @@ -789,6 +1038,16 @@ toolbar[mode="icons"] #forward-button:-moz-lwtheme { -moz-image-region: rect(0, 420px, 20px, 400px); } +@media (min-resolution: 2dppx) { + #zoom-out-button { + -moz-image-region: rect(0, 800px, 40px, 760px); + } + + #zoom-in-button { + -moz-image-region: rect(0, 480px, 40px, 440px); + } +} + toolbar[mode="icons"] #zoom-out-button { -moz-margin-end: 0; } @@ -821,12 +1080,24 @@ toolbar[mode="icons"] #zoom-in-button { -moz-image-region: rect(0, 20px, 20px, 0px); } +@media (min-resolution: 2dppx) { + #sync-button:not([status="active"]) { + -moz-image-region: rect(0, 880px, 40px, 840px); + } +} + /* feed button */ #feed-button { -moz-image-region: rect(0, 460px, 20px, 440px); } +@media (min-resolution: 2dppx) { + #feed-button { + -moz-image-region: rect(0, 920px, 40px, 880px); + } +} + /* ----- FULLSCREEN WINDOW CONTROLS ----- */ @@ -1027,6 +1298,22 @@ toolbar[mode="icons"] #zoom-in-button { background-image: -moz-radial-gradient(center, circle closest-side, hsla(205,100%,70%,.3), hsla(205,100%,70%,0)); } +@media (min-resolution: 2dppx) { + .urlbar-history-dropmarker { + list-style-image: url("chrome://browser/skin/urlbar-history-dropmarker@2x.png"); + -moz-image-region: rect(0px, 22px, 28px, 0px); + } + + .urlbar-history-dropmarker[open="true"], + .urlbar-history-dropmarker:hover:active { + -moz-image-region: rect(0px, 44px, 28px, 22px); + } + + .urlbar-history-dropmarker > .dropmarker-icon { + width: 11px; + } +} + #urlbar-icons { -moz-box-align: center; } @@ -1071,6 +1358,26 @@ toolbar[mode="icons"] #zoom-in-button { -moz-image-region: rect(0, 32px, 16px, 16px); } +@media (min-resolution: 2dppx) { + #page-proxy-favicon { + list-style-image: url(chrome://browser/skin/identity-icons-generic@2x.png); + -moz-image-region: rect(0, 32px, 32px, 0); + } + + .verifiedDomain > #page-proxy-favicon[pageproxystate="valid"] { + list-style-image: url(chrome://browser/skin/identity-icons-https@2x.png); + } + + .verifiedIdentity > #page-proxy-favicon[pageproxystate="valid"] { + list-style-image: url(chrome://browser/skin/identity-icons-https-ev@2x.png); + } + + #identity-box:hover:active > #page-proxy-favicon, + #identity-box[open=true] > #page-proxy-favicon { + -moz-image-region: rect(0, 64px, 32px, 32px); + } +} + #page-proxy-favicon[pageproxystate="invalid"] { opacity: 0.3; } @@ -1155,6 +1462,40 @@ window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"][s -moz-image-region: rect(11px, 32px, 22px, 16px); } +@media (min-resolution: 2dppx) { + .ac-result-type-bookmark { + list-style-image: url("chrome://browser/skin/places/star-icons@2x.png"); + -moz-image-region: rect(0, 64px, 32px, 32px); + } + + richlistitem[selected="true"][current="true"] > .ac-title-box > .ac-result-type-bookmark { + list-style-image: url("chrome://browser/skin/places/star-icons@2x.png"); + -moz-image-region: rect(0, 128px, 32px, 96px); + } + + .ac-result-type-tag { + list-style-image: url("chrome://browser/skin/places/tag@2x.png"); + } + + richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-icon { + list-style-image: url("chrome://browser/skin/actionicon-tab@2x.png"); + -moz-image-region: rect(0, 32px, 22px, 0); + width: 16px; + } + + richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-box > .ac-action-icon { + -moz-image-region: rect(22px, 32px, 44px, 0); + } + + window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"] > .ac-url-box > .ac-action-icon { + -moz-image-region: rect(0, 64px, 22px, 32px); + } + + window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"][selected="true"] > .ac-url-box > .ac-action-icon { + -moz-image-region: rect(22px, 64px, 44px, 32px); + } +} + .autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) { color: GrayText; } @@ -1231,6 +1572,44 @@ window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"][s -moz-image-region: rect(14px, 28px, 28px, 14px); } +@media (min-resolution: 2dppx) { + #go-button, + #urlbar > toolbarbutton { + list-style-image: url("chrome://browser/skin/reload-stop-go@2x.png"); + } + + #go-button, + #urlbar-go-button { + -moz-image-region: rect(0, 84px, 28px, 56px); + } + + #go-button:hover:active, + #urlbar-go-button:hover:active { + -moz-image-region: rect(28px, 84px, 56px, 56px); + } + + #urlbar-reload-button { + -moz-image-region: rect(0, 28px, 28px, 0); + } + + #urlbar-reload-button:not([disabled]):hover:active { + -moz-image-region: rect(28px, 28px, 56px, 0); + } + + #urlbar-stop-button { + -moz-image-region: rect(0, 56px, 28px, 28px); + } + + #urlbar-stop-button:hover:active { + -moz-image-region: rect(28px, 56px, 56px, 28px); + } + + #go-button > .toolbarbutton-icon, + #urlbar > toolbarbutton > .toolbarbutton-icon { + width: 14px; + } +} + /* POPUP BLOCKER BUTTON */ #page-report-button { list-style-image: url("chrome://browser/skin/urlbar-popup-blocked.png"); @@ -1242,6 +1621,19 @@ window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"][s -moz-image-region: rect(0, 32px, 16px, 16px); } +@media (min-resolution: 2dppx) { + #page-report-button { + list-style-image: url("chrome://browser/skin/urlbar-popup-blocked@2x.png"); + -moz-image-region: rect(0, 32px, 32px, 0); + width: 22px; + } + + #page-report-button:hover:active, + #page-report-button[open="true"] { + -moz-image-region: rect(0, 64px, 32px, 32px); + } +} + /* social recommending panel */ #share-button { @@ -1303,6 +1695,23 @@ window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"][s -moz-image-region: rect(0, 48px, 16px, 32px); } +@media (min-resolution: 2dppx) { + #star-button { + list-style-image: url("chrome://browser/skin/places/star-icons@2x.png"); + -moz-image-region: rect(0, 32px, 32px, 0); + width: 22px; + } + + #star-button:hover:active, + #star-button[starred="true"] { + -moz-image-region: rect(0, 64px, 32px, 32px); + } + + #star-button:hover:active[starred="true"] { + -moz-image-region: rect(0, 96px, 32px, 64px); + } +} + /* BOOKMARKING PANEL */ #editBookmarkPanelStarIcon { list-style-image: url("chrome://browser/skin/places/starred48.png"); @@ -1530,6 +1939,21 @@ window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"][s display: none; } +@media (min-resolution: 2dppx) { + #editBookmarkPanel .expander-up { + list-style-image: url("chrome://browser/skin/panel-expander-open@2x.png"); + } + + #editBookmarkPanel .expander-down { + list-style-image: url("chrome://browser/skin/panel-expander-closed@2x.png"); + } + + #editBookmarkPanel .expander-up > .button-box > .button-icon, + #editBookmarkPanel .expander-down > .button-box > .button-icon { + width: 9px; + } +} + #editBMPanel_tagsField > .autocomplete-textbox-container > .textbox-input-box > html|*.textbox-input:-moz-placeholder { color: #bbb; } @@ -1575,6 +1999,25 @@ window[tabsontop="false"] richlistitem[type~="action"][actiontype="switchtab"][s margin: 0; } +@media (min-resolution: 2dppx) { + .panel-promo-closebutton { + list-style-image: url("chrome://global/skin/icons/close@2x.png"); + -moz-image-region: rect(0, 32px, 32px, 0); + } + + .panel-promo-closebutton:hover { + -moz-image-region: rect(0, 64px, 32px, 32px); + } + + .panel-promo-closebutton:hover:active { + -moz-image-region: rect(0, 96px, 32px, 64px); + } + + .panel-promo-closebutton > .toolbarbutton-icon { + width: 16px; + } +} + /* ----- SIDEBAR ELEMENTS ----- */ #sidebar, @@ -1653,6 +2096,16 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png"); } +@media (min-resolution: 2dppx) { + .bookmark-item { + list-style-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png"); + } + + image.bookmark-item { + width: 16px; + } +} + .openintabs-menuitem { list-style-image: none; } @@ -1678,6 +2131,21 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { list-style-image: url("chrome://browser/skin/tabbrowser/loading.png"); } +@media (min-resolution: 2dppx) { + .tab-throbber, + .tab-icon-image { + list-style-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png"); + } + + .tab-throbber { + list-style-image: url("chrome://browser/skin/tabbrowser/connecting@2x.png"); + } + + .tab-throbber[progress] { + list-style-image: url("chrome://browser/skin/tabbrowser/loading@2x.png"); + } +} + .tabbrowser-tab:not(:hover) > .tab-stack > .tab-content > .tab-icon-image:not([selected="true"]) { opacity: .8; } @@ -1844,6 +2312,22 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { -moz-border-image: url(chrome://browser/skin/tabbrowser/tab-bottom-normal-active.png) 0 11 fill repeat stretch; } +@media (min-resolution: 2dppx) { + @TABSONTOP_TAB_STACK@ > .tab-content, + @TABSONTOP_NEWTAB_BUTTON@ > .toolbarbutton-icon { + -moz-border-image: url(chrome://browser/skin/tabbrowser/tab-top-normal-active@2x.png) 0 22 fill repeat stretch; + } + + @TABSONTOP_TAB@:hover > .tab-stack > .tab-content:not([selected="true"]), + @TABSONTOP_NEWTAB_BUTTON@:hover > .toolbarbutton-icon { + -moz-border-image: url(chrome://browser/skin/tabbrowser/tab-top-hover-active@2x.png) 0 22 fill repeat stretch; + } + + @TABSONTOP_TAB_STACK@ > .tab-content[selected="true"] { + -moz-border-image: url(chrome://browser/skin/tabbrowser/tab-top-selected-active@2x.png) 0 22 fill repeat stretch; + } +} + @TABSONBOTTOM_TAB@:hover > .tab-stack > .tab-content:not([selected="true"]), @TABSONBOTTOM_NEWTAB_BUTTON@:hover > .toolbarbutton-icon { -moz-border-image: url(chrome://browser/skin/tabbrowser/tab-bottom-hover-active.png) 0 11 fill repeat stretch; @@ -1870,6 +2354,24 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-inactive.png); } +@media (min-resolution: 2dppx) { + #TabsToolbar::after { + content: ''; + display: block; + background-image: + url(chrome://browser/skin/tabbrowser/tab-top-normal-active@2x.png), + url(chrome://browser/skin/tabbrowser/tab-top-hover-active@2x.png), + url(chrome://browser/skin/tabbrowser/tab-top-selected-active@2x.png), + url(chrome://browser/skin/tabbrowser/tab-bottom-normal-active.png), + url(chrome://browser/skin/tabbrowser/tab-bottom-hover-active.png), + url(chrome://browser/skin/tabbrowser/tab-bottom-selected-active.png), + url(chrome://browser/skin/tabbrowser/tabbar-top-bg-active.png), + url(chrome://browser/skin/tabbrowser/tabbar-top-bg-inactive.png), + url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-active.png), + url(chrome://browser/skin/tabbrowser/tabbar-bottom-bg-inactive.png); + } +} + .tabbrowser-tab:focus > .tab-stack { box-shadow: @focusRingShadow@; } @@ -1977,6 +2479,13 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { margin-bottom: -8px; } +@media (min-resolution: 2dppx) { + .tab-drop-indicator { + list-style-image: url(chrome://browser/skin/tabbrowser/tabDragIndicator@2x.png); + width: 12px; + } +} + /** * In-tab close button */ @@ -2004,6 +2513,25 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { -moz-image-region: rect(0, 48px, 16px, 32px); } +@media (min-resolution: 2dppx) { + .tab-close-button { + list-style-image: url("chrome://global/skin/icons/close@2x.png"); + -moz-image-region: rect(0, 32px, 32px, 0); + } + + .tab-close-button:hover { + -moz-image-region: rect(0, 64px, 32px, 32px); + } + + .tab-close-button:hover:active { + -moz-image-region: rect(0, 96px, 32px, 64px); + } + + .tab-close-button > .toolbarbutton-icon { + width: 16px; + } +} + .tabbrowser-arrowscrollbox > .scrollbutton-up, .tabbrowser-arrowscrollbox > .scrollbutton-down { -moz-image-region: rect(0, 13px, 20px, 0); @@ -2059,6 +2587,43 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { opacity: .5; } +@media (min-resolution: 2dppx) { + .tabbrowser-arrowscrollbox > .scrollbutton-up, + .tabbrowser-arrowscrollbox > .scrollbutton-down { + -moz-image-region: rect(0, 26px, 40px, 0); + } + + .tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-locale-dir(ltr), + .tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-locale-dir(rtl) { + list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-left@2x.png"); + } + + .tabbrowser-arrowscrollbox > .scrollbutton-down:-moz-locale-dir(ltr), + .tabbrowser-arrowscrollbox > .scrollbutton-up:-moz-locale-dir(rtl) { + list-style-image: url("chrome://browser/skin/tabbrowser/tab-arrow-right@2x.png"); + } + + .tabbrowser-arrowscrollbox > .scrollbutton-up:hover, + .tabbrowser-arrowscrollbox > .scrollbutton-down:hover { + -moz-image-region: rect(0, 52px, 40px, 26px); + } + + .tabbrowser-arrowscrollbox > .scrollbutton-up:hover:active, + .tabbrowser-arrowscrollbox > .scrollbutton-down:hover:active { + -moz-image-region: rect(0, 78px, 40px, 52px); + } + + .tabbrowser-arrowscrollbox > .scrollbutton-up[disabled] > .toolbarbutton-icon, + .tabbrowser-arrowscrollbox > .scrollbutton-down[disabled] > .toolbarbutton-icon { + -moz-image-region: rect(0, 26px, 40px, 0) !important; + } + + .tabbrowser-arrowscrollbox > .scrollbutton-up > .toolbarbutton-icon, + .tabbrowser-arrowscrollbox > .scrollbutton-down > .toolbarbutton-icon { + width: 13px; + } +} + .tabbrowser-arrowscrollbox > .scrollbutton-up:not([disabled]):-moz-locale-dir(ltr), .tabbrowser-arrowscrollbox > .scrollbutton-down:not([disabled]):-moz-locale-dir(rtl) { border-width: 0 2px 0 0; @@ -2131,6 +2696,34 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { -moz-image-region: rect(0, 54px, 20px, 36px); } +@media (min-resolution: 2dppx) { + .tabs-newtab-button, + #TabsToolbar > #new-tab-button, + #TabsToolbar > toolbarpaletteitem > #new-tab-button { + list-style-image: url(chrome://browser/skin/tabbrowser/newtab@2x.png); + -moz-image-region: rect(0, 36px, 40px, 0); + } + + .tabs-newtab-button:hover, + #TabsToolbar > #new-tab-button:hover { + -moz-image-region: rect(0, 72px, 40px, 36px); + } + + .tabs-newtab-button:hover:active, + #TabsToolbar > #new-tab-button:hover:active { + -moz-image-region: rect(0, 108px, 40px, 72px); + } + + .tabs-newtab-button > .toolbarbutton-icon { + width: 40px; + } + + #TabsToolbar > #new-tab-button > .toolbarbutton-icon, + #TabsToolbar > toolbarpaletteitem > #new-tab-button > .toolbarbutton-icon { + width: 18px; + } +} + #TabsToolbar #alltabs-button { list-style-image: url(chrome://browser/skin/tabbrowser/alltabs-box-bkgnd-icon.png); -moz-image-region: rect(0, 17px, 20px, 0); @@ -2145,6 +2738,26 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { -moz-image-region: rect(0, 51px, 20px, 34px); } +@media (min-resolution: 2dppx) { + #TabsToolbar #alltabs-button { + list-style-image: url(chrome://browser/skin/tabbrowser/alltabs-box-bkgnd-icon@2x.png); + -moz-image-region: rect(0, 34px, 40px, 0); + } + + #TabsToolbar > #alltabs-button:not([disabled="true"]):hover { + -moz-image-region: rect(0, 68px, 40px, 34px); + } + + #TabsToolbar > #alltabs-button[type="menu"][open="true"]:not([disabled="true"]), + #TabsToolbar > #alltabs-button:not([disabled="true"]):hover:active { + -moz-image-region: rect(0, 102px, 40px, 68px); + } + + #TabsToolbar #alltabs-button > .toolbarbutton-icon { + width: 17px; + } +} + #alltabs-button[type="menu"] > .toolbarbutton-menu-dropmarker { display: none; } @@ -2158,6 +2771,12 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png"); } +@media (min-resolution: 2dppx) { + .alltabs-item > .menu-iconic-left > .menu-iconic-icon { + list-style-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png"); + } +} + .alltabs-item[busy] > .menu-iconic-left > .menu-iconic-icon { list-style-image: url("chrome://global/skin/icons/loading_16.png") !important; } @@ -2187,6 +2806,25 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { -moz-image-region: rect(0, 48px, 16px, 32px); } +@media (min-resolution: 2dppx) { + :not(#sidebar-header) > .tabs-closebutton { + list-style-image: url("chrome://global/skin/icons/close@2x.png"); + -moz-image-region: rect(0, 32px, 32px, 0); + } + + :not(#sidebar-header) > .tabs-closebutton:hover { + -moz-image-region: rect(0, 64px, 32px, 32px); + } + + :not(#sidebar-header) > .tabs-closebutton:hover:active { + -moz-image-region: rect(0, 96px, 32px, 64px); + } + + :not(#sidebar-header) > .tabs-closebutton > .toolbarbutton-icon { + width: 16px; + } +} + /* Bookmarks toolbar */ #PlacesToolbarDropIndicator { list-style-image: url(chrome://browser/skin/places/toolbarDropMarker.png); @@ -2235,6 +2873,21 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { -moz-image-region: rect(128px, 64px, 192px, 0px); } +@media (min-resolution: 2dppx) { + #identity-popup-icon { + list-style-image: url("chrome://browser/skin/identity@2x.png"); + -moz-image-region: rect(0px, 128px, 128px, 0px); + } + + #identity-popup.verifiedDomain > #identity-popup-container > #identity-popup-icon { + -moz-image-region: rect(128px, 128px, 256px, 0px); + } + + #identity-popup.verifiedIdentity > #identity-popup-container > #identity-popup-icon { + -moz-image-region: rect(256px, 128px, 384px, 0px); + } +} + /* Popup Body Text */ .identity-popup-description { white-space: pre-wrap; @@ -2279,6 +2932,14 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { list-style-image: url("chrome://browser/skin/Secure-Glyph.png"); } +@media (min-resolution: 2dppx) { + #identity-popup-content-box.verifiedIdentity > #identity-popup-encryption > vbox > #identity-popup-encryption-icon , + #identity-popup-content-box.verifiedDomain > #identity-popup-encryption > vbox > #identity-popup-encryption-icon { + list-style-image: url("chrome://browser/skin/Secure-Glyph@2x.png"); + width: 24px; + } +} + #notification-popup-box { position: relative; background-color: #fff; @@ -2291,6 +2952,12 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { -moz-margin-end: -8px; } +@media (min-resolution: 2dppx) { + #notification-popup-box { + -moz-border-image: url("chrome://browser/skin/urlbar-arrow@2x.png") 0 16 0 0 fill; + } +} + @conditionalForwardWithUrlbar@[forwarddisabled] + #urlbar-container > #urlbar > #notification-popup-box { padding-left: 7px; } @@ -2323,6 +2990,12 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { list-style-image: url(chrome://browser/skin/Geolocation-16.png); } +@media (min-resolution: 2dppx) { + #geo-notification-icon { + list-style-image: url(chrome://browser/skin/Geolocation-16@2x.png); + } +} + #notification-popup .text-link, .panel-arrowcontent .text-link { color: #0073e6; text-decoration: none; @@ -2344,6 +3017,12 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { list-style-image: url(chrome://browser/skin/webapps-16.png); } +@media (min-resolution: 2dppx) { + #webapps-notification-icon { + list-style-image: url(chrome://browser/skin/webapps-16@2x.png); + } +} + #plugins-notification-icon { list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric-16.png); } @@ -2358,6 +3037,12 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { list-style-image: url(chrome://browser/skin/Geolocation-64.png); } +@media (min-resolution: 2dppx) { + .popup-notification-icon[popupid="geolocation"] { + list-style-image: url(chrome://browser/skin/Geolocation-64@2x.png); + } +} + .popup-notification-icon[popupid="xpinstall-disabled"], .popup-notification-icon[popupid="addon-progress"], .popup-notification-icon[popupid="addon-install-cancelled"], @@ -2629,6 +3314,25 @@ toolbarbutton.chevron > .toolbarbutton-menu-dropmarker { -moz-image-region: rect(0, 48px, 16px, 32px); } +@media (min-resolution: 2dppx) { + #addonbar-closebutton { + list-style-image: url("chrome://global/skin/icons/close@2x.png"); + -moz-image-region: rect(0, 32px, 32px, 0); + } + + #addonbar-closebutton:hover { + -moz-image-region: rect(0, 64px, 32px, 32px); + } + + #addonbar-closebutton:hover:active { + -moz-image-region: rect(0, 96px, 32px, 64px); + } + + #addonbar-closebutton > .toolbarbutton-icon { + width: 16px; + } +} + /* Status panel */ .statuspanel-label { @@ -3368,6 +4072,12 @@ html|*#gcli-output-frame { list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png"); } +@media (min-resolution: 2dppx) { + .social-notification-icon-image { + list-style-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png"); + } +} + /* === end of social toolbar button === */ /* === social toolbar provider menu === */ diff --git a/browser/themes/pinstripe/devtools/debugger.css b/browser/themes/pinstripe/devtools/debugger.css index 4de928e9c372..9b8fb49a5d93 100644 --- a/browser/themes/pinstripe/devtools/debugger.css +++ b/browser/themes/pinstripe/devtools/debugger.css @@ -299,6 +299,14 @@ opacity: 0.5; } +@media (min-resolution: 2dppx) { + .variable[non-writable] > .title:after, + .property[non-writable] > .title:after { + background-image: url("chrome://browser/skin/identity-icons-https@2x.png"); + background-size: 32px; + } +} + #element-tooltip > label { margin: 0 2px 0 2px; } diff --git a/browser/themes/pinstripe/downloads/downloads.css b/browser/themes/pinstripe/downloads/downloads.css index f468d376b854..bc909af7d179 100644 --- a/browser/themes/pinstripe/downloads/downloads.css +++ b/browser/themes/pinstripe/downloads/downloads.css @@ -206,6 +206,17 @@ richlistitem[type="download"][state="1"]:hover { 14, 34, 34, 14); } +@media (min-resolution: 2dppx) { + #downloads-indicator-icon:not(:-moz-lwtheme-brighttext) { + background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 0, 280, 40, 240); + background-size: 20px; + } + + #downloads-indicator:not([counter]) #downloads-indicator-counter { + background-image: -moz-image-rect(url("chrome://browser/skin/Toolbar@2x.png"), 0, 280, 40, 240); + } +} + /*** Event notification ***/ #downloads-indicator-notification { diff --git a/browser/themes/pinstripe/identity-icons-generic@2x.png b/browser/themes/pinstripe/identity-icons-generic@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..5cce49f892e81a5f8036cce30df6be00e991452d GIT binary patch literal 1235 zcmV;^1T6cBP)R*$K7%{i^c&7;x7hFujZ z`l?sM38egbU(@7$f6(DQvuN=}7rax&N52H<^_Kc>ed;jfygt8oTL>AAZn@2Z-G+dX z3g7Qh^%!%?UcXilLM&&&LWPf>2eJn3==2z1QBmxo^D4VfqjL&e(q|Dy2)^4>fIAk| zddnYG_8B>+%m+{O3*Z??V_&fvK*4o+=af{|?H(uLJC4Cf@LA7j1Tb&HM@}iKtlxGo z2Tz}AS>fXZ9@j}r;Nw;+DOj%S zavFV1r^lTncleNwTdAChkGN*bCvbG!GAt-ybHaKlc!Kg(us@JT}F0Yq;oWNG@ z7&Bu+LG_?TyF{&otx)!E8#ZCYyy`)lO%khvkB$*3`44;0U0N{Z4XBZf{#X8Uy0l`< zOJyH_l5Ny(!31c~q*;PQ*-1X}#5VfaC}_6U+Okgo(GkeYNtLzAO(oRZ;0oy13%KGm zv)1ro6`oD!OBHUu8^Fkr}uvX2uOwo7QI7Jt)igMvS4QycacC4dPD!;tnosMRTb zy4>`dyVM~8OTmu>AD7_mFhGZXv|3}rtVd>{#z31cb$h=+tw@S-^Y>$JIC;o}5&&Otj!ylb0S$PM?KHwdz3MM`kV zb3odk)h8=t+8%QTK%HqdDIfi~;)eouctB-;b_L|L%ln9e-7Wy*Y3~7hRraPK&}M@v z*D8GUBcZ1pm!ZLvYK7eJnk9WUy6vDO9+38AtygqSNu*h9rizcgzud#(yEaM3hYowz5~%?z@-@;eIcBpb x9Cg+lm~+-qPuT2enzK?Leb37J*Z=$L_}_|I(s$=3_QwDK002ovPDHLkV1h%aV~zj- literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/identity-icons-https-ev@2x.png b/browser/themes/pinstripe/identity-icons-https-ev@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..b8d54de6582bfe6cdb473273a47fb7bc4ad479a6 GIT binary patch literal 1162 zcmV;51ah zr6UYs)?*?BBNC)FpuDEI6HvfwdUviucN_0s6kPbGP*z%#qWhh&au++ZI7xv6*I^}G#7~^ ziwT0+Ab4@uO<$xJa2hesH_CD!pyzs%H;`oz6p+c&J&P#(zM$*f@YH4KJ5%jnw65?; zZNr{x8(r&v!`}gh5ON8f!lEhVhd_Ci^aIWU#Dti;0{ZME;Aw1)MW;`dA9*!#*XIj% z!8T&@?TP632Rq&lP2YhvCCqA^$X)Q4!#n|CBsT#^sIiztGoUw17tn&9%zVCZd}!)Q zcsYD91@St-+*(+3i4jo1WI2rVO-sOqLAQsUD&FJ^pcCL?=wxGf&Z*ei?5rT}0^W~v z9^X=+gSx5)@cD0Lpef*{E1W{b5p3#hx%>|H=( zkIxUd2cRDZRIxD!3zj`uME|%2{FwjM6>}|3sN|ThKfM1;$>xoJm`{@fb)MG?zZWOR z2B&UEBhhm0aOqn2-pU#DRS@~lp=g4DR?fUHamvRU9iz{=U=l5T;}F8JC znBcO%c-p($v-3TkOV^^@fhRyPYXMFyw712(m~1XQTjDIh`5)#VJ2^F~N|;pFruBa0 zzA{RR$Ocz&0MCuBU9kY!$O6*G041{smg#&00&wOhtI7YD(UjNkpEzGO$R35XiO{)c z)g#ayvM9A3z18-)F-0PzDNfC`7~txEIQ$?SitMvubJ;0Pw;yXd4nJw&^s%@>6C*`R zagtUkPfQTW`@b9tTBAH|OqOgE2&EjD^8dPkBL?fs6poByKpyHOx_^Jw+z=p|4}!|7 zE3YFV2NuXHFWAunP;kzz{PZrc`Y|9cEx8Niw^mA4t5|DW3s|lF?Gyu4U5;=4{)VOU z6fPj-LwO}$;kBLszErN-(E{S-?Ht4aTqZYT0eK@J!ipDGH?1(Lm@0_C0gPr)15AfE z8Js>XbOfRD^TDe9LDnRd$zgihLE8=d|j@P c#9IXN7ryS1^94Aj;Q#;t07*qoM6N<$g7=#$8UO$Q literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/identity-icons-https@2x.png b/browser/themes/pinstripe/identity-icons-https@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..2ca81aa61c5962197aa2dbb6f005e54ade6c35b7 GIT binary patch literal 1077 zcmV-51j_q~P)Bg5`&b}l9Kc@n?0S}-8UZRcusx;>&TbcRSyyP>q zc(HI?a654h=wSbDV?r1bK|Z64@1VsC&NCrQiC|iQm6eqtU+3rR+<(O}oMS?Gjfh}afaT?76?hK^R|0qj3<6%lM`H=F2?6aE zh#=E`u2epqPG5{fB5!tgch@qR%;RFQcop)g2;BGM7|wys+hj6%nRSAj3D8&vghC-q z^ce^Mvd*cFbF;u2`dF~|O7&Bz)P-m?`Z1f$KB|`=Y#zj7u@C6Ox}c^Ah6I4X?|{1| z9&dMmC9C#6Ea+9CP`G6@2-y0;=cSRepsoPHU~srpD$N2e#vfo3xI|3S7`J(fzRh+( zB9Rz|_I}7?!}YJXxA*zz=;&<(?{SRVfX@{AHr)YG$!S1g)%^|J3TczuDE*l|=9!$8e5s2lQpwP&gB0#@pQJXrp zUo^J;O&)+A*w0t^`7$st@Iy2wrX=v*<@5Ps+!lRBoLbw!$QDp}(1nGC{aUs#m(m=D zYJ=4m2cQRHcz8^xa+-WZmx$`RIy*Zvn*1InfKsgsjC6oYa{yUtUt|9tS4}6Lo1XP; zbYCmKTO)#OXbUVZE=GZ}HXx4aQNuoJV)2#AhQr}ctE;PVZ9E*)qnbU&Vx4kA1X-t& zW7=R%FlP1%kk99DSoO+{v1&aDWTUOzEGEu@N|kKLFRCv&Q2>4jR{q+MU)JQ1oYn!n zD3aB`Jh80b0}nWq}R(%M8a0 zP_iL^$&>)6yajl5iuihKL;eEAKG6wIIs?S(ZIRybt-g*Zc8Pa^o&eu06yUoF0kBee zMN#5b<%d{5F($<}CIGy_jRTTJjG3(d;mpj;{kgfhKHwTK2n+$k1{oqB^zDOK_b_I) zE^yNS42k_;q-y1W43GlwC$N2!9FT8@V&z%<`W?`M#S02z8_);O0_g_Hvc-$I#ty+2 vT_tu79MK0qB!n17$T7dX_~DerKfeA0R8}{cfW~}=00000NkvXXu0mjf1kC)p literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/identity.png b/browser/themes/pinstripe/identity.png index 2480f5b74746945efe535d32820ce45fa8965b86..99db29c752183a9c74aa6d757299633ed6c471d7 100644 GIT binary patch literal 13607 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 diff --git a/browser/themes/pinstripe/identity@2x.png b/browser/themes/pinstripe/identity@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..f95b18ae98695daacec9fc5c3b545a858456098e GIT binary patch literal 33250 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.7 diff --git a/browser/themes/pinstripe/keyhole-circle-lion@2x.png b/browser/themes/pinstripe/keyhole-circle-lion@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..bfd4b7d09471c94ecb3d99e840c0ac8438bbf181 GIT binary patch literal 5642 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 literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/newtab/controls.png b/browser/themes/pinstripe/newtab/controls.png index 14f382fbdd18a1209f3dcd63831014b5ad2fc428..f42794644f4dc2b4ae69534a8c8cce352afc0092 100644 GIT binary patch literal 4671 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 JF4MG&_#f2%Xxab( literal 4180 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 literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/panel-expander-closed@2x.png b/browser/themes/pinstripe/panel-expander-closed@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..0e7ded50f4143b22ec7ecbd831f33b07f8d3a339 GIT binary patch literal 362 zcmV-w0hRuVP)&O`qVFwY z--2k_tt8Q=uQ(a2CEA*Hd6T|@Rh z&LEBWjgwrcW{{LpHwn(ujK5LgQa*E*;38%Gj}C@7M;pex0osjr2JJ-x4*&oF07*qo IM6N<$g0z^DmUbF>|{_mBMVYuz!SC;Voxy{$EB1m3&rs zhJ}{!beyD*j=#ivwktm39ET|2QtG#N=$&G8(0#ilKfpr4-&i(LL~HK;PN#cu3#f2 zmHK&Z(nS|HUUE_yDcCFRQGia2{h=l-?7`?18KV~f=wY-|gn=aNP;=}@u#6sRs5Gk7 zsr;_=QEyaHK^?td8B`cyf^kNvO&kU_Mj2;<5h~v@1#mNpUWG>h0000h-!IXFPLBpemIL!Z2(}6AITs38%k{xa>+p=)BzS88ZFdc#-rFk15zznd{h1uqthS zF^58_15VEXynoc7`SCtJgG zvlx9H$Ct4_l>8f0-F01~Kw1L!MisZkD||{P0HIs*gaQ4jOwuGXrdq99#fCsq5=jUi zZ0sDP85Z%x;6CV pApS9#x2mM^hXlC04W9fO{{q52_lSVR30eRE002ovPDHLkV1lks>pTDe delta 379 zcmV->0fhdH1eF7jBYyxHbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBUz zH%UZ6RCwBA{Qv(y10{fwVgtm)#OeeE1@Dog`R&`cnvBbqE&Fe7Zcdi%Cr_SaVEO+2 zJHwYRU&t~5q?hI2zkduMj1BBQcppr=+ACs}2kB$^^XCu4?|~uXJC(P)r8#fByW)5b4eW=I=lLk>T67Zx~?!(u*??%aYlEPJ9Mtn`-eg zJbCgPdmw@cbQgfYy?cnn`TF&1tkDS4%V=wB`(IR4l&pjVGMEuaivck^nR)3a#kmn6 ZzySHlw21z)?iBz4002ovPDHLkV1kONwVMC{ diff --git a/browser/themes/pinstripe/places/bookmarksToolbar@2x.png b/browser/themes/pinstripe/places/bookmarksToolbar@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..dd458981e276b8144fd2db789f8e637857f51990 GIT binary patch literal 1179 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 delta 535 zcmV+y0_gqA2CoE=BYyw{XF*Lt007q5)K6G40000PbVXQnQ*UN;cVTj606}DLVr3vn zZDD6+Qe|Oed2z{QJOBUz!AV3xRCwBA{Qv(y10{e3U7(|*lLtr@0kH=Vn?Z$70r3tX z?yIOM|AMTZ5!nT;t!?(q%*+c64Gk4EH8mKdrKQ2*PoF+zxPN~A2E+OD=O6t2`!}Jw zy6PZY6UYD%ZftA{?Cb0Q|NQy$|1dCT&Yb_q03-)e15yjq#{@E@uC87P$XOH>70DnW zApth{*|TR1KY#v2@g7JHqz0rGqz5DhHsJT~-$g)Y^N5R!qiFc{?Hfj*fz*K1g7hF8 z;H|5xgQ57#mwzu!}sss8FuX0fg%3q z&mWK;W@H2IKYaKQLt#x#4a3EY7a1l@n1JG%Cr_S$^xQ%A!qyWfPGE#M8yg!#Qc@Cw zii!$De}6y2$B!Suav-%JJ;(-3+_7Wlm&cDE!wq0!Vt--~78YjU;NV~|H8o{ONJwDd z=jUetsR5}4=|M?I!NDORsi|rIfnNEK4uH-D(;zvJ8jxC;K9r;!5D@6f%E~&+!^2&{ z!oq?S&_4NZ~rcxZ4seAM0O}H}?IRGHQ Z0NC3m(hxkZMV zQITbaeHjKAMNniB6l6d^0Rd&$Mg~vM|E8Zx1O=JoA3p9q=l8$M`R?425z%`U5FGY3 zYd6b>by(7gQ)m34H`@?{SmdmS{T}1cFIe_0-(%qse#NDl_`d#!I+MvXvb?;!ME`&A zj5hQk2C>LNE*KjgfPc`jEv)S<-_YYH{cqoCFE*RaGqlbRVv&PfFu($HJp+LGN31_t zM{@ECqUPr2#wGBQ#X<{O5F>q%n^$l(8Z0oue&+y=28L{5{l)UD z*EM8G%M9?d=QA`p{fzGQ-lv+ndb(D4ow9RsDK{^lii%6nhCaj~7CF-PSik}kYOmI2W4jGP<%onB_&^^Y<|9S^%`Bda+NZ(veAY< z#2^+qB6n#?%;6=NV8dh80dUoP$@0(4&W*vS7Zw+3Y~m>mk3OctqGF1RPXJuZl=qkJ z_x005;~@1t9H5^256~w1vN#5@$U*Md_ymCkCfM+R*INVNO>ztgJ$`I#3Bc|V1NZC*zkbYiUIf@ z4g7``)N-p;Yc{{2q2Uo4ExS|a)h(!+XI~ZUICfMv@f){(*iUAxx;{ORNxKvY?H8nj=y$|}to?c8zrTl^` z*ke)IT#yW3UZJS-(G(pM`&K(*k%Qay6<1REaOvhpnU41u@I$M@*>tgr`t{jCV- z;yu*y@|};4p&K__L=i16E@EbH>G+8g6c!e~Y9Dft%iD@Uf+^VWfEPUBE%WyE`;`?w zJUlvnx1)=oYlTH()V=&(PfbnZRa#YEUf!hkIJ9Oza__TY>ZLTnl=$$1C%k1|hmTmX zP7DkVF17Ki1YJr?r$R0s?BmRgiC(-|T2*p|BiZh^TeBazU|cUM7EFl`FL=UR=IP^W z9}pCBx}&R`Zt`+L7m|{xvbu&wpN!FrX%?p%Yf)%^Vd0hb?A=E@{@5x0THDx?!qJI5 zc~!!~!zm&00##I2iQ=oStrJX%4=;GaTjuF~_+UU_@L2=zcaz};B$BIm0FQY9;}cKU zl$W=U7{IRGR-q-R_fOoT3gOV1L+#{;vCSFmE%}NF@BJct1Yhp zOE4uqyx<9MaTKf6hg_Uhp7BMcnz^!yN(6}_jEsz;*0$TI1)j~54GDYScKZ&m$v~I0vhn)x;n695tF22Ia7SmCD7?#= zS%M{T;Q=r9-1d3^D)knnO6{j`Ri_r0YG*2|Yl+1(Xs6_hsg#_YB4#sS9K_7lG)5m{ za5qRvO`{~_@w3EZwn^@yPK6gdSKJ4bZth>no!nxBLnBIRYU`J4>QJ!_JdHB!E4nknTt}j(@yS^ z92pbe+|bxakiMyjdU|_F&(GKn94NSGU|*Y>4cy*D6}-1NbP_KlAqKG`r?I)2Bo3Hh z!(+`mp{vqutE010Y3tye5)+qbXg1tfHr%*L5b9vSXrwkSN{zORa(ECpE7H?5C_ldd zZ75j8h*&AF$zXU17MRR-g~vOuGFZhL)B&e$AG}uSjEMNRqp#vY|KI5QA9cAa@f#PT$sV zyX-#OW$mziw~d268+h-rl?Ot2MjQGNvk|83^B;F^Mq8lGF#ZE_Rn=mqA|HqV0000< KMNUMnLSTa2xs%oa literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/places/organizer.css b/browser/themes/pinstripe/places/organizer.css index 832c2477ef3c..bcc1e176e81e 100644 --- a/browser/themes/pinstripe/places/organizer.css +++ b/browser/themes/pinstripe/places/organizer.css @@ -108,6 +108,16 @@ -moz-margin-end: 2px; } +@media (min-resolution: 2dppx) { + #placesToolbar > toolbarbutton[type="menu"] > .toolbarbutton-menu-dropmarker { + list-style-image: url(chrome://browser/skin/toolbarbutton-dropmarker@2x.png); + } + + #placesToolbar > toolbarbutton[type="menu"] > .toolbarbutton-menu-dropmarker > .dropmarker-icon { + width: 7px; + } +} + @media (-moz-mac-lion-theme) { #placesToolbar > toolbarbutton[disabled="true"] > .toolbarbutton-icon, #placesToolbar > toolbarbutton:not(:hover):-moz-window-inactive > .toolbarbutton-icon, diff --git a/browser/themes/pinstripe/places/query@2x.png b/browser/themes/pinstripe/places/query@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..20b458aaca5ec3f06510c9d12ea1ffb70a48fe67 GIT binary patch literal 1055 zcmV+)1mOFLP)j^kjC$jL@b!64@}7{iFDr9^7oWG!d(Ly7&$ov(L1Q(v z?JEDP09s<5Kn^SuuRqlQQl2~i5HCH=0AQk>^N*$0nNUJ35YPU{00B*2-fR2`CK8%| zEa8qhI2|$WXCi$5Nnp3eVhCu7^#dPxQBu^3CeKh#G}I>X$^J&rxhI01?ABQHfpr2V zT`P_si=)Y%&Kd6Ka|a5%TZWzN<^W)R`hFdY^MCIM>{7fk0B!6f8v~pNbL+d`@$K|) zn7aNDlVfY!0?%d#yA-bsaC7RBU}AJNXWo9Rh}p^+>B$IiWAc$;d}LLX6YdxSzG3;U zEA%q*z4gmMxa-54&5#}$z)TNjdg7sA?An8@GzCK(BMd zb+nE4T+r^VfVZJXZI1K^uLw|d4$L>>Yl5%S_p{Q`HV&iyBDidR!Y4`w8N zUoaTIn?e4&4w#D1&~-=Ys*@-w_Mta2EBE`TrZwK<9`5Bc*=9+P;*|lerS1s^F5k&u zVsuSlFAvgH_oLL>4zsZt;fpiq4*keAuhHHW>S>q#S!OAo4FPn1FzMuqARb#%rLHE1 zO1l7h-6{IXxfrg+TE*cWG}QHNHbZ(8F9q;{NhR(IE=Lx!;;D<{;}1P>lt*yH7KOd6 z8@AFehHIA7UYL5^_`;h~nDdtA3>bgQ3<9TrMzi~eZG|1| zQoNet!qz{HRO|-i{!63HuPoRyJhvzB1>zOr)g9(#;zbVd4DmdXx5MmV Z_rJhNzO~NC{we?f002ovPDHLkV1l@m15*G1 literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/places/star-icons@2x.png b/browser/themes/pinstripe/places/star-icons@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..a6b1100148c4c956301096f5e66e0a18e1ca8a93 GIT binary patch literal 4458 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 literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/places/tag@2x.png b/browser/themes/pinstripe/places/tag@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..673814bb5c3ce861368b9bfce05176ee9c3144be GIT binary patch literal 1593 zcmXAo2{e>z7{{mRlIrTv9WBZ*GiKkrjZjG=WXV=^Do5J1DAmjeU2C%M%#dvwvW+^0 z3}$R6gR%|cmM}^&V;Q^3a?gFM@BF{#d*A2#p7;4Z&-=Ym4)&JYGj(t8|4nRE*4;V1-UPSM%=EY9Yexq>?bCWabODFx!YVH1}v9G3?rbx z04R=(%gW_3E>1Z2nPf3%FfO%iGuqb=!S%A z?STIFUqR|cld$PDqV``pA$SzXy927jp%IfP_!J8MI#Mr=jPpbz!Gc^G!G-eE&!G{( z2Q*#XK%601A1IQD0sa^gCX|2z%qdj-4J0gqf{P$wz{>Zq$g=W^030%vN_bgTcG6%U zmz$PK#S2PHg9+%O;*#Rxl2|gfAR{9@EHsvcd&1A-^YhLj^zLI3j|dombRBH~U=qmK zn<$v0fgbSi>G6EzZkTEwsor!@v!(kCbGynzwEDZb(+Ta#SpJlv1ok|2GpmhMo z4FS7h2uq{k6OWm>!eOAUQ*gbr2>ok@`aUTAheUJ|84vs(NCR&)oP{;Ke}Lj=W)gri z3^;x?kb(yVhFLSh578q))ie@lT{IaRN5X;ah^G=jEZ|Ie^e`nk5fsY-ijCqPJIqZ> z;c`+z_Kb8+W(GGmJCm1_mG>k!?+GuD&nqm*7nBs020wVl=RGeKyzpn2y?jw#US1Ir zSXogn6bfsqt3)-`B9TZe7T4F;H`LWOG&D3eHokuSx~Zv2B9XMTw6wOiwiOq)wY9b9 z^V{3oJ32Z#J3G6&x};KRcXxMBPfu@e@4I*J`ouMTeSQ7?{qNtu|M20%z`(%Aj~@pI z2ZuV^hK7cQhlgcvT4gfX2++vLr%#_gfBrl=3N$)4Ha0#EG%lCR6$-_~#Kh#}YF!fXlg@u>F(8o8NlI4LqilAgQe2w2M-=T#;~-pv9)(_ za5;6})AQn0pL;A8+dnuYGAcSgH8ZbRAP|&Q)riEkb@dHD8v!~X?e6XE?+29)4a-J8 zfBEutT&@7DfN^I27uQdsRY3CJuPgA7iwQV_|5!7Qx)_}d@4D>f?5Nu^cM)g2M_Wb0 zX8Q_v?kpFH&Q2+tPrEQ2@w)e*p~ev^S)p>5FUsZWgSz6SK}W7hZi`H`@Zd;SkO;CC z6mHDMeVvp^X+g4N_gbHs%Qh_u9dAFh4!HBj;*s8T_mv4JL(yPfEn{-Tu~24ewBpD? zRs=-`YG18A%%16NyyvRCn2dhw?%6zB8cVYLQ}4Zw*4=3#TBAoV&W%EI<|vittLt7@ zwP|kJ?+CB-ev_KNN2l-r)@j_o2sUdxn4~Q0gzdltbdxfG$zUwfIW|$WL$6+L zRrzX4x#U`aR!{WtG}@wXTWL|}-z8<%$!h{aY-ZQ!R+1$A>cInZepox_o6o%}gSu6B zvD7gsgq}t+Lp*dz=!Ae@j-f^@Gbyd&yF(YEP*T>QS3;Dv{$^uKTX&k(?L;Hab^?s>b|CdTOTjtn;+|NPU%ok=9<}8NO4t{VBCqo%EuB z0_3c^dG)Op4W@&_d<*#*sTEpu@$vAbzJU^tCWk}x3Nh~gE5v0dq!r8%ooMOf(my}?=%7tQl#!Id}0M)LyKH@&OQn(Keq%m?QJVr^m1 Jcy8_y`agOR`||(* literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/places/unfiledBookmarks.png b/browser/themes/pinstripe/places/unfiledBookmarks.png index cf97942445c8413dfe678f9fca452a187e65f047..69495dac0f98c528bc1f12514de6f61ec41ed2d4 100644 GIT binary patch delta 562 zcmV-20?qx;183)^DrB1SJ-v=V}}=)EOz%EC7=a9PtacaHA$xaIWed8& z;NkiHp2J}+?KgLX{S*>8R2XFZe;EGWN6);wg+?O0$n$(k+??P~3GP5M`&o6Vh0lvb;Y(%BrC z4TzhqHrFI=Xv>z@lC05mU3vS-n?*UJteQhf`Qf6<6dV>-Vz}jfwWzsdKT2B`ib{+# zUb{Er4@#qNKYwFyWdpeGJ7^ks2%Y^gp-f%&=6%iM%lCkE!Z0{YTc)}=u*c?nFc*%c zpf>hmU!5NHW*1al9%%aR6Ux+OZ=9hA@~@-AF)~M6cIjXtL5QbNT6G*1oDnq_ z2B9=LP-k%y%GA*<`z9EXFg`IQG@R?Rvih^V&&BxqR(~X!LeAZ1K2+*^P<5uCP^OM< zc|uIulD98d?dfhlCZ+Ks6v6zGnDy@KJj&H=sL+@RW$NfwfVNDj@8T2dY4}5Hc?&@i zBjY}BZT76;F&}kwD?nRzq{YTd=?yHe#tZo6!IBUqlyiLn+Ois5yE~GQGD0kg?Ffp| zj6!?G!z&b8>p_`Y#&5@=lNQebm9dun-pK68ALCNB{B;sWHvj+t07*qoM6N<$f+o}$ A=l}o! delta 696 zcmV;p0!RJI1kVMKBYyxHbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU! zaY;l$RCwB)QcY+RK^T3z*=9H0C5@#>Z2jqv+6t+tpfm}J6oRx>krEUFB6v}$g2jv8 zJbLsZ=+UDh?XgOsic-<~L)AmINMlRW*u>~&w_DQg%&s$A41boS9{k`j-^{%C_SaMPVI^x*zK#;M8{!0AZub?0kr|L>cZx*EXT}zm>#;9*i-Joz_lA{Q2tyr(_fKE z>sTr}uuPYMt;X7F8V>RcIuw!y=W_-hi9}fBT(0p9&JPT#HX+G)Jk}hnB`E3!^0TX0{AQz&B`|f$Dxz?xi(iI; zpi05HT*I{@B{Ug}Mt9bS>Xf08=MW?XrdKk-kG$c*G;HY1Nb)Nfe*6NQ%Qajp5$2TW zKHBV;e1Et(nDQDLJvD_@yNH1L$=e&nPSn)YMu`TeONKo+tP*!xOK36ahgWD4QGXGq~%UI7ArY29>PO2zPC>>ZX@LI~8V2sbw2_`$Xc z9@lyXioa&v#r}>KXqtvEISYYcJ=z;&Yz@g3V==sDU~>bh;r<3v7>A!e<{wZqP5(g6G&Pz{Qm6s z#=>!$aZ+pgkcZ0YpaBWUvMjso!Y)uc+}*!-dYO%OkwZowu9;`^Ke=oE{HImaU$M zX5{tn`fjZD065@+)8he2rAHU?EF*JkPFD4s9l!r#veSjH@6fwxmCFJ<*o6ZwIN=_$ zI)ytzUvhLI{*3Ioa`R%pd6Mp$9F$StNt-qK%K|&tg##`)nSddyOSmI+2U-@A%*Y=H z$42jsItch^^Xc`7)MeqrN2vQh4O&LwgnQWL67Gn^{mt&IXJm6%Z#({eeYpPWEm|KO zzap>;2VBkFz3p%#V`Rc5R767Y5qDx3`OTgFTfbSRsDEsdbfrdm$v1LEU>6R!;Dj3) ze>*^1WK?;Mky(ZlhC%Dp!vS6buLW!9g)N~gVk3VA)dOdCb%y~N$THcd1rVCTCY2yY zUc7p{lu&n$bPXR- zQd19(0C=N@9%e9$9c5QrR7dYDmW{ZlKj3&*?|hrTxD+Sc$Uqh{$EWy!=$ymPGjd;5d(D_*`jLsR1eyYavb-T!OCj0y6q?&aI}2NA z*MT;Q;$OI@yn~`EP6518Lk}~U#SV5AhbG@Zsuvl^LMF1s?(AAWM)qF6eVIQAnH@6< z8vwrAI~w1GnNj18WX1#il!C5wBGD#vb zvpR>7cIWJzgPWePJ7;LnY@>Jd<>Z^p|JkG-qHSqaw2i|6-l(C68O&nGn-5vYM7D^? zFi2o=xae1tjqX0M{)2lXRvNO{$yZ-SZzq(})srEDZbbp)Rf-o&#z&2Q5Uk*T(L9#kOTu*pufDYUp7`nSGp3%@tv32PMGL .site-container > .site-favicon { list-style-image: none; } @@ -102,6 +108,12 @@ list-style-image: url(chrome://global/skin/icons/question-64.png); } +@media (min-resolution: 2dppx) { + .pref-icon[type="geo"] { + list-style-image: url(chrome://browser/skin/Geolocation-64@2x.png); + } +} + .pref-title { font-size: 125%; margin-bottom: 0; diff --git a/browser/themes/pinstripe/reload-stop-go@2x.png b/browser/themes/pinstripe/reload-stop-go@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..704c7a894af75b78a5016c08623da06ad64a31f3 GIT binary patch literal 1850 zcmYk7eLT}^AIH}rMxORSD>TdPu@%k`%F{eMOHQ^9Au>6bi6M)4c^He<+DRDqGLBj( zilSSGZu7Vkqng4_^037@c|7FgX>bw2UY@hV(7#q2&BBn$K4fA6)%W?y`)dj>H8CLq5zs>0F76EW9J7O zZPY~jZo}FlwAgkr!B{ou+cVdbQ>U*CN(TZoeWTO7Q=eq*4W@OMdsnKdF(r$3y;k}~ zs&^8?Wb4O1On>^+o<>-E*~0m&*y#v2Y02?^!-6oVv8`leXUQRRn>qq*|KdArA-K@T z)PL|DVnpF+a};GZjnm~bEbQB(yL`~8Q%y0Kv<|v-p}k0?>}nR~nUp^=%t^uwVU38b zHfz7XuKq%VJG&6xV~?LDcF2PYBg6^&^WgS}u=9hpGcXqMv``mmPr197>uPq&wS|`V zv-}s#y*glg$!qkh!{xm(; zx*NT{y_a2?DC=%1!=?Bij$4!bTqm_iE7L%$Ls-F2UYPOcEqoW|aTqyavLl;rr5xm0 zC;jY}ct&Tc)U2}-1Ox|D=BtClj;KWzJg$yik;}Fwve2`ywO|wb2t_Sm%2k9QB0-mO zH$EzV>uE{rX-IuzLHd_PnO0NVLD+BVMnB!Vma+BMhNV9PCzSfVEa0zdYl@%zI7AS< z2}Cu(e9hp95_?3V6#2L?~gR4~4wi)S1Odt;ChperwllL^mg)pKtG&It{C@)A8Vtq9Oxw)*D zNkc;%B4El&N+0Oxg?;0=!OvP)CTQ1(<=H=-ENm<1W=TW+fh+bL0E@VLilr| z45f$NI*M!>x`=8kYz++!y~8r{W=XmN?e8aYwQt>%FPLIWzX0(tg!Epn03wS!l?&HX_;PsdYu)KZt=s-1zW)j5MyfJcu-YdfI^owy_bl z|873tjmGz=eejeO8oj8QGQ&wqS5rC^OeaG_y5oM`Pt~*_))%!5|MPif&&s*;{iG{L zAElGX8?*KNd(Xw)fLo~3jqN$%mQ^9L(mcLO_kmU94!Wm5x+@fZ zMoI-Yo+vHfu}%GkGVJu*=j+Zp&;HMkMYXyISSe2t0IVi5Rj4lO7k))39W#_U!Z530 zfCJc`ii7~!@eA>=MXXLP7RRJ(QBD?h5yjbH%3Us5ynTPn#!l1TsqZ@VRUx_ia!9_p zPati#h^iMO9BC}WXNer)k1t4W5Q<{0ZR|$Zz%hXpEuYPS)ZBvq7q##nD$rvZ!er#g z4YDOmB8(KCTwCa3=b{Y>l+7x;+QM~-I#Q_#0iQ(C^j2+|qLr<(vp~tKHseG*iRh9` z$!heqf~CAVpI}8KpPr3YdWQ0n3zO$gZjb@k%noO^)NTld>8y`$*`x8M1!#|D)K!G3 zCojqt`AY)_fv+H^%}+KzVBKrPhM3&Ozbk!xmHP7UAbnny?YvMZMgswf%5uq+t<{~WmKe!04X_T5x}NR4 z^yNVN=2w)a`w|c7x2-ru1}%^Ayp(%)4a@pUz?ENyUUl!=Wnc}s+3Y=G&~JnujT0F< zPVBlB-m^QUI)>WIWD*O$O9^;EW#8r|>U|d41UmB$wHhbNAAEEYP&0+ib-Cy$IQQM$ zQvJ$Z%VQ9Q(^<~uq}b)2KzP=T@pz$OEe61Z!!dUw$5xQVuh!n~BE^r5TA4mO6(C65 z`-q4+_!t_j6%K8}O^@Mc`W^sa3$K92D|rrd1c Zg4VS0iBIo(ae+S(!3HEx3Z6Ryq*^>(978H@O+CGl_mF`I%LV<5 z7t^^Tl(JJMUYVw|v*6*OuBV2ZT+0$Tqon$*H3L}OCp?;~^WS>)R=<{JHSMKyGSvQL zUOUDRaqg!N_rrGA*jyh)&82;LEwZ~x-|u^*e5_)jb)s{9cPQ@=@6i)nlx83%r p`1`*O=dWIPr7>$x@!~gk0}BOUblB!KQ=@O1TaS?83{1ONhnONRge literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/searchbar.css b/browser/themes/pinstripe/searchbar.css index 3c028703f164..0a45f7510b04 100644 --- a/browser/themes/pinstripe/searchbar.css +++ b/browser/themes/pinstripe/searchbar.css @@ -45,3 +45,19 @@ .search-go-button { list-style-image: url("chrome://browser/skin/Search.png"); } + +@media (min-resolution: 2dppx) { + .searchbar-engine-image { + list-style-image: url("chrome://mozapps/skin/places/defaultFavicon@2x.png"); + } + + .searchbar-dropmarker-image { + list-style-image: url("chrome://browser/skin/searchbar-dropmarker@2x.png"); + width: 7px; + } + + .search-go-button { + list-style-image: url("chrome://browser/skin/Search@2x.png"); + width: 14px; + } +} diff --git a/browser/themes/pinstripe/tabbrowser/alltabs-box-bkgnd-icon-lion@2x.png b/browser/themes/pinstripe/tabbrowser/alltabs-box-bkgnd-icon-lion@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..875f73c5e2080b247f9345f10677fdf42f33039a GIT binary patch literal 1350 zcmV-M1-bf(P)Y^1S&@}yk23ydYU=v%^IHPEjT9w2wZFC&x&FlHgeQ>?J=jhCPI@o*QhsX2I zy`Fi0&;1y;uIo%udbpXgk~AfZ5=NO4MhSED?D9{gff7b_%#kpcfV)7%Ig~Iqh~YL7 z#KZA&d=f_7$dd(fTZyEE$uEjor-*_WB9vJmiX;jocaBR5Q~dHJb_rg-Um(B{V`WnJ z=v<0@bb$o@Jrnzca7R(Z0s1XAWT3Ip+drl2Lxffs$=ZkW8`JbCv;0d z5at-CLJ-9-2_r9OYL6*E6lSvV8^TzLVkM3&jLYQj>`NF-cAPj#g!afuKE`X~%Q}oY zT)PNUCJ7^VOohc#=CNxj^ENg%zTD|tZ9HH@)anELwq%QW|G;#=Zo9*}bz zV{E8n$5Qt32bVs)`fkT$Z!G$2?|YXCN zACR9SR)}Q_@GON~jKNqNg~^VOkAD;jh3=BSPCO;nEWopMKjeBft?7OC>rX~7)j`*FJlt63_ImpEryM>`H zbd8RVe%8>?FipSD5ci1RBoLcH4stQ3$U1a6aK7nS<0rlGuWRe-7Rp0sS@2Xd3%>Bm zPAGF&n=O=;2UlWmzwv3MYvXbG@oE;V4HM6E!VEDyLk@B=MxMv6 zd(2`a5}6+y983g*!74uSCPznXU|=AL9OOE9Vp?o&Zl3M$@Bcm!2vo{-AlBE{_XBc@ zs6#gsgp<>9Oq*O`iMqPlrHijeKKG;+(mra+fWK@T_=sJ+5cvW*$i*0pwU~29_v}{~ zOgh)v+WLS#_^Qw6tKzX7e8k$?+GhAtmvc~gr06kAIRX_=wq9hbW2x=G`JP=`4FT z|CCK%c=e_GFF(h=%&aDL03R_tLk@EJ7)_eXbV)1pg1JE?y1TpoATc}uK4SdYLD_a4 z)TuwWx3@0?_zu+}cgz-l*_&${?8(Cvn|ib5{4Y%vYc~LV#PEzSv4${Nsbg&auIyhT zN&C%R0H4PW+P3SUjs7NZpbp(+DKk38IQ(oZ{lk`5*V%N}TP-&Le8l)ah;cYF6UNq# zF%0*Ghn%%T{QAVHI&`U9WMMLfFt{_#K4yQWHdz9|=XWhb7_*Ma*}2Ea_JniT=2RV4 z9g`7Gf@vVG0*VlTT;j zVL;mK#U(6faa2~qI3SRCN;5;-KJ88m?L2S0cs2?Tl1;c0RR9107*qo IM6N<$f|C1(vH$=8 literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/tabbrowser/connecting@2x.png b/browser/themes/pinstripe/tabbrowser/connecting@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..97e2b2eb67ecc58e98dd839187143ab6870699e5 GIT binary patch literal 30143 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 z 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 z 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 LqWB+CWB>mG4ll9t literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/tabbrowser/newtab@2x.png b/browser/themes/pinstripe/tabbrowser/newtab@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..ffde5f05086c366c5873e0d5fa383f45982ae002 GIT binary patch literal 1742 zcmV;<1~K`GP)76roF8j&% z-g|CRBM1VPX}gYoF`6=1cJ0KKOQ?ab448gMh7ijn%guo8qN7AWCYK6aVrUsKy|84E z@`_jmE(12?=}?4)vbgdJXqm%?42mUy6$gza0ha;Oa~Z^8CIMC8Dsn~twg@!(Z04{b zPluwjC@cz1bXwwRF)c8B`6OsB*CcNn-nW&@^`sgP%@L((lVM6A*<58oQF~G0w!WK? zw7|xy)#?Z1;OB70$AWv#MNU`H3l3oO(DE#@zAI z{m5yy!fB@XejS?*9}Y`B6viU}%on6{a}l>@m8iQyhn4PN*2Ml$7!z0(1u)f`re~Mv z`@TyxBEUQ@e+L{U0<$E*B2^9WglTNb*z`wL$f3Y2#g<>6!@ybSFqiAU=CE9XlZ>dg zihxmFO=9*0M!#29yrB9o7RzLD`BLOTz<-3+qUt*JA2~yx&&C4k8!U;NygJ}D=&jqqR{fiO3z^!3$RKF3Tk7J zDRB(8>gR0RJ|$DRT%Lwn=N7=~qApbXPg^oc^lK^XCTc7;%1B^!o z%{qPL@$X)Ld3pgf51IqbfX;$Wo<05QD~0j9d%!TpHoV7kX81Gs>;m@1p(ziBV;yFi z<_c`t7iF?6YZ&)+um*2ab(b~ zs_c7!6{>q!9^Hk&AjURTKK8}rzjk4X*D&}g{2RXLKV}$duT^HdQ|MrC}|p zgVq$n+N(o=b$FX9zn*q5_Fea}@%tZ9# ziLU{X!z^s;lRrDactlv?rsk73o`3P&v$dmdK2tk>>QL>>YfshQKK5j7=A|cU?;n2j z;GA1uh4sq}g)z3_JI4rJzn*g&l zj3-dQ3SFExm}`M`;IoT@IQ#@dITn0+t((0~2gVk^M{{|MeYj+HkUtav*-8ljb<0YCSYLGJm0xbg8{b-qeJpVKM^y05<{+r*~XN!NZ z&zJsU7nfJrSC`k=*R0#>0mB&E@E+!1E>X!yAFZIUv9S z4SlJm!w8zg)dsb=n*89o$pW`mIAgr!-tGK0>Bkic|1HpT9RAW%j!`-3(0TY9NT$V} z!?-#GSd*v`o^(VXNjI5ozC?oz#Iv%4GyMZ z807HRFd|?L!DSIJM*_^(IwfMqK9Q85|b>i-bD4F9YTZ@6hTn zd_fUlRZ;v*%-Ka)4mr;&X&euo4g+Bg6J6G%E^A%C!fyWZZ77TdcQyOC%M;$IWeuyt zEVu$PxmI+X9;B?(E`WaEx}b49LCh9Eg4Ur^oaIa2r)5eM z>!S7DbQo;Yw~dFl>E49~3D>lC$zmO?QUg3S$A1vflc)XNlRBe4`U6+~x>VpQG5iC)yxo!1TC_DT-=Zt92#L z@`T-NtjjWBdcnm(bK_1jGKUQhRv^@W6q+pdlWa0FU^@>jkQDDSNXo5y25k7#q6(ZZ kxt|zT25fkaQ)%GqALCVo4dAKT@c;k-07*qoM6N<$g0bmK6aWAK literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/tabbrowser/tab-arrow-left@2x.png b/browser/themes/pinstripe/tabbrowser/tab-arrow-left@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..20bf78db21347a968e519564dc6aa39f4cc5fa78 GIT binary patch literal 2768 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 R+(7^U002ovPDHLkV1gobpZWj* literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/tabbrowser/tab-top-normal-active@2x.png b/browser/themes/pinstripe/tabbrowser/tab-top-normal-active@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..658b291d3940b0a53d321f54ff86e2ade53cf82f GIT binary patch literal 968 zcmV;(12_DMP)yBAT}V*Be4Oo zVjg@X6KfOc6#s8W0^i75JDj$1052PkhA(Y+lvL6pR$-m z9KmI1UU)5x3m=3Tp^}gp&Kl?JJhNP8TOe&Qhi5P=3<)KaQA~+hS!O%wiN(v$Wxy+; zjNl*$KCiB>P8}Q^OkQ4ImSo2JBwz++VJ2o%u8d4(yX;~m7mM$y4A0&)0&BI}r>mdwy2WPGKx5F!)V>=3Y%om9*hLY}ee>FMbk1nLBt6q{uiKMk>r5D7JK zc6Rnsw-_>!O(JwkD(19{ot&KX%Xj;9g3LR_oHWD+ggJ10d>rZ)LngAxKv%32vBSed z{3Ffj1esm2M~Hm^#>AMfOl*IDA6sx%C&*MORtLt!n6EBcBVx5Y~PY7(mzD|&-Qmg@ti7{V=*mqz|jQPsMwzs#j1$#O{rb@9UFeb)) zWnx=fTiB^wogh=C*gP;M#{8~Wr(&C%o7ky(b%IQlVn2W}G3Kif`w5JRF<+V3#>NJ= zU`Hp&R4Mig7!zZDnqt`}D3(oAYym7SEny3`b%M;>{ItaepODyKGO_rfUrrc$Dq`%C zV>j!uVi=g`!|g@i_ZM2N7S_F`6J#PA9ngiH+)l+T;t0ObFBCC!czAeTZe&}x7&4Jf zu_8P9>}Y|9irG9PIj-pnhBg|F83dUC*%Yg=Q;r?&hlp8syeaTe_>H9??_i9X5<@mR zpbI*+zd-=*6SH}lM}#s4fwi@@sq^#mk!rQtYXW4W1G9UT^wjHhPksxH?CtFp*Vota95^ru qI-m^brL#r^;aVB9|VL(Vk-0000@tRxdwFn-1@72=~6h)*69@9gGVinpn>HF*(9oNk!n^iZ|9r&2tVfTCAoA+jRVV*QxG%2O9fl~`L zfKxkR%av9)PHDHe7PVSU5>y}3U@}4tVE5c1r?OK=gEz;lv!xjh(JgRELxd4_3H6@N zr5sgG+UoHfG36A$1BXl&0AW!=OzS&bB4*(TGq=gMr0$&Oh-ovUW=)S$n8tbuLxe|! zaYBwTL3rX46a4NtbAhv0b1=jaRO#6;EoC!n3hAIZg;`9}*aPZE2-gV-9{1Wz<^tyk z+em7W3$d1lYfidIKNYbQjXk73-QV9IFO^Eq%H{H_{r&y7H2%&DzyU6Bf*Us2R!XI0 zvuPxRXflW1-K^&JL}vuD;3Ta{2D=?!IU=8uuD5aDWS(;D!y@Vw;_;;h461 zQIid#CG^dL?gwCKZf@>gp-^}kiA1ml%7m|kb;1{qSZA&>xM2gf*tr4AW+J@qih_wU z)L$7K9E{J*%)Agn?9%-PJGMutU@knO!d&3ofDPD!P1t4)QvbHK;+W8$!7TM)jAn40 zX7d+aZxMbIs%HdnZ^0I9vYsAotr<=Z%4YsBnCvnJhKGmmQn!5y(PV@Gmg}W$gxd>HJtd>YITiC%{gJ3=I%L0>i}$1ShSqVFO@z!d*>J} zg}pjjT6Rp>kX3wetkOV}r=MVz*EOFYnvIr|V@@PhpWsSoD-rX{u~UhdQ){P)1&#%& z_&-MMk53397Ob(0vfcZ&#)4D~A{J~O!3R3{KnD>EB6blXCfabj7iW=*!3VnCKhRb} zzc&xzIu&hBEo2*S9*)|j8nhhG3d{LeyG2aeY1REeX^-PcCIiJKBArf${c?KnShffuKyrf&Kb zF}5vOi>lf&?X=@sTGo=aoG3~UWvRbPEt1dYZ~5gIY(oRIu%@VCDNEAVp5!AMJrz}y zGF)HLhXuK?u<$gQOn&prG1!I%-W>X%jjIThb9yQsmgA}Nx)`B@fYbSFC_%_%GLfaF zrF=GLRcvTxS65eca&j_0KRH0oE#d?&0B-V@f^z$t|_*0jPJZ7YKQ0=|nxD8hth Q`2YX_07*qoM6N<$f{=0vr2qf` literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/toolbarbutton-dropmarker-lion@2x.png b/browser/themes/pinstripe/toolbarbutton-dropmarker-lion@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..631fb1352eb5c64e6840cc082bcabf48ff7304d6 GIT binary patch literal 286 zcmV+(0pb3MP);Xf`2yB25$y$=9DtW|2$ABur$|y_5VgK@eFYcamn8Q`TjF8AOoO)#($H5Fz0~(f@o4; kX`%n3K$|%KGcyne0KZ&E_-Ym1ZU6uP07*qoM6N<$g4Tz0M*si- literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/urlbar-arrow@2x.png b/browser/themes/pinstripe/urlbar-arrow@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..59b5118ff601cb8f98ca52a9a28703cc2ce0240e GIT binary patch literal 362 zcmV-w0hRuVP)M#s%UDrLJ0E+pLs>t&^Is{nPRYy@omDF|pi~=a*I8qgH9DkdN?oa^5 zI6;u2DBceNmSxdF5d8b`+ceD+3ZM+bKvkIbe!_q)Omh^#G)Dnka~!}m#{pb(48S#4 z0ANS+J;0vkAb@L*1GwfF5WqE;0=~q*AYDYfjgI4NZM=s?Qc7(iy@*s6Zzjohew7?3 zAL1kJtV5OSD!o`PqO0x9%a!XY88DQ1#5r%sV!EC^Xo^SOKU%wdS+xUyr~m)}07*qo IM6N<$g2d35#{d8T literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/urlbar-history-dropmarker@2x.png b/browser/themes/pinstripe/urlbar-history-dropmarker@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..e7d4937b8d15d764dde4440cc0abd2f7152b9610 GIT binary patch literal 807 zcmV+?1K9kDP)-% zw`o}x&6GfC-(T*Gv$?bFZ0I6WM~>F{_q?$aG1=FdguyO;V>{>F;bG@F@B5A;qW?-I za3ydh@IS`A9M+ek61bSaT9_Iie@7ooCNh~ORAJv8d-IlXts!>d_7^K!m;zcSL%#zL z>kXX2IMOybIkoI^xybAFs^WAyX=37|glp-PU!!eksSTEa$|QkKdFV87&|<%Nek$q@NBob#GPUli25-mD#I2j7oZXeP`4&9>#=cUlpW}Bd%XQT&$C~yU|30#$U8gxQwRjE5z!vt za%mZuKMz!bG#t-0ttr*0hGVG4`yhIW(0Qv62m}aY2Z^W?w7})F<57GNs7QAU&BIDH z8WtB9&)_yEB9TbWz@iu?tIZ~?uBN()s2;dNwm+0~5Ctm00X6voXIEpdkLR!Ze7ua? zz9wum8YPd%`y(WZmoT;!xMDTm3-^EwltT&*6ur{1(3vOwsM&1Mvl&3ChEfGV5D3%Y z6O1_mRlt>^=}zb|P!4^iF3n0cbjf70$7ZufFcbV$1(EgEl}@KmVoV)yrE0tttOY+% zmQSEnwU@w(#Rlva0>P_nCScWIRdBoA-z6z_0q0sWV^rDJFLXf~C}RcM)oy;2YG|R; zY_UFPHQ@bzayXn1aO@ChGGkQRdeeU!DC0`GyESF1t52m;-P1EO!ZcpkipW+*oGW{` z)^LNb20M&_Mn&M9)o2yN;fwPN3+LF1h>ow@_OhYZw;!5S?1%GKqY4f~$H?d_c1$_H lq5mS)LQUmAT_x}a^9x6Q`jGJYHVps(002ovPDHLkV1nR^Y}Eh& literal 0 HcmV?d00001 diff --git a/browser/themes/pinstripe/urlbar-popup-blocked@2x.png b/browser/themes/pinstripe/urlbar-popup-blocked@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..4d6aa6f2009e0f025f4b759ed3014c199de36ee0 GIT binary patch literal 769 zcmV+c1OEJpP)GT7>Ds48_l$f2Q4zF4&8zbO{ENttO&EB^dfcceFrtJYi=d;mqGlaBL>Sr5^js!hrX7DY?(!ab;B)@M>+CYDRw9vzXm+-wRdwG+ zx^l4;ndlpS!H~|r?YgcUD90JpA_ti$g{SDm+lVjieH&gIFoFVPvPG!JGgRX}#07Ns zt#~}{4Gg0m+3XJX%Yk#nt*ZO-BT$2ESLYva9o>B!Uirv&MIga()%N8RpvHBy_RR-) zh&D_kOv}-S1_bA5?VAtKA;!b_gf`3=o&cqN^8r3!p?$__9K;I40TlML^Bs^2SG;|7 z;{-Yo1qmsI{R|%<2Tf>34VJ;h3`TGh_izFC|9%1-)qSg{r$@e%$t;-Kh|4I$e7!U!l-7Ru z16b%o0c8E?#T!I$635dVp&ylCm>j+Rum{+Ka>&}z2d};8p679_$1r#T9JT$h2WW=u zMw;kDo^!WY<7&boZ@T zEG9=*BZjRggzPKUVHS_E4gRj93l=JI44WZ)gq_~t#km&MeJdJ`Mnbd(qbSC|^aU02 zvwi7ji|W3OFpZ-TLns0nO`#D<-#UqB=T@e7Ev_X~Sv@0}r~ooO~7LIe>k zRxHw}D}qf5Z}aylPB9F#yPVy#D*=mNbKaRbPdg(b@}~aZfO@^Yj3zFyGSq-tt>(uA zM0vp4Py)DU26qsbd-w((P_0&fL)!Q=(11#%vIObEKd^vux!izs(J&sME}zB=#KFRz z>+A(zjR%xUrCo@_DaMo&*S2jupja#(K^y{(ZNs%48Vx8E3ZrO2lv_+=4zrlTjblGI z8j#QDLl6x%wu}Via=9R+2R6R<6_CwlEl3}1{OBnllgaEu46w1I9gt3^#UNWdAeBmq zN!kI)WKs;$4@e{uVvv47JRTQ=^aEnCn6z=#VY_a(X$M53QSs2kXIy%0m-vEHk4--y z5{ZaQ3qG}Ndh7wUO`+-9^aH}-usHm~g4(*`Ssz*uML!@E3W@TJb&vfRi&(|6$3BmH z2s#F63kHLe5G>;xY)o`|$8^9aJmL(0@r3c=1Spne6(P!jIv;Al2mHcMeC+i*?|;Xy XVUtHDW|gfX00000NkvXXu0mjfaw*F# literal 0 HcmV?d00001 diff --git a/toolkit/themes/pinstripe/global/findBar.css b/toolkit/themes/pinstripe/global/findBar.css index 2815ac4ee81d..0f31def98e12 100644 --- a/toolkit/themes/pinstripe/global/findBar.css +++ b/toolkit/themes/pinstripe/global/findBar.css @@ -47,6 +47,25 @@ label.findbar-find-fast:-moz-lwtheme, -moz-image-region: rect(0, 48px, 16px, 32px); } +@media (min-resolution: 2dppx) { + .findbar-closebutton { + list-style-image: url("chrome://global/skin/icons/close@2x.png"); + -moz-image-region: rect(0, 32px, 32px, 0); + } + + .findbar-closebutton:hover { + -moz-image-region: rect(0, 64px, 32px, 32px); + } + + .findbar-closebutton:hover:active { + -moz-image-region: rect(0, 96px, 32px, 64px); + } + + .findbar-closebutton > .toolbarbutton-icon { + width: 16px; + } +} + .findbar-find-next, .findbar-find-previous, .findbar-highlight { diff --git a/toolkit/themes/pinstripe/global/icons/chevron.png b/toolkit/themes/pinstripe/global/icons/chevron.png index 49bc32bda36446a10e73d6126bbe30e3d2cc3f9d..b2d31e38f56dda9807001c84e1d2bc31ced0eb0e 100644 GIT binary patch literal 251 zcmeAS@N?(olHy`uVBq!ia0vp@K+MU(0wkS_^Bw{z$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWw1Gb3I)gLpY+769m#DP8#$lDmE(!aWnnnj?GQcNI#J_!_JZK zSki-L&#st^6pbX0)ERpM_)ciCY+7dU;eg6f|7*r7MlMD^_q6zv4GWx9jn7Cdl4z1B z(qa+R>FCjM)@_z|{`0y@Hq}7;Vd>v`z6mWV&Z^DU&PP65rK`4aalE!S_i$=i*sM53 v@t0$66I0LE`TVbb{O3*3Xi0F)VPtr}*M4EaiEoTRhcbA&`njxgN@xNAvglRU literal 401 zcmV;C0dD?@P)$^ zOG`pg6opriQi44uc1tt8r9@FC5s@kOen~Hiuqb=bLo32bl9XV9^iU%L8y7U{r!?ya z)TBw1AP8#EV7GO2@AaI;oqT((v-dgN1JY3yNmN^qM3qzuh?r`Tq2dltc)&gD(VStM zPQ=t99o1T{kV6J({&G^5E#(5H?nd&Tw=IEvY_OupSiM4+Fo8#EVB7)dLw(f!latWC7Y*a!`9|MjU zLYQZ*BP}P{(pqX!qk6=$w_$8zvY=@kJ;WM z&I(}37bO=Nideg1Jkr0|O=md92!=6=g^nnBNEWbq#eeZ?H6^(`fqo2P)_p*|Bny~T z5&5)m`H0It_%Y?$CoegQSTEUB5px1D9>4=H0$mX< ziCy50@y1hV47-3T|Mdh}paa|l!4$d)yR!a|_$tAO1eey!PRUPFOLj_HFTn*Ps4D3M zdzdp|91Mej6dDHOuyfCj11Or(nlmkXkA6@_uf0bzEose)ruWASJHQoqZE?_+LOATY z0=sv*%+_Y*v8a<(CblM>;A-sZw*!0OD6l644m%w&2Z!Bsg_UAc*ugE% zCzt~>(*k^zWgwMllv|!$-(2@ylUHRLL!MD#c3;_e^}A2@dBib@lco^(E*AFk(8}7| zi?gx7Fn+_WwKrEEfUX$AcXU_3M9?F#3j5KVn6pnf0G%$hf(D>5vlPl8H$T2X{6@@e zKKpS(W>y)XQ|Y?0`HYw&)}H%h$1)9MpSY0%pdEA!-hTSx-rc7!BM2~lz3=HO=sdsr z2u`#16aXBBU@)UrS&{Ljpf`-b*(c~rKM9>0UO)OF)i}|4r5?)A*tYpA@gw0T{1D-q z)GRfJ;s>B}bMu$p4uyg26P>33zzZC!FBX<&e9J3OU$xG{z@7EJC+o|%XM8^`u0B8N ziA*$V03u_qTUo6%C`@TJf*#HR&d2=Tv^s@JX^@?m=_WF%#tF|UbPAnZFRr!qY`9?D z5W=kq$7m$Jn{W;Fit6O0WS{UH6#y92JH5VX|8@W3?I-Ik^JjvO*O%{H_fPw$eU(ly z1TLkVLPYj*hvIX&US<$~A!rk{iECvBxnBC&EjzKFdKAAwRt%++RPd}{4a5=R@jC{1 ztrD|LNA~d>D5ub6Fp=-}_`QMYz`~u?*N-JK421D=3x3OHg<0UZE|uws{4GISYw z$x%r~x;{gfe(csabnziTeTJ4)da5>`r)wBjtDETmc}STD89WP z`&w9$rj7RS&QJn`5gd75SI|A{fpX8fX0`4u@lyi;U@Mj$6BmXhs>I7u^<$?cMNx^5 z@Q&l78&gq$P1oQU?}SJj@4!ye0FY0@w+6p+ZtAD7oO5O$7>vyR?ExU!Xe+l&pb3j> zL@y$rrT{o4DvYQ|Q0gAp_>J(y?to`=&G)^aRCGAngPo$i1NJk4mG!9w=X_XG^UJSV z77{kHQ~=Cu_BU(`R>ai^v=S{>gB5bB*fu6D0$L~3gjB#U@eIWu-T31?JH{^&7KXdf zI!XXCzW?Eyxkru#Qj_!Kckt1}zqTOI0Wh*zm)KRD0yGaZ&R=}kCMZMmI2v{(3un+E zaO(K^P#RvbXD}ZB(qO|-0>UU)$Jda394dfN{0DDle|9W77AF^vOsi)m7s%g%pYOkc z2=SJ@d4F1b{#hlO4EEUVd3mS+K|?! z-Z(W`eX4MIVO&gbv}x4e*im<<&%A^S}FiARDWZ9 z1!@__cY+?M$vp41Wzw_$z!=`nMppEFE6W^gk1w1g0&4EJ5~T!#Y7|m~9)eP{OOR$y zPbmI*b}5>R=Cbw3xn{UK2m4qp&{30pNDbu_>Hjugj^b6AHEEp&7&b@Vtr z=@}4?CH&j(g0GHU3ELL=2V)>%BWvf6f}O5vE22RTM3jRZgr5Tm+UjVklU``_+JQ|xyn6b-WTY)Z z`p(vLR%K#n>7_C?oqcB`q{-u7c9)Nc`ry=|m8h?Lu#HPxTL*J*#a{MQgDD0000 .toolbarbutton-icon { + width: 16px; + } +} + /* Popup notification */ .popup-notification-description { diff --git a/toolkit/themes/pinstripe/global/tree/folder@2x.png b/toolkit/themes/pinstripe/global/tree/folder@2x.png new file mode 100755 index 0000000000000000000000000000000000000000..c07acf5ffbb3a4a30fe550fe5d9d3db1770bcfdd GIT binary patch literal 589 zcmV-T0E3x4VELmAt+DX_*BrK5;GE6Yj z-Bs7Eer385laZ>a=k(cSeGJm(+U=<-OK5I+7P0O8{71g7Vgf}ikDqruTh zu61%Du z`bSJ;K#2IROhDux<2`^V0);}U08IF&64WOHA#aoc9z5WR1tk4jVK;EpBmm=GXeCpl zatwbev4wzjDFH@PfDnsZbp|5;znueI_c;*u1V>F72zb7ogpT7supO>cK-x6p83=3f z>A3!GyGjL^;hPW>Q&0|wONs@g0s-Hqz;^u-logjCllo-}Y}WtX z@36SyhuxiHzMq}FW%kZ>-II>Tqa(_tBu8^KJU5@upS#`eN2AfGMp0DteLs|Sg&4DD zWXI#g$PEJ)OxVDk*=+U{hGDhUYJD}E%?cl0+W!{IPkE|>NF zeqWb$q!43UCLSk7PI3$-!QuevU}h*?*SUc?RHyCp(#~XQ`&B~16t+D zWb!KW0wxk@%TZxEoqASVJ{pYz9t*u*uQDEwz5kt1*AzL)-RX3`VZqb}ob`JBj-#}m zX0Tww){j$nv)Pn!CFQ6k^*ALr3|KH>Up~+8MK7X~sEkY<85>#g_^}cUSep9>l>ICo TwZ!z800000NkvXXu0mjfjK0|C literal 0 HcmV?d00001 From 4e97ee62c286f075b09a2d2ddee56e6a8f27d987 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Sun, 30 Sep 2012 19:20:24 +1300 Subject: [PATCH 14/64] Bug 795631 - Update BasicLayerManager::mPhase variable in release mode as well as debug. r=cjones --- gfx/layers/basic/BasicLayerManager.cpp | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/gfx/layers/basic/BasicLayerManager.cpp b/gfx/layers/basic/BasicLayerManager.cpp index 206f2d34e7d1..5634045c1b82 100644 --- a/gfx/layers/basic/BasicLayerManager.cpp +++ b/gfx/layers/basic/BasicLayerManager.cpp @@ -210,9 +210,7 @@ public: }; BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) : -#ifdef DEBUG mPhase(PHASE_NONE), -#endif mWidget(aWidget) , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(false) , mCachedSurfaceInUse(false) @@ -224,9 +222,7 @@ BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) : } BasicLayerManager::BasicLayerManager() : -#ifdef DEBUG mPhase(PHASE_NONE), -#endif mWidget(nullptr) , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(false) , mCachedSurfaceInUse(false) @@ -324,9 +320,7 @@ BasicLayerManager::BeginTransactionWithTarget(gfxContext* aTarget) #endif NS_ASSERTION(!InTransaction(), "Nested transactions not allowed"); -#ifdef DEBUG mPhase = PHASE_CONSTRUCTION; -#endif mTarget = aTarget; } @@ -513,9 +507,7 @@ void BasicLayerManager::AbortTransaction() { NS_ASSERTION(InConstruction(), "Should be in construction phase"); -#ifdef DEBUG mPhase = PHASE_NONE; -#endif mUsingDefaultTarget = false; mInTransaction = false; } @@ -532,9 +524,7 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback, #endif NS_ASSERTION(InConstruction(), "Should be in construction phase"); -#ifdef DEBUG mPhase = PHASE_DRAWING; -#endif Layer* aLayer = GetRoot(); RenderTraceLayers(aLayer, "FF00"); @@ -602,11 +592,9 @@ BasicLayerManager::EndTransactionInternal(DrawThebesLayerCallback aCallback, MOZ_LAYERS_LOG(("]----- EndTransaction")); #endif -#ifdef DEBUG // Go back to the construction phase if the transaction isn't complete. // Layout will update the layer tree and call EndTransaction(). mPhase = mTransactionIncomplete ? PHASE_CONSTRUCTION : PHASE_NONE; -#endif if (!mTransactionIncomplete) { // This is still valid if the transaction was incomplete. @@ -1157,9 +1145,7 @@ void BasicShadowLayerManager::ForwardTransaction() { RenderTraceScope rendertrace("Foward Transaction", "000090"); -#ifdef DEBUG mPhase = PHASE_FORWARD; -#endif // forward this transaction's changeset to our ShadowLayerManager AutoInfallibleTArray replies; @@ -1223,9 +1209,7 @@ BasicShadowLayerManager::ForwardTransaction() NS_WARNING("failed to forward Layers transaction"); } -#ifdef DEBUG mPhase = PHASE_NONE; -#endif // this may result in Layers being deleted, which results in // PLayer::Send__delete__() and DeallocShmem() From ae64d70a132cb50b1920927e9d90f02e7a6e1393 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Sun, 30 Sep 2012 19:20:24 +1300 Subject: [PATCH 15/64] Bug 795646 - Add crashtest for merged nsDisplayFixedPosition items. r=cjones --- layout/base/crashtests/795646.html | 7 +++++++ layout/base/crashtests/crashtests.list | 1 + 2 files changed, 8 insertions(+) create mode 100644 layout/base/crashtests/795646.html diff --git a/layout/base/crashtests/795646.html b/layout/base/crashtests/795646.html new file mode 100644 index 000000000000..5ef210f115a1 --- /dev/null +++ b/layout/base/crashtests/795646.html @@ -0,0 +1,7 @@ + + + +
+V + + diff --git a/layout/base/crashtests/crashtests.list b/layout/base/crashtests/crashtests.list index b05211700630..718a7341f580 100644 --- a/layout/base/crashtests/crashtests.list +++ b/layout/base/crashtests/crashtests.list @@ -369,3 +369,4 @@ load 749816-1.html load 763223-1.html test-pref(font.size.inflation.emPerLine,15) test-pref(font.size.inflation.lineThreshold,100) load 763702.xhtml load 770381-1.html +load 795646.html From 6f574cafa6615c12c79e58b7e5c7262f660231a1 Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Sun, 30 Sep 2012 19:20:24 +1300 Subject: [PATCH 16/64] Bug 795576 - Correctly add the NS_FRAME_UPDATE_LAYER_TREE when invalidating inside a popup. r=cjones --- layout/generic/nsFrame.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 43f6b3112955..b312e014cdd2 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -4770,17 +4770,24 @@ static void InvalidateFrameInternal(nsIFrame *aFrame, bool aHasDisplayItem = tru } nsSVGEffects::InvalidateDirectRenderingObservers(aFrame); nsIFrame *parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame); + bool needsSchedulePaint = false; while (parent && !parent->HasAnyStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT)) { if (aHasDisplayItem) { parent->AddStateBits(NS_FRAME_DESCENDANT_NEEDS_PAINT); } + // If we're inside a popup, then we need to make sure that we + // call schedule paint so that the NS_FRAME_UPDATE_LAYER_TREE + // flag gets added to the popup display root frame. + if (nsLayoutUtils::IsPopup(parent)) { + needsSchedulePaint = true; + } nsSVGEffects::InvalidateDirectRenderingObservers(parent); parent = nsLayoutUtils::GetCrossDocParentFrame(parent); } if (!aHasDisplayItem) { return; } - if (!parent) { + if (!parent || needsSchedulePaint) { aFrame->SchedulePaint(); } if (aFrame->HasAnyStateBits(NS_FRAME_HAS_INVALID_RECT)) { From 930cae2bd23a367de4c822db427d5fd8c329a3fe Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Sun, 30 Sep 2012 19:20:25 +1300 Subject: [PATCH 17/64] Bug 795611 - Call virtual InvalidateFrame from InvalidateFrameSubtree since nsTable*Frame overloads it. r=cjones --- layout/generic/nsFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index b312e014cdd2..f80d231ac33d 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -4801,7 +4801,7 @@ nsIFrame::InvalidateFrameSubtree(uint32_t aDisplayItemKey) { bool hasDisplayItem = !aDisplayItemKey || FrameLayerBuilder::HasRetainedDataFor(this, aDisplayItemKey); - InvalidateFrameInternal(this, hasDisplayItem); + InvalidateFrame(aDisplayItemKey); if (HasAnyStateBits(NS_FRAME_ALL_DESCENDANTS_NEED_PAINT) || !hasDisplayItem) { return; From 202bc0e49e85ad57073356d0377bcf8b3c777b7f Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Sun, 30 Sep 2012 19:20:25 +1300 Subject: [PATCH 18/64] Bug 770617 - Always mark inactive CanvasLayers as being dirty. r=cjones --- gfx/layers/Layers.h | 22 ++++++++++++++++++++++ gfx/layers/basic/BasicCanvasLayer.cpp | 6 +++--- gfx/layers/d3d10/CanvasLayerD3D10.cpp | 4 ++-- gfx/layers/d3d9/CanvasLayerD3D9.cpp | 4 ++-- gfx/layers/opengl/CanvasLayerOGL.cpp | 4 ++-- 5 files changed, 31 insertions(+), 9 deletions(-) diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index c2060c926f15..199954b2da80 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -1389,6 +1389,26 @@ public: */ void Updated() { mDirty = true; SetInvalidRectToVisibleRegion(); } + /** + * Notify this CanvasLayer that the canvas surface contents have + * been painted since the last change. + */ + void Painted() { mDirty = false; } + + /** + * Returns true if the canvas surface contents have changed since the + * last paint. + */ + bool IsDirty() + { + // We can only tell if we are dirty if we're part of the + // widget's retained layer tree. + if (!mManager || !mManager->IsWidgetLayerManager()) { + return true; + } + return mDirty; + } + /** * Register a callback to be called at the end of each transaction. */ @@ -1443,6 +1463,8 @@ protected: DidTransactionCallback mCallback; void* mCallbackData; gfxPattern::GraphicsFilter mFilter; + +private: /** * Set to true in Updated(), cleared during a transaction. */ diff --git a/gfx/layers/basic/BasicCanvasLayer.cpp b/gfx/layers/basic/BasicCanvasLayer.cpp index 50ad498ef415..d434d10f2b32 100644 --- a/gfx/layers/basic/BasicCanvasLayer.cpp +++ b/gfx/layers/basic/BasicCanvasLayer.cpp @@ -120,9 +120,9 @@ BasicCanvasLayer::Initialize(const Data& aData) void BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer) { - if (!mDirty) + if (!IsDirty()) return; - mDirty = false; + Painted(); if (mDrawTarget) { mDrawTarget->Flush(); @@ -393,7 +393,7 @@ BasicShadowableCanvasLayer::Paint(gfxContext* aContext, Layer* aMaskLayer) return; } - if (!mDirty) + if (!IsDirty()) return; if (mGLContext && diff --git a/gfx/layers/d3d10/CanvasLayerD3D10.cpp b/gfx/layers/d3d10/CanvasLayerD3D10.cpp index 56882d960655..7f61d44cbcdf 100644 --- a/gfx/layers/d3d10/CanvasLayerD3D10.cpp +++ b/gfx/layers/d3d10/CanvasLayerD3D10.cpp @@ -103,9 +103,9 @@ CanvasLayerD3D10::Initialize(const Data& aData) void CanvasLayerD3D10::UpdateSurface() { - if (!mDirty) + if (!IsDirty()) return; - mDirty = false; + Painted(); if (mDrawTarget) { mDrawTarget->Flush(); diff --git a/gfx/layers/d3d9/CanvasLayerD3D9.cpp b/gfx/layers/d3d9/CanvasLayerD3D9.cpp index b8a545db14cf..8ded717659ef 100644 --- a/gfx/layers/d3d9/CanvasLayerD3D9.cpp +++ b/gfx/layers/d3d9/CanvasLayerD3D9.cpp @@ -58,9 +58,9 @@ CanvasLayerD3D9::Initialize(const Data& aData) void CanvasLayerD3D9::UpdateSurface() { - if (!mDirty && mTexture) + if (!IsDirty() && mTexture) return; - mDirty = false; + Painted(); if (!mTexture) { CreateTexture(); diff --git a/gfx/layers/opengl/CanvasLayerOGL.cpp b/gfx/layers/opengl/CanvasLayerOGL.cpp index 95229d37b06c..ca468e578194 100644 --- a/gfx/layers/opengl/CanvasLayerOGL.cpp +++ b/gfx/layers/opengl/CanvasLayerOGL.cpp @@ -172,9 +172,9 @@ MakeIOSurfaceTexture(void* aCGIOSurfaceContext, mozilla::gl::GLContext* aGL) void CanvasLayerOGL::UpdateSurface() { - if (!mDirty) + if (!IsDirty()) return; - mDirty = false; + Painted(); if (mDestroyed || mDelayedUpdates) { return; From 682d9b310b634d33b4a4c8340e3a4bbfcf0e7e5a Mon Sep 17 00:00:00 2001 From: Gary Kwong Date: Sat, 29 Sep 2012 23:28:54 -0700 Subject: [PATCH 19/64] Bug 696305 - Removing suppression from Valgrind files. DONTBUILD --HG-- rename : dom/tests/mochitest/localstorage/test_clear_browser_data.html => dom/tests/mochitest/localstorage/test_app_uninstall.html extra : rebase_source : 5a6769cf1f4ccd569ad0325785ebb9635f048f54 --- build/valgrind/cross-architecture.sup | 7 ------- 1 file changed, 7 deletions(-) diff --git a/build/valgrind/cross-architecture.sup b/build/valgrind/cross-architecture.sup index 8ed85ca1d3aa..e75efd17bf12 100644 --- a/build/valgrind/cross-architecture.sup +++ b/build/valgrind/cross-architecture.sup @@ -260,10 +260,3 @@ fun:_ZL29nsGSettingsServiceConstructorP11nsISupportsRK4nsIDPPv ... } -{ - Bug 795631 - Memcheck:Cond - fun:_ZN7mozilla17FrameLayerBuilder18ClippedDisplayItemD1Ev - fun:_ZN12nsTHashtableIN7mozilla17FrameLayerBuilder21ThebesLayerItemsEntryEE12s_ClearEntryEP12PLDHashTableP15PLDHashEntryHdr - ... -} From 2b5268c071bd531eab83787d28acc8b48718a238 Mon Sep 17 00:00:00 2001 From: Gary Kwong Date: Sat, 29 Sep 2012 23:30:47 -0700 Subject: [PATCH 20/64] Bug 696305 - Removing another suppression from Valgrind files. DONTBUILD --- build/valgrind/cross-architecture.sup | 9 --------- 1 file changed, 9 deletions(-) diff --git a/build/valgrind/cross-architecture.sup b/build/valgrind/cross-architecture.sup index e75efd17bf12..e2e97b8b3fce 100644 --- a/build/valgrind/cross-architecture.sup +++ b/build/valgrind/cross-architecture.sup @@ -251,12 +251,3 @@ fun:_ZN22nsComponentManagerImpl17ManifestComponentERNS_25ManifestProcessingContextEiPKPc ... } -{ - Bug 795395 - Memcheck:Addr4 - fun:PR_UnloadLibrary - fun:_ZN18nsGSettingsServiceD1Ev - fun:_ZN18nsGSettingsService7ReleaseEv - fun:_ZL29nsGSettingsServiceConstructorP11nsISupportsRK4nsIDPPv - ... -} From 8f5c5c9f3fe902d71484ce6cb5f5c16029712bc8 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Sat, 29 Sep 2012 23:38:46 -0700 Subject: [PATCH 21/64] Bug 666041 patch 6.5: Add flag to nsHTMLReflowState & ComputeSize for measuring auto height. r=dbaron --- layout/generic/nsFrame.cpp | 6 +++++- layout/generic/nsHTMLReflowState.cpp | 20 +++++++++++++++++--- layout/generic/nsHTMLReflowState.h | 3 +++ layout/generic/nsIFrame.h | 6 +++++- 4 files changed, 30 insertions(+), 5 deletions(-) diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 43f6b3112955..f61c40fd782d 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -4004,7 +4004,11 @@ nsFrame::ComputeSize(nsRenderingContext *aRenderingContext, result.width = NS_MAX(minWidth, result.width); // Compute height - if (!nsLayoutUtils::IsAutoHeight(*heightStyleCoord, aCBSize.height)) { + // (but not if we're auto-height or if we recieved the "eUseAutoHeight" + // flag -- then, we'll just stick with the height that we already calculated + // in the initial ComputeAutoSize() call.) + if (!nsLayoutUtils::IsAutoHeight(*heightStyleCoord, aCBSize.height) && + !(aFlags & nsIFrame::eUseAutoHeight)) { result.height = nsLayoutUtils::ComputeHeightValue(aCBSize.height, boxSizingAdjust.height, diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index 7b0ceddca10a..5bb75837dfca 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -174,6 +174,7 @@ nsHTMLReflowState::nsHTMLReflowState(nsPresContext* aPresContext, mFlags.mAssumingHScrollbar = mFlags.mAssumingVScrollbar = false; mFlags.mHasClearance = false; mFlags.mIsColumnBalancing = false; + mFlags.mIsFlexContainerMeasuringHeight = false; mFlags.mDummyParentReflowState = false; mDiscoveredClearance = nullptr; @@ -2009,6 +2010,12 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext, computeSizeFlags |= nsIFrame::eShrinkWrap; } + // If we're inside of a flexbox that needs to measure our auto height, + // pass that information along to ComputeSize(). + if (mFlags.mIsFlexContainerMeasuringHeight) { + computeSizeFlags |= nsIFrame::eUseAutoHeight; + } + nsSize size = frame->ComputeSize(rendContext, nsSize(aContainingBlockWidth, @@ -2487,6 +2494,9 @@ nsHTMLReflowState::ComputeMinMaxValues(nscoord aContainingBlockWidth, // depends on the content height. Treat them like 'auto' // Likewise, check for calc() on internal table elements; calc() on // such elements is unsupported. + // Likewise, if we're a child of a flex container who's measuring our + // intrinsic height, then we want to disregard our min-height. + // NOTE: We treat "min-height:auto" as "0" for the purpose of this code, // since that's what it means in all cases except for on flex items -- and // even there, we're supposed to ignore it (i.e. treat it as 0) until the @@ -2496,7 +2506,8 @@ nsHTMLReflowState::ComputeMinMaxValues(nscoord aContainingBlockWidth, (NS_AUTOHEIGHT == aContainingBlockHeight && minHeight.HasPercent()) || (mFrameType == NS_CSS_FRAME_TYPE_INTERNAL_TABLE && - minHeight.IsCalcUnit())) { + minHeight.IsCalcUnit()) || + mFlags.mIsFlexContainerMeasuringHeight) { mComputedMinHeight = 0; } else { mComputedMinHeight = ComputeHeightValue(aContainingBlockHeight, @@ -2510,13 +2521,16 @@ nsHTMLReflowState::ComputeMinMaxValues(nscoord aContainingBlockWidth, mComputedMaxHeight = NS_UNCONSTRAINEDSIZE; // no limit } else { // Check for percentage based values and a containing block height that - // depends on the content height. Treat them like 'auto' + // depends on the content height. Treat them like 'none' // Likewise, check for calc() on internal table elements; calc() on // such elements is unsupported. + // Likewise, if we're a child of a flex container who's measuring our + // intrinsic height, then we want to disregard our max-height. if ((NS_AUTOHEIGHT == aContainingBlockHeight && maxHeight.HasPercent()) || (mFrameType == NS_CSS_FRAME_TYPE_INTERNAL_TABLE && - maxHeight.IsCalcUnit())) { + maxHeight.IsCalcUnit()) || + mFlags.mIsFlexContainerMeasuringHeight) { mComputedMaxHeight = NS_UNCONSTRAINEDSIZE; } else { mComputedMaxHeight = ComputeHeightValue(aContainingBlockHeight, diff --git a/layout/generic/nsHTMLReflowState.h b/layout/generic/nsHTMLReflowState.h index e8be0f17ccce..941d26743123 100644 --- a/layout/generic/nsHTMLReflowState.h +++ b/layout/generic/nsHTMLReflowState.h @@ -349,6 +349,9 @@ public: uint16_t mHeightDependsOnAncestorCell:1; // Does frame height depend on // an ancestor table-cell? uint16_t mIsColumnBalancing:1; // nsColumnSetFrame is balancing columns + uint16_t mIsFlexContainerMeasuringHeight:1; // nsFlexContainerFrame is + // reflowing this child to + // measure its intrinsic height. uint16_t mDummyParentReflowState:1; // a "fake" reflow state made // in order to be the parent // of a real one diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 39996ffbd9ae..7eba85572320 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -1738,7 +1738,11 @@ public: /* Set if the frame is in a context where non-replaced blocks should * shrink-wrap (e.g., it's floating, absolutely positioned, or * inline-block). */ - eShrinkWrap = 1 << 0 + eShrinkWrap = 1 << 0, + /* Set if we'd like to compute our 'auto' height, regardless of our actual + * computed value of 'height'. (e.g. to get an intrinsic height for flex + * items with "min-height: auto" to use during flexbox layout.) */ + eUseAutoHeight = 1 << 1 }; /** From e71e5f416143cfcaceb2d9383ae8feaded2363f8 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Sat, 29 Sep 2012 23:38:46 -0700 Subject: [PATCH 22/64] Bug 666041 patch 7: implementation of flex container class for CSS3 flexbox. r=dbaron --- layout/generic/nsFlexContainerFrame.cpp | 2172 ++++++++++++++++++++++- layout/generic/nsFlexContainerFrame.h | 79 +- layout/generic/nsFrameIdList.h | 2 - layout/generic/nsHTMLReflowState.cpp | 51 +- layout/style/ua.css | 1 + 5 files changed, 2289 insertions(+), 16 deletions(-) diff --git a/layout/generic/nsFlexContainerFrame.cpp b/layout/generic/nsFlexContainerFrame.cpp index 59f65142740e..d04a26a0bba2 100644 --- a/layout/generic/nsFlexContainerFrame.cpp +++ b/layout/generic/nsFlexContainerFrame.cpp @@ -8,14 +8,900 @@ /* rendering object for CSS display: -moz-flex */ #include "nsFlexContainerFrame.h" +#include "nsLayoutUtils.h" #include "nsPresContext.h" #include "nsStyleContext.h" #include "prlog.h" -#ifdef PR_LOGGING +using namespace mozilla::css; + +#ifdef PR_LOGGING static PRLogModuleInfo* nsFlexContainerFrameLM = PR_NewLogModule("nsFlexContainerFrame"); #endif /* PR_LOGGING */ +// XXXdholbert Some of this helper-stuff should be separated out into a general +// "LogicalAxisUtils.h" helper. Should that be a class, or a namespace (under +// what super-namespace?), or what? + +// Helper enums +// ============ + +// Represents a physical orientation for an axis. +// The directional suffix indicates the direction in which the axis *grows*. +// So e.g. eAxis_LR means a horizontal left-to-right axis, whereas eAxis_BT +// means a vertical bottom-to-top axis. +// NOTE: The order here is important -- these values are used as indices into +// the static array 'kAxisOrientationToSidesMap', defined below. +enum AxisOrientationType { + eAxis_LR, + eAxis_RL, + eAxis_TB, + eAxis_BT, + eNumAxisOrientationTypes // For sizing arrays that use these values as indices +}; + +// Represents one or the other extreme of an axis (e.g. for the main axis, the +// main-start vs. main-end edge. +// NOTE: The order here is important -- these values are used as indices into +// the sub-arrays in 'kAxisOrientationToSidesMap', defined below. +enum AxisEdgeType { + eAxisEdge_Start, + eAxisEdge_End, + eNumAxisEdges // For sizing arrays that use these values as indices +}; + +// This array maps each axis orientation to a pair of corresponding +// [start, end] physical mozilla::css::Side values. +static const Side +kAxisOrientationToSidesMap[eNumAxisOrientationTypes][eNumAxisEdges] = { + { eSideLeft, eSideRight }, // eAxis_LR + { eSideRight, eSideLeft }, // eAxis_RL + { eSideTop, eSideBottom }, // eAxis_TB + { eSideBottom, eSideTop } // eAxis_BT +}; + +// Helper structs / classes / methods +// ================================== + +// Indicates whether advancing along the given axis is equivalent to +// increasing our X or Y position (as opposed to decreasing it). +static inline bool +AxisGrowsInPositiveDirection(AxisOrientationType aAxis) +{ + return eAxis_LR == aAxis || eAxis_TB == aAxis; +} + +// Indicates whether the given axis is horizontal. +static inline bool +IsAxisHorizontal(AxisOrientationType aAxis) +{ + return eAxis_LR == aAxis || eAxis_RL == aAxis; +} + +// Given an AxisOrientationType, returns the "reverse" AxisOrientationType +// (in the same dimension, but the opposite direction) +static inline AxisOrientationType +GetReverseAxis(AxisOrientationType aAxis) +{ + AxisOrientationType reversedAxis; + + if (aAxis % 2 == 0) { + // even enum value. Add 1 to reverse. + reversedAxis = AxisOrientationType(aAxis + 1); + } else { + // odd enum value. Subtract 1 to reverse. + reversedAxis = AxisOrientationType(aAxis - 1); + } + + // Check that we're still in the enum's valid range + MOZ_ASSERT(reversedAxis >= eAxis_LR && + reversedAxis <= eAxis_BT); + + return reversedAxis; +} + +// Returns aFrame's computed value for 'height' or 'width' -- whichever is in +// the same dimension as aAxis. +static inline const nsStyleCoord& +GetSizePropertyForAxis(const nsIFrame* aFrame, AxisOrientationType aAxis) +{ + const nsStylePosition* stylePos = aFrame->GetStylePosition(); + + return IsAxisHorizontal(aAxis) ? + stylePos->mWidth : + stylePos->mHeight; +} + +static nscoord +MarginComponentForSide(const nsMargin& aMargin, Side aSide) +{ + switch (aSide) { + case eSideLeft: + return aMargin.left; + case eSideRight: + return aMargin.right; + case eSideTop: + return aMargin.top; + case eSideBottom: + return aMargin.bottom; + } + + NS_NOTREACHED("unexpected Side enum"); + return aMargin.left; // have to return something + // (but something's busted if we got here) +} + +static nscoord& +MarginComponentForSide(nsMargin& aMargin, Side aSide) +{ + switch (aSide) { + case eSideLeft: + return aMargin.left; + case eSideRight: + return aMargin.right; + case eSideTop: + return aMargin.top; + case eSideBottom: + return aMargin.bottom; + } + + NS_NOTREACHED("unexpected Side enum"); + return aMargin.left; // have to return something + // (but something's busted if we got here) +} + +// Encapsulates our flex container's main & cross axes. +NS_STACK_CLASS class FlexboxAxisTracker { +public: + FlexboxAxisTracker(nsFlexContainerFrame* aFlexContainerFrame); + + // Accessors: + AxisOrientationType GetMainAxis() const { return mMainAxis; } + AxisOrientationType GetCrossAxis() const { return mCrossAxis; } + + nscoord GetMainComponent(const nsSize& aSize) const { + return IsAxisHorizontal(mMainAxis) ? + aSize.width : aSize.height; + } + int32_t GetMainComponent(const nsIntSize& aIntSize) const { + return IsAxisHorizontal(mMainAxis) ? + aIntSize.width : aIntSize.height; + } + nscoord GetMainComponent(const nsHTMLReflowMetrics& aMetrics) const { + return IsAxisHorizontal(mMainAxis) ? + aMetrics.width : aMetrics.height; + } + + nscoord GetCrossComponent(const nsSize& aSize) const { + return IsAxisHorizontal(mCrossAxis) ? + aSize.width : aSize.height; + } + int32_t GetCrossComponent(const nsIntSize& aIntSize) const { + return IsAxisHorizontal(mCrossAxis) ? + aIntSize.width : aIntSize.height; + } + nscoord GetCrossComponent(const nsHTMLReflowMetrics& aMetrics) const { + return IsAxisHorizontal(mCrossAxis) ? + aMetrics.width : aMetrics.height; + } + + nscoord GetMarginSizeInMainAxis(const nsMargin& aMargin) const { + return IsAxisHorizontal(mMainAxis) ? + aMargin.LeftRight() : + aMargin.TopBottom(); + } + nscoord GetMarginSizeInCrossAxis(const nsMargin& aMargin) const { + return IsAxisHorizontal(mCrossAxis) ? + aMargin.LeftRight() : + aMargin.TopBottom(); + } + + nsPoint PhysicalPositionFromLogicalPosition(nscoord aMainPosn, + nscoord aCrossPosn) const { + return IsAxisHorizontal(mMainAxis) ? + nsPoint(aMainPosn, aCrossPosn) : + nsPoint(aCrossPosn, aMainPosn); + } + nsSize PhysicalSizeFromLogicalSizes(nscoord aMainSize, + nscoord aCrossSize) const { + return IsAxisHorizontal(mMainAxis) ? + nsSize(aMainSize, aCrossSize) : + nsSize(aCrossSize, aMainSize); + } + +private: + AxisOrientationType mMainAxis; + AxisOrientationType mCrossAxis; +}; + +// Encapsulates a frame for a flex item, with enough information for us to +// sort by 'order' (and by the frame's actual index inside the parent's +// child-frames array, among frames with the same 'order'). +class SortableFrame { +public: + SortableFrame(nsIFrame* aFrame, + int32_t aOrderValue, + uint32_t aIndexInFrameList) + : mFrame(aFrame), + mOrderValue(aOrderValue), + mIndexInFrameList(aIndexInFrameList) + { + MOZ_ASSERT(aFrame, "expecting a non-null child frame"); + } + + // Implement operator== and operator< so that we can use nsDefaultComparator + bool operator==(const SortableFrame& rhs) const { + MOZ_ASSERT(mFrame != rhs.mFrame || + (mOrderValue == rhs.mOrderValue && + mIndexInFrameList == rhs.mIndexInFrameList), + "if frames are equal, the other member data should be too"); + return mFrame == rhs.mFrame; + } + + bool operator<(const SortableFrame& rhs) const { + if (mOrderValue == rhs.mOrderValue) { + return mIndexInFrameList < rhs.mIndexInFrameList; + } + return mOrderValue < rhs.mOrderValue; + } + + // Accessor for the frame + inline nsIFrame* Frame() const { return mFrame; } + +protected: + nsIFrame* const mFrame; // The flex item's frame + int32_t const mOrderValue; // mFrame's computed value of 'order' property + uint32_t const mIndexInFrameList; // mFrame's idx in parent's child frames +}; + +// Represents a flex item. +// Includes the various pieces of input that the Flexbox Layout Algorithm uses +// to resolve a flexible width. +class FlexItem { +public: + FlexItem(nsIFrame* aChildFrame, + float aFlexGrow, float aFlexShrink, nscoord aMainBaseSize, + nscoord aMainMinSize, nscoord aMainMaxSize, + nscoord aCrossMinSize, nscoord aCrossMaxSize, + nsMargin aMargin, nsMargin aBorderPadding, + const FlexboxAxisTracker& aAxisTracker); + + // Accessors + nsIFrame* Frame() const { return mFrame; } + nscoord GetFlexBaseSize() const { return mFlexBaseSize; } + + nscoord GetMainMinSize() const { return mMainMinSize; } + nscoord GetMainMaxSize() const { return mMainMaxSize; } + + // Note: These return the main-axis position and size of our *content box*. + nscoord GetMainSize() const { return mMainSize; } + nscoord GetMainPosition() const { return mMainPosn; } + + nscoord GetCrossMinSize() const { return mCrossMinSize; } + nscoord GetCrossMaxSize() const { return mCrossMaxSize; } + + // Note: These return the cross-axis position and size of our *content box*. + nscoord GetCrossSize() const { return mCrossSize; } + nscoord GetCrossPosition() const { return mCrossPosn; } + + nscoord GetAscent() const { return mAscent; } + + float GetShareOfFlexWeightSoFar() const { return mShareOfFlexWeightSoFar; } + + bool IsFrozen() const { return mIsFrozen; } + + bool HadMinViolation() const { return mHadMinViolation; } + bool HadMaxViolation() const { return mHadMaxViolation; } + + // Indicates whether this item's cross-size has been stretched (from having + // "align-self: stretch" with an auto cross-size and no auto margins in the + // cross axis). + bool IsStretched() const { return mIsStretched; } + + uint8_t GetAlignSelf() const { return mAlignSelf; } + + // Returns the flex weight that we should use in the "resolving flexible + // lengths" algorithm. If we've got a positive amount of free space, we use + // the flex-grow weight; otherwise, we use the "scaled flex shrink weight" + // (scaled by our flex base size) + float GetFlexWeightToUse(bool aHavePositiveFreeSpace) + { + if (IsFrozen()) { + return 0.0f; + } + + return aHavePositiveFreeSpace ? + mFlexGrow : + mFlexShrink * mFlexBaseSize; + } + + // Getters for margin: + // =================== + const nsMargin& GetMargin() const { return mMargin; } + + // Returns the margin component for a given mozilla::css::Side + nscoord GetMarginComponentForSide(Side aSide) const + { return MarginComponentForSide(mMargin, aSide); } + + // Returns the total space occupied by this item's margins in the given axis + nscoord GetMarginSizeInAxis(AxisOrientationType aAxis) const + { + Side startSide = kAxisOrientationToSidesMap[aAxis][eAxisEdge_Start]; + Side endSide = kAxisOrientationToSidesMap[aAxis][eAxisEdge_End]; + return GetMarginComponentForSide(startSide) + + GetMarginComponentForSide(endSide); + } + + // Getters for border/padding + // ========================== + // Returns the border+padding component for a given mozilla::css::Side + nscoord GetBorderPaddingComponentForSide(Side aSide) const + { return MarginComponentForSide(mBorderPadding, aSide); } + + // Returns the total space occupied by this item's borders and padding in + // the given axis + nscoord GetBorderPaddingSizeInAxis(AxisOrientationType aAxis) const + { + Side startSide = kAxisOrientationToSidesMap[aAxis][eAxisEdge_Start]; + Side endSide = kAxisOrientationToSidesMap[aAxis][eAxisEdge_End]; + return GetBorderPaddingComponentForSide(startSide) + + GetBorderPaddingComponentForSide(endSide); + } + + // Getter for combined margin/border/padding + // ========================================= + // Returns the total space occupied by this item's margins, borders and + // padding in the given axis + nscoord GetMarginBorderPaddingSizeInAxis(AxisOrientationType aAxis) const + { + return GetMarginSizeInAxis(aAxis) + GetBorderPaddingSizeInAxis(aAxis); + } + + // Setters + // ======= + + // Setters used while we're resolving flexible lengths + // --------------------------------------------------- + + // Sets the main-size of our flex item's content-box. + void SetMainSize(nscoord aNewMainSize) + { + MOZ_ASSERT(!mIsFrozen, "main size shouldn't change after we're frozen"); + mMainSize = aNewMainSize; + } + + void SetShareOfFlexWeightSoFar(float aNewShare) + { + MOZ_ASSERT(!mIsFrozen || aNewShare == 0.0f, + "shouldn't be giving this item any share of the weight " + "after it's frozen"); + mShareOfFlexWeightSoFar = aNewShare; + } + + void Freeze() { mIsFrozen = true; } + + void SetHadMinViolation() + { + MOZ_ASSERT(!mIsFrozen, + "shouldn't be changing main size & having violations " + "after we're frozen"); + mHadMinViolation = true; + } + void SetHadMaxViolation() + { + MOZ_ASSERT(!mIsFrozen, + "shouldn't be changing main size & having violations " + "after we're frozen"); + mHadMaxViolation = true; + } + void ClearViolationFlags() + { mHadMinViolation = mHadMaxViolation = false; } + + // Setters for values that are determined after we've resolved our main size + // ------------------------------------------------------------------------- + + // Sets the main-axis position of our flex item's content-box. + // (This is the distance between the main-start edge of the flex container + // and the main-start edge of the flex item's content-box.) + void SetMainPosition(nscoord aPosn) { + MOZ_ASSERT(mIsFrozen, "main size should be resolved before this"); + mMainPosn = aPosn; + } + + // Sets the cross-size of our flex item's content-box. + void SetCrossSize(nscoord aCrossSize) { + MOZ_ASSERT(mIsFrozen, "main size should be resolved before this"); + mCrossSize = aCrossSize; + } + + // Sets the cross-axis position of our flex item's content-box. + // (This is the distance between the cross-start edge of the flex container + // and the cross-start edge of the flex item.) + void SetCrossPosition(nscoord aPosn) { + MOZ_ASSERT(mIsFrozen, "main size should be resolved before this"); + mCrossPosn = aPosn; + } + + void SetAscent(nscoord aAscent) { + mAscent = aAscent; + } + + void SetIsStretched() { + MOZ_ASSERT(mIsFrozen, "main size should be resolved before this"); + mIsStretched = true; + } + + // Setter for margin components (for resolving "auto" margins) + void SetMarginComponentForSide(Side aSide, nscoord aLength) + { + MOZ_ASSERT(mIsFrozen, "main size should be resolved before this"); + MarginComponentForSide(mMargin, aSide) = aLength; + } + + uint32_t GetNumAutoMarginsInAxis(AxisOrientationType aAxis) const; + +protected: + // Our frame: + nsIFrame* const mFrame; + + // Values that we already know in constructor: (and are hence mostly 'const') + const float mFlexGrow; + const float mFlexShrink; + + const nsMargin mBorderPadding; + nsMargin mMargin; // non-const because we need to resolve auto margins + + const nscoord mFlexBaseSize; + + const nscoord mMainMinSize; + const nscoord mMainMaxSize; + const nscoord mCrossMinSize; + const nscoord mCrossMaxSize; + + // Values that we compute after constructor: + nscoord mMainSize; + nscoord mMainPosn; + nscoord mCrossSize; + nscoord mCrossPosn; + nscoord mAscent; + + // Temporary state, while we're resolving flexible widths (for our main size) + // XXXdholbert To save space, we could use a union to make these variables + // overlay the same memory as some other member vars that aren't touched + // until after main-size has been resolved. In particular, these could share + // memory with mMainPosn through mAscent, and mIsStretched. + float mShareOfFlexWeightSoFar; + bool mIsFrozen; + bool mHadMinViolation; + bool mHadMaxViolation; + + // Misc: + bool mIsStretched; // See IsStretched() documentation + uint8_t mAlignSelf; // My "align-self" computed value (with "auto" + // swapped out for parent"s "align-items" value, + // in our constructor). +}; + +bool +nsFlexContainerFrame::IsHorizontal() +{ + const FlexboxAxisTracker axisTracker(this); + return IsAxisHorizontal(axisTracker.GetMainAxis()); +} + +nsresult +nsFlexContainerFrame::AppendFlexItemForChild( + nsPresContext* aPresContext, + nsIFrame* aChildFrame, + const nsHTMLReflowState& aParentReflowState, + const FlexboxAxisTracker& aAxisTracker, + nsTArray& aFlexItems) +{ + // Create temporary reflow state just for sizing -- to get hypothetical + // main-size and the computed values of min / max main-size property. + // (This reflow state will _not_ be used for reflow.) + nsHTMLReflowState childRS(aPresContext, aParentReflowState, aChildFrame, + nsSize(aParentReflowState.ComputedWidth(), + aParentReflowState.ComputedHeight())); + + // MAIN SIZES (flex base size, min/max size) + // ----------------------------------------- + nscoord flexBaseSize = + aAxisTracker.GetMainComponent(nsSize(childRS.ComputedWidth(), + childRS.ComputedHeight())); + nscoord mainMinSize = + aAxisTracker.GetMainComponent(nsSize(childRS.mComputedMinWidth, + childRS.mComputedMinHeight)); + nscoord mainMaxSize = + aAxisTracker.GetMainComponent(nsSize(childRS.mComputedMaxWidth, + childRS.mComputedMaxHeight)); + // This is enforced by the nsHTMLReflowState where these values come from: + MOZ_ASSERT(mainMinSize <= mainMaxSize, "min size is larger than max size"); + + // SPECIAL MAIN-SIZING FOR VERTICAL FLEX CONTAINERS + // If we're vertical and our main size ended up being unconstrained + // (e.g. because we had height:auto), we need to instead use our + // "max-content" height, which is what we get from reflowing into our + // available width. This is the same as our "min-content" height -- + // so if we have "min-height:auto", we need to use this value as our + // min-height. + if (!IsAxisHorizontal(aAxisTracker.GetMainAxis())) { + bool isMainSizeAuto = (NS_UNCONSTRAINEDSIZE == flexBaseSize); + bool isMainMinSizeAuto = + (eStyleUnit_Auto == + aChildFrame->GetStylePosition()->mMinHeight.GetUnit()); + + if (isMainSizeAuto || isMainMinSizeAuto) { + // Give the item a special reflow with "mIsFlexContainerMeasuringHeight" + // set. This tells it to behave as if it had "height: auto", regardless + // of what the "height" property is actually set to. + nsHTMLReflowState + childRSForMeasuringHeight(aPresContext, aParentReflowState, + aChildFrame, + nsSize(aParentReflowState.ComputedWidth(), + NS_UNCONSTRAINEDSIZE), + -1, -1, false); + childRSForMeasuringHeight.mFlags.mIsFlexContainerMeasuringHeight = true; + childRSForMeasuringHeight.Init(aPresContext); + + nsHTMLReflowMetrics childDesiredSize; + nsReflowStatus childReflowStatus; + nsresult rv = ReflowChild(aChildFrame, aPresContext, + childDesiredSize, childRSForMeasuringHeight, + 0, 0, NS_FRAME_NO_MOVE_FRAME, + childReflowStatus); + NS_ENSURE_SUCCESS(rv, rv); + + MOZ_ASSERT(NS_FRAME_IS_COMPLETE(childReflowStatus), + "We gave flex item unconstrained available height, so it " + "should be complete"); + + // Subtract border/padding in vertical axis, to get _just_ + // the effective computed value of the "height" property. + nscoord childDesiredHeight = childDesiredSize.height - + childRS.mComputedBorderPadding.TopBottom(); + childDesiredHeight = NS_MAX(0, childDesiredHeight); + + if (isMainSizeAuto) { + flexBaseSize = childDesiredHeight; + } + if (isMainMinSizeAuto) { + mainMinSize = childDesiredHeight; + mainMaxSize = NS_MAX(mainMaxSize, mainMinSize); + } + } + } + + // CROSS MIN/MAX SIZE + // ------------------ + + nscoord crossMinSize = + aAxisTracker.GetCrossComponent(nsSize(childRS.mComputedMinWidth, + childRS.mComputedMinHeight)); + nscoord crossMaxSize = + aAxisTracker.GetCrossComponent(nsSize(childRS.mComputedMaxWidth, + childRS.mComputedMaxHeight)); + + // SPECIAL-CASE FOR WIDGET-IMPOSED SIZES + // Check if we're a themed widget, in which case we might have a minimum + // main & cross size imposed by our widget (which we can't go below), or + // (more severe) our widget might have only a single valid size. + bool isFixedSizeWidget = false; + const nsStyleDisplay* disp = aChildFrame->GetStyleDisplay(); + if (aChildFrame->IsThemed(disp)) { + nsIntSize widgetMinSize(0, 0); + bool canOverride = true; + aPresContext->GetTheme()-> + GetMinimumWidgetSize(childRS.rendContext, aChildFrame, + disp->mAppearance, + &widgetMinSize, &canOverride); + + nscoord widgetMainMinSize = + aPresContext->DevPixelsToAppUnits( + aAxisTracker.GetMainComponent(widgetMinSize)); + nscoord widgetCrossMinSize = + aPresContext->DevPixelsToAppUnits( + aAxisTracker.GetCrossComponent(widgetMinSize)); + + // GMWS() returns border-box; we need content-box + widgetMainMinSize -= + aAxisTracker.GetMarginSizeInMainAxis(childRS.mComputedBorderPadding); + widgetCrossMinSize -= + aAxisTracker.GetMarginSizeInCrossAxis(childRS.mComputedBorderPadding); + + if (!canOverride) { + // Fixed-size widget: freeze our main-size at the widget's mandated size. + // (Set min and max main-sizes to that size, too, to keep us from + // clamping to any other size later on.) + flexBaseSize = mainMinSize = mainMaxSize = widgetMainMinSize; + crossMinSize = crossMaxSize = widgetCrossMinSize; + isFixedSizeWidget = true; + } else { + // Variable-size widget: ensure our min/max sizes are at least as large + // as the widget's mandated minimum size, so we don't flex below that. + mainMinSize = NS_MAX(mainMinSize, widgetMainMinSize); + mainMaxSize = NS_MAX(mainMaxSize, widgetMainMinSize); + + crossMinSize = NS_MAX(crossMinSize, widgetCrossMinSize); + crossMaxSize = NS_MAX(crossMaxSize, widgetCrossMinSize); + } + } + + // FLEX GROW & SHRINK WEIGHTS + const nsStylePosition* stylePos = aChildFrame->GetStylePosition(); + float flexGrow = stylePos->mFlexGrow; + float flexShrink = stylePos->mFlexShrink; + + aFlexItems.AppendElement(FlexItem(aChildFrame, + flexGrow, flexShrink, flexBaseSize, + mainMinSize, mainMaxSize, + crossMinSize, crossMaxSize, + childRS.mComputedMargin, + childRS.mComputedBorderPadding, + aAxisTracker)); + + // If we're inflexible, we can just freeze to our hypothetical main-size + // up-front. Similarly, if we're a fixed-size widget, we only have one + // valid size, so we freeze to keep ourselves from flexing. + if (isFixedSizeWidget || (flexGrow == 0.0f && flexShrink == 0.0f)) { + aFlexItems.LastElement().Freeze(); + } + + return NS_OK; +} + +FlexItem::FlexItem(nsIFrame* aChildFrame, + float aFlexGrow, float aFlexShrink, nscoord aFlexBaseSize, + nscoord aMainMinSize, nscoord aMainMaxSize, + nscoord aCrossMinSize, nscoord aCrossMaxSize, + nsMargin aMargin, nsMargin aBorderPadding, + const FlexboxAxisTracker& aAxisTracker) + : mFrame(aChildFrame), + mFlexGrow(aFlexGrow), + mFlexShrink(aFlexShrink), + mBorderPadding(aBorderPadding), + mMargin(aMargin), + mFlexBaseSize(aFlexBaseSize), + mMainMinSize(aMainMinSize), + mMainMaxSize(aMainMaxSize), + mCrossMinSize(aCrossMinSize), + mCrossMaxSize(aCrossMaxSize), + // Init main-size to 'hypothetical main size', which is flex base size + // clamped to [min,max] range: + mMainSize(NS_CSS_MINMAX(aFlexBaseSize, aMainMinSize, aMainMaxSize)), + mMainPosn(0), + mCrossSize(0), + mCrossPosn(0), + mAscent(0), + mShareOfFlexWeightSoFar(0.0f), + mIsFrozen(false), + mHadMinViolation(false), + mHadMaxViolation(false), + mIsStretched(false), + mAlignSelf(aChildFrame->GetStylePosition()->mAlignSelf) +{ + MOZ_ASSERT(aChildFrame, "expecting a non-null child frame"); + + // Assert that any "auto" margin components are set to 0. + // (We'll resolve them later; until then, we want to treat them as 0-sized.) +#ifdef DEBUG + { + const nsStyleSides& styleMargin = mFrame->GetStyleMargin()->mMargin; + NS_FOR_CSS_SIDES(side) { + if (styleMargin.GetUnit(side) == eStyleUnit_Auto) { + MOZ_ASSERT(GetMarginComponentForSide(side) == 0, + "Someone else tried to resolve our auto margin"); + } + } + } +#endif // DEBUG + + // Resolve "align-self: auto" to parent's "align-items" value. + if (mAlignSelf == NS_STYLE_ALIGN_SELF_AUTO) { + mAlignSelf = mFrame->GetParent()->GetStylePosition()->mAlignItems; + } + + // If the flex item's inline axis is the same as the cross axis, then + // 'align-self:baseline' is identical to 'flex-start'. If that's the case, we + // just directly convert our align-self value here, so that we don't have to + // handle this with special cases elsewhere. + // Moreover: for the time being (until we support writing-modes), + // all inline axes are horizontal -- so we can just check if the cross axis + // is horizontal. + // FIXME: Once we support writing-mode (vertical text), this IsAxisHorizontal + // check won't be sufficient anymore -- we'll actually need to compare our + // inline axis vs. the cross axis. + if (mAlignSelf == NS_STYLE_ALIGN_ITEMS_BASELINE && + IsAxisHorizontal(aAxisTracker.GetCrossAxis())) { + mAlignSelf = NS_STYLE_ALIGN_ITEMS_FLEX_START; + } +} + +uint32_t +FlexItem::GetNumAutoMarginsInAxis(AxisOrientationType aAxis) const +{ + uint32_t numAutoMargins = 0; + const nsStyleSides& styleMargin = mFrame->GetStyleMargin()->mMargin; + for (uint32_t i = 0; i < eNumAxisEdges; i++) { + Side side = kAxisOrientationToSidesMap[aAxis][i]; + if (styleMargin.GetUnit(side) == eStyleUnit_Auto) { + numAutoMargins++; + } + } + + // Mostly for clarity: + MOZ_ASSERT(numAutoMargins <= 2, + "We're just looking at one item along one dimension, so we " + "should only have examined 2 margins"); + + return numAutoMargins; +} + +// Keeps track of our position along a particular axis (where a '0' position +// corresponds to the 'start' edge of that axis). +// This class shouldn't be instantiated directly -- rather, it should only be +// instantiated via its subclasses defined below. +NS_STACK_CLASS +class PositionTracker { +public: + // Accessor for the current value of the position that we're tracking. + inline nscoord GetPosition() const { return mPosition; } + inline AxisOrientationType GetAxis() const { return mAxis; } + + // Advances our position across the start edge of the given margin, in the + // axis we're tracking. + void EnterMargin(const nsMargin& aMargin) + { + Side side = kAxisOrientationToSidesMap[mAxis][eAxisEdge_Start]; + mPosition += MarginComponentForSide(aMargin, side); + } + + // Advances our position across the end edge of the given margin, in the axis + // we're tracking. + void ExitMargin(const nsMargin& aMargin) + { + Side side = kAxisOrientationToSidesMap[mAxis][eAxisEdge_End]; + mPosition += MarginComponentForSide(aMargin, side); + } + + // Advances our current position from the start side of a child frame's + // border-box to the frame's upper or left edge (depending on our axis). + // (Note that this is a no-op if our axis grows in positive direction.) + void EnterChildFrame(nscoord aChildFrameSize) + { + if (!AxisGrowsInPositiveDirection(mAxis)) + mPosition += aChildFrameSize; + } + + // Advances our current position from a frame's upper or left border-box edge + // (whichever is in the axis we're tracking) to the 'end' side of the frame + // in the axis that we're tracking. (Note that this is a no-op if our axis + // grows in the negative direction.) + void ExitChildFrame(nscoord aChildFrameSize) + { + if (AxisGrowsInPositiveDirection(mAxis)) + mPosition += aChildFrameSize; + } + +protected: + // Protected constructor, to be sure we're only instantiated via a subclass. + PositionTracker(AxisOrientationType aAxis) + : mPosition(0), + mAxis(aAxis) + {} + +private: + // Private copy-constructor, since we don't want any instances of our + // subclasses to be accidentally copied. + PositionTracker(const PositionTracker& aOther) + : mPosition(aOther.mPosition), + mAxis(aOther.mAxis) + {} + +protected: + // Member data: + nscoord mPosition; // The position we're tracking + const AxisOrientationType mAxis; // The axis along which we're moving +}; + +// Tracks our position in the main axis, when we're laying out flex items. +NS_STACK_CLASS +class MainAxisPositionTracker : public PositionTracker { +public: + MainAxisPositionTracker(nsFlexContainerFrame* aFlexContainerFrame, + const FlexboxAxisTracker& aAxisTracker, + const nsHTMLReflowState& aReflowState, + const nsTArray& aItems); + + ~MainAxisPositionTracker() { + MOZ_ASSERT(mNumPackingSpacesRemaining == 0, + "miscounted the number of packing spaces"); + MOZ_ASSERT(mNumAutoMarginsInMainAxis == 0, + "miscounted the number of auto margins"); + } + + // Advances past the packing space (if any) between two flex items + void TraversePackingSpace(); + + // If aItem has any 'auto' margins in the main axis, this method updates the + // corresponding values in its margin. + void ResolveAutoMarginsInMainAxis(FlexItem& aItem); + +private: + nscoord mPackingSpaceRemaining; + uint32_t mNumAutoMarginsInMainAxis; + uint32_t mNumPackingSpacesRemaining; + uint8_t mJustifyContent; +}; + +// Utility class for managing our position along the cross axis along +// the whole flex container (at a higher level than a single line) +class SingleLineCrossAxisPositionTracker; +NS_STACK_CLASS +class CrossAxisPositionTracker : public PositionTracker { +public: + CrossAxisPositionTracker(nsFlexContainerFrame* aFlexContainerFrame, + const FlexboxAxisTracker& aAxisTracker, + const nsHTMLReflowState& aReflowState); + + // XXXdholbert This probably needs a ResolveStretchedLines() method, + // (which takes an array of SingleLineCrossAxisPositionTracker objects + // and distributes an equal amount of space to each one). + // For now, we just have Reflow directly call + // SingleLineCrossAxisPositionTracker::SetLineCrossSize(). +}; + +// Utility class for managing our position along the cross axis, *within* a +// single flex line. +NS_STACK_CLASS +class SingleLineCrossAxisPositionTracker : public PositionTracker { +public: + SingleLineCrossAxisPositionTracker(nsFlexContainerFrame* aFlexContainerFrame, + const FlexboxAxisTracker& aAxisTracker, + const nsTArray& aItems); + + void ComputeLineCrossSize(const nsTArray& aItems); + inline nscoord GetLineCrossSize() const { return mLineCrossSize; } + + // Used to override the flex line's size, for cases when the flex container is + // single-line and has a fixed size, and also in cases where + // "align-self: stretch" triggers some space-distribution between lines + // (when we support that property). + inline void SetLineCrossSize(nscoord aNewLineCrossSize) { + mLineCrossSize = aNewLineCrossSize; + } + + void ResolveStretchedCrossSize(FlexItem& aItem); + void ResolveAutoMarginsInCrossAxis(FlexItem& aItem); + + void EnterAlignPackingSpace(const FlexItem& aItem); + + // Resets our position to the cross-start edge of this line. + inline void ResetPosition() { mPosition = 0; } + +private: + // Returns the distance from the cross-start side of the given flex item's + // margin-box to its baseline. (Used in baseline alignment.) + nscoord GetBaselineOffsetFromCrossStart(const FlexItem& aItem) const; + + nscoord mLineCrossSize; + + // Largest distance from an item's cross-start margin-box edge to its + // baseline. Computed in ComputeLineCrossSize, and used for alignment of any + // "align-self: baseline" items in this line (and possibly used for computing + // the baseline of the flex container, as well). + nscoord mCrossStartToFurthestBaseline; +}; + +//---------------------------------------------------------------------- + +// Frame class boilerplate +// ======================= + +NS_QUERYFRAME_HEAD(nsFlexContainerFrame) + NS_QUERYFRAME_ENTRY(nsFlexContainerFrame) +NS_QUERYFRAME_TAIL_INHERITING(nsFlexContainerFrameSuper) + NS_IMPL_FRAMEARENA_HELPERS(nsFlexContainerFrame) nsIFrame* @@ -27,15 +913,15 @@ NS_NewFlexContainerFrame(nsIPresShell* aPresShell, //---------------------------------------------------------------------- +// nsFlexContainerFrame Method Implementations +// =========================================== + /* virtual */ nsFlexContainerFrame::~nsFlexContainerFrame() { } -NS_QUERYFRAME_HEAD(nsFlexContainerFrame) - NS_QUERYFRAME_ENTRY(nsFlexContainerFrame) -NS_QUERYFRAME_TAIL_INHERITING(nsFlexContainerFrameSuper) - +/* virtual */ void nsFlexContainerFrame::DestroyFrom(nsIFrame* aDestructRoot) { @@ -43,6 +929,7 @@ nsFlexContainerFrame::DestroyFrom(nsIFrame* aDestructRoot) nsFlexContainerFrameSuper::DestroyFrom(aDestructRoot); } +/* virtual */ nsIAtom* nsFlexContainerFrame::GetType() const { @@ -56,3 +943,1278 @@ nsFlexContainerFrame::GetFrameName(nsAString& aResult) const return MakeFrameName(NS_LITERAL_STRING("FlexContainer"), aResult); } #endif // DEBUG + +NS_IMETHODIMP +nsFlexContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, + const nsRect& aDirtyRect, + const nsDisplayListSet& aLists) +{ + nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists); + NS_ENSURE_SUCCESS(rv, rv); + + for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) { + rv = BuildDisplayListForChild(aBuilder, e.get(), aDirtyRect, aLists); + NS_ENSURE_SUCCESS(rv, rv); + } + + return NS_OK; +} + +#ifdef DEBUG +// helper for the debugging method below +bool +FrameWantsToBeInAnonymousFlexItem(nsIFrame* aFrame) +{ + // Note: This needs to match the logic in + // nsCSSFrameConstructor::FrameConstructionItem::NeedsAnonFlexItem() + return (aFrame->IsFrameOfType(nsIFrame::eLineParticipant) || + nsGkAtoms::placeholderFrame == aFrame->GetType()); +} + +// Debugging method, to let us assert that our anonymous flex items are +// set up correctly -- in particular, we assert: +// (1) we don't have any inline non-replaced children +// (2) we don't have any consecutive anonymous flex items +// (3) we don't have any empty anonymous flex items +// +// XXXdholbert This matches what nsCSSFrameConstructor currently does, and what +// the spec used to say. However, the spec has now changed regarding what +// types of content get wrapped in an anonymous flexbox item. The patch that +// implements those changes (in nsCSSFrameConstructor) will need to change +// this method as well. +void +nsFlexContainerFrame::SanityCheckAnonymousFlexItems() const +{ + bool prevChildWasAnonFlexItem = false; + for (nsIFrame* child = mFrames.FirstChild(); child; + child = child->GetNextSibling()) { + MOZ_ASSERT(!FrameWantsToBeInAnonymousFlexItem(child), + "frame wants to be inside an anonymous flex item, " + "but it isn't"); + if (child->GetStyleContext()->GetPseudo() == + nsCSSAnonBoxes::anonymousFlexItem) { + MOZ_ASSERT(!prevChildWasAnonFlexItem, + "two anon flex items in a row (shouldn't happen)"); + + nsIFrame* firstWrappedChild = child->GetFirstPrincipalChild(); + MOZ_ASSERT(firstWrappedChild, + "anonymous flex item is empty (shouldn't happen)"); + prevChildWasAnonFlexItem = true; + } else { + prevChildWasAnonFlexItem = false; + } + } +} +#endif // DEBUG + +// Based on the sign of aTotalViolation, this function freezes a subset of our +// flexible sizes, and restores the remaining ones to their initial pref sizes. +static void +FreezeOrRestoreEachFlexibleSize( + const nscoord aTotalViolation, + nsTArray& aItems) +{ + enum FreezeType { + eFreezeEverything, + eFreezeMinViolations, + eFreezeMaxViolations + }; + + FreezeType freezeType; + if (aTotalViolation == 0) { + freezeType = eFreezeEverything; + } else if (aTotalViolation > 0) { + freezeType = eFreezeMinViolations; + } else { // aTotalViolation < 0 + freezeType = eFreezeMaxViolations; + } + + for (uint32_t i = 0; i < aItems.Length(); i++) { + FlexItem& item = aItems[i]; + MOZ_ASSERT(!item.HadMinViolation() || !item.HadMaxViolation(), + "Can have either min or max violation, but not both"); + + if (!item.IsFrozen()) { + if (eFreezeEverything == freezeType || + (eFreezeMinViolations == freezeType && item.HadMinViolation()) || + (eFreezeMaxViolations == freezeType && item.HadMaxViolation())) { + + MOZ_ASSERT(item.GetMainSize() >= item.GetMainMinSize(), + "Freezing item at a size below its minimum"); + MOZ_ASSERT(item.GetMainSize() <= item.GetMainMaxSize(), + "Freezing item at a size above its maximum"); + + item.Freeze(); + } // else, we'll reset this item's main size to its flex base size on the + // next iteration of this algorithm. + + // Clear this item's violation(s), now that we've dealt with them + item.ClearViolationFlags(); + } + } +} + +// Implementation of flexbox spec's "Determine sign of flexibility" step. +// NOTE: aTotalFreeSpace should already have the flex items' margin, border, +// & padding values subtracted out. +static bool +ShouldUseFlexGrow(nscoord aTotalFreeSpace, + nsTArray& aItems) +{ + // NOTE: The FlexItem constructor sets its main-size to the + // *hypothetical main size*, which is the flex base size, clamped + // to the min/max range. That's what we want here. Good. + for (uint32_t i = 0; i < aItems.Length(); i++) { + aTotalFreeSpace -= aItems[i].GetMainSize(); + if (aTotalFreeSpace <= 0) { + return false; + } + } + MOZ_ASSERT(aTotalFreeSpace > 0, + "if we used up all the space, should've already returned"); + return true; +} + +// Implementation of flexbox spec's "resolve the flexible lengths" algorithm. +// NOTE: aTotalFreeSpace should already have the flex items' margin, border, +// & padding values subtracted out, so that all we need to do is distribute the +// remaining free space among content-box sizes. (The spec deals with +// margin-box sizes, but we can have fewer values in play & a simpler algorithm +// if we subtract margin/border/padding up front.) +void +nsFlexContainerFrame::ResolveFlexibleLengths( + const FlexboxAxisTracker& aAxisTracker, + nscoord aFlexContainerMainSize, + nsTArray& aItems) +{ + PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG, ("ResolveFlexibleLengths\n")); + if (aItems.IsEmpty()) { + return; + } + + // Subtract space occupied by our items' margins/borders/padding, so we can + // just be dealing with the space available for our flex items' content + // boxes. + nscoord spaceAvailableForFlexItemsContentBoxes = aFlexContainerMainSize; + for (uint32_t i = 0; i < aItems.Length(); i++) { + spaceAvailableForFlexItemsContentBoxes -= + aItems[i].GetMarginBorderPaddingSizeInAxis(aAxisTracker.GetMainAxis()); + } + + // Determine whether we're going to be growing or shrinking items. + bool havePositiveFreeSpace = + ShouldUseFlexGrow(spaceAvailableForFlexItemsContentBoxes, aItems); + + // NOTE: I claim that this chunk of the algorithm (the looping part) needs to + // run the loop at MOST aItems.Length() times. This claim should hold up + // because we'll freeze at least one item on each loop iteration, and once + // we've run out of items to freeze, there's nothing left to do. However, + // in most cases, we'll break out of this loop long before we hit that many + // iterations. + for (uint32_t iterationCounter = 0; + iterationCounter < aItems.Length(); iterationCounter++) { + // Set every not-yet-frozen item's used main size to its + // flex base size, and subtract all the used main sizes from our + // total amount of space to determine the 'available free space' + // (positive or negative) to be distributed among our flexible items. + nscoord availableFreeSpace = spaceAvailableForFlexItemsContentBoxes; + for (uint32_t i = 0; i < aItems.Length(); i++) { + FlexItem& item = aItems[i]; + if (!item.IsFrozen()) { + item.SetMainSize(item.GetFlexBaseSize()); + } + availableFreeSpace -= item.GetMainSize(); + } + + PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG, + (" available free space = %d\n", availableFreeSpace)); + + // If sign of free space matches flexType, give each flexible + // item a portion of availableFreeSpace. + if ((availableFreeSpace > 0 && havePositiveFreeSpace) || + (availableFreeSpace < 0 && !havePositiveFreeSpace)) { + + // STRATEGY: On each item, we compute & store its "share" of the total + // flex weight that we've seen so far: + // curFlexWeight / runningFlexWeightSum + // + // Then, when we go to actually distribute the space (in the next loop), + // we can simply walk backwards through the elements and give each item + // its "share" multiplied by the remaining available space. + // + // SPECIAL CASE: If the sum of the flex weights is larger than the + // maximum representable float (overflowing to infinity), then we can't + // sensibly divide out proportional shares anymore. In that case, we + // simply treat the flex item(s) with the largest flex weights as if + // their weights were infinite (dwarfing all the others), and we + // distribute all of the available space among them. + float runningFlexWeightSum = 0.0f; + float largestFlexWeight = 0.0f; + uint32_t numItemsWithLargestFlexWeight = 0; + for (uint32_t i = 0; i < aItems.Length(); i++) { + FlexItem& item = aItems[i]; + float curFlexWeight = item.GetFlexWeightToUse(havePositiveFreeSpace); + MOZ_ASSERT(curFlexWeight >= 0.0f, "weights are non-negative"); + + runningFlexWeightSum += curFlexWeight; + if (NS_finite(runningFlexWeightSum)) { + if (curFlexWeight == 0.0f) { + item.SetShareOfFlexWeightSoFar(0.0f); + } else { + item.SetShareOfFlexWeightSoFar(curFlexWeight / + runningFlexWeightSum); + } + } // else, the sum of weights overflows to infinity, in which + // case we don't bother with "SetShareOfFlexWeightSoFar" since + // we know we won't use it. (instead, we'll just give every + // item with the largest flex weight an equal share of space.) + + // Update our largest-flex-weight tracking vars + if (curFlexWeight > largestFlexWeight) { + largestFlexWeight = curFlexWeight; + numItemsWithLargestFlexWeight = 1; + } else if (curFlexWeight == largestFlexWeight) { + numItemsWithLargestFlexWeight++; + } + } + + if (runningFlexWeightSum != 0.0f) { // no distribution if no flexibility + PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG, + (" Distributing available space:")); + for (uint32_t i = aItems.Length() - 1; i < aItems.Length(); --i) { + FlexItem& item = aItems[i]; + + if (!item.IsFrozen()) { + // To avoid rounding issues, we compute the change in size for this + // item, and then subtract it from the remaining available space. + nscoord sizeDelta = 0; + if (NS_finite(runningFlexWeightSum)) { + float myShareOfRemainingSpace = + item.GetShareOfFlexWeightSoFar(); + + MOZ_ASSERT(myShareOfRemainingSpace >= 0.0f && + myShareOfRemainingSpace <= 1.0f, + "my share should be nonnegative fractional amount"); + + if (myShareOfRemainingSpace == 1.0f) { + // (We special-case 1.0f to avoid float error from converting + // availableFreeSpace from integer*1.0f --> float --> integer) + sizeDelta = availableFreeSpace; + } else if (myShareOfRemainingSpace > 0.0f) { + sizeDelta = NSToCoordRound(availableFreeSpace * + myShareOfRemainingSpace); + } + } else if (item.GetFlexWeightToUse(havePositiveFreeSpace) == + largestFlexWeight) { + // Total flexibility is infinite, so we're just distributing + // the available space equally among the items that are tied for + // having the largest weight (and this is one of those items). + sizeDelta = + NSToCoordRound(availableFreeSpace / + float(numItemsWithLargestFlexWeight)); + numItemsWithLargestFlexWeight--; + } + + availableFreeSpace -= sizeDelta; + + item.SetMainSize(item.GetMainSize() + sizeDelta); + PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG, + (" child %d receives %d, for a total of %d\n", + i, sizeDelta, item.GetMainSize())); + } + } + } + } + + // Fix min/max violations: + nscoord totalViolation = 0; // keeps track of adjustments for min/max + PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG, + (" Checking for violations:")); + + for (uint32_t i = 0; i < aItems.Length(); i++) { + FlexItem& item = aItems[i]; + if (!item.IsFrozen()) { + if (item.GetMainSize() < item.GetMainMinSize()) { + // min violation + totalViolation += item.GetMainMinSize() - item.GetMainSize(); + item.SetMainSize(item.GetMainMinSize()); + item.SetHadMinViolation(); + } else if (item.GetMainSize() > item.GetMainMaxSize()) { + // max violation + totalViolation += item.GetMainMaxSize() - item.GetMainSize(); + item.SetMainSize(item.GetMainMaxSize()); + item.SetHadMaxViolation(); + } + } + } + + FreezeOrRestoreEachFlexibleSize(totalViolation, aItems); + + PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG, + (" Total violation: %d\n", totalViolation)); + + if (totalViolation == 0) { + break; + } + } + + // Post-condition: all lengths should've been frozen. +#ifdef DEBUG + for (uint32_t i = 0; i < aItems.Length(); ++i) { + MOZ_ASSERT(aItems[i].IsFrozen(), + "All flexible lengths should've been resolved"); + } +#endif // DEBUG +} + +const nsTArray +BuildSortedChildArray(const nsFrameList& aChildren) +{ + // NOTE: To benefit from Return Value Optimization, we must only return + // this value: + nsTArray sortedChildArray(aChildren.GetLength()); + + // Throw all our children in the array... + uint32_t indexInFrameList = 0; + for (nsFrameList::Enumerator e(aChildren); !e.AtEnd(); e.Next()) { + int32_t orderValue = e.get()->GetStylePosition()->mOrder; + sortedChildArray.AppendElement(SortableFrame(e.get(), orderValue, + indexInFrameList)); + indexInFrameList++; + } + + // ... and sort (by 'order' property) + sortedChildArray.Sort(); + + return sortedChildArray; +} + +MainAxisPositionTracker:: + MainAxisPositionTracker(nsFlexContainerFrame* aFlexContainerFrame, + const FlexboxAxisTracker& aAxisTracker, + const nsHTMLReflowState& aReflowState, + const nsTArray& aItems) + : PositionTracker(aAxisTracker.GetMainAxis()), + mNumAutoMarginsInMainAxis(0), + mNumPackingSpacesRemaining(0) +{ + MOZ_ASSERT(aReflowState.frame == aFlexContainerFrame, + "Expecting the reflow state for the flex container frame"); + + // Step over flex container's own main-start border/padding. + // XXXdholbert Check GetSkipSides() here when we support pagination. + EnterMargin(aReflowState.mComputedBorderPadding); + + // Set up our state for managing packing space & auto margins. + // * If our main-size is unconstrained, then we just shrinkwrap our + // contents, and we don't have any packing space. + // * Otherwise, we subtract our items' margin-box main-sizes from our + // computed main-size to get our available packing space. + mPackingSpaceRemaining = + aAxisTracker.GetMainComponent(nsSize(aReflowState.ComputedWidth(), + aReflowState.ComputedHeight())); + if (mPackingSpaceRemaining == NS_UNCONSTRAINEDSIZE) { + mPackingSpaceRemaining = 0; + } else { + for (uint32_t i = 0; i < aItems.Length(); i++) { + nscoord itemMarginBoxMainSize = + aItems[i].GetMainSize() + + aItems[i].GetMarginBorderPaddingSizeInAxis(aAxisTracker.GetMainAxis()); + mPackingSpaceRemaining -= itemMarginBoxMainSize; + } + } + + if (mPackingSpaceRemaining > 0) { + for (uint32_t i = 0; i < aItems.Length(); i++) { + mNumAutoMarginsInMainAxis += aItems[i].GetNumAutoMarginsInAxis(mAxis); + } + } + + mJustifyContent = aFlexContainerFrame->GetStylePosition()->mJustifyContent; + // If packing space is negative, 'justify' behaves like 'start', and + // 'distribute' behaves like 'center'. In those cases, it's simplest to + // just pretend we have a different 'justify-content' value and share code. + if (mPackingSpaceRemaining < 0) { + if (mJustifyContent == NS_STYLE_JUSTIFY_CONTENT_SPACE_BETWEEN) { + mJustifyContent = NS_STYLE_JUSTIFY_CONTENT_FLEX_START; + } else if (mJustifyContent == NS_STYLE_JUSTIFY_CONTENT_SPACE_AROUND) { + mJustifyContent = NS_STYLE_JUSTIFY_CONTENT_CENTER; + } + } + + // Figure out how much space we'll set aside for auto margins or + // packing spaces, and advance past any leading packing-space. + if (mNumAutoMarginsInMainAxis == 0 && + mPackingSpaceRemaining != 0 && + !aItems.IsEmpty()) { + switch (mJustifyContent) { + case NS_STYLE_JUSTIFY_CONTENT_FLEX_START: + // All packing space should go at the end --> nothing to do here. + break; + case NS_STYLE_JUSTIFY_CONTENT_FLEX_END: + // All packing space goes at the beginning + mPosition += mPackingSpaceRemaining; + break; + case NS_STYLE_JUSTIFY_CONTENT_CENTER: + // Half the packing space goes at the beginning + mPosition += mPackingSpaceRemaining / 2; + break; + case NS_STYLE_JUSTIFY_CONTENT_SPACE_BETWEEN: + MOZ_ASSERT(mPackingSpaceRemaining >= 0, + "negative packing space should make us use 'flex-start' " + "instead of 'space-between'"); + // 1 packing space between each flex item, no packing space at ends. + mNumPackingSpacesRemaining = aItems.Length() - 1; + break; + case NS_STYLE_JUSTIFY_CONTENT_SPACE_AROUND: + MOZ_ASSERT(mPackingSpaceRemaining >= 0, + "negative packing space should make us use 'center' " + "instead of 'space-around'"); + // 1 packing space between each flex item, plus half a packing space + // at beginning & end. So our number of full packing-spaces is equal + // to the number of flex items. + mNumPackingSpacesRemaining = aItems.Length(); + if (mNumPackingSpacesRemaining > 0) { + // The edges (start/end) share one full packing space + nscoord totalEdgePackingSpace = + mPackingSpaceRemaining / mNumPackingSpacesRemaining; + + // ...and we'll use half of that right now, at the start + mPosition += totalEdgePackingSpace / 2; + // ...but we need to subtract all of it right away, so that we won't + // hand out any of it to intermediate packing spaces. + mPackingSpaceRemaining -= totalEdgePackingSpace; + mNumPackingSpacesRemaining--; + } + break; + default: + MOZ_NOT_REACHED("Unexpected justify-content value"); + } + } + + MOZ_ASSERT(mNumPackingSpacesRemaining == 0 || + mNumAutoMarginsInMainAxis == 0, + "extra space should either go to packing space or to " + "auto margins, but not to both"); +} + +void +MainAxisPositionTracker::ResolveAutoMarginsInMainAxis(FlexItem& aItem) +{ + if (mNumAutoMarginsInMainAxis) { + const nsStyleSides& styleMargin = aItem.Frame()->GetStyleMargin()->mMargin; + for (uint32_t i = 0; i < eNumAxisEdges; i++) { + Side side = kAxisOrientationToSidesMap[mAxis][i]; + if (styleMargin.GetUnit(side) == eStyleUnit_Auto) { + // NOTE: This integer math will skew the distribution of remainder + // app-units towards the end, which is fine. + nscoord curAutoMarginSize = + mPackingSpaceRemaining / mNumAutoMarginsInMainAxis; + + MOZ_ASSERT(aItem.GetMarginComponentForSide(side) == 0, + "Expecting auto margins to have value '0' before we " + "resolve them"); + aItem.SetMarginComponentForSide(side, curAutoMarginSize); + + mNumAutoMarginsInMainAxis--; + mPackingSpaceRemaining -= curAutoMarginSize; + } + } + } +} + +void +MainAxisPositionTracker::TraversePackingSpace() +{ + if (mNumPackingSpacesRemaining) { + MOZ_ASSERT(mJustifyContent == NS_STYLE_JUSTIFY_CONTENT_SPACE_BETWEEN || + mJustifyContent == NS_STYLE_JUSTIFY_CONTENT_SPACE_AROUND, + "mNumPackingSpacesRemaining only applies for " + "space-between/space-around"); + + MOZ_ASSERT(mPackingSpaceRemaining >= 0, + "ran out of packing space earlier than we expected"); + + // NOTE: This integer math will skew the distribution of remainder + // app-units towards the end, which is fine. + nscoord curPackingSpace = + mPackingSpaceRemaining / mNumPackingSpacesRemaining; + + mPosition += curPackingSpace; + mNumPackingSpacesRemaining--; + mPackingSpaceRemaining -= curPackingSpace; + } +} + +CrossAxisPositionTracker:: + CrossAxisPositionTracker(nsFlexContainerFrame* aFlexContainerFrame, + const FlexboxAxisTracker& aAxisTracker, + const nsHTMLReflowState& aReflowState) + : PositionTracker(aAxisTracker.GetCrossAxis()) +{ + // Step over flex container's cross-start border/padding. + EnterMargin(aReflowState.mComputedBorderPadding); +} + +SingleLineCrossAxisPositionTracker:: + SingleLineCrossAxisPositionTracker(nsFlexContainerFrame* aFlexContainerFrame, + const FlexboxAxisTracker& aAxisTracker, + const nsTArray& aItems) + : PositionTracker(aAxisTracker.GetCrossAxis()), + mLineCrossSize(0), + mCrossStartToFurthestBaseline(nscoord_MIN) // Starts at -infinity, and then + // we progressively increase it. +{ +} + +void +SingleLineCrossAxisPositionTracker:: + ComputeLineCrossSize(const nsTArray& aItems) +{ + // NOTE: mCrossStartToFurthestBaseline is a member var rather than a local + // var, because we'll need it when we're baseline-aligning our children, and + // we'd prefer to not have to recompute it. + MOZ_ASSERT(mCrossStartToFurthestBaseline == nscoord_MIN, + "Computing largest baseline offset more than once"); + + nscoord crossEndToFurthestBaseline = nscoord_MIN; + nscoord largestOuterCrossSize = 0; + for (uint32_t i = 0; i < aItems.Length(); ++i) { + const FlexItem& curItem = aItems[i]; + nscoord curOuterCrossSize = curItem.GetCrossSize() + + curItem.GetMarginBorderPaddingSizeInAxis(mAxis); + + if (curItem.GetAlignSelf() == NS_STYLE_ALIGN_ITEMS_BASELINE && + curItem.GetNumAutoMarginsInAxis(mAxis) == 0) { + // FIXME: Once we support multi-line flexbox with "wrap-reverse", that'll + // give us bottom-to-top cross axes. (But for now, we assume eAxis_TB.) + // FIXME: Once we support "writing-mode", we'll have to do baseline + // alignment in vertical flex containers here (w/ horizontal cross-axes). + MOZ_ASSERT(mAxis == eAxis_TB, + "Only expecting to do baseline-alignment in horizontal " + "flex containers, with top-to-bottom cross axis"); + + // Find distance from our item's cross-start and cross-end margin-box + // edges to its baseline. + // + // Here's a diagram of a flex-item that we might be doing this on. + // "mmm" is the margin-box, "bbb" is the border-box. The bottom of + // the text "BASE" is the baseline. + // + // ---(cross-start)--- + // ___ ___ ___ + // mmmmmmmmmmmm | |margin-start | + // m m | _|_ ___ | + // m bbbbbbbb m |curOuterCrossSize | |crossStartToBaseline + // m b b m | |ascent | + // m b BASE b m | _|_ _|_ + // m b b m | | + // m bbbbbbbb m | |crossEndToBaseline + // m m | | + // mmmmmmmmmmmm _|_ _|_ + // + // ---(cross-end)--- + // + // We already have the curOuterCrossSize, margin-start, and the ascent. + // * We can get crossStartToBaseline by adding margin-start + ascent. + // * If we subtract that from the curOuterCrossSize, we get + // crossEndToBaseline. + + nscoord crossStartToBaseline = GetBaselineOffsetFromCrossStart(curItem); + nscoord crossEndToBaseline = curOuterCrossSize - crossStartToBaseline; + + // Now, update our "largest" values for these (across all the flex items + // in this flex line), so we can use them in computing mLineCrossSize + // below: + mCrossStartToFurthestBaseline = NS_MAX(mCrossStartToFurthestBaseline, + crossStartToBaseline); + crossEndToFurthestBaseline = NS_MAX(crossEndToFurthestBaseline, + crossEndToBaseline); + } else { + largestOuterCrossSize = NS_MAX(largestOuterCrossSize, curOuterCrossSize); + } + } + + // The line's cross-size is the larger of: + // (a) [largest cross-start-to-baseline + largest baseline-to-cross-end] of + // all baseline-aligned items with no cross-axis auto margins... + // and + // (b) largest cross-size of all other children. + mLineCrossSize = NS_MAX(mCrossStartToFurthestBaseline + + crossEndToFurthestBaseline, + largestOuterCrossSize); +} + +nscoord +SingleLineCrossAxisPositionTracker:: + GetBaselineOffsetFromCrossStart(const FlexItem& aItem) const +{ + Side crossStartSide = kAxisOrientationToSidesMap[mAxis][eAxisEdge_Start]; + + // XXXdholbert This assumes cross axis is Top-To-Bottom. + // For bottom-to-top support, probably want to make this depend on + // AxisGrowsInPositiveDirection(mAxis) + return aItem.GetAscent() + aItem.GetMarginComponentForSide(crossStartSide); +} + +void +SingleLineCrossAxisPositionTracker:: + ResolveStretchedCrossSize(FlexItem& aItem) +{ + // We stretch IFF we are align-self:stretch, have no auto margins in + // cross axis, and have cross-axis size property == "auto". If any of those + // conditions don't hold up, we can just return. + if (aItem.GetAlignSelf() != NS_STYLE_ALIGN_ITEMS_STRETCH || + aItem.GetNumAutoMarginsInAxis(mAxis) != 0 || + GetSizePropertyForAxis(aItem.Frame(), mAxis).GetUnit() != + eStyleUnit_Auto) { + return; + } + + // Reserve space for margins & border & padding, and then use whatever + // remains as our item's cross-size (clamped to its min/max range). + nscoord stretchedSize = mLineCrossSize - + aItem.GetMarginBorderPaddingSizeInAxis(mAxis); + + stretchedSize = NS_CSS_MINMAX(stretchedSize, + aItem.GetCrossMinSize(), + aItem.GetCrossMaxSize()); + + // Update the cross-size & make a note that it's stretched, so we know to + // override the reflow state's computed cross-size in our final reflow. + aItem.SetCrossSize(stretchedSize); + aItem.SetIsStretched(); +} + +void +SingleLineCrossAxisPositionTracker:: + ResolveAutoMarginsInCrossAxis(FlexItem& aItem) +{ + // Subtract the space that our item is already occupying, to see how much + // space (if any) is available for its auto margins. + nscoord spaceForAutoMargins = mLineCrossSize - + (aItem.GetCrossSize() + aItem.GetMarginBorderPaddingSizeInAxis(mAxis)); + + if (spaceForAutoMargins <= 0) { + return; // No available space --> nothing to do + } + + uint32_t numAutoMargins = aItem.GetNumAutoMarginsInAxis(mAxis); + if (numAutoMargins == 0) { + return; // No auto margins --> nothing to do. + } + + // OK, we have at least one auto margin and we have some available space. + // Give each auto margin a share of the space. + const nsStyleSides& styleMargin = aItem.Frame()->GetStyleMargin()->mMargin; + for (uint32_t i = 0; i < eNumAxisEdges; i++) { + Side side = kAxisOrientationToSidesMap[mAxis][i]; + if (styleMargin.GetUnit(side) == eStyleUnit_Auto) { + MOZ_ASSERT(aItem.GetMarginComponentForSide(side) == 0, + "Expecting auto margins to have value '0' before we " + "update them"); + + // NOTE: integer divison is fine here; numAutoMargins is either 1 or 2. + // If it's 2 & spaceForAutoMargins is odd, 1st margin gets smaller half. + nscoord curAutoMarginSize = spaceForAutoMargins / numAutoMargins; + aItem.SetMarginComponentForSide(side, curAutoMarginSize); + numAutoMargins--; + spaceForAutoMargins -= curAutoMarginSize; + } + } +} + +void +SingleLineCrossAxisPositionTracker:: + EnterAlignPackingSpace(const FlexItem& aItem) +{ + // We don't do align-self alignment on items that have auto margins + // in the cross axis. + if (aItem.GetNumAutoMarginsInAxis(mAxis)) { + return; + } + + switch (aItem.GetAlignSelf()) { + case NS_STYLE_ALIGN_ITEMS_FLEX_START: + case NS_STYLE_ALIGN_ITEMS_STRETCH: + // No space to skip over -- we're done. + // NOTE: 'stretch' behaves like 'start' once we've stretched any + // auto-sized items (which we've already done). + break; + case NS_STYLE_ALIGN_ITEMS_FLEX_END: + mPosition += + mLineCrossSize - + (aItem.GetCrossSize() + + aItem.GetMarginBorderPaddingSizeInAxis(mAxis)); + break; + case NS_STYLE_ALIGN_ITEMS_CENTER: + // Note: If cross-size is odd, the "after" space will get the extra unit. + mPosition += + (mLineCrossSize - + (aItem.GetCrossSize() + + aItem.GetMarginBorderPaddingSizeInAxis(mAxis))) / 2; + break; + case NS_STYLE_ALIGN_ITEMS_BASELINE: + MOZ_ASSERT(mCrossStartToFurthestBaseline != nscoord_MIN, + "using uninitialized baseline offset"); + MOZ_ASSERT(mCrossStartToFurthestBaseline >= + GetBaselineOffsetFromCrossStart(aItem), + "failed at finding largest ascent"); + + // Advance so that aItem's baseline is aligned with + // largest baseline offset. + mPosition += (mCrossStartToFurthestBaseline - + GetBaselineOffsetFromCrossStart(aItem)); + break; + default: + NS_NOTREACHED("Unexpected align-self value"); + break; + } +} + +FlexboxAxisTracker::FlexboxAxisTracker(nsFlexContainerFrame* aFlexContainerFrame) +{ + uint32_t flexDirection = + aFlexContainerFrame->GetStylePosition()->mFlexDirection; + uint32_t cssDirection = + aFlexContainerFrame->GetStyleVisibility()->mDirection; + + MOZ_ASSERT(cssDirection == NS_STYLE_DIRECTION_LTR || + cssDirection == NS_STYLE_DIRECTION_RTL, + "Unexpected computed value for 'direction' property"); + // (Not asserting for flexDirection here; it's checked by the switch below.) + + // These are defined according to writing-modes' definitions of + // start/end (for the inline dimension) and before/after (for the block + // dimension), here: + // http://www.w3.org/TR/css3-writing-modes/#logical-directions + // (NOTE: I'm intentionally not calling this "inlineAxis"/"blockAxis", since + // those terms have explicit definition in the writing-modes spec, which are + // the opposite of how I'd be using them here.) + // XXXdholbert Once we support the 'writing-mode' property, use its value + // here to further customize inlineDimension & blockDimension. + + // Inline dimension ("start-to-end"): + AxisOrientationType inlineDimension = + cssDirection == NS_STYLE_DIRECTION_RTL ? eAxis_RL : eAxis_LR; + + // Block dimension ("before-to-after"): + AxisOrientationType blockDimension = eAxis_TB; + + // Determine main axis: + switch (flexDirection) { + case NS_STYLE_FLEX_DIRECTION_ROW: + mMainAxis = inlineDimension; + break; + case NS_STYLE_FLEX_DIRECTION_ROW_REVERSE: + mMainAxis = GetReverseAxis(inlineDimension); + break; + case NS_STYLE_FLEX_DIRECTION_COLUMN: + mMainAxis = blockDimension; + break; + case NS_STYLE_FLEX_DIRECTION_COLUMN_REVERSE: + mMainAxis = GetReverseAxis(blockDimension); + break; + default: + MOZ_NOT_REACHED("Unexpected computed value for 'flex-flow' property"); + mMainAxis = inlineDimension; + break; + } + + // Determine cross axis: + // (This is set up so that a bogus |flexDirection| value will + // give us blockDimension. + if (flexDirection == NS_STYLE_FLEX_DIRECTION_COLUMN || + flexDirection == NS_STYLE_FLEX_DIRECTION_COLUMN_REVERSE) { + mCrossAxis = inlineDimension; + } else { + mCrossAxis = blockDimension; + } + + // FIXME: Once we support "flex-wrap", check if it's "wrap-reverse" + // here to determine whether we should reverse mCrossAxis. + MOZ_ASSERT(IsAxisHorizontal(mMainAxis) != IsAxisHorizontal(mCrossAxis), + "main & cross axes should be in different dimensions"); + + + // NOTE: Right now, cross axis is never bottom-to-top. + // The only way for it to be different would be if we used a vertical + // "writing-mode" or if we had "flex-wrap: wrap-reverse" -- but we don't + // support either of those yet, so that can't happen right now. + // (When we add support for either of those properties, this assert will + // no longer hold.) + MOZ_ASSERT(mCrossAxis != eAxis_BT, "Not expecting bottom-to-top cross axis"); +} + +nsresult +nsFlexContainerFrame::GenerateFlexItems( + nsPresContext* aPresContext, + const nsHTMLReflowState& aReflowState, + const FlexboxAxisTracker& aAxisTracker, + nsTArray& aFlexItems) +{ + MOZ_ASSERT(aFlexItems.IsEmpty(), "Expecting outparam to start out empty"); + + // Sort by 'order' property: + const nsTArray sortedChildren = BuildSortedChildArray(mFrames); + + // Build list of unresolved flex items: + + // XXXdholbert When we support multi-line, we might want this to be a linked + // list, so we can easily split into multiple lines. + aFlexItems.SetCapacity(sortedChildren.Length()); + for (uint32_t i = 0; i < sortedChildren.Length(); ++i) { + nsresult rv = AppendFlexItemForChild(aPresContext, + sortedChildren[i].Frame(), + aReflowState, aAxisTracker, + aFlexItems); + NS_ENSURE_SUCCESS(rv,rv); + } + + return NS_OK; +} + +// Computes the content-box main-size of our flex container. +nscoord +nsFlexContainerFrame::ComputeFlexContainerMainSize( + const nsHTMLReflowState& aReflowState, + const FlexboxAxisTracker& aAxisTracker, + const nsTArray& aItems) +{ + // If we've got a finite computed main-size, use that. + nscoord mainSize = + aAxisTracker.GetMainComponent(nsSize(aReflowState.ComputedWidth(), + aReflowState.ComputedHeight())); + if (mainSize != NS_UNCONSTRAINEDSIZE) { + return mainSize; + } + + MOZ_ASSERT(!IsAxisHorizontal(aAxisTracker.GetMainAxis()), + "Computed width should always be constrained, so horizontal " + "flex containers should always have a constrained main-size"); + + // Otherwise, use the sum of our items' hypothetical main sizes, clamped + // to our computed min/max main-size properties. + mainSize = 0; + for (uint32_t i = 0; i < aItems.Length(); ++i) { + mainSize += + aItems[i].GetMainSize() + + aItems[i].GetMarginBorderPaddingSizeInAxis(aAxisTracker.GetMainAxis()); + } + + nscoord minMainSize = + aAxisTracker.GetMainComponent(nsSize(aReflowState.mComputedMinWidth, + aReflowState.mComputedMinHeight)); + nscoord maxMainSize = + aAxisTracker.GetMainComponent(nsSize(aReflowState.mComputedMaxWidth, + aReflowState.mComputedMaxHeight)); + + return NS_CSS_MINMAX(mainSize, minMainSize, maxMainSize); +} + +void +nsFlexContainerFrame::PositionItemInMainAxis( + MainAxisPositionTracker& aMainAxisPosnTracker, + FlexItem& aItem) +{ + nscoord itemMainBorderBoxSize = + aItem.GetMainSize() + + aItem.GetBorderPaddingSizeInAxis(aMainAxisPosnTracker.GetAxis()); + + // Resolve any main-axis 'auto' margins on aChild to an actual value. + aMainAxisPosnTracker.ResolveAutoMarginsInMainAxis(aItem); + + // Advance our position tracker to child's upper-left content-box corner, + // and use that as its position in the main axis. + aMainAxisPosnTracker.EnterMargin(aItem.GetMargin()); + aMainAxisPosnTracker.EnterChildFrame(itemMainBorderBoxSize); + + aItem.SetMainPosition(aMainAxisPosnTracker.GetPosition()); + + aMainAxisPosnTracker.ExitChildFrame(itemMainBorderBoxSize); + aMainAxisPosnTracker.ExitMargin(aItem.GetMargin()); + aMainAxisPosnTracker.TraversePackingSpace(); +} + +nsresult +nsFlexContainerFrame::SizeItemInCrossAxis( + nsPresContext* aPresContext, + const FlexboxAxisTracker& aAxisTracker, + const nsHTMLReflowState& aChildReflowState, + FlexItem& aItem) +{ + // In vertical flexbox (with horizontal cross-axis), we can just trust the + // reflow state's computed-width as our cross-size. We also don't need to + // record the baseline because we'll have converted any "align-self:baseline" + // items to be "align-self:flex-start" in the FlexItem constructor. + // FIXME: Once we support writing-mode (vertical text), we will be able to + // have baseline-aligned items in a vertical flexbox, and we'll need to + // record baseline information here. + if (IsAxisHorizontal(aAxisTracker.GetCrossAxis())) { + MOZ_ASSERT(aItem.GetAlignSelf() != NS_STYLE_ALIGN_ITEMS_BASELINE, + "In vert flex container, we depend on FlexItem constructor to " + "convert 'align-self: baseline' to 'align-self: flex-start'"); + aItem.SetCrossSize(aChildReflowState.ComputedWidth()); + return NS_OK; + } + + nsHTMLReflowMetrics childDesiredSize; + nsReflowStatus childReflowStatus; + nsresult rv = ReflowChild(aItem.Frame(), aPresContext, + childDesiredSize, aChildReflowState, + 0, 0, NS_FRAME_NO_MOVE_FRAME, + childReflowStatus); + NS_ENSURE_SUCCESS(rv, rv); + + // XXXdholbert Once we do pagination / splitting, we'll need to actually + // handle incomplete childReflowStatuses. But for now, we give our kids + // unconstrained available height, which means they should always complete. + MOZ_ASSERT(NS_FRAME_IS_COMPLETE(childReflowStatus), + "We gave flex item unconstrained available height, so it " + "should be complete"); + + // Tell the child we're done with its initial reflow. + // (Necessary for e.g. GetBaseline() to work below w/out asserting) + rv = FinishReflowChild(aItem.Frame(), aPresContext, + &aChildReflowState, childDesiredSize, 0, 0, 0); + NS_ENSURE_SUCCESS(rv, rv); + + // Save the sizing info that we learned from this reflow + // ----------------------------------------------------- + + // Tentatively accept the child's desired size, minus border/padding, as its + // cross-size: + MOZ_ASSERT(childDesiredSize.height >= + aItem.GetBorderPaddingSizeInAxis(aAxisTracker.GetCrossAxis()), + "Child should ask for at least enough space for border/padding"); + nscoord crossSize = + aAxisTracker.GetCrossComponent(childDesiredSize) - + aItem.GetBorderPaddingSizeInAxis(aAxisTracker.GetCrossAxis()); + aItem.SetCrossSize(crossSize); + + // If we need to do baseline-alignment, store the child's ascent. + if (aItem.GetAlignSelf() == NS_STYLE_ALIGN_ITEMS_BASELINE) { + if (childDesiredSize.ascent == nsHTMLReflowMetrics::ASK_FOR_BASELINE) { + // Use GetFirstLineBaseline(), or just GetBaseline() if that fails. + if (!nsLayoutUtils::GetFirstLineBaseline(aItem.Frame(), + &childDesiredSize.ascent)) { + childDesiredSize.ascent = aItem.Frame()->GetBaseline(); + } + } + aItem.SetAscent(childDesiredSize.ascent); + } + + return NS_OK; +} + +void +nsFlexContainerFrame::PositionItemInCrossAxis( + nscoord aLineStartPosition, + SingleLineCrossAxisPositionTracker& aLineCrossAxisPosnTracker, + FlexItem& aItem) +{ + MOZ_ASSERT(aLineCrossAxisPosnTracker.GetPosition() == 0, + "per-line cross-axis position tracker wasn't correctly reset"); + + // Resolve any to-be-stretched cross-sizes & auto margins in cross axis. + aLineCrossAxisPosnTracker.ResolveStretchedCrossSize(aItem); + aLineCrossAxisPosnTracker.ResolveAutoMarginsInCrossAxis(aItem); + + // Compute the cross-axis position of this item + nscoord itemCrossBorderBoxSize = + aItem.GetCrossSize() + + aItem.GetBorderPaddingSizeInAxis(aLineCrossAxisPosnTracker.GetAxis()); + aLineCrossAxisPosnTracker.EnterAlignPackingSpace(aItem); + aLineCrossAxisPosnTracker.EnterMargin(aItem.GetMargin()); + aLineCrossAxisPosnTracker.EnterChildFrame(itemCrossBorderBoxSize); + + aItem.SetCrossPosition(aLineStartPosition + + aLineCrossAxisPosnTracker.GetPosition()); + + // Back out to cross-axis edge of the line. + aLineCrossAxisPosnTracker.ResetPosition(); +} + +NS_IMETHODIMP +nsFlexContainerFrame::Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) +{ + DO_GLOBAL_REFLOW_COUNT("nsFlexContainerFrame"); + DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); + PR_LOG(nsFlexContainerFrameLM, PR_LOG_DEBUG, + ("Reflow() for nsFlexContainerFrame %p\n", this)); + + // We (and our children) can only depend on our ancestor's height if we have + // a percent-height. (There are actually other cases, too -- e.g. if our + // parent is itself a vertical flex container and we're flexible -- but we'll + // let our ancestors handle those sorts of cases.) + if (GetStylePosition()->mHeight.HasPercent()) { + AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT); + } + +#ifdef DEBUG + SanityCheckAnonymousFlexItems(); +#endif // DEBUG + + // If our subtree is dirty (i.e. some of our descendants have changed), we + // reflow _all_ of our children. We have to do this -- we can't just reflow + // select children, as we would in other frame classes. This is because flex + // items' sizes (in both axes) are highly dependent on their siblings' sizes. + bool shouldReflowChildren = + NS_SUBTREE_DIRTY(this) || aReflowState.ShouldReflowAllKids(); + + const FlexboxAxisTracker axisTracker(this); + + // Generate a list of our flex items (already sorted), and get our main + // size (which may depend on those items). + nsTArray items; + nsresult rv = GenerateFlexItems(aPresContext, aReflowState, + axisTracker, items); + NS_ENSURE_SUCCESS(rv, rv); + + // XXXdholbert FOR MULTI-LINE FLEX CONTAINERS: Do line-breaking here. + // This would produce an array of arrays, or a list of arrays, + // or something like that. (one list/array per line) + + nscoord flexContainerMainSize = + ComputeFlexContainerMainSize(aReflowState, axisTracker, items); + + ResolveFlexibleLengths(axisTracker, flexContainerMainSize, items); + + // Our frame's main-size is the content-box size plus border and padding. + nscoord frameMainSize = flexContainerMainSize + + axisTracker.GetMarginSizeInMainAxis(aReflowState.mComputedBorderPadding); + + nscoord frameCrossSize; + + if (!shouldReflowChildren) { + // Children don't need reflow --> assume our content-box size is the same + // since our last reflow. + frameCrossSize = mCachedContentBoxCrossSize + + axisTracker.GetMarginSizeInCrossAxis(aReflowState.mComputedBorderPadding); + } else { + MainAxisPositionTracker mainAxisPosnTracker(this, axisTracker, + aReflowState, items); + + // First loop: Compute main axis position & cross-axis size of each item + for (uint32_t i = 0; i < items.Length(); ++i) { + FlexItem& curItem = items[i]; + + nsHTMLReflowState childReflowState(aPresContext, aReflowState, + curItem.Frame(), + nsSize(aReflowState.ComputedWidth(), + NS_UNCONSTRAINEDSIZE)); + // Override computed main-size + if (IsAxisHorizontal(axisTracker.GetMainAxis())) { + childReflowState.SetComputedWidth(curItem.GetMainSize()); + } else { + childReflowState.SetComputedHeight(curItem.GetMainSize()); + } + + PositionItemInMainAxis(mainAxisPosnTracker, curItem); + + nsresult rv = + SizeItemInCrossAxis(aPresContext, axisTracker, + childReflowState, curItem); + NS_ENSURE_SUCCESS(rv, rv); + } + + // SIZE & POSITION THE FLEX LINE (IN CROSS AXIS) + // Set up state for cross-axis alignment, at a high level (outside the + // scope of a particular flex line) + CrossAxisPositionTracker + crossAxisPosnTracker(this, axisTracker, aReflowState); + + // Set up state for cross-axis-positioning of children _within_ a single + // flex line. + SingleLineCrossAxisPositionTracker + lineCrossAxisPosnTracker(this, axisTracker, items); + + lineCrossAxisPosnTracker.ComputeLineCrossSize(items); + // XXXdholbert Once we've got multi-line flexbox support: here, after we've + // computed the cross size of all lines, we need to check if if + // 'align-content' is 'stretch' -- if it is, we need to give each line an + // additional share of our flex container's desired cross-size. (if it's + // not NS_AUTOHEIGHT and there's any cross-size left over to distribute) + + // Figure out our flex container's cross size + mCachedContentBoxCrossSize = + axisTracker.GetCrossComponent(nsSize(aReflowState.ComputedWidth(), + aReflowState.ComputedHeight())); + + if (mCachedContentBoxCrossSize == NS_AUTOHEIGHT) { + // unconstrained 'auto' cross-size: shrink-wrap our line(s) + mCachedContentBoxCrossSize = + lineCrossAxisPosnTracker.GetLineCrossSize(); + } else { + // XXXdholbert When we support multi-line flex containers, we should + // distribute any extra space among or between our lines here according + // to 'align-content'. For now, we do the single-line special behavior: + // "If the flex container has only a single line (even if it's a + // multi-line flex container), the cross size of the flex line is the + // flex container's inner cross size." + lineCrossAxisPosnTracker.SetLineCrossSize(mCachedContentBoxCrossSize); + } + frameCrossSize = mCachedContentBoxCrossSize + + axisTracker.GetMarginSizeInCrossAxis(aReflowState.mComputedBorderPadding); + + // XXXdholbert FOLLOW ACTUAL RULES FOR FLEX CONTAINER BASELINE + // If we have any baseline-aligned items on first line, use their baseline. + // ...ELSE if we have at least one flex item and our first flex item's + // baseline is parallel to main axis, then use that baseline. + // ...ELSE use "after" edge of content box. + // Default baseline: the "after" edge of content box. (Note: if we have any + // flex items, they'll override this.) + mCachedAscent = mCachedContentBoxCrossSize + + aReflowState.mComputedBorderPadding.top; + + // Position the items in cross axis, within their line + for (uint32_t i = 0; i < items.Length(); ++i) { + PositionItemInCrossAxis(crossAxisPosnTracker.GetPosition(), + lineCrossAxisPosnTracker, items[i]); + } + + // FINAL REFLOW: Give each child frame another chance to reflow, now that + // we know its final size and position. + for (uint32_t i = 0; i < items.Length(); ++i) { + FlexItem& curItem = items[i]; + nsHTMLReflowState childReflowState(aPresContext, aReflowState, + curItem.Frame(), + nsSize(aReflowState.ComputedWidth(), + NS_UNCONSTRAINEDSIZE)); + + // Override computed main-size + if (IsAxisHorizontal(axisTracker.GetMainAxis())) { + childReflowState.SetComputedWidth(curItem.GetMainSize()); + } else { + childReflowState.SetComputedHeight(curItem.GetMainSize()); + } + + // Override reflow state's computed cross-size, for stretched items. + if (curItem.IsStretched()) { + MOZ_ASSERT(curItem.GetAlignSelf() == NS_STYLE_ALIGN_ITEMS_STRETCH, + "stretched item w/o 'align-self: stretch'?"); + if (IsAxisHorizontal(axisTracker.GetCrossAxis())) { + childReflowState.SetComputedWidth(curItem.GetCrossSize()); + } else { + childReflowState.SetComputedHeight(curItem.GetCrossSize()); + } + } + + // XXXdholbert Might need to actually set the correct margins in the + // reflow state at some point, so that they can be saved on the frame for + // UsedMarginPropeorty(). Maybe doesn't matter though...? + + // XXXdholbert Assuming horizontal + nscoord mainPosn = curItem.GetMainPosition(); + nscoord crossPosn = curItem.GetCrossPosition(); + if (!AxisGrowsInPositiveDirection(axisTracker.GetMainAxis())) { + mainPosn = frameMainSize - mainPosn; + } + if (!AxisGrowsInPositiveDirection(axisTracker.GetCrossAxis())) { + crossPosn = frameCrossSize - crossPosn; + } + + nsPoint physicalPosn = + axisTracker.PhysicalPositionFromLogicalPosition(mainPosn, crossPosn); + + nsHTMLReflowMetrics childDesiredSize; + nsReflowStatus childReflowStatus; + nsresult rv = ReflowChild(curItem.Frame(), aPresContext, + childDesiredSize, childReflowState, + physicalPosn.x, physicalPosn.y, + 0, childReflowStatus); + NS_ENSURE_SUCCESS(rv, rv); + + // XXXdholbert Once we do pagination / splitting, we'll need to actually + // handle incomplete childReflowStatuses. But for now, we give our kids + // unconstrained available height, which means they should always + // complete. + MOZ_ASSERT(NS_FRAME_IS_COMPLETE(childReflowStatus), + "We gave flex item unconstrained available height, so it " + "should be complete"); + + // Apply CSS relative positioning + const nsStyleDisplay* styleDisp = curItem.Frame()->GetStyleDisplay(); + if (NS_STYLE_POSITION_RELATIVE == styleDisp->mPosition) { + physicalPosn.x += childReflowState.mComputedOffsets.left; + physicalPosn.y += childReflowState.mComputedOffsets.top; + } + + rv = FinishReflowChild(curItem.Frame(), aPresContext, + &childReflowState, childDesiredSize, + physicalPosn.x, physicalPosn.y, 0); + NS_ENSURE_SUCCESS(rv, rv); + } + } + + // XXXdholbert This could be more elegant + aDesiredSize.width = + IsAxisHorizontal(axisTracker.GetMainAxis()) ? + frameMainSize : frameCrossSize; + aDesiredSize.height = + IsAxisHorizontal(axisTracker.GetCrossAxis()) ? + frameMainSize : frameCrossSize; + + aDesiredSize.ascent = mCachedAscent; + + // Overflow area = union(my overflow area, kids' overflow areas) + aDesiredSize.SetOverflowAreasToDesiredBounds(); + for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) { + ConsiderChildOverflow(aDesiredSize.mOverflowAreas, e.get()); + } + + NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize) + + aStatus = NS_FRAME_COMPLETE; + + FinishReflowWithAbsoluteFrames(aPresContext, aDesiredSize, + aReflowState, aStatus); + + return NS_OK; +} + +/* virtual */ nscoord +nsFlexContainerFrame::GetMinWidth(nsRenderingContext* aRenderingContext) +{ + FlexboxAxisTracker axisTracker(this); + + nscoord minWidth = 0; + for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) { + nscoord childMinWidth = + nsLayoutUtils::IntrinsicForContainer(aRenderingContext, e.get(), + nsLayoutUtils::MIN_WIDTH); + if (IsAxisHorizontal(axisTracker.GetMainAxis())) { + minWidth += childMinWidth; + } else { + minWidth = NS_MAX(minWidth, childMinWidth); + } + } + return minWidth; +} + +/* virtual */ nscoord +nsFlexContainerFrame::GetPrefWidth(nsRenderingContext* aRenderingContext) +{ + // XXXdholbert Optimization: We could cache our intrinsic widths like + // nsBlockFrame does (and return it early from this function if it's set). + // Whenever anything happens that might change it, set it to + // NS_INTRINSIC_WIDTH_UNKNOWN (like nsBlockFrame::MarkIntrinsicWidthsDirty + // does) + FlexboxAxisTracker axisTracker(this); + + nscoord prefWidth = 0; + for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) { + nscoord childPrefWidth = + nsLayoutUtils::IntrinsicForContainer(aRenderingContext, e.get(), + nsLayoutUtils::PREF_WIDTH); + if (IsAxisHorizontal(axisTracker.GetMainAxis())) { + prefWidth += childPrefWidth; + } else { + prefWidth = NS_MAX(prefWidth, childPrefWidth); + } + } + return prefWidth; +} diff --git a/layout/generic/nsFlexContainerFrame.h b/layout/generic/nsFlexContainerFrame.h index dcbbbca46535..bcb218aca736 100644 --- a/layout/generic/nsFlexContainerFrame.h +++ b/layout/generic/nsFlexContainerFrame.h @@ -11,6 +11,7 @@ #define nsFlexContainerFrame_h___ #include "nsContainerFrame.h" +#include "nsTArray.h" #include "mozilla/Types.h" nsIFrame* NS_NewFlexContainerFrame(nsIPresShell* aPresShell, @@ -18,6 +19,11 @@ nsIFrame* NS_NewFlexContainerFrame(nsIPresShell* aPresShell, typedef nsContainerFrame nsFlexContainerFrameSuper; +class FlexItem; +class FlexboxAxisTracker; +class MainAxisPositionTracker; +class SingleLineCrossAxisPositionTracker; + class nsFlexContainerFrame : public nsFlexContainerFrameSuper { NS_DECL_FRAMEARENA_HELPERS NS_DECL_QUERYFRAME_TARGET(nsFlexContainerFrame) @@ -27,20 +33,89 @@ class nsFlexContainerFrame : public nsFlexContainerFrameSuper { friend nsIFrame* NS_NewFlexContainerFrame(nsIPresShell* aPresShell, nsStyleContext* aContext); +public: // nsIFrame overrides + NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder, + const nsRect& aDirtyRect, + const nsDisplayListSet& aLists) MOZ_OVERRIDE; + + NS_IMETHOD Reflow(nsPresContext* aPresContext, + nsHTMLReflowMetrics& aDesiredSize, + const nsHTMLReflowState& aReflowState, + nsReflowStatus& aStatus) MOZ_OVERRIDE; + + virtual nscoord + GetMinWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE; + virtual nscoord + GetPrefWidth(nsRenderingContext* aRenderingContext) MOZ_OVERRIDE; + virtual nsIAtom* GetType() const MOZ_OVERRIDE; #ifdef DEBUG NS_IMETHOD GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; -#endif +#endif // DEBUG + // Flexbox-specific public methods + bool IsHorizontal(); protected: // Protected constructor & destructor - nsFlexContainerFrame(nsStyleContext* aContext) : nsFlexContainerFrameSuper(aContext) {} + nsFlexContainerFrame(nsStyleContext* aContext) : + nsFlexContainerFrameSuper(aContext), + mCachedContentBoxCrossSize(nscoord_MIN), + mCachedAscent(nscoord_MIN) + {} virtual ~nsFlexContainerFrame(); // Protected nsIFrame overrides: virtual void DestroyFrom(nsIFrame* aDestructRoot); + // Protected flex-container-specific methods / member-vars +#ifdef DEBUG + void SanityCheckAnonymousFlexItems() const; +#endif // DEBUG + + + // Returns nsresult because we might have to reflow aChildFrame (to get its + // vertical intrinsic size in a vertical flexbox), and if that reflow fails + // (returns a failure nsresult), we want to bail out. + nsresult AppendFlexItemForChild(nsPresContext* aPresContext, + nsIFrame* aChildFrame, + const nsHTMLReflowState& aParentReflowState, + const FlexboxAxisTracker& aAxisTracker, + nsTArray& aFlexItems); + + // Runs the "resolve the flexible lengths" algorithm, distributing + // |aFlexContainerMainSize| among the |aItems| and freezing them. + void ResolveFlexibleLengths(const FlexboxAxisTracker& aAxisTracker, + nscoord aFlexContainerMainSize, + nsTArray& aItems); + + nsresult GenerateFlexItems(nsPresContext* aPresContext, + const nsHTMLReflowState& aReflowState, + const FlexboxAxisTracker& aAxisTracker, + nsTArray& aItems); + + nscoord ComputeFlexContainerMainSize(const nsHTMLReflowState& aReflowState, + const FlexboxAxisTracker& aAxisTracker, + const nsTArray& aFlexItems); + + void PositionItemInMainAxis(MainAxisPositionTracker& aMainAxisPosnTracker, + FlexItem& aItem); + + nsresult SizeItemInCrossAxis(nsPresContext* aPresContext, + const FlexboxAxisTracker& aAxisTracker, + const nsHTMLReflowState& aChildReflowState, + FlexItem& aItem); + + void PositionItemInCrossAxis( + nscoord aLineStartPosition, + SingleLineCrossAxisPositionTracker& aLineCrossAxisPosnTracker, + FlexItem& aItem); + + // Cached values from running flexbox layout algorithm, used in setting our + // reflow metrics w/out actually reflowing all of our children, in any + // reflows where we're not dirty: + nscoord mCachedContentBoxCrossSize; // cross size of our content-box size + nscoord mCachedAscent; // our ascent, in prev. reflow. }; #endif /* nsFlexContainerFrame_h___ */ diff --git a/layout/generic/nsFrameIdList.h b/layout/generic/nsFrameIdList.h index d592e149b471..b0ca1531cf40 100644 --- a/layout/generic/nsFrameIdList.h +++ b/layout/generic/nsFrameIdList.h @@ -22,9 +22,7 @@ FRAME_ID(nsFieldSetFrame) FRAME_ID(nsFileControlFrame) FRAME_ID(nsFirstLetterFrame) FRAME_ID(nsFirstLineFrame) -#ifdef MOZ_FLEXBOX FRAME_ID(nsFlexContainerFrame) -#endif // MOZ_FLEXBOX FRAME_ID(nsFormControlFrame) FRAME_ID(nsFrame) FRAME_ID(nsGfxButtonControlFrame) diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index 5bb75837dfca..b4a57f8a4ddb 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -16,6 +16,7 @@ #include "nsFontMetrics.h" #include "nsBlockFrame.h" #include "nsLineBox.h" +#include "nsFlexContainerFrame.h" #include "nsImageFrame.h" #include "nsTableFrame.h" #include "nsTableCellFrame.h" @@ -687,6 +688,9 @@ nsHTMLReflowState::InitFrameType(nsIAtom* aFrameType) case NS_STYLE_DISPLAY_LIST_ITEM: case NS_STYLE_DISPLAY_TABLE: case NS_STYLE_DISPLAY_TABLE_CAPTION: +#ifdef MOZ_FLEXBOX + case NS_STYLE_DISPLAY_FLEX: +#endif // MOZ_FLEXBOX frameType = NS_CSS_FRAME_TYPE_BLOCK; break; @@ -696,6 +700,9 @@ nsHTMLReflowState::InitFrameType(nsIAtom* aFrameType) case NS_STYLE_DISPLAY_INLINE_BOX: case NS_STYLE_DISPLAY_INLINE_GRID: case NS_STYLE_DISPLAY_INLINE_STACK: +#ifdef MOZ_FLEXBOX + case NS_STYLE_DISPLAY_INLINE_FLEX: +#endif // MOZ_FLEXBOX frameType = NS_CSS_FRAME_TYPE_INLINE; break; @@ -1799,6 +1806,20 @@ IsSideCaption(nsIFrame* aFrame, const nsStyleDisplay* aStyleDisplay) captionSide == NS_STYLE_CAPTION_SIDE_RIGHT; } +#ifdef MOZ_FLEXBOX +static nsFlexContainerFrame* +GetFlexContainer(nsIFrame* aFrame) +{ + nsIFrame* parent = aFrame->GetParent(); + if (!parent || + parent->GetType() != nsGkAtoms::flexContainerFrame) { + return nullptr; + } + + return static_cast(parent); +} +#endif // MOZ_FLEXBOX + // XXX refactor this code to have methods for each set of properties // we are computing: width,height,line-height; margin; offsets @@ -2010,11 +2031,22 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext, computeSizeFlags |= nsIFrame::eShrinkWrap; } - // If we're inside of a flexbox that needs to measure our auto height, - // pass that information along to ComputeSize(). - if (mFlags.mIsFlexContainerMeasuringHeight) { - computeSizeFlags |= nsIFrame::eUseAutoHeight; +#ifdef MOZ_FLEXBOX + const nsFlexContainerFrame* flexContainerFrame = GetFlexContainer(frame); + if (flexContainerFrame) { + computeSizeFlags |= nsIFrame::eShrinkWrap; + + // If we're inside of a flex container that needs to measure our + // auto height, pass that information along to ComputeSize(). + if (mFlags.mIsFlexContainerMeasuringHeight) { + computeSizeFlags |= nsIFrame::eUseAutoHeight; + } + } else { + MOZ_ASSERT(!mFlags.mIsFlexContainerMeasuringHeight, + "We're not in a flex container, so the flag " + "'mIsFlexContainerMeasuringHeight' shouldn't be set"); } +#endif // MOZ_FLEXBOX nsSize size = frame->ComputeSize(rendContext, @@ -2037,9 +2069,14 @@ nsHTMLReflowState::InitConstraints(nsPresContext* aPresContext, NS_ASSERTION(mComputedHeight == NS_UNCONSTRAINEDSIZE || mComputedHeight >= 0, "Bogus height"); - // Exclude inline tables from the block margin calculations - if (isBlock && !IsSideCaption(frame, mStyleDisplay) && - frame->GetStyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE_TABLE) + // Exclude inline tables and flex items from the block margin calculations + if (isBlock && + !IsSideCaption(frame, mStyleDisplay) && + mStyleDisplay->mDisplay != NS_STYLE_DISPLAY_INLINE_TABLE +#ifdef MOZ_FLEXBOX + && !flexContainerFrame +#endif // MOZ_FLEXBOX + ) CalculateBlockSideMargins(availableWidth, mComputedWidth, aFrameType); } } diff --git a/layout/style/ua.css b/layout/style/ua.css index e818300cddf6..e3f87a8731f2 100644 --- a/layout/style/ua.css +++ b/layout/style/ua.css @@ -41,6 +41,7 @@ page-break-after: inherit; vertical-align: inherit; /* needed for inline-table */ line-height: inherit; /* needed for vertical-align on inline-table */ + -moz-align-self: inherit; /* needed for "align-self: auto" to work on table */ /* Bug 722777 */ -moz-transform: inherit; -moz-transform-origin: inherit; From 8d95ac617b3c16e75222be15c0637c2ebc66cd4d Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Sat, 29 Sep 2012 23:38:46 -0700 Subject: [PATCH 23/64] Bug 666041 patch 8: Add special handling for "min-width: auto" value on flex items. r=dbaron --- layout/generic/nsHTMLReflowState.cpp | 14 +++++++++++++- layout/style/nsComputedDOMStyle.cpp | 19 +++++++++++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/layout/generic/nsHTMLReflowState.cpp b/layout/generic/nsHTMLReflowState.cpp index b4a57f8a4ddb..7bde97c420f5 100644 --- a/layout/generic/nsHTMLReflowState.cpp +++ b/layout/generic/nsHTMLReflowState.cpp @@ -2502,10 +2502,22 @@ nsHTMLReflowState::ComputeMinMaxValues(nscoord aContainingBlockWidth, nscoord aContainingBlockHeight, const nsHTMLReflowState* aContainingBlockRS) { +#ifdef MOZ_FLEXBOX + nsFlexContainerFrame* flexContainerFrame = GetFlexContainer(frame); +#endif // MOZ_FLEXBOX + // Handle "min-width: auto" if (eStyleUnit_Auto == mStylePosition->mMinWidth.GetUnit()) { - // XXXdholbert For flex items, this needs to behave like -moz-min-content. mComputedMinWidth = 0; +#ifdef MOZ_FLEXBOX + if (flexContainerFrame && flexContainerFrame->IsHorizontal()) { + mComputedMinWidth = + ComputeWidthValue(aContainingBlockWidth, + mStylePosition->mBoxSizing, + nsStyleCoord(NS_STYLE_WIDTH_MIN_CONTENT, + eStyleUnit_Enumerated)); + } +#endif // MOZ_FLEXBOX } else { mComputedMinWidth = ComputeWidthValue(aContainingBlockWidth, mStylePosition->mBoxSizing, diff --git a/layout/style/nsComputedDOMStyle.cpp b/layout/style/nsComputedDOMStyle.cpp index 2e84d420f0df..8b9d4ca2f02b 100644 --- a/layout/style/nsComputedDOMStyle.cpp +++ b/layout/style/nsComputedDOMStyle.cpp @@ -23,6 +23,7 @@ #include "nsCSSProps.h" #include "nsCSSKeywords.h" #include "nsDOMCSSRect.h" +#include "nsFlexContainerFrame.h" #include "nsGkAtoms.h" #include "nsHTMLReflowState.h" #include "nsThemeConstants.h" @@ -3388,12 +3389,22 @@ nsComputedDOMStyle::DoGetMinWidth() nsStyleCoord minWidth = GetStylePosition()->mMinWidth; if (eStyleUnit_Auto == minWidth.GetUnit()) { - // In non-flexbox contexts, "min-width: auto" means "min-width: 0". - // XXXdholbert For flex items, we should set |minWidth| to the - // -moz-min-content keyword, instead of 0. + // "min-width: auto" means "0", unless we're a flex item in a horizontal + // flex container, in which case it means "min-content" minWidth.SetCoordValue(0); - } +#ifdef MOZ_FLEXBOX + if (mOuterFrame && mOuterFrame->IsFlexItem()) { + nsIFrame* flexContainer = mOuterFrame->GetParent(); + MOZ_ASSERT(flexContainer && + flexContainer->GetType() == nsGkAtoms::flexContainerFrame, + "IsFlexItem() lied...?"); + if (static_cast(flexContainer)->IsHorizontal()) { + minWidth.SetIntValue(NS_STYLE_WIDTH_MIN_CONTENT, eStyleUnit_Enumerated); + } + } +#endif // MOZ_FLEXBOX + } SetValueToCoord(val, minWidth, true, &nsComputedDOMStyle::GetCBContentWidth, nsCSSProps::kWidthKTable); From a3cb31110c9a909166d48602a33995e6b086b915 Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Sat, 29 Sep 2012 23:42:29 -0700 Subject: [PATCH 24/64] Bug 666041: Reftests for css3-flexbox. (tests-only) --HG-- rename : layout/reftests/bugs/solidblue.png => layout/reftests/flexbox/solidblue.png --- layout/reftests/flexbox/ahem.css | 4 + ...xbox-align-self-baseline-horiz-1-ref.xhtml | 67 ++++++++ .../flexbox-align-self-baseline-horiz-1.xhtml | 63 +++++++ ...xbox-align-self-baseline-horiz-2-ref.xhtml | 52 ++++++ .../flexbox-align-self-baseline-horiz-2.xhtml | 56 ++++++ ...xbox-align-self-baseline-horiz-3-ref.xhtml | 58 +++++++ .../flexbox-align-self-baseline-horiz-3.xhtml | 54 ++++++ .../flexbox-align-self-horiz-1-ref.xhtml | 89 ++++++++++ .../flexbox/flexbox-align-self-horiz-1.xhtml | 94 ++++++++++ .../flexbox-align-self-horiz-2-ref.xhtml | 81 +++++++++ .../flexbox/flexbox-align-self-horiz-2.xhtml | 75 ++++++++ .../flexbox-align-self-horiz-3-ref.xhtml | 91 ++++++++++ .../flexbox/flexbox-align-self-horiz-3.xhtml | 89 ++++++++++ .../flexbox-align-self-horiz-4-ref.xhtml | 85 +++++++++ .../flexbox/flexbox-align-self-horiz-4.xhtml | 80 +++++++++ .../flexbox-align-self-horiz-5-ref.xhtml | 96 +++++++++++ .../flexbox/flexbox-align-self-horiz-5.xhtml | 100 +++++++++++ .../flexbox-align-self-vert-1-ref.xhtml | 94 ++++++++++ .../flexbox/flexbox-align-self-vert-1.xhtml | 88 ++++++++++ .../flexbox-align-self-vert-2-ref.xhtml | 92 ++++++++++ .../flexbox/flexbox-align-self-vert-2.xhtml | 73 ++++++++ .../flexbox-align-self-vert-3-ref.xhtml | 76 ++++++++ .../flexbox/flexbox-align-self-vert-3.xhtml | 64 +++++++ .../flexbox-align-self-vert-4-ref.xhtml | 102 +++++++++++ .../flexbox/flexbox-align-self-vert-4.xhtml | 75 ++++++++ .../flexbox-align-self-vert-rtl-1-ref.xhtml | 97 +++++++++++ .../flexbox-align-self-vert-rtl-1.xhtml | 91 ++++++++++ .../flexbox-align-self-vert-rtl-2-ref.xhtml | 95 ++++++++++ .../flexbox-align-self-vert-rtl-2.xhtml | 76 ++++++++ .../flexbox-align-self-vert-rtl-3-ref.xhtml | 78 +++++++++ .../flexbox-align-self-vert-rtl-3.xhtml | 66 +++++++ .../flexbox-align-self-vert-rtl-4-ref.xhtml | 103 +++++++++++ .../flexbox-align-self-vert-rtl-4.xhtml | 84 +++++++++ .../flexbox-basic-block-horiz-1-ref.xhtml | 63 +++++++ .../flexbox/flexbox-basic-block-horiz-1.xhtml | 61 +++++++ .../flexbox-basic-block-vert-1-ref.xhtml | 58 +++++++ .../flexbox/flexbox-basic-block-vert-1.xhtml | 62 +++++++ .../flexbox-basic-canvas-horiz-1-ref.xhtml | 58 +++++++ .../flexbox-basic-canvas-horiz-1.xhtml | 97 +++++++++++ .../flexbox-basic-canvas-horiz-2-ref.xhtml | 27 +++ .../flexbox-basic-canvas-horiz-2.xhtml | 31 ++++ .../flexbox-basic-canvas-vert-1-ref.xhtml | 62 +++++++ .../flexbox/flexbox-basic-canvas-vert-1.xhtml | 99 +++++++++++ .../flexbox-basic-canvas-vert-2-ref.xhtml | 28 +++ .../flexbox/flexbox-basic-canvas-vert-2.xhtml | 32 ++++ .../flexbox-basic-fieldset-horiz-1-ref.xhtml | 63 +++++++ .../flexbox-basic-fieldset-horiz-1.xhtml | 101 +++++++++++ .../flexbox-basic-fieldset-horiz-2-ref.xhtml | 27 +++ .../flexbox-basic-fieldset-horiz-2.xhtml | 31 ++++ .../flexbox-basic-fieldset-vert-1-ref.xhtml | 64 +++++++ .../flexbox-basic-fieldset-vert-1.xhtml | 103 +++++++++++ .../flexbox-basic-fieldset-vert-2-ref.xhtml | 28 +++ .../flexbox-basic-fieldset-vert-2.xhtml | 33 ++++ .../flexbox-basic-iframe-horiz-1-ref.xhtml | 58 +++++++ .../flexbox-basic-iframe-horiz-1.xhtml | 98 +++++++++++ .../flexbox-basic-iframe-horiz-2-ref.xhtml | 27 +++ .../flexbox-basic-iframe-horiz-2.xhtml | 31 ++++ .../flexbox-basic-iframe-vert-1-ref.xhtml | 62 +++++++ .../flexbox/flexbox-basic-iframe-vert-1.xhtml | 100 +++++++++++ .../flexbox-basic-iframe-vert-2-ref.xhtml | 28 +++ .../flexbox/flexbox-basic-iframe-vert-2.xhtml | 32 ++++ .../flexbox-basic-img-horiz-1-ref.xhtml | 58 +++++++ .../flexbox/flexbox-basic-img-horiz-1.xhtml | 99 +++++++++++ .../flexbox-basic-img-horiz-2-ref.xhtml | 27 +++ .../flexbox/flexbox-basic-img-horiz-2.xhtml | 31 ++++ .../flexbox-basic-img-vert-1-ref.xhtml | 62 +++++++ .../flexbox/flexbox-basic-img-vert-1.xhtml | 101 +++++++++++ .../flexbox-basic-img-vert-2-ref.xhtml | 28 +++ .../flexbox/flexbox-basic-img-vert-2.xhtml | 32 ++++ .../flexbox-basic-textarea-horiz-1-ref.xhtml | 61 +++++++ .../flexbox-basic-textarea-horiz-1.xhtml | 104 +++++++++++ .../flexbox-basic-textarea-horiz-2-ref.xhtml | 27 +++ .../flexbox-basic-textarea-horiz-2.xhtml | 31 ++++ .../flexbox-basic-textarea-vert-1-ref.xhtml | 66 +++++++ .../flexbox-basic-textarea-vert-1.xhtml | 107 ++++++++++++ .../flexbox-basic-textarea-vert-2-ref.xhtml | 28 +++ .../flexbox-basic-textarea-vert-2.xhtml | 33 ++++ .../flexbox-basic-video-horiz-1-ref.xhtml | 58 +++++++ .../flexbox/flexbox-basic-video-horiz-1.xhtml | 97 +++++++++++ .../flexbox-basic-video-horiz-2-ref.xhtml | 27 +++ .../flexbox/flexbox-basic-video-horiz-2.xhtml | 31 ++++ .../flexbox-basic-video-vert-1-ref.xhtml | 62 +++++++ .../flexbox/flexbox-basic-video-vert-1.xhtml | 99 +++++++++++ .../flexbox-basic-video-vert-2-ref.xhtml | 28 +++ .../flexbox/flexbox-basic-video-vert-2.xhtml | 32 ++++ .../flexbox-dyn-insertAroundDiv-1-ref.xhtml | 39 +++++ .../flexbox-dyn-insertAroundDiv-1.xhtml | 87 ++++++++++ .../flexbox-dyn-insertAroundDiv-2-ref.xhtml | 41 +++++ .../flexbox-dyn-insertAroundDiv-2.xhtml | 104 +++++++++++ .../flexbox-dyn-insertAroundDiv-3-ref.xhtml | 40 +++++ .../flexbox-dyn-insertAroundDiv-3.xhtml | 104 +++++++++++ .../flexbox-dyn-insertAroundSpan-1.xhtml | 87 ++++++++++ .../flexbox-dyn-insertAroundSpan-2.xhtml | 107 ++++++++++++ .../flexbox-dyn-insertAroundSpan-3.xhtml | 107 ++++++++++++ .../flexbox-dyn-insertAroundText-1-ref.xhtml | 39 +++++ .../flexbox-dyn-insertAroundText-1.xhtml | 87 ++++++++++ .../flexbox-dyn-insertAroundText-2-ref.xhtml | 44 +++++ .../flexbox-dyn-insertAroundText-2.xhtml | 107 ++++++++++++ .../flexbox-dyn-insertAroundText-3-ref.xhtml | 43 +++++ .../flexbox-dyn-insertAroundText-3.xhtml | 107 ++++++++++++ .../flexbox-dyn-insertEmptySpan-1-ref.xhtml | 43 +++++ .../flexbox-dyn-insertEmptySpan-1.xhtml | 103 +++++++++++ .../flexbox/flexbox-empty-1-ref.xhtml | 38 ++++ .../reftests/flexbox/flexbox-empty-1a.xhtml | 39 +++++ .../reftests/flexbox/flexbox-empty-1b.xhtml | 45 +++++ .../flexbox/flexbox-float-1-ref.xhtml | 39 +++++ .../reftests/flexbox/flexbox-float-1a.xhtml | 47 +++++ .../reftests/flexbox/flexbox-float-1b.xhtml | 43 +++++ .../reftests/flexbox/flexbox-float-1c.xhtml | 75 ++++++++ .../reftests/flexbox/flexbox-float-1d.xhtml | 75 ++++++++ .../flexbox/flexbox-float-2-ref.xhtml | 39 +++++ .../reftests/flexbox/flexbox-float-2a.xhtml | 42 +++++ .../reftests/flexbox/flexbox-float-2b.xhtml | 46 +++++ .../flexbox-inlinecontent-horiz-1-ref.xhtml | 45 +++++ .../flexbox-inlinecontent-horiz-1a.xhtml | 39 +++++ .../flexbox-inlinecontent-horiz-1b.xhtml | 55 ++++++ .../flexbox-inlinecontent-horiz-2-ref.xhtml | 34 ++++ .../flexbox-inlinecontent-horiz-2.xhtml | 46 +++++ .../flexbox-inlinecontent-horiz-3-ref.xhtml | 22 +++ .../flexbox-inlinecontent-horiz-3a.xhtml | 24 +++ .../flexbox-inlinecontent-horiz-3b.xhtml | 39 +++++ .../flexbox-inlinecontent-horiz-3c.xhtml | 39 +++++ .../flexbox-inlinecontent-horiz-4-ref.xhtml | 21 +++ .../flexbox-inlinecontent-horiz-4.xhtml | 27 +++ .../flexbox-inlinecontent-horiz-5-ref.xhtml | 25 +++ .../flexbox-inlinecontent-horiz-5.xhtml | 36 ++++ .../flexbox-inlinecontent-horiz-6-ref.xhtml | 39 +++++ .../flexbox-inlinecontent-horiz-6.xhtml | 40 +++++ ...flexbox-intrinsic-sizing-horiz-1-ref.xhtml | 91 ++++++++++ .../flexbox-intrinsic-sizing-horiz-1a.xhtml | 102 +++++++++++ .../flexbox-intrinsic-sizing-horiz-1b.xhtml | 102 +++++++++++ ...flexbox-intrinsic-sizing-horiz-2-ref.xhtml | 45 +++++ .../flexbox-intrinsic-sizing-horiz-2a.xhtml | 38 ++++ .../flexbox-intrinsic-sizing-horiz-2b.xhtml | 44 +++++ .../flexbox/flexbox-invalidation-1-ref.html | 36 ++++ .../flexbox/flexbox-invalidation-1.html | 47 +++++ .../flexbox-justify-content-horiz-1-ref.xhtml | 107 ++++++++++++ .../flexbox-justify-content-horiz-1.xhtml | 102 +++++++++++ .../flexbox-justify-content-horiz-2-ref.xhtml | 121 +++++++++++++ .../flexbox-justify-content-horiz-2.xhtml | 115 +++++++++++++ .../flexbox-justify-content-horiz-3-ref.xhtml | 103 +++++++++++ .../flexbox-justify-content-horiz-3.xhtml | 110 ++++++++++++ .../flexbox-justify-content-horiz-4-ref.xhtml | 115 +++++++++++++ .../flexbox-justify-content-horiz-4.xhtml | 121 +++++++++++++ .../flexbox-justify-content-horiz-5-ref.xhtml | 128 ++++++++++++++ .../flexbox-justify-content-horiz-5.xhtml | 100 +++++++++++ .../flexbox-justify-content-vert-1-ref.xhtml | 105 ++++++++++++ .../flexbox-justify-content-vert-1.xhtml | 104 +++++++++++ .../flexbox-justify-content-vert-2-ref.xhtml | 118 +++++++++++++ .../flexbox-justify-content-vert-2.xhtml | 117 +++++++++++++ .../flexbox-justify-content-vert-3-ref.xhtml | 101 +++++++++++ .../flexbox-justify-content-vert-3.xhtml | 113 ++++++++++++ .../flexbox-justify-content-vert-4-ref.xhtml | 112 ++++++++++++ .../flexbox-justify-content-vert-4.xhtml | 124 ++++++++++++++ .../flexbox-justify-content-vert-5-ref.xhtml | 100 +++++++++++ .../flexbox-justify-content-vert-5.xhtml | 107 ++++++++++++ .../flexbox-margin-auto-horiz-1-ref.xhtml | 85 +++++++++ .../flexbox/flexbox-margin-auto-horiz-1.xhtml | 79 +++++++++ .../flexbox-margin-auto-horiz-2-ref.xhtml | 59 +++++++ .../flexbox/flexbox-margin-auto-horiz-2.xhtml | 64 +++++++ .../flexbox/flexbox-mbp-horiz-1-ref.xhtml | 69 ++++++++ .../flexbox-mbp-horiz-1-reverse-ref.xhtml | 72 ++++++++ .../flexbox/flexbox-mbp-horiz-1-reverse.xhtml | 68 ++++++++ .../flexbox-mbp-horiz-1-rtl-reverse.xhtml | 70 ++++++++ .../flexbox/flexbox-mbp-horiz-1-rtl.xhtml | 68 ++++++++ .../flexbox/flexbox-mbp-horiz-1.xhtml | 66 +++++++ .../flexbox/flexbox-mbp-horiz-2-ref.xhtml | 73 ++++++++ .../flexbox/flexbox-mbp-horiz-2a.xhtml | 70 ++++++++ .../flexbox/flexbox-mbp-horiz-2b.xhtml | 77 +++++++++ .../flexbox/flexbox-mbp-horiz-3-ref.xhtml | 79 +++++++++ .../flexbox-mbp-horiz-3-reverse-ref.xhtml | 79 +++++++++ .../flexbox/flexbox-mbp-horiz-3-reverse.xhtml | 79 +++++++++ .../flexbox/flexbox-mbp-horiz-3.xhtml | 79 +++++++++ .../flexbox/flexbox-minSize-horiz-1-ref.xhtml | 78 +++++++++ .../flexbox/flexbox-minSize-horiz-1.xhtml | 71 ++++++++ .../flexbox/flexbox-minSize-vert-1-ref.xhtml | 55 ++++++ .../flexbox/flexbox-minSize-vert-1.xhtml | 73 ++++++++ .../flexbox-position-absolute-1-ref.xhtml | 74 ++++++++ .../flexbox/flexbox-position-absolute-1.xhtml | 70 ++++++++ .../flexbox-position-absolute-2-ref.xhtml | 73 ++++++++ .../flexbox/flexbox-position-absolute-2.xhtml | 71 ++++++++ .../flexbox-position-absolute-3-ref.xhtml | 44 +++++ .../flexbox/flexbox-position-absolute-3.xhtml | 46 +++++ .../flexbox-position-absolute-4-ref.xhtml | 50 ++++++ .../flexbox/flexbox-position-absolute-4.xhtml | 52 ++++++ .../flexbox-position-fixed-1-ref.xhtml | 74 ++++++++ .../flexbox/flexbox-position-fixed-1.xhtml | 70 ++++++++ .../flexbox-position-fixed-2-ref.xhtml | 73 ++++++++ .../flexbox/flexbox-position-fixed-2.xhtml | 71 ++++++++ .../flexbox-position-fixed-3-ref.xhtml | 44 +++++ .../flexbox/flexbox-position-fixed-3.xhtml | 46 +++++ .../flexbox-position-fixed-4-ref.xhtml | 51 ++++++ .../flexbox/flexbox-position-fixed-4.xhtml | 52 ++++++ .../flexbox-resizeviewport-1-helper.html | 31 ++++ .../flexbox-resizeviewport-1-ref.xhtml | 22 +++ .../flexbox/flexbox-resizeviewport-1.xhtml | 40 +++++ .../flexbox/flexbox-sizing-horiz-1-ref.xhtml | 73 ++++++++ .../flexbox/flexbox-sizing-horiz-1.xhtml | 80 +++++++++ .../flexbox/flexbox-sizing-vert-1-ref.xhtml | 79 +++++++++ .../flexbox/flexbox-sizing-vert-1.xhtml | 94 ++++++++++ .../flexbox/flexbox-table-fixup-1-ref.xhtml | 59 +++++++ .../flexbox/flexbox-table-fixup-1a.xhtml | 62 +++++++ .../flexbox/flexbox-table-fixup-1b.xhtml | 70 ++++++++ .../flexbox-whitespace-handling-1-ref.xhtml | 50 ++++++ .../flexbox-whitespace-handling-1a.xhtml | 53 ++++++ .../flexbox-whitespace-handling-1b.xhtml | 42 +++++ .../flexbox-whitespace-handling-2-ref.xhtml | 50 ++++++ .../flexbox-whitespace-handling-2.xhtml | 50 ++++++ .../flexbox-whitespace-handling-3-ref.xhtml | 32 ++++ .../flexbox-whitespace-handling-3.xhtml | 36 ++++ .../flexbox-widget-flex-items-1-ref.html | 34 ++++ .../flexbox/flexbox-widget-flex-items-1.html | 46 +++++ .../flexbox-widget-flex-items-2-ref.html | 34 ++++ .../flexbox/flexbox-widget-flex-items-2.html | 42 +++++ .../flexbox-widget-flex-items-3-ref.html | 34 ++++ .../flexbox/flexbox-widget-flex-items-3.html | 43 +++++ .../flexbox-widget-flex-items-4-ref.html | 36 ++++ .../flexbox/flexbox-widget-flex-items-4.html | 42 +++++ layout/reftests/flexbox/reftest.list | 162 ++++++++++++++++++ layout/reftests/flexbox/solidblue.png | Bin 0 -> 135 bytes layout/reftests/reftest.list | 4 + 221 files changed, 14431 insertions(+) create mode 100644 layout/reftests/flexbox/ahem.css create mode 100644 layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-baseline-horiz-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-baseline-horiz-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-horiz-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-horiz-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-horiz-3-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-horiz-3.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-horiz-4-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-horiz-4.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-horiz-5-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-horiz-5.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-3-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-3.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-4-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-4.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-rtl-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-rtl-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-rtl-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-rtl-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-rtl-3-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-rtl-3.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-rtl-4-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-align-self-vert-rtl-4.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-block-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-block-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-block-vert-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-block-vert-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-canvas-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-canvas-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-canvas-horiz-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-canvas-horiz-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-canvas-vert-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-canvas-vert-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-canvas-vert-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-canvas-vert-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-fieldset-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-fieldset-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-fieldset-horiz-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-fieldset-horiz-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-fieldset-vert-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-fieldset-vert-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-fieldset-vert-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-fieldset-vert-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-iframe-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-iframe-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-iframe-horiz-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-iframe-horiz-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-iframe-vert-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-iframe-vert-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-iframe-vert-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-iframe-vert-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-img-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-img-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-img-horiz-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-img-horiz-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-img-vert-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-img-vert-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-img-vert-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-img-vert-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-textarea-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-textarea-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-textarea-horiz-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-textarea-horiz-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-textarea-vert-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-textarea-vert-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-textarea-vert-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-textarea-vert-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-video-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-video-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-video-horiz-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-video-horiz-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-video-vert-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-video-vert-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-video-vert-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-basic-video-vert-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundDiv-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundDiv-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundDiv-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundDiv-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundDiv-3-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundDiv-3.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundSpan-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundSpan-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundSpan-3.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundText-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundText-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundText-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundText-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundText-3-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertAroundText-3.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertEmptySpan-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-dyn-insertEmptySpan-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-empty-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-empty-1a.xhtml create mode 100644 layout/reftests/flexbox/flexbox-empty-1b.xhtml create mode 100644 layout/reftests/flexbox/flexbox-float-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-float-1a.xhtml create mode 100644 layout/reftests/flexbox/flexbox-float-1b.xhtml create mode 100644 layout/reftests/flexbox/flexbox-float-1c.xhtml create mode 100644 layout/reftests/flexbox/flexbox-float-1d.xhtml create mode 100644 layout/reftests/flexbox/flexbox-float-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-float-2a.xhtml create mode 100644 layout/reftests/flexbox/flexbox-float-2b.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-1a.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-1b.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-3-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-3a.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-3b.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-3c.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-4-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-4.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-5-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-5.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-6-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-inlinecontent-horiz-6.xhtml create mode 100644 layout/reftests/flexbox/flexbox-intrinsic-sizing-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-intrinsic-sizing-horiz-1a.xhtml create mode 100644 layout/reftests/flexbox/flexbox-intrinsic-sizing-horiz-1b.xhtml create mode 100644 layout/reftests/flexbox/flexbox-intrinsic-sizing-horiz-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-intrinsic-sizing-horiz-2a.xhtml create mode 100644 layout/reftests/flexbox/flexbox-intrinsic-sizing-horiz-2b.xhtml create mode 100644 layout/reftests/flexbox/flexbox-invalidation-1-ref.html create mode 100644 layout/reftests/flexbox/flexbox-invalidation-1.html create mode 100644 layout/reftests/flexbox/flexbox-justify-content-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-horiz-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-horiz-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-horiz-3-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-horiz-3.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-horiz-4-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-horiz-4.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-horiz-5-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-horiz-5.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-vert-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-vert-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-vert-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-vert-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-vert-3-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-vert-3.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-vert-4-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-vert-4.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-vert-5-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-justify-content-vert-5.xhtml create mode 100644 layout/reftests/flexbox/flexbox-margin-auto-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-margin-auto-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-margin-auto-horiz-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-margin-auto-horiz-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-mbp-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-mbp-horiz-1-reverse-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-mbp-horiz-1-reverse.xhtml create mode 100644 layout/reftests/flexbox/flexbox-mbp-horiz-1-rtl-reverse.xhtml create mode 100644 layout/reftests/flexbox/flexbox-mbp-horiz-1-rtl.xhtml create mode 100644 layout/reftests/flexbox/flexbox-mbp-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-mbp-horiz-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-mbp-horiz-2a.xhtml create mode 100644 layout/reftests/flexbox/flexbox-mbp-horiz-2b.xhtml create mode 100644 layout/reftests/flexbox/flexbox-mbp-horiz-3-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-mbp-horiz-3-reverse-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-mbp-horiz-3-reverse.xhtml create mode 100644 layout/reftests/flexbox/flexbox-mbp-horiz-3.xhtml create mode 100644 layout/reftests/flexbox/flexbox-minSize-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-minSize-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-minSize-vert-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-minSize-vert-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-absolute-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-absolute-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-absolute-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-absolute-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-absolute-3-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-absolute-3.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-absolute-4-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-absolute-4.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-fixed-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-fixed-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-fixed-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-fixed-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-fixed-3-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-fixed-3.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-fixed-4-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-position-fixed-4.xhtml create mode 100644 layout/reftests/flexbox/flexbox-resizeviewport-1-helper.html create mode 100644 layout/reftests/flexbox/flexbox-resizeviewport-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-resizeviewport-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-sizing-horiz-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-sizing-horiz-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-sizing-vert-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-sizing-vert-1.xhtml create mode 100644 layout/reftests/flexbox/flexbox-table-fixup-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-table-fixup-1a.xhtml create mode 100644 layout/reftests/flexbox/flexbox-table-fixup-1b.xhtml create mode 100644 layout/reftests/flexbox/flexbox-whitespace-handling-1-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-whitespace-handling-1a.xhtml create mode 100644 layout/reftests/flexbox/flexbox-whitespace-handling-1b.xhtml create mode 100644 layout/reftests/flexbox/flexbox-whitespace-handling-2-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-whitespace-handling-2.xhtml create mode 100644 layout/reftests/flexbox/flexbox-whitespace-handling-3-ref.xhtml create mode 100644 layout/reftests/flexbox/flexbox-whitespace-handling-3.xhtml create mode 100644 layout/reftests/flexbox/flexbox-widget-flex-items-1-ref.html create mode 100644 layout/reftests/flexbox/flexbox-widget-flex-items-1.html create mode 100644 layout/reftests/flexbox/flexbox-widget-flex-items-2-ref.html create mode 100644 layout/reftests/flexbox/flexbox-widget-flex-items-2.html create mode 100644 layout/reftests/flexbox/flexbox-widget-flex-items-3-ref.html create mode 100644 layout/reftests/flexbox/flexbox-widget-flex-items-3.html create mode 100644 layout/reftests/flexbox/flexbox-widget-flex-items-4-ref.html create mode 100644 layout/reftests/flexbox/flexbox-widget-flex-items-4.html create mode 100644 layout/reftests/flexbox/reftest.list create mode 100644 layout/reftests/flexbox/solidblue.png diff --git a/layout/reftests/flexbox/ahem.css b/layout/reftests/flexbox/ahem.css new file mode 100644 index 000000000000..884a41198b8b --- /dev/null +++ b/layout/reftests/flexbox/ahem.css @@ -0,0 +1,4 @@ +@font-face { + font-family: "Ahem"; + src: url(../fonts/Ahem.ttf); +} diff --git a/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1-ref.xhtml new file mode 100644 index 000000000000..5e86a376a33a --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1-ref.xhtml @@ -0,0 +1,67 @@ + + + + + + + + +
+
blk_1line
blk
2lines
super
sub
big
text
3lines
+ +
tr1
tr2
+ ital
ic
+
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1.xhtml b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1.xhtml new file mode 100644 index 000000000000..96c2b55a98ce --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-1.xhtml @@ -0,0 +1,63 @@ + + + + + + + + +
+
blk_1line
+
blk
2lines
+
super
+
sub
+
big
text
3lines
+ + +
tr1
tr2
+ ital
ic
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-2-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-2-ref.xhtml new file mode 100644 index 000000000000..26033bf78f82 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-2-ref.xhtml @@ -0,0 +1,52 @@ + + + + + + + + +
+
text
+
b
t
n
+
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-2.xhtml b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-2.xhtml new file mode 100644 index 000000000000..33cddfd459ad --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-2.xhtml @@ -0,0 +1,56 @@ + + + + + + + + +
+
text
+ + + +
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3-ref.xhtml new file mode 100644 index 000000000000..34a1b081c35a --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3-ref.xhtml @@ -0,0 +1,58 @@ + + + + + + + + +
+
text
+ +
+
field
set
+
+
legfield
set
+
+
leg
end
field
set
+
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3.xhtml b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3.xhtml new file mode 100644 index 000000000000..4a87ae97de51 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-baseline-horiz-3.xhtml @@ -0,0 +1,54 @@ + + + + + + + + +
+
text
+ + + + + +
field
set
+
legfield
set
+
leg
end
field
set
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-horiz-1-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-horiz-1-ref.xhtml new file mode 100644 index 000000000000..7de7df769dd3 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-horiz-1-ref.xhtml @@ -0,0 +1,89 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+ +
+
base
abc
+
+
stretch
+
a b c d e f
+
auto
+
unspec
+
initial
+
inherit
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-horiz-1.xhtml b/layout/reftests/flexbox/flexbox-align-self-horiz-1.xhtml new file mode 100644 index 000000000000..0211b25bc264 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-horiz-1.xhtml @@ -0,0 +1,94 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
base
+
abc
+
stretch
+
a b c d e f
+
auto
+
unspec
+
initial
+
inherit
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-horiz-2-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-horiz-2-ref.xhtml new file mode 100644 index 000000000000..673043aacb9f --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-horiz-2-ref.xhtml @@ -0,0 +1,81 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
+
+ +
+
base
abc
+
+
stretch
+
a b c d e f
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-horiz-2.xhtml b/layout/reftests/flexbox/flexbox-align-self-horiz-2.xhtml new file mode 100644 index 000000000000..46cb58bcd122 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-horiz-2.xhtml @@ -0,0 +1,75 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
+
+
base
+
abc
+
stretch
+
a b c d e f
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-horiz-3-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-horiz-3-ref.xhtml new file mode 100644 index 000000000000..f65d1df82b3e --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-horiz-3-ref.xhtml @@ -0,0 +1,91 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+ +
+
base
abc
+
+
stretch
+
a b c d e f
+
auto
+
unspec
+
initial
+
inherit
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-horiz-3.xhtml b/layout/reftests/flexbox/flexbox-align-self-horiz-3.xhtml new file mode 100644 index 000000000000..a5d0369476b1 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-horiz-3.xhtml @@ -0,0 +1,89 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
base
+
abc
+
stretch
+
a b c d e f
+
auto
+
unspec
+
initial
+
inherit
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-horiz-4-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-horiz-4-ref.xhtml new file mode 100644 index 000000000000..092287918da7 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-horiz-4-ref.xhtml @@ -0,0 +1,85 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
+
+ +
+
base
abc
+
+
stretch
+
a b c d e f
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-horiz-4.xhtml b/layout/reftests/flexbox/flexbox-align-self-horiz-4.xhtml new file mode 100644 index 000000000000..88619e864c96 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-horiz-4.xhtml @@ -0,0 +1,80 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
+
+
base
+
abc
+
stretch
+
a b c d e f
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-horiz-5-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-horiz-5-ref.xhtml new file mode 100644 index 000000000000..98410f9f5da0 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-horiz-5-ref.xhtml @@ -0,0 +1,96 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
base
+
a b c d e f
+
stretch
+
a b c d e f
+
+ +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
base
+
a b c d e f
+
stretch
+
a b c d e f
+
+ +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
base
+
a b c d e f
+
stretch
+
a b c d e f
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-horiz-5.xhtml b/layout/reftests/flexbox/flexbox-align-self-horiz-5.xhtml new file mode 100644 index 000000000000..7fdb428d056c --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-horiz-5.xhtml @@ -0,0 +1,100 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
base
+
a b c d e f
+
stretch
+
a b c d e f
+
+ +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
base
+
a b c d e f
+
stretch
+
a b c d e f
+
+ +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
base
+
a b c d e f
+
stretch
+
a b c d e f
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-1-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-1-ref.xhtml new file mode 100644 index 000000000000..d1d51a69ec1b --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-1-ref.xhtml @@ -0,0 +1,94 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
base
+
abc
+
stretch
+
a b c d e f
+
auto
+
unspec
+
initial
+
inherit
+ + hacky text +
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-1.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-1.xhtml new file mode 100644 index 000000000000..7362a4ccf32d --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-1.xhtml @@ -0,0 +1,88 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
base
+
abc
+
stretch
+
a b c d e f
+
auto
+
unspec
+
initial
+
inherit
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-2-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-2-ref.xhtml new file mode 100644 index 000000000000..0001f50bb90a --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-2-ref.xhtml @@ -0,0 +1,92 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
+
center
+
+
+
a b c d e f
+
+
+ +
+
base
+
abc
+
stretch
+
a b c d e f
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-2.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-2.xhtml new file mode 100644 index 000000000000..9f5ab1064053 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-2.xhtml @@ -0,0 +1,73 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
+
+
base
+
abc
+
stretch
+
a b c d e f
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-3-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-3-ref.xhtml new file mode 100644 index 000000000000..cdfa5006dd9e --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-3-ref.xhtml @@ -0,0 +1,76 @@ + + + + + + + + +
+
start
+
a b
+
end
+
a b
+ +
+
center
+
a b
+
+
base
+
abc
+
stretch
+
a b
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-3.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-3.xhtml new file mode 100644 index 000000000000..37708d4dbcaf --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-3.xhtml @@ -0,0 +1,64 @@ + + + + + + + + +
+
start
+
a b
+
end
+
a b
+
center
+
a b
+
base
+
abc
+
stretch
+
a b
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-4-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-4-ref.xhtml new file mode 100644 index 000000000000..6e2522e935ea --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-4-ref.xhtml @@ -0,0 +1,102 @@ + + + + + + + + +
+
start
+
a b
+
end
+
a b
+ +
+
+
center
+
+
+
a b
+
+
+
+ +
+
base
+
abc
+
stretch
+
a b
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-4.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-4.xhtml new file mode 100644 index 000000000000..f3724711f442 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-4.xhtml @@ -0,0 +1,75 @@ + + + + + + + + +
+
start
+
a b
+
end
+
a b
+
center
+
a b
+
+
+
base
+
abc
+
stretch
+
a b
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-rtl-1-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-1-ref.xhtml new file mode 100644 index 000000000000..9dab46d03726 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-1-ref.xhtml @@ -0,0 +1,97 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
base
+
abc
+
stretch
+
a b c d e f
+
auto
+
unspec
+
initial
+
inherit
+ + hacky text +
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-rtl-1.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-1.xhtml new file mode 100644 index 000000000000..268b1f41fbba --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-1.xhtml @@ -0,0 +1,91 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
base
+
abc
+
stretch
+
a b c d e f
+
auto
+
unspec
+
initial
+
inherit
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-rtl-2-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-2-ref.xhtml new file mode 100644 index 000000000000..ffaee61d881d --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-2-ref.xhtml @@ -0,0 +1,95 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
+
center
+
+
+
a b c d e f
+
+
+ +
+
base
+
abc
+
stretch
+
a b c d e f
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-rtl-2.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-2.xhtml new file mode 100644 index 000000000000..514f0cd31881 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-2.xhtml @@ -0,0 +1,76 @@ + + + + + + + + +
+
start
+
a b c d e f
+
end
+
a b c d e f
+
center
+
a b c d e f
+
+
+
base
+
abc
+
stretch
+
a b c d e f
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-rtl-3-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-3-ref.xhtml new file mode 100644 index 000000000000..4c9fe8ae0c10 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-3-ref.xhtml @@ -0,0 +1,78 @@ + + + + + + + + +
+
start
+
a b
+
end
+
a b
+ +
+
center
+
a b
+
+
base
+
abc
+
stretch
+
a b
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-rtl-3.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-3.xhtml new file mode 100644 index 000000000000..522d0fe2a336 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-3.xhtml @@ -0,0 +1,66 @@ + + + + + + + + +
+
start
+
a b
+
end
+
a b
+
center
+
a b
+
base
+
abc
+
stretch
+
a b
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-rtl-4-ref.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-4-ref.xhtml new file mode 100644 index 000000000000..e2f2441ece1d --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-4-ref.xhtml @@ -0,0 +1,103 @@ + + + + + + + + + +
+
start
+
a b
+
stretch
+
a b
+ +
+
+
center
+
+
+
a b
+
+
+
+
+
base
+
abc
+
end
+
a b
+
+ + diff --git a/layout/reftests/flexbox/flexbox-align-self-vert-rtl-4.xhtml b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-4.xhtml new file mode 100644 index 000000000000..528a809ab5a4 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-align-self-vert-rtl-4.xhtml @@ -0,0 +1,84 @@ + + + + + + + + + +
+
start
+
a b
+
stretch
+
a b
+
center
+
a b
+
+
+
base
+
abc
+
end
+
a b
+
+ + diff --git a/layout/reftests/flexbox/flexbox-basic-block-horiz-1-ref.xhtml b/layout/reftests/flexbox/flexbox-basic-block-horiz-1-ref.xhtml new file mode 100644 index 000000000000..71c8f20ca3cb --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-block-horiz-1-ref.xhtml @@ -0,0 +1,63 @@ + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/layout/reftests/flexbox/flexbox-basic-block-horiz-1.xhtml b/layout/reftests/flexbox/flexbox-basic-block-horiz-1.xhtml new file mode 100644 index 000000000000..6025fc1e7317 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-block-horiz-1.xhtml @@ -0,0 +1,61 @@ + + + + + + + + +
+
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/layout/reftests/flexbox/flexbox-basic-block-vert-1-ref.xhtml b/layout/reftests/flexbox/flexbox-basic-block-vert-1-ref.xhtml new file mode 100644 index 000000000000..6e927001e59e --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-block-vert-1-ref.xhtml @@ -0,0 +1,58 @@ + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + diff --git a/layout/reftests/flexbox/flexbox-basic-block-vert-1.xhtml b/layout/reftests/flexbox/flexbox-basic-block-vert-1.xhtml new file mode 100644 index 000000000000..3b7923a6c37e --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-block-vert-1.xhtml @@ -0,0 +1,62 @@ + + + + + + + + +
+
+
+
+
+
+
+
+
+ +
+
+
+ + diff --git a/layout/reftests/flexbox/flexbox-basic-canvas-horiz-1-ref.xhtml b/layout/reftests/flexbox/flexbox-basic-canvas-horiz-1-ref.xhtml new file mode 100644 index 000000000000..fb5ef6cde9cc --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-canvas-horiz-1-ref.xhtml @@ -0,0 +1,58 @@ + + + + + + + +
+ +
+ +
+ some words + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + + diff --git a/layout/reftests/flexbox/flexbox-basic-canvas-horiz-1.xhtml b/layout/reftests/flexbox/flexbox-basic-canvas-horiz-1.xhtml new file mode 100644 index 000000000000..7efb68e78d0b --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-canvas-horiz-1.xhtml @@ -0,0 +1,97 @@ + + + + + + + + + + +
+ +
+ + +
+ some words +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + + +
+ + +
+ + + +
+ + +
+ + + diff --git a/layout/reftests/flexbox/flexbox-basic-canvas-horiz-2-ref.xhtml b/layout/reftests/flexbox/flexbox-basic-canvas-horiz-2-ref.xhtml new file mode 100644 index 000000000000..38d6c71c48fc --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-canvas-horiz-2-ref.xhtml @@ -0,0 +1,27 @@ + + + + + + + +
+ +
+ + diff --git a/layout/reftests/flexbox/flexbox-basic-canvas-horiz-2.xhtml b/layout/reftests/flexbox/flexbox-basic-canvas-horiz-2.xhtml new file mode 100644 index 000000000000..4d1c7f9c035f --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-canvas-horiz-2.xhtml @@ -0,0 +1,31 @@ + + + + + + + + +
+ +
+ + diff --git a/layout/reftests/flexbox/flexbox-basic-canvas-vert-1-ref.xhtml b/layout/reftests/flexbox/flexbox-basic-canvas-vert-1-ref.xhtml new file mode 100644 index 000000000000..fb85eba91d94 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-canvas-vert-1-ref.xhtml @@ -0,0 +1,62 @@ + + + + + + + +
+ +
+ +
+
+ a b +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + + diff --git a/layout/reftests/flexbox/flexbox-basic-canvas-vert-1.xhtml b/layout/reftests/flexbox/flexbox-basic-canvas-vert-1.xhtml new file mode 100644 index 000000000000..e10feaa3bb0b --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-canvas-vert-1.xhtml @@ -0,0 +1,99 @@ + + + + + + + + + + +
+ +
+ + +
+ a b +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+ + + +
+ + +
+ + + +
+ + +
+ + + diff --git a/layout/reftests/flexbox/flexbox-basic-canvas-vert-2-ref.xhtml b/layout/reftests/flexbox/flexbox-basic-canvas-vert-2-ref.xhtml new file mode 100644 index 000000000000..c34d9feb54eb --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-canvas-vert-2-ref.xhtml @@ -0,0 +1,28 @@ + + + + + + + +
+ +
+ + diff --git a/layout/reftests/flexbox/flexbox-basic-canvas-vert-2.xhtml b/layout/reftests/flexbox/flexbox-basic-canvas-vert-2.xhtml new file mode 100644 index 000000000000..57e16a4ffc75 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-canvas-vert-2.xhtml @@ -0,0 +1,32 @@ + + + + + + + + +
+ +
+ + diff --git a/layout/reftests/flexbox/flexbox-basic-fieldset-horiz-1-ref.xhtml b/layout/reftests/flexbox/flexbox-basic-fieldset-horiz-1-ref.xhtml new file mode 100644 index 000000000000..c4daa393d3fe --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-fieldset-horiz-1-ref.xhtml @@ -0,0 +1,63 @@ + + + + + + + +
+
+
+ +
+ some words +
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ + + diff --git a/layout/reftests/flexbox/flexbox-basic-fieldset-horiz-1.xhtml b/layout/reftests/flexbox/flexbox-basic-fieldset-horiz-1.xhtml new file mode 100644 index 000000000000..375c7c2660c1 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-fieldset-horiz-1.xhtml @@ -0,0 +1,101 @@ + + + + + + + + + + +
+
+
+ + +
+ some words
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + + +
+
+
+
+ + + +
+
+
+
+ + + diff --git a/layout/reftests/flexbox/flexbox-basic-fieldset-horiz-2-ref.xhtml b/layout/reftests/flexbox/flexbox-basic-fieldset-horiz-2-ref.xhtml new file mode 100644 index 000000000000..7bc050a92f87 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-fieldset-horiz-2-ref.xhtml @@ -0,0 +1,27 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/flexbox/flexbox-basic-fieldset-horiz-2.xhtml b/layout/reftests/flexbox/flexbox-basic-fieldset-horiz-2.xhtml new file mode 100644 index 000000000000..f06f37449994 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-fieldset-horiz-2.xhtml @@ -0,0 +1,31 @@ + + + + + + + + +
+
+
+ + diff --git a/layout/reftests/flexbox/flexbox-basic-fieldset-vert-1-ref.xhtml b/layout/reftests/flexbox/flexbox-basic-fieldset-vert-1-ref.xhtml new file mode 100644 index 000000000000..19453984ed18 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-fieldset-vert-1-ref.xhtml @@ -0,0 +1,64 @@ + + + + + + + +
+
+
+ +
+
+ a b +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ + + diff --git a/layout/reftests/flexbox/flexbox-basic-fieldset-vert-1.xhtml b/layout/reftests/flexbox/flexbox-basic-fieldset-vert-1.xhtml new file mode 100644 index 000000000000..630e7c8eae3f --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-fieldset-vert-1.xhtml @@ -0,0 +1,103 @@ + + + + + + + + + + +
+
+
+ + +
+ a b
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + + +
+
+
+
+ + + +
+
+
+
+ + + diff --git a/layout/reftests/flexbox/flexbox-basic-fieldset-vert-2-ref.xhtml b/layout/reftests/flexbox/flexbox-basic-fieldset-vert-2-ref.xhtml new file mode 100644 index 000000000000..b025d7fb55b7 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-fieldset-vert-2-ref.xhtml @@ -0,0 +1,28 @@ + + + + + + + +
+
+
+ + diff --git a/layout/reftests/flexbox/flexbox-basic-fieldset-vert-2.xhtml b/layout/reftests/flexbox/flexbox-basic-fieldset-vert-2.xhtml new file mode 100644 index 000000000000..36d0b74a18f5 --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-fieldset-vert-2.xhtml @@ -0,0 +1,33 @@ + + + + + + + + +
+
+
+ + diff --git a/layout/reftests/flexbox/flexbox-basic-iframe-horiz-1-ref.xhtml b/layout/reftests/flexbox/flexbox-basic-iframe-horiz-1-ref.xhtml new file mode 100644 index 000000000000..a3a93e67f69a --- /dev/null +++ b/layout/reftests/flexbox/flexbox-basic-iframe-horiz-1-ref.xhtml @@ -0,0 +1,58 @@ + + + + + + + +
+