diff --git a/accessible/public/nsIAccessNode.idl b/accessible/public/nsIAccessNode.idl index c49adf265707..a3cdc0b11821 100644 --- a/accessible/public/nsIAccessNode.idl +++ b/accessible/public/nsIAccessNode.idl @@ -54,7 +54,7 @@ interface nsIDOMCSSPrimitiveValue; * If the DOM node for this access node is "accessible", * then a QueryInterface to nsIAccessible will succeed. */ -[scriptable, uuid(ef16ff42-0256-4b48-ae87-b18a95b7f7d6)] +[scriptable, uuid(bbbd5a68-bad2-48c1-ab09-beb6c34f03d9)] interface nsIAccessNode : nsISupports { /** @@ -99,12 +99,6 @@ interface nsIAccessNode : nsISupports */ void scrollToPoint(in unsigned long aCoordinateType, in long aX, in long aY); - /** - * The OS window handle for the window this node - * is being displayed in. - */ - [noscript] readonly attribute voidPtr ownerWindow; - /** * A unique ID calculated for this DOM node, for the * purposes of caching and referencing this object. diff --git a/accessible/src/atk/nsApplicationAccessibleWrap.cpp b/accessible/src/atk/nsApplicationAccessibleWrap.cpp index d79c65b9c620..f3c21fb64b27 100644 --- a/accessible/src/atk/nsApplicationAccessibleWrap.cpp +++ b/accessible/src/atk/nsApplicationAccessibleWrap.cpp @@ -117,7 +117,6 @@ static gint sListener_idx = 1; static GHashTable* sKey_listener_list = NULL; static guint sKey_snooper_id = 0; -static GQuark sQuark_gecko_acc_obj = g_quark_from_static_string("GeckoAccObj"); static bool sToplevel_event_hook_added = false; static gulong sToplevel_show_hook = 0; static gulong sToplevel_hide_hook = 0; @@ -570,6 +569,11 @@ toplevel_event_watcher(GSignalInvocationHint* ihint, const GValue* param_values, gpointer data) { + static GQuark sQuark_gecko_acc_obj = 0; + + if (!sQuark_gecko_acc_obj) + sQuark_gecko_acc_obj = g_quark_from_static_string("GeckoAccObj"); + if (nsAccessibilityService::IsShutdown()) return TRUE; diff --git a/accessible/src/base/NotificationController.cpp b/accessible/src/base/NotificationController.cpp index d99adc3a9c6d..cd6821ecdf7f 100644 --- a/accessible/src/base/NotificationController.cpp +++ b/accessible/src/base/NotificationController.cpp @@ -45,6 +45,7 @@ #include "nsEventShell.h" #include "nsTextAccessible.h" #include "TextUpdater.h" +#include "mozilla/dom/Element.h" //////////////////////////////////////////////////////////////////////////////// @@ -281,6 +282,10 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime) return; } + // Process invalidation list of the document after all accessible tree + // modification are done. + mDocument->ProcessInvalidationList(); + // If a generic notification occurs after this point then we may be allowed to // process it synchronously. mObservingState = eRefreshObserving; diff --git a/accessible/src/base/nsAccDocManager.h b/accessible/src/base/nsAccDocManager.h index 1bd5256c5540..f17148f15d5c 100644 --- a/accessible/src/base/nsAccDocManager.h +++ b/accessible/src/base/nsAccDocManager.h @@ -206,6 +206,19 @@ private: printf("document type: [failed]"); \ } +#define NS_LOG_ACCDOC_DOCSHELLTREE(aDocument) \ + if (aDocument->IsActive()) { \ + nsCOMPtr container = aDocument->GetContainer(); \ + nsCOMPtr treeItem(do_QueryInterface(container)); \ + nsCOMPtr parentTreeItem; \ + treeItem->GetParent(getter_AddRefs(parentTreeItem)); \ + nsCOMPtr rootTreeItem; \ + treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem)); \ + printf("docshell hierarchy, parent: %p, root: %p, is tab document: %s;", \ + parentTreeItem, rootTreeItem, \ + (nsCoreUtils::IsTabDocument(aDocument) ? "yes" : "no")); \ + } + #define NS_LOG_ACCDOC_SHELLSTATE(aDocument) \ nsCAutoString docShellBusy; \ nsCOMPtr container = aDocument->GetContainer(); \ @@ -352,6 +365,8 @@ private: printf("; "); \ NS_LOG_ACCDOC_TYPE(aDocument) \ printf("\n "); \ + NS_LOG_ACCDOC_DOCSHELLTREE(aDocument) \ + printf("\n "); \ NS_LOG_ACCDOC_DOCSTATES(aDocument) \ printf("\n "); \ NS_LOG_ACCDOC_DOCPRESSHELL(aDocument) \ diff --git a/accessible/src/base/nsAccessNode.cpp b/accessible/src/base/nsAccessNode.cpp index 5bba5fd44a28..32f204bfd2ff 100644 --- a/accessible/src/base/nsAccessNode.cpp +++ b/accessible/src/base/nsAccessNode.cpp @@ -161,19 +161,6 @@ nsAccessNode::GetUniqueID(void **aUniqueID) return NS_OK; } -// nsIAccessNode -NS_IMETHODIMP -nsAccessNode::GetOwnerWindow(void **aWindow) -{ - NS_ENSURE_ARG_POINTER(aWindow); - *aWindow = nsnull; - - if (IsDefunct()) - return NS_ERROR_FAILURE; - - return GetDocAccessible()->GetWindowHandle(aWindow); -} - nsApplicationAccessible* nsAccessNode::GetApplicationAccessible() { diff --git a/accessible/src/base/nsAccessible.cpp b/accessible/src/base/nsAccessible.cpp index 2074016fd082..95f484861a8c 100644 --- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -105,6 +105,7 @@ #include "mozilla/unused.h" #include "mozilla/Preferences.h" +#include "mozilla/dom/Element.h" using namespace mozilla; @@ -3109,16 +3110,7 @@ nsAccessible::EnsureChildren() // State is embedded children until text leaf accessible is appended. SetChildrenFlag(eEmbeddedChildren); // Prevent reentry - // Notify the document about caching status. - nsDocAccessible* document = GetDocAccessible(); - if (document) - document->NotifyOfCachingStart(this); - CacheChildren(); - - if (document) - document->NotifyOfCachingEnd(this); - return false; } diff --git a/accessible/src/base/nsApplicationAccessible.cpp b/accessible/src/base/nsApplicationAccessible.cpp index 2486f7e6bd68..d4a5f1160833 100644 --- a/accessible/src/base/nsApplicationAccessible.cpp +++ b/accessible/src/base/nsApplicationAccessible.cpp @@ -483,14 +483,6 @@ nsApplicationAccessible::ScrollToPoint(PRUint32 aCoordinateType, return NS_OK; } -NS_IMETHODIMP -nsApplicationAccessible::GetOwnerWindow(void **aOwnerWindow) -{ - NS_ENSURE_ARG_POINTER(aOwnerWindow); - *aOwnerWindow = nsnull; - return NS_OK; -} - NS_IMETHODIMP nsApplicationAccessible::GetComputedStyleValue(const nsAString &aPseudoElt, const nsAString &aPropertyName, diff --git a/accessible/src/base/nsApplicationAccessible.h b/accessible/src/base/nsApplicationAccessible.h index 39bac37fc17d..ad51804fee1f 100644 --- a/accessible/src/base/nsApplicationAccessible.h +++ b/accessible/src/base/nsApplicationAccessible.h @@ -76,7 +76,6 @@ public: NS_SCRIPTABLE NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML); NS_SCRIPTABLE NS_IMETHOD ScrollTo(PRUint32 aScrollType); NS_SCRIPTABLE NS_IMETHOD ScrollToPoint(PRUint32 aCoordinateType, PRInt32 aX, PRInt32 aY); - NS_IMETHOD GetOwnerWindow(void **aOwnerWindow); NS_SCRIPTABLE NS_IMETHOD GetComputedStyleValue(const nsAString& aPseudoElt, const nsAString& aPropertyName, nsAString& aValue NS_OUTPARAM); diff --git a/accessible/src/base/nsCoreUtils.cpp b/accessible/src/base/nsCoreUtils.cpp index 20c4b03b2fdf..28bf586720d0 100644 --- a/accessible/src/base/nsCoreUtils.cpp +++ b/accessible/src/base/nsCoreUtils.cpp @@ -66,6 +66,7 @@ #include "nsContentCID.h" #include "nsComponentManagerUtils.h" #include "nsIInterfaceRequestorUtils.h" +#include "mozilla/dom/Element.h" static NS_DEFINE_IID(kRangeCID, NS_RANGE_CID); @@ -479,6 +480,26 @@ nsCoreUtils::IsContentDocument(nsIDocument *aDocument) return (contentType == nsIDocShellTreeItem::typeContent); } +bool +nsCoreUtils::IsTabDocument(nsIDocument* aDocumentNode) +{ + nsCOMPtr container = aDocumentNode->GetContainer(); + nsCOMPtr treeItem(do_QueryInterface(container)); + + nsCOMPtr parentTreeItem; + treeItem->GetParent(getter_AddRefs(parentTreeItem)); + + // Tab document running in own process doesn't have parent. + if (XRE_GetProcessType() == GeckoProcessType_Content) + return !parentTreeItem; + + // Parent of docshell for tab document running in chrome process is root. + nsCOMPtr rootTreeItem; + treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem)); + + return parentTreeItem == rootTreeItem; +} + PRBool nsCoreUtils::IsErrorPage(nsIDocument *aDocument) { diff --git a/accessible/src/base/nsCoreUtils.h b/accessible/src/base/nsCoreUtils.h index f603f450ab62..6aa375c529f3 100644 --- a/accessible/src/base/nsCoreUtils.h +++ b/accessible/src/base/nsCoreUtils.h @@ -233,6 +233,11 @@ public: */ static PRBool IsContentDocument(nsIDocument *aDocument); + /** + * Return true if the given document node is for tab document accessible. + */ + static bool IsTabDocument(nsIDocument* aDocumentNode); + /** * Return true if the given document is an error page. */ diff --git a/accessible/src/base/nsDocAccessible.cpp b/accessible/src/base/nsDocAccessible.cpp index c16d9db19d86..ae7179ad5a7e 100644 --- a/accessible/src/base/nsDocAccessible.cpp +++ b/accessible/src/base/nsDocAccessible.cpp @@ -104,8 +104,7 @@ nsDocAccessible:: nsDocAccessible(nsIDocument *aDocument, nsIContent *aRootContent, nsIWeakReference *aShell) : nsHyperTextAccessibleWrap(aRootContent, aShell), - mDocument(aDocument), mScrollPositionChangedTicks(0), mIsLoaded(PR_FALSE), - mCacheRoot(nsnull), mIsPostCacheProcessing(PR_FALSE) + mDocument(aDocument), mScrollPositionChangedTicks(0), mIsLoaded(PR_FALSE) { mFlags |= eDocAccessible; @@ -1425,43 +1424,30 @@ nsDocAccessible::RecreateAccessible(nsIContent* aContent) } void -nsDocAccessible::NotifyOfCachingStart(nsAccessible* aAccessible) +nsDocAccessible::ProcessInvalidationList() { - if (!mCacheRoot) - mCacheRoot = aAccessible; -} - -void -nsDocAccessible::NotifyOfCachingEnd(nsAccessible* aAccessible) -{ - if (mCacheRoot == aAccessible && !mIsPostCacheProcessing) { - // Allow invalidation list insertions while container children are recached. - mIsPostCacheProcessing = PR_TRUE; - - // Invalidate children of container accessible for each element in - // invalidation list. - for (PRUint32 idx = 0; idx < mInvalidationList.Length(); idx++) { - nsIContent* content = mInvalidationList[idx]; - nsAccessible* accessible = GetAccessible(content); - if (!accessible) { - nsAccessible* container = GetContainerAccessible(content); - NS_ASSERTION(container, - "Got a referenced element that is not in document!"); - if (container) { - container->UpdateChildren(); - accessible = GetAccessible(content); - } + // Invalidate children of container accessible for each element in + // invalidation list. Allow invalidation list insertions while container + // children are recached. + for (PRUint32 idx = 0; idx < mInvalidationList.Length(); idx++) { + nsIContent* content = mInvalidationList[idx]; + nsAccessible* accessible = GetAccessible(content); + if (!accessible) { + nsAccessible* container = GetContainerAccessible(content); + NS_ASSERTION(container, + "Got a referenced element that is not in document!"); + if (container) { + container->UpdateChildren(); + accessible = GetAccessible(content); } - - // Make sure the subtree is created. - if (accessible) - CacheChildrenInSubtree(accessible); } - mInvalidationList.Clear(); - mCacheRoot = nsnull; - mIsPostCacheProcessing = PR_FALSE; + // Make sure the subtree is created. + if (accessible) + CacheChildrenInSubtree(accessible); } + + mInvalidationList.Clear(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/accessible/src/base/nsDocAccessible.h b/accessible/src/base/nsDocAccessible.h index 2b9662452309..bd52cf0bc488 100644 --- a/accessible/src/base/nsDocAccessible.h +++ b/accessible/src/base/nsDocAccessible.h @@ -325,17 +325,6 @@ public: */ void RecreateAccessible(nsIContent* aContent); - /** - * Used to notify the document that the accessible caching is started or - * finished. - * - * While children are cached we may encounter the case there's no accessible - * for referred content by related accessible. Keep the caching root and - * these related nodes to invalidate their containers after root caching. - */ - void NotifyOfCachingStart(nsAccessible* aAccessible); - void NotifyOfCachingEnd(nsAccessible* aAccessible); - protected: // nsAccessible @@ -439,6 +428,15 @@ protected: void ProcessContentInserted(nsAccessible* aContainer, const nsTArray >* aInsertedContent); + /** + * Used to notify the document to make it process the invalidation list. + * + * While children are cached we may encounter the case there's no accessible + * for referred content by related accessible. Store these related nodes to + * invalidate their containers later. + */ + void ProcessInvalidationList(); + /** * Update the accessible tree for content insertion or removal. */ @@ -532,15 +530,12 @@ protected: friend class RelatedAccIterator; /** - * Used for our caching algorithm. We store the root of the tree that needs - * caching, the list of nodes that should be invalidated, and whether we are - * processing the invalidation list. + * Used for our caching algorithm. We store the list of nodes that should be + * invalidated. * - * @see NotifyOfCachingStart/NotifyOfCachingEnd + * @see ProcessInvalidationList */ - nsAccessible* mCacheRoot; nsTArray mInvalidationList; - PRBool mIsPostCacheProcessing; /** * Used to process notification from core and accessible events. diff --git a/accessible/src/html/nsHTMLLinkAccessible.cpp b/accessible/src/html/nsHTMLLinkAccessible.cpp index b4e8f7cf35a6..d22198559cbc 100644 --- a/accessible/src/html/nsHTMLLinkAccessible.cpp +++ b/accessible/src/html/nsHTMLLinkAccessible.cpp @@ -43,6 +43,7 @@ #include "nsCoreUtils.h" #include "nsEventStates.h" +#include "mozilla/dom/Element.h" //////////////////////////////////////////////////////////////////////////////// // nsHTMLLinkAccessible diff --git a/accessible/src/msaa/Makefile.in b/accessible/src/msaa/Makefile.in index 15979a26e6c7..6ffaa14f4851 100644 --- a/accessible/src/msaa/Makefile.in +++ b/accessible/src/msaa/Makefile.in @@ -107,6 +107,8 @@ EXPORTS = \ # we don't want the shared lib, but we want to force the creation of a static lib. FORCE_STATIC_LIB = 1 +include $(topsrcdir)/config/config.mk +include $(topsrcdir)/ipc/chromium/chromium-config.mk include $(topsrcdir)/config/rules.mk LOCAL_INCLUDES += \ @@ -114,5 +116,6 @@ LOCAL_INCLUDES += \ -I$(srcdir)/../base \ -I$(srcdir)/../html \ -I$(srcdir)/../xul \ + -I$(srcdir)/../../../content/base/src \ + -I$(srcdir)/../../../content/events/src \ $(NULL) - diff --git a/accessible/src/msaa/nsAccessibleWrap.cpp b/accessible/src/msaa/nsAccessibleWrap.cpp index 47cbbf280994..fe4c88d7755a 100644 --- a/accessible/src/msaa/nsAccessibleWrap.cpp +++ b/accessible/src/msaa/nsAccessibleWrap.cpp @@ -204,7 +204,7 @@ __try { // accessibles. if (!doc->ParentDocument() || nsWinUtils::IsWindowEmulationStarted() && - nsWinUtils::IsTabDocument(doc->GetDocumentNode())) { + nsCoreUtils::IsTabDocument(doc->GetDocumentNode())) { HWND hwnd = static_cast(doc->GetNativeWindow()); if (hwnd && SUCCEEDED(AccessibleObjectFromWindow(hwnd, OBJID_WINDOW, IID_IAccessible, diff --git a/accessible/src/msaa/nsDocAccessibleWrap.cpp b/accessible/src/msaa/nsDocAccessibleWrap.cpp index b89cbb8e3eeb..a2a92f925a24 100644 --- a/accessible/src/msaa/nsDocAccessibleWrap.cpp +++ b/accessible/src/msaa/nsDocAccessibleWrap.cpp @@ -36,6 +36,8 @@ * * ***** END LICENSE BLOCK ***** */ +#include "mozilla/dom/TabChild.h" + #include "nsDocAccessibleWrap.h" #include "ISimpleDOMDocument_i.c" #include "nsIAccessibilityService.h" @@ -242,7 +244,7 @@ nsDocAccessibleWrap::Shutdown() // Do window emulation specific shutdown if emulation was started. if (nsWinUtils::IsWindowEmulationStarted()) { // Destroy window created for root document. - if (nsWinUtils::IsTabDocument(mDocument)) { + if (nsCoreUtils::IsTabDocument(mDocument)) { sHWNDCache.Remove(mHWND); ::DestroyWindow(static_cast(mHWND)); } @@ -272,9 +274,19 @@ nsDocAccessibleWrap::NotifyOfInitialUpdate() if (nsWinUtils::IsWindowEmulationStarted()) { // Create window for tab document. - if (nsWinUtils::IsTabDocument(mDocument)) { + if (nsCoreUtils::IsTabDocument(mDocument)) { + mozilla::dom::TabChild* tabChild = + mozilla::dom::GetTabChildFrom(mDocument->GetShell()); + nsRootAccessible* rootDocument = RootAccessible(); + mozilla::WindowsHandle nativeData = nsnull; + if (tabChild) + tabChild->SendGetWidgetNativeData(&nativeData); + else + nativeData = reinterpret_cast( + rootDocument->GetNativeWindow()); + PRBool isActive = PR_TRUE; PRInt32 x = CW_USEDEFAULT, y = CW_USEDEFAULT, width = 0, height = 0; if (nsWinUtils::IsWindowEmulationFor(kDolphinModuleHandle)) { @@ -289,7 +301,7 @@ nsDocAccessibleWrap::NotifyOfInitialUpdate() docShell->GetIsActive(&isActive); } - HWND parentWnd = static_cast(rootDocument->GetNativeWindow()); + HWND parentWnd = reinterpret_cast(nativeData); mHWND = nsWinUtils::CreateNativeWindow(kClassNameTabContent, parentWnd, x, y, width, height, isActive); diff --git a/accessible/src/msaa/nsRootAccessibleWrap.cpp b/accessible/src/msaa/nsRootAccessibleWrap.cpp index 7aa993ae3ade..767bdd8a9577 100644 --- a/accessible/src/msaa/nsRootAccessibleWrap.cpp +++ b/accessible/src/msaa/nsRootAccessibleWrap.cpp @@ -64,7 +64,7 @@ void nsRootAccessibleWrap::DocumentActivated(nsDocAccessible* aDocument) { if (nsWinUtils::IsWindowEmulationFor(kDolphinModuleHandle) && - nsWinUtils::IsTabDocument(aDocument->GetDocumentNode())) { + nsCoreUtils::IsTabDocument(aDocument->GetDocumentNode())) { PRUint32 count = mChildDocuments.Length(); for (PRUint32 idx = 0; idx < count; idx++) { nsDocAccessible* childDoc = mChildDocuments[idx]; diff --git a/accessible/src/msaa/nsWinUtils.cpp b/accessible/src/msaa/nsWinUtils.cpp index 17f3ce7ac9ca..8c25afc35bbb 100644 --- a/accessible/src/msaa/nsWinUtils.cpp +++ b/accessible/src/msaa/nsWinUtils.cpp @@ -176,23 +176,13 @@ nsWinUtils::HideNativeWindow(HWND aWnd) bool nsWinUtils::IsWindowEmulationFor(LPCWSTR kModuleHandle) { +#ifdef MOZ_E10S_COMPAT + // Window emulation is always enabled in multiprocess Firefox. + return kModuleHandle ? ::GetModuleHandleW(kModuleHandle) : true; +#else return kModuleHandle ? ::GetModuleHandleW(kModuleHandle) : ::GetModuleHandleW(kJAWSModuleHandle) || ::GetModuleHandleW(kWEModuleHandle) || ::GetModuleHandleW(kDolphinModuleHandle); -} - -bool -nsWinUtils::IsTabDocument(nsIDocument* aDocumentNode) -{ - nsCOMPtr container = aDocumentNode->GetContainer(); - nsCOMPtr treeItem(do_QueryInterface(container)); - - nsCOMPtr parentTreeItem; - treeItem->GetParent(getter_AddRefs(parentTreeItem)); - - nsCOMPtr rootTreeItem; - treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem)); - - return parentTreeItem == rootTreeItem; +#endif } diff --git a/accessible/src/msaa/nsWinUtils.h b/accessible/src/msaa/nsWinUtils.h index 3837b87411d4..5d17f4d1f961 100644 --- a/accessible/src/msaa/nsWinUtils.h +++ b/accessible/src/msaa/nsWinUtils.h @@ -104,11 +104,6 @@ public: * Return true if window emulation is enabled. */ static bool IsWindowEmulationFor(LPCWSTR kModuleHandle); - - /** - * Return true if the given document node is for tab document accessible. - */ - static bool IsTabDocument(nsIDocument* aDocumentNode); }; #endif diff --git a/accessible/src/xul/nsXULMenuAccessible.cpp b/accessible/src/xul/nsXULMenuAccessible.cpp index 2ddee3769cd7..53d83308ef0e 100644 --- a/accessible/src/xul/nsXULMenuAccessible.cpp +++ b/accessible/src/xul/nsXULMenuAccessible.cpp @@ -58,6 +58,7 @@ #include "nsWidgetsCID.h" #include "mozilla/Preferences.h" +#include "mozilla/dom/Element.h" using namespace mozilla; @@ -464,7 +465,7 @@ nsXULMenuitemAccessible::KeyboardShortcut() const PRUint32 modifierMask = 0; if (modifiersStr.Find("shift") != -1) - modifierMask != KeyBinding::kShift; + modifierMask |= KeyBinding::kShift; if (modifiersStr.Find("alt") != -1) modifierMask |= KeyBinding::kAlt; if (modifiersStr.Find("meta") != -1) diff --git a/accessible/tests/mochitest/attributes/test_obj_group.xul b/accessible/tests/mochitest/attributes/test_obj_group.xul index a8fb69561d3a..30511b511d04 100644 --- a/accessible/tests/mochitest/attributes/test_obj_group.xul +++ b/accessible/tests/mochitest/attributes/test_obj_group.xul @@ -13,11 +13,66 @@ + + @@ -148,5 +188,8 @@ + + + diff --git a/accessible/tests/mochitest/tree/Makefile.in b/accessible/tests/mochitest/tree/Makefile.in index 6003b0f79ea5..ddb386614bcb 100644 --- a/accessible/tests/mochitest/tree/Makefile.in +++ b/accessible/tests/mochitest/tree/Makefile.in @@ -63,6 +63,7 @@ _TEST_FILES =\ test_groupbox.xul \ test_iframe.html \ test_img.html \ + test_invalidationlist.html \ test_list.html \ test_media.html \ test_select.html \ diff --git a/accessible/tests/mochitest/tree/test_invalidationlist.html b/accessible/tests/mochitest/tree/test_invalidationlist.html new file mode 100644 index 000000000000..c66993452bb1 --- /dev/null +++ b/accessible/tests/mochitest/tree/test_invalidationlist.html @@ -0,0 +1,59 @@ + + + + Test document hierarchy + + + + + + + + + + + + + + + Mozilla Bug 673757 + +

+ +
+  
+ +
+
+
Z
+
+ + diff --git a/browser/app/blocklist.xml b/browser/app/blocklist.xml index 5af334dd0318..cb4478830b11 100644 --- a/browser/app/blocklist.xml +++ b/browser/app/blocklist.xml @@ -1,6 +1,10 @@ - + + + + + @@ -25,6 +29,10 @@ + + + + @@ -52,6 +60,10 @@ + + + + diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index e31f36b6aca2..d803ba6308e5 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -6797,9 +6797,9 @@ var gPluginHandler = { submitReport : function(pluginDumpID, browserDumpID) { // The crash reporter wants a DOM element it can append an IFRAME to, // which it uses to submit a form. Let's just give it gBrowser. - this.CrashSubmit.submit(pluginDumpID, gBrowser, null, null); + this.CrashSubmit.submit(pluginDumpID); if (browserDumpID) - this.CrashSubmit.submit(browserDumpID, gBrowser, null, null); + this.CrashSubmit.submit(browserDumpID); }, // Callback for user clicking a "reload page" link diff --git a/browser/base/content/inspector.js b/browser/base/content/inspector.js index ad07ec0f7858..d55699f35705 100644 --- a/browser/base/content/inspector.js +++ b/browser/base/content/inspector.js @@ -882,6 +882,7 @@ var InspectorUI = { { this.attachPageListeners(); this.inspecting = true; + this.highlighter.veilTransparentBox.removeAttribute("locked"); }, /** @@ -901,6 +902,7 @@ var InspectorUI = { } else { this.select(null, true, true); } + this.highlighter.veilTransparentBox.setAttribute("locked", true); }, /** diff --git a/browser/base/content/scratchpad.xul b/browser/base/content/scratchpad.xul index 6271b692794f..eca6ee9de80e 100644 --- a/browser/base/content/scratchpad.xul +++ b/browser/base/content/scratchpad.xul @@ -330,6 +330,7 @@ ") - .addClass('newTabButton') - .click(function() { - self.newTab(); - }) - .attr('title', tabviewString('groupItem.newTabButton')) - .appendTo($container); - // ___ Resizer this.$resizer = iQ("
") .addClass('resizer') @@ -1660,9 +1651,45 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), { // Helper routine for the constructor; adds various event handlers to the container. _addHandlers: function GroupItem__addHandlers(container) { let self = this; + let lastMouseDownTarget; - var dropIndex = false; - var dropSpaceTimer = null; + container.mousedown(function(e) { + let target = e.target; + // only set the last mouse down target if it is a left click, not on the + // close button, not on the new tab button, not on the title bar and its + // element + if (Utils.isLeftClick(e) && + self.$closeButton[0] != target && + self.$titlebar[0] != target && + !self.$titlebar.contains(target) && + !self.$appTabTray.contains(target)) { + lastMouseDownTarget = target; + } else { + lastMouseDownTarget = null; + } + }); + container.mouseup(function(e) { + let same = (e.target == lastMouseDownTarget); + lastMouseDownTarget = null; + + if (same && !self.isDragging) { + if (gBrowser.selectedTab.pinned && + UI.getActiveTab() != self.getActiveTab() && + self.getChildren().length > 0) { + UI.setActive(self, { dontSetActiveTabInGroup: true }); + UI.goToTab(gBrowser.selectedTab); + } else { + let tabItem = self.getTopChild(); + if (tabItem) + tabItem.zoomIn(); + else + self.newTab(); + } + } + }); + + let dropIndex = false; + let dropSpaceTimer = null; // When the _dropSpaceActive flag is turned on on a group, and a tab is // dragged on top, a space will open up. diff --git a/browser/base/content/tabview/modules/AllTabs.jsm b/browser/base/content/tabview/modules/AllTabs.jsm index 86f7f1714988..3c8285348111 100644 --- a/browser/base/content/tabview/modules/AllTabs.jsm +++ b/browser/base/content/tabview/modules/AllTabs.jsm @@ -35,6 +35,8 @@ * * ***** END LICENSE BLOCK ***** */ +"use strict"; + const Cu = Components.utils; Cu.import("resource://gre/modules/Services.jsm"); @@ -164,8 +166,8 @@ function tabEventListener(event) { function observer(subject, topic, data) { switch (topic) { case "domwindowopened": - subject.addEventListener("load", function() { - subject.removeEventListener("load", arguments.callee, false); + subject.addEventListener("load", function onLoad() { + subject.removeEventListener("load", onLoad, false); // Now that the window has loaded, only register on browser windows let doc = subject.document.documentElement; diff --git a/browser/base/content/tabview/modules/utils.jsm b/browser/base/content/tabview/modules/utils.jsm index df5333d04db8..289358cdbbb0 100644 --- a/browser/base/content/tabview/modules/utils.jsm +++ b/browser/base/content/tabview/modules/utils.jsm @@ -45,6 +45,8 @@ * * ***** END LICENSE BLOCK ***** */ +"use strict"; + // ********** // Title: utils.js @@ -369,10 +371,11 @@ Range.prototype = { // little graph. It goes from near 0 at x=0 to near 1 at x=1 // smoothly and beautifully. // http://www.wolframalpha.com/input/?i=.5+%2B+.5+*+tanh%28%284+*+x%29+-+2%29 - function tanh(x) { + let tanh = function tanh(x) { var e = Math.exp(x); return (e - 1/e) / (e + 1/e); - } + }; + return .5 - .5 * tanh(2 - 4 * proportion); } diff --git a/browser/base/content/tabview/search.js b/browser/base/content/tabview/search.js index 950fa48d4666..8968531b7e10 100644 --- a/browser/base/content/tabview/search.js +++ b/browser/base/content/tabview/search.js @@ -585,8 +585,7 @@ function ensureSearchShown(activatedByKeypress) { // NOTE: when this function is called by keydown handler, next keypress // event or composition events of IME will be fired on the focused editor. - - function dispatchTabViewSearchEnabledEvent() { + let dispatchTabViewSearchEnabledEvent = function dispatchTabViewSearchEnabledEvent() { let newEvent = document.createEvent("Events"); newEvent.initEvent("tabviewsearchenabled", false, false); dispatchEvent(newEvent); @@ -595,7 +594,7 @@ function ensureSearchShown(activatedByKeypress) { if (activatedByKeypress) { // set the focus so key strokes are entered into the textbox. $searchbox[0].focus(); - dispatchTabViewSearchEnabledEvent(); + dispatchTabViewSearchEnabledEvent(); } else { // marshal the focusing, otherwise it ends up with searchbox[0].focus gets // called before the search button gets the focus after being pressed. diff --git a/browser/base/content/tabview/tabitems.js b/browser/base/content/tabview/tabitems.js index cd519424ebc4..6d7843cd64c5 100644 --- a/browser/base/content/tabview/tabitems.js +++ b/browser/base/content/tabview/tabitems.js @@ -482,6 +482,7 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), { // closing tab doesn't belong to a group and no empty group, create a new // one for the new tab. if (!groupClose && gBrowser.tabs.length == 1) { + let group; if (this.tab._tabViewTabItem.parent) { group = this.tab._tabViewTabItem.parent; } else { diff --git a/browser/base/content/tabview/tabview.css b/browser/base/content/tabview/tabview.css index 902c30632907..eac215d09213 100644 --- a/browser/base/content/tabview/tabview.css +++ b/browser/base/content/tabview/tabview.css @@ -144,11 +144,6 @@ body { /* Other ----------------------------------*/ -.newTabButton { - position: absolute !important; - z-index: 99999; -} - .titlebar { position: absolute; } diff --git a/browser/base/content/tabview/tabview.js b/browser/base/content/tabview/tabview.js index e30929cf8871..15a5c9380c6f 100644 --- a/browser/base/content/tabview/tabview.js +++ b/browser/base/content/tabview/tabview.js @@ -1,3 +1,5 @@ +"use strict"; + const Cc = Components.classes; const Ci = Components.interfaces; const Cu = Components.utils; diff --git a/browser/base/content/tabview/thumbnailStorage.js b/browser/base/content/tabview/thumbnailStorage.js index 1bad6193c324..bb28d2e8af0a 100644 --- a/browser/base/content/tabview/thumbnailStorage.js +++ b/browser/base/content/tabview/thumbnailStorage.js @@ -105,8 +105,8 @@ let ThumbnailStorage = { }; if (browser.contentDocument.readyState != "complete" || browser.webProgress.isLoadingDocument) { - browser.addEventListener("load", function() { - browser.removeEventListener("load", arguments.callee, true); + browser.addEventListener("load", function onLoad() { + browser.removeEventListener("load", onLoad, true); checkAndAddToList(browser); }, true); } else { diff --git a/browser/base/content/tabview/ui.js b/browser/base/content/tabview/ui.js index f608c61622b4..accfb5588a35 100644 --- a/browser/base/content/tabview/ui.js +++ b/browser/base/content/tabview/ui.js @@ -861,8 +861,8 @@ let UI = { if (this.restoredClosedTab) { // when the tab view UI is being displayed, update the thumb for the // restored closed tab after the page load - tab.linkedBrowser.addEventListener("load", function (event) { - tab.linkedBrowser.removeEventListener("load", arguments.callee, true); + tab.linkedBrowser.addEventListener("load", function onLoad(event) { + tab.linkedBrowser.removeEventListener("load", onLoad, true); TabItems._update(tab); }, true); } diff --git a/browser/base/content/test/Makefile.in b/browser/base/content/test/Makefile.in index 37bcad78e7e3..364055c8a970 100644 --- a/browser/base/content/test/Makefile.in +++ b/browser/base/content/test/Makefile.in @@ -260,6 +260,9 @@ _BROWSER_FILES = \ browser_addon_bar_shortcut.js \ browser_addon_bar_aomlistener.js \ test_bug628179.html \ + browser_wyciwyg_urlbarCopying.js \ + test_wyciwyg_copying.html \ + authenticate.sjs \ browser_minimize.js \ $(NULL) diff --git a/browser/base/content/test/authenticate.sjs b/browser/base/content/test/authenticate.sjs new file mode 100644 index 000000000000..7c2102fd0dbb --- /dev/null +++ b/browser/base/content/test/authenticate.sjs @@ -0,0 +1,205 @@ +function handleRequest(request, response) +{ + try { + reallyHandleRequest(request, response); + } catch (e) { + response.setStatusLine("1.0", 200, "AlmostOK"); + response.write("Error handling request: " + e); + } +} + + +function reallyHandleRequest(request, response) { + var match; + var requestAuth = true, requestProxyAuth = true; + + // Allow the caller to drive how authentication is processed via the query. + // Eg, http://localhost:8888/authenticate.sjs?user=foo&realm=bar + var query = request.queryString; + + var expected_user = "", expected_pass = "", realm = "mochitest"; + var proxy_expected_user = "", proxy_expected_pass = "", proxy_realm = "mochi-proxy"; + var huge = false, plugin = false; + var authHeaderCount = 1; + // user=xxx + match = /user=([^&]*)/.exec(query); + if (match) + expected_user = match[1]; + + // pass=xxx + match = /pass=([^&]*)/.exec(query); + if (match) + expected_pass = match[1]; + + // realm=xxx + match = /realm=([^&]*)/.exec(query); + if (match) + realm = match[1]; + + // proxy_user=xxx + match = /proxy_user=([^&]*)/.exec(query); + if (match) + proxy_expected_user = match[1]; + + // proxy_pass=xxx + match = /proxy_pass=([^&]*)/.exec(query); + if (match) + proxy_expected_pass = match[1]; + + // proxy_realm=xxx + match = /proxy_realm=([^&]*)/.exec(query); + if (match) + proxy_realm = match[1]; + + // huge=1 + match = /huge=1/.exec(query); + if (match) + huge = true; + + // plugin=1 + match = /plugin=1/.exec(query); + if (match) + plugin = true; + + // multiple=1 + match = /multiple=([^&]*)/.exec(query); + if (match) + authHeaderCount = match[1]+0; + + + // Look for an authentication header, if any, in the request. + // + // EG: Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== + // + // This test only supports Basic auth. The value sent by the client is + // "username:password", obscured with base64 encoding. + + var actual_user = "", actual_pass = "", authHeader; + if (request.hasHeader("Authorization")) { + authHeader = request.getHeader("Authorization"); + match = /Basic (.+)/.exec(authHeader); + if (match.length != 2) + throw "Couldn't parse auth header: " + authHeader; + + var userpass = base64ToString(match[1]); // no atob() :-( + match = /(.*):(.*)/.exec(userpass); + if (match.length != 3) + throw "Couldn't decode auth header: " + userpass; + actual_user = match[1]; + actual_pass = match[2]; + } + + var proxy_actual_user = "", proxy_actual_pass = ""; + if (request.hasHeader("Proxy-Authorization")) { + authHeader = request.getHeader("Proxy-Authorization"); + match = /Basic (.+)/.exec(authHeader); + if (match.length != 2) + throw "Couldn't parse auth header: " + authHeader; + + var userpass = base64ToString(match[1]); // no atob() :-( + match = /(.*):(.*)/.exec(userpass); + if (match.length != 3) + throw "Couldn't decode auth header: " + userpass; + proxy_actual_user = match[1]; + proxy_actual_pass = match[2]; + } + + // Don't request authentication if the credentials we got were what we + // expected. + if (expected_user == actual_user && + expected_pass == actual_pass) { + requestAuth = false; + } + if (proxy_expected_user == proxy_actual_user && + proxy_expected_pass == proxy_actual_pass) { + requestProxyAuth = false; + } + + if (requestProxyAuth) { + response.setStatusLine("1.0", 407, "Proxy authentication required"); + for (i = 0; i < authHeaderCount; ++i) + response.setHeader("Proxy-Authenticate", "basic realm=\"" + proxy_realm + "\"", true); + } else if (requestAuth) { + response.setStatusLine("1.0", 401, "Authentication required"); + for (i = 0; i < authHeaderCount; ++i) + response.setHeader("WWW-Authenticate", "basic realm=\"" + realm + "\"", true); + } else { + response.setStatusLine("1.0", 200, "OK"); + } + + response.setHeader("Content-Type", "application/xhtml+xml", false); + response.write(""); + response.write("

Login: " + (requestAuth ? "FAIL" : "PASS") + "

\n"); + response.write("

Proxy: " + (requestProxyAuth ? "FAIL" : "PASS") + "

\n"); + response.write("

Auth: " + authHeader + "

\n"); + response.write("

User: " + actual_user + "

\n"); + response.write("

Pass: " + actual_pass + "

\n"); + + if (huge) { + response.write("
"); + for (i = 0; i < 100000; i++) { + response.write("123456789\n"); + } + response.write("
"); + response.write("This is a footnote after the huge content fill"); + } + + if (plugin) { + response.write("\n"); + } + + response.write(""); +} + + +// base64 decoder +// +// Yoinked from extensions/xml-rpc/src/nsXmlRpcClient.js because btoa() +// doesn't seem to exist. :-( +/* Convert Base64 data to a string */ +const toBinaryTable = [ + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, + -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63, + 52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1, + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14, + 15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1, + -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40, + 41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1 +]; +const base64Pad = '='; + +function base64ToString(data) { + + var result = ''; + var leftbits = 0; // number of bits decoded, but yet to be appended + var leftdata = 0; // bits decoded, but yet to be appended + + // Convert one by one. + for (var i = 0; i < data.length; i++) { + var c = toBinaryTable[data.charCodeAt(i) & 0x7f]; + var padding = (data[i] == base64Pad); + // Skip illegal characters and whitespace + if (c == -1) continue; + + // Collect data into leftdata, update bitcount + leftdata = (leftdata << 6) | c; + leftbits += 6; + + // If we have 8 or more bits, append 8 bits to the result + if (leftbits >= 8) { + leftbits -= 8; + // Append if not padding. + if (!padding) + result += String.fromCharCode((leftdata >> leftbits) & 0xff); + leftdata &= (1 << leftbits) - 1; + } + } + + // If there are any bits left, the base64 string was corrupted + if (leftbits) + throw Components.Exception('Corrupted base64 string'); + + return result; +} diff --git a/browser/base/content/test/browser_locationBarExternalLoad.js b/browser/base/content/test/browser_locationBarExternalLoad.js index b0b177534cfd..2bc88a989e32 100644 --- a/browser/base/content/test/browser_locationBarExternalLoad.js +++ b/browser/base/content/test/browser_locationBarExternalLoad.js @@ -46,6 +46,10 @@ function testURL(url, loadFunc, endFunc) { loadFunc(url); addPageShowListener(function () { + let fm = Cc["@mozilla.org/focus-manager;1"].getService(Ci.nsIFocusManager); + is(fm.focusedElement, null, "should be no focused element"); + is(fm.focusedWindow, gBrowser.contentWindow, "content window should be focused"); + ok(!gBrowser.contentPrincipal.equals(pagePrincipal), "load of " + url + " by " + loadFunc.name + " should produce a page with a different principal"); endFunc(); diff --git a/browser/base/content/test/browser_relatedTabs.js b/browser/base/content/test/browser_relatedTabs.js index 893f16570550..e08291ba0315 100644 --- a/browser/base/content/test/browser_relatedTabs.js +++ b/browser/base/content/test/browser_relatedTabs.js @@ -78,5 +78,14 @@ function test() { testPosition(7, 8, "blank tab without referrer opens at the end"); testPosition(8, 9, "tab without referrer opens at the end"); + gBrowser.selectedTab = tabs[0]; + gBrowser.pinTab(gBrowser.selectedTab); + addTab("http://mochi.test:8888/#8", gBrowser.currentURI); + testPosition(9, 10, "tab with referrer should open at the end when the selected tab is pinned"); + gBrowser.selectedTab = tabs[9]; + gBrowser.removeTab(tabs.pop()); + is(gBrowser.selectedTab, tabs[0], + "opening a tab from a pinned tab, selecting it and closing it should go back to the pinned tab"); + tabs.forEach(gBrowser.removeTab, gBrowser); } diff --git a/browser/base/content/test/browser_urlbarCopying.js b/browser/base/content/test/browser_urlbarCopying.js index 59e1c4f01754..8024fd4b6b45 100644 --- a/browser/base/content/test/browser_urlbarCopying.js +++ b/browser/base/content/test/browser_urlbarCopying.js @@ -2,18 +2,21 @@ http://creativecommons.org/publicdomain/zero/1.0/ */ const trimPref = "browser.urlbar.trimURLs"; +const phishyUserPassPref = "network.http.phishy-userpass-length"; function test() { - gBrowser.selectedTab = gBrowser.addTab(); + let tab = gBrowser.selectedTab = gBrowser.addTab(); registerCleanupFunction(function () { - gBrowser.removeCurrentTab(); + gBrowser.removeTab(tab); Services.prefs.clearUserPref(trimPref); + Services.prefs.clearUserPref(phishyUserPassPref); URLBarSetURI(); }); Services.prefs.setBoolPref(trimPref, true); + Services.prefs.setIntPref(phishyUserPassPref, 32); // avoid prompting about phishing waitForExplicitFinish(); @@ -32,7 +35,6 @@ var tests = [ copyExpected: "e" }, - // pageproxystate="valid" from this point on (due to the load) { loadURL: "http://example.com/", @@ -52,6 +54,13 @@ var tests = [ copyExpected: "http://e" }, + // Test that userPass is stripped out + { + loadURL: "http://user:pass@mochi.test:8888/browser/browser/base/content/test/authenticate.sjs?user=user&pass=pass", + expectedURL: "mochi.test:8888/browser/browser/base/content/test/authenticate.sjs?user=user&pass=pass", + copyExpected: "http://mochi.test:8888/browser/browser/base/content/test/authenticate.sjs?user=user&pass=pass" + }, + // Test escaping { loadURL: "http://example.com/()%C3%A9", diff --git a/browser/base/content/test/browser_wyciwyg_urlbarCopying.js b/browser/base/content/test/browser_wyciwyg_urlbarCopying.js new file mode 100644 index 000000000000..f908e5254c90 --- /dev/null +++ b/browser/base/content/test/browser_wyciwyg_urlbarCopying.js @@ -0,0 +1,39 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +function test() { + waitForExplicitFinish(); + + let url = "http://mochi.test:8888/browser/browser/base/content/test/test_wyciwyg_copying.html"; + let tab = gBrowser.selectedTab = gBrowser.addTab(url); + tab.linkedBrowser.addEventListener("pageshow", function () { + let btn = content.document.getElementById("btn"); + executeSoon(function () { + EventUtils.synthesizeMouseAtCenter(btn, {}, content); + let currentURL = gBrowser.currentURI.spec; + ok(/^wyciwyg:\/\//i.test(currentURL), currentURL + " is a wyciwyg URI"); + + executeSoon(function () { + testURLBarCopy(url, endTest); + }); + }); + }, false); + + function endTest() { + while (gBrowser.tabs.length > 1) + gBrowser.removeCurrentTab(); + finish(); + } + + function testURLBarCopy(targetValue, cb) { + info("Expecting copy of: " + targetValue); + waitForClipboard(targetValue, function () { + gURLBar.focus(); + gURLBar.select(); + + goDoCommand("cmd_copy"); + }, cb, cb); + } +} + + diff --git a/browser/base/content/test/tabview/Makefile.in b/browser/base/content/test/tabview/Makefile.in index 63e116880bbf..f480613a78b6 100644 --- a/browser/base/content/test/tabview/Makefile.in +++ b/browser/base/content/test/tabview/Makefile.in @@ -150,6 +150,7 @@ _BROWSER_FILES = \ browser_tabview_bug663421.js \ browser_tabview_bug665502.js \ browser_tabview_bug669694.js \ + browser_tabview_click_group.js \ browser_tabview_dragdrop.js \ browser_tabview_exit_button.js \ browser_tabview_expander.js \ @@ -167,7 +168,6 @@ _BROWSER_FILES = \ head.js \ search1.html \ search2.html \ - test_bug599626.html \ test_bug600645.html \ test_bug644097.html \ $(NULL) diff --git a/browser/base/content/test/tabview/browser_tabview_bug588265.js b/browser/base/content/test/tabview/browser_tabview_bug588265.js index 44caa9a31fdf..a4d532682b5c 100644 --- a/browser/base/content/test/tabview/browser_tabview_bug588265.js +++ b/browser/base/content/test/tabview/browser_tabview_bug588265.js @@ -1,53 +1,37 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ +let contentWindow; +let groupItemTwoId; + function test() { waitForExplicitFinish(); - - window.addEventListener("tabviewshown", setup, false); - TabView.toggle(); + + registerCleanupFunction(function() { + while (gBrowser.tabs[1]) + gBrowser.removeTab(gBrowser.tabs[1]); + hideTabView(function() {}); + }); + gBrowser.loadOneTab("about:blank", { inBackground: true }); + showTabView(setup); } function setup() { - window.removeEventListener("tabviewshown", setup, false); + registerCleanupFunction(function() { + let groupItem = contentWindow.GroupItems.groupItem(groupItemTwoId); + if (groupItem) + closeGroupItem(groupItem, function() {}); + }); - let contentWindow = document.getElementById("tab-view").contentWindow; + let contentWindow = TabView.getContentWindow(); is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group"); let groupItemOne = contentWindow.GroupItems.groupItems[0]; - // add a blank tab to group one. - createNewTabItemInGroupItem(groupItemOne, contentWindow, function() { - is(groupItemOne.getChildren().length, 2, "Group one has 2 tab items"); + is(groupItemOne.getChildren().length, 2, "Group one has 2 tab items"); - // create group two with a blank tab. - let groupItemTwo = createEmptyGroupItem(contentWindow, 250, 250, 40); - createNewTabItemInGroupItem(groupItemTwo, contentWindow, function() { - // start the first test. - testGroups(groupItemOne, groupItemTwo, contentWindow); - }); - }); -} - -function createNewTabItemInGroupItem(groupItem, contentWindow, callback) { - // click on the + button to create a blank tab in group item - let newTabButton = groupItem.container.getElementsByClassName("newTabButton"); - ok(newTabButton[0], "New tab button exists"); - - let onTabViewHidden = function() { - window.removeEventListener("tabviewhidden", onTabViewHidden, false); - - ok(!TabView.isVisible(), "Tab View is hidden because we just opened a tab"); - TabView.toggle(); - }; - let onTabViewShown = function() { - window.removeEventListener("tabviewshown", onTabViewShown, false); - - ok(TabView.isVisible(), "Tab View is visible"); - callback(); - }; - window.addEventListener("tabviewhidden", onTabViewHidden, false); - window.addEventListener("tabviewshown", onTabViewShown, false); - EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow); + let groupItemTwo = createGroupItemWithBlankTabs(window, 250, 250, 40, 1); + groupItemTwoId = groupItemTwo.id; + testGroups(groupItemOne, groupItemTwo, contentWindow); } function testGroups(groupItemOne, groupItemTwo, contentWindow) { @@ -70,15 +54,12 @@ function testGroups(groupItemOne, groupItemTwo, contentWindow) { is(contentWindow.UI.getActiveTab(), groupItemOne.getChild(0), "The first tab item in group one is active"); - let onTabViewHidden = function() { - window.removeEventListener("tabviewhidden", onTabViewHidden, false); + whenTabViewIsHidden(function() { is(groupItemOne.getChildren().length, 2, "The num of childen in group one is 2"); // clean up and finish - groupItemTwo.addSubscriber("close", function onClose() { - groupItemTwo.removeSubscriber("close", onClose); - + closeGroupItem(groupItemTwo, function() { gBrowser.removeTab(groupItemOne.getChild(1).tab); is(contentWindow.GroupItems.groupItems.length, 1, "Has only one group"); is(groupItemOne.getChildren().length, 1, @@ -87,10 +68,7 @@ function testGroups(groupItemOne, groupItemTwo, contentWindow) { finish(); }); - gBrowser.removeTab(groupItemTwo.getChild(0).tab); - groupItemTwo.close(); - } - window.addEventListener("tabviewhidden", onTabViewHidden, false); + }); EventUtils.synthesizeKey("t", { accelKey: true }); }); // close a tab item in group one diff --git a/browser/base/content/test/tabview/browser_tabview_bug590606.js b/browser/base/content/test/tabview/browser_tabview_bug590606.js index 23688023762e..31990b107fb7 100644 --- a/browser/base/content/test/tabview/browser_tabview_bug590606.js +++ b/browser/base/content/test/tabview/browser_tabview_bug590606.js @@ -3,6 +3,7 @@ let originalTab; let newTabOne; +let groupItemTwoId; function test() { waitForExplicitFinish(); @@ -11,10 +12,20 @@ function test() { // add a tab to the existing group. newTabOne = gBrowser.addTab(); - let onTabviewShown = function() { - window.removeEventListener("tabviewshown", onTabviewShown, false); + registerCleanupFunction(function() { + while (gBrowser.tabs[1]) + gBrowser.removeTab(gBrowser.tabs[1]); + hideTabView(function() {}); + }); - let contentWindow = document.getElementById("tab-view").contentWindow; + showTabView(function() { + let contentWindow = TabView.getContentWindow(); + + registerCleanupFunction(function() { + let groupItem = contentWindow.GroupItems.groupItem(groupItemTwoId); + if (groupItem) + closeGroupItem(groupItem, function() {}); + }); is(contentWindow.GroupItems.groupItems.length, 1, "There is one group item on startup"); @@ -25,22 +36,13 @@ function test() { "The currently selected tab should be the first tab in the groupItemOne"); // create another group with a tab. - let groupItemTwo = createEmptyGroupItem(contentWindow, 300, 300, 200); - - let onTabViewHidden = function() { - window.removeEventListener("tabviewhidden", onTabViewHidden, false); + let groupItemTwo = createGroupItemWithBlankTabs(window, 300, 300, 200, 1); + groupItemTwoId = groupItemTwoId; + hideTabView(function() { // start the test testGroupSwitch(contentWindow, groupItemOne, groupItemTwo); - }; - window.addEventListener("tabviewhidden", onTabViewHidden, false); - - // click on the + button - let newTabButton = groupItemTwo.container.getElementsByClassName("newTabButton"); - ok(newTabButton[0], "New tab button exists"); - EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow); - }; - window.addEventListener("tabviewshown", onTabviewShown, false); - TabView.toggle(); + }); + }); } function testGroupSwitch(contentWindow, groupItemOne, groupItemTwo) { diff --git a/browser/base/content/test/tabview/browser_tabview_bug595560.js b/browser/base/content/test/tabview/browser_tabview_bug595560.js index 5ebeeff1723c..cc6aab2312a0 100644 --- a/browser/base/content/test/tabview/browser_tabview_bug595560.js +++ b/browser/base/content/test/tabview/browser_tabview_bug595560.js @@ -23,75 +23,49 @@ function test() { } function testOne() { - whenSearchEnabledAndDisabled(testTwo); + hideSearchWhenSearchEnabled(testTwo); // press cmd/ctrl F EventUtils.synthesizeKey("f", {accelKey: true}, cw); } function testTwo() { - whenSearchEnabledAndDisabled(testThree); + hideSearchWhenSearchEnabled(testThree); // press / EventUtils.synthesizeKey("VK_SLASH", {}, cw); } function testThree() { - let onTabViewShown = function () { - is(cw.UI.getActiveTab(), groupItem.getChild(0), - "The active tab is newly created tab item"); + ok(win.TabView.isVisible(), "Tab View is visible"); + // create another group with a tab. + let groupItem = createGroupItemWithBlankTabs(win, 300, 300, 200, 1); + is(cw.UI.getActiveTab(), groupItem.getChild(0), + "The active tab is newly created tab item"); - let onSearchEnabled = function () { - let doc = cw.document; - let searchBox = cw.iQ("#searchbox"); - let hasFocus = doc.hasFocus() && doc.activeElement == searchBox[0]; - ok(hasFocus, "The search box has focus"); + whenSearchIsEnabled(function () { + let doc = cw.document; + let searchBox = cw.iQ("#searchbox"); + let hasFocus = doc.hasFocus() && doc.activeElement == searchBox[0]; + ok(hasFocus, "The search box has focus"); - let tab = win.gBrowser.tabs[1]; - searchBox.val(tab._tabViewTabItem.$tabTitle[0].innerHTML); + let tab = win.gBrowser.tabs[1]; + searchBox.val(tab._tabViewTabItem.$tabTitle[0].innerHTML); - cw.performSearch(); + cw.performSearch(); - whenTabViewIsHidden(function () { - is(tab, win.gBrowser.selectedTab, "The search result tab is shown"); - waitForFocus(finish); - }, win); + whenTabViewIsHidden(function () { + is(tab, win.gBrowser.selectedTab, "The search result tab is shown"); + finish() + }, win); - // use the tabview menu (the same as pressing cmd/ctrl + e) - win.document.getElementById("menu_tabview").doCommand(); - }; - - whenSearchEnabled(onSearchEnabled); - EventUtils.synthesizeKey("VK_SLASH", {}, cw); - }; - - whenTabViewIsHidden(function () { - showTabView(onTabViewShown, win); + // use the tabview menu (the same as pressing cmd/ctrl + e) + win.document.getElementById("menu_tabview").doCommand(); }, win); - - // click on the + button - let groupItem = createEmptyGroupItem(cw, 300, 300, 200); - let newTabButton = groupItem.container.getElementsByClassName("newTabButton"); - ok(newTabButton[0], "New tab button exists"); - - EventUtils.sendMouseEvent({type: "click"}, newTabButton[0], cw); + EventUtils.synthesizeKey("VK_SLASH", {}, cw); } -function whenSearchEnabledAndDisabled(callback) { - whenSearchEnabled(function () { - whenSearchDisabled(callback); - cw.hideSearch(); - }); +function hideSearchWhenSearchEnabled(callback) { + whenSearchIsEnabled(function() { + hideSearch(callback, win); + }, win); } -function whenSearchEnabled(callback) { - cw.addEventListener("tabviewsearchenabled", function onSearchEnabled() { - cw.removeEventListener("tabviewsearchenabled", onSearchEnabled, false); - callback(); - }, false); -} - -function whenSearchDisabled(callback) { - cw.addEventListener("tabviewsearchdisabled", function onSearchDisabled() { - cw.removeEventListener("tabviewsearchdisabled", onSearchDisabled, false); - callback(); - }, false); -} diff --git a/browser/base/content/test/tabview/browser_tabview_bug597980.js b/browser/base/content/test/tabview/browser_tabview_bug597980.js index 079003933e83..7a828c9b5f9c 100644 --- a/browser/base/content/test/tabview/browser_tabview_bug597980.js +++ b/browser/base/content/test/tabview/browser_tabview_bug597980.js @@ -71,12 +71,12 @@ function part2(win) { // switch the selected tab to new tab win.gBrowser.selectedTab = newTab; - win.addEventListener("tabviewhidden", function () { - win.removeEventListener("tabviewhidden", arguments.callee, false); + whenTabViewIsHidden(function () { is(win.gBrowser.selectedTab, newTab, "The seleted tab should be the same as before (new tab)"); win.close(); finish(); - }, false); + }); + // show tabview EventUtils.synthesizeKey("e", { accelKey: true, shiftKey: true }, win); // hide tabview diff --git a/browser/base/content/test/tabview/browser_tabview_bug598600.js b/browser/base/content/test/tabview/browser_tabview_bug598600.js index 3bd903be922c..36bec81d3e51 100644 --- a/browser/base/content/test/tabview/browser_tabview_bug598600.js +++ b/browser/base/content/test/tabview/browser_tabview_bug598600.js @@ -9,8 +9,8 @@ function test() { // open a new window and setup the window state. newWin = openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no"); - newWin.addEventListener("load", function(event) { - this.removeEventListener("load", arguments.callee, false); + newWin.addEventListener("load", function onLoad(event) { + this.removeEventListener("load", onLoad, false); let newState = { windows: [{ diff --git a/browser/base/content/test/tabview/browser_tabview_bug599626.js b/browser/base/content/test/tabview/browser_tabview_bug599626.js index 231e4973e24d..8699fcf94545 100644 --- a/browser/base/content/test/tabview/browser_tabview_bug599626.js +++ b/browser/base/content/test/tabview/browser_tabview_bug599626.js @@ -1,41 +1,26 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ -let handleDialog; -let timer; // keep in outer scope so it's not GC'd before firing +const TEST_URL = 'data:text/html,'; function test() { waitForExplicitFinish(); - - window.addEventListener("tabviewshown", onTabViewWindowLoaded, false); - TabView.toggle(); + showTabView(onTabViewShown); } -function onTabViewWindowLoaded() { - window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false); - - let contentWindow = document.getElementById("tab-view").contentWindow; +function onTabViewShown() { + let contentWindow = TabView.getContentWindow(); let groupItemOne = contentWindow.GroupItems.getActiveGroupItem(); + let groupItemTwo = createGroupItemWithTabs(window, 300, 300, 10, [TEST_URL]); - // Create a group and make it active - let box = new contentWindow.Rect(10, 10, 300, 300); - let groupItemTwo = new contentWindow.GroupItem([], { bounds: box }); - contentWindow.UI.setActive(groupItemTwo); - - let testTab = - gBrowser.addTab( - "http://mochi.test:8888/browser/browser/base/content/test/tabview/test_bug599626.html"); - let browser = gBrowser.getBrowserForTab(testTab); - let onLoad = function() { - browser.removeEventListener("load", onLoad, true); - + afterAllTabsLoaded(function () { testStayOnPage(contentWindow, groupItemOne, groupItemTwo); - } - browser.addEventListener("load", onLoad, true); + }); } function testStayOnPage(contentWindow, groupItemOne, groupItemTwo) { - setupAndRun(contentWindow, groupItemOne, groupItemTwo, function(doc) { + whenDialogOpened(function (dialog) { groupItemTwo.addSubscriber("groupShown", function onShown() { groupItemTwo.removeSubscriber("groupShown", onShown); @@ -44,22 +29,21 @@ function testStayOnPage(contentWindow, groupItemOne, groupItemTwo) { is(contentWindow.TabItems.getItems().length, 2, "The total number of tab items is 2 when staying on the page"); - let onTabViewShown = function() { - window.removeEventListener("tabviewshown", onTabViewShown, false); - + showTabView(function () { // start the next test testLeavePage(contentWindow, groupItemOne, groupItemTwo); - }; - window.addEventListener("tabviewshown", onTabViewShown, false); - TabView.toggle(); + }); }); + // stay on page - doc.documentElement.getButton("cancel").click(); + dialog.cancelDialog(); }); + + closeGroupItem(groupItemTwo); } function testLeavePage(contentWindow, groupItemOne, groupItemTwo) { - setupAndRun(contentWindow, groupItemOne, groupItemTwo, function(doc) { + whenDialogOpened(function (dialog) { // clean up and finish the test groupItemTwo.addSubscriber("close", function onClose() { groupItemTwo.removeSubscriber("close", onClose); @@ -69,93 +53,35 @@ function testLeavePage(contentWindow, groupItemOne, groupItemTwo) { is(contentWindow.TabItems.getItems().length, 1, "The total number of tab items is 1 after leaving the page"); - let endGame = function() { - window.removeEventListener("tabviewhidden", endGame, false); - finish(); - }; - window.addEventListener("tabviewhidden", endGame, false); + hideTabView(finish); }); // Leave page - doc.documentElement.getButton("accept").click(); + dialog.acceptDialog(); }); + + closeGroupItem(groupItemTwo); } -function setupAndRun(contentWindow, groupItemOne, groupItemTwo, callback) { - let closeButton = groupItemTwo.container.getElementsByClassName("close"); - ok(closeButton[0], "Group close button exists"); - // click the close button - EventUtils.sendMouseEvent({ type: "click" }, closeButton[0], contentWindow); +// ---------- +function whenDialogOpened(callback) { + let listener = { + onCloseWindow: function () {}, + onWindowTitleChange: function () {}, - let onTabViewHidden = function() { - window.removeEventListener("tabviewhidden", onTabViewHidden, false); + onOpenWindow: function (xulWin) { + let domWin = xulWin.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow); - handleDialog = function(doc) { - callback(doc); - }; - startCallbackTimer(); + whenWindowLoaded(domWin, function () { + let dialog = domWin.document.querySelector("dialog"); + if (dialog) { + Services.wm.removeListener(listener); + callback(dialog); + } + }); + } }; - window.addEventListener("tabviewhidden", onTabViewHidden, false); - let tabItem = groupItemOne.getChild(0); - tabItem.zoomIn(); -} - -// Copied from http://mxr.mozilla.org/mozilla-central/source/toolkit/components/places/tests/mochitest/prompt_common.js -let observer = { - QueryInterface : function (iid) { - const interfaces = [Ci.nsIObserver, Ci.nsISupports, Ci.nsISupportsWeakReference]; - - if (!interfaces.some( function(v) { return iid.equals(v) } )) - throw Components.results.NS_ERROR_NO_INTERFACE; - return this; - }, - - observe : function (subject, topic, data) { - let doc = getDialogDoc(); - if (doc) - handleDialog(doc); - else - startCallbackTimer(); // try again in a bit - } -}; - -function startCallbackTimer() { - // Delay before the callback twiddles the prompt. - const dialogDelay = 10; - - // Use a timer to invoke a callback to twiddle the authentication dialog - timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer); - timer.init(observer, dialogDelay, Ci.nsITimer.TYPE_ONE_SHOT); -} - -function getDialogDoc() { - // Find the which contains notifyWindow, by looking - // through all the open windows and all the in each. - let wm = Cc["@mozilla.org/appshell/window-mediator;1"]. - getService(Ci.nsIWindowMediator); - let enumerator = wm.getXULWindowEnumerator(null); - - while (enumerator.hasMoreElements()) { - let win = enumerator.getNext(); - let windowDocShell = win.QueryInterface(Ci.nsIXULWindow).docShell; - - let containedDocShells = windowDocShell.getDocShellEnumerator( - Ci.nsIDocShellTreeItem.typeChrome, - Ci.nsIDocShell.ENUMERATE_FORWARDS); - while (containedDocShells.hasMoreElements()) { - // Get the corresponding document for this docshell - let childDocShell = containedDocShells.getNext(); - // We don't want it if it's not done loading. - if (childDocShell.busyFlags != Ci.nsIDocShell.BUSY_FLAGS_NONE) - continue; - let childDoc = childDocShell.QueryInterface(Ci.nsIDocShell). - contentViewer.DOMDocument; - - if (childDoc.location.href == "chrome://global/content/commonDialog.xul") - return childDoc; - } - } - - return null; + Services.wm.addListener(listener); } diff --git a/browser/base/content/test/tabview/browser_tabview_bug618828.js b/browser/base/content/test/tabview/browser_tabview_bug618828.js index c04291067641..d1aaf0949fb1 100644 --- a/browser/base/content/test/tabview/browser_tabview_bug618828.js +++ b/browser/base/content/test/tabview/browser_tabview_bug618828.js @@ -55,8 +55,8 @@ function onTabViewWindowLoaded(win, tab) { contentWindow.performSearch(); // prepare to finish when the main window gets focus back - window.addEventListener('focus', function () { - window.removeEventListener('focus', arguments.callee, true); + window.addEventListener('focus', function onFocus() { + window.removeEventListener('focus', onFocus, true); assertSearchIsDisabled(); // check that the right tab is active diff --git a/browser/base/content/test/tabview/browser_tabview_bug622835.js b/browser/base/content/test/tabview/browser_tabview_bug622835.js index 5d2dd0f27eb6..b01047d48eba 100644 --- a/browser/base/content/test/tabview/browser_tabview_bug622835.js +++ b/browser/base/content/test/tabview/browser_tabview_bug622835.js @@ -11,12 +11,10 @@ function onTabViewShown(win) { let contentWindow = win.TabView.getContentWindow(); let finishTest = function () { - win.addEventListener('tabviewhidden', function () { - win.removeEventListener('tabviewhidden', arguments.callee, false); + hideTabView(function () { win.close(); finish(); - }, false); - win.TabView.hide(); + }, win); } // do not let the group arrange itself diff --git a/browser/base/content/test/tabview/browser_tabview_bug630157.js b/browser/base/content/test/tabview/browser_tabview_bug630157.js index 924f387bcbea..40308abde1b8 100644 --- a/browser/base/content/test/tabview/browser_tabview_bug630157.js +++ b/browser/base/content/test/tabview/browser_tabview_bug630157.js @@ -65,11 +65,6 @@ function test() { simulateDoubleClick(container, 2); assertNumberOfTabs(1); - // simulate double click with left mouse button - let container = groupItem.container; - simulateDoubleClick(container); - assertNumberOfTabs(1); - groupItem.close(); hideTabView(finishTest); } diff --git a/browser/base/content/test/tabview/browser_tabview_click_group.js b/browser/base/content/test/tabview/browser_tabview_click_group.js new file mode 100644 index 000000000000..d58e323f44d9 --- /dev/null +++ b/browser/base/content/test/tabview/browser_tabview_click_group.js @@ -0,0 +1,68 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +let contentWindow; +let groupItem; +let groupItemId; + +function test() { + waitForExplicitFinish(); + + registerCleanupFunction(function() { + contentWindow.gPrefBranch.clearUserPref("animate_zoom"); + let createdGroupItem = contentWindow.GroupItems.groupItem(groupItemId) + if (createdGroupItem) + closeGroupItem(createdGroupItem, function() {}); + hideTabView(function() {}); + }); + + showTabView(function() { + contentWindow = TabView.getContentWindow(); + groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200); + groupItemId = groupItem.id; + testMouseClickOnEmptyGroupItem(); + }); +} + +function testMouseClickOnEmptyGroupItem() { + whenTabViewIsHidden(function() { + is(groupItem.getChildren().length, 1, "The group item contains one tab item now"); + showTabView(testDraggingWithinGroupItem); + }); + is(groupItem.getChildren().length, 0, "The group item doesn't contain any tab items"); + EventUtils.sendMouseEvent({ type: "mousedown" }, groupItem.container, contentWindow); + EventUtils.sendMouseEvent({ type: "mouseup" }, groupItem.container, contentWindow); +} + +function testDraggingWithinGroupItem() { + let target = groupItem.container; + contentWindow.gPrefBranch.setBoolPref("animate_zoom", false); + + // stimulate drag and drop + EventUtils.sendMouseEvent( {type: "mousedown" }, target, contentWindow); + EventUtils.synthesizeMouse(target, 10, 10, { type: "mousemove" }, contentWindow); + ok(groupItem.isDragging, "The group item is being dragged") + + EventUtils.sendMouseEvent({ type: "mouseup" }, target, contentWindow); + ok(!groupItem.isDragging, "The dragging is competely"); + + executeSoon(function() { + ok(TabView.isVisible(), "The tab view is still visible after dragging"); + contentWindow.gPrefBranch.clearUserPref("animate_zoom"); + + testMouseClickOnGroupItem(); + }); +} + +function testMouseClickOnGroupItem() { + whenTabViewIsHidden(function() { + is(groupItem.getChildren().length, 1, "The group item still contains one tab item"); + + closeGroupItem(groupItem, function() { + hideTabView(finish); + }); + }); + EventUtils.sendMouseEvent({ type: "mousedown" }, groupItem.container, contentWindow); + EventUtils.sendMouseEvent({ type: "mouseup" }, groupItem.container, contentWindow); +} + diff --git a/browser/base/content/test/tabview/browser_tabview_group.js b/browser/base/content/test/tabview/browser_tabview_group.js index e499e7e0caf8..236ee99b7a60 100644 --- a/browser/base/content/test/tabview/browser_tabview_group.js +++ b/browser/base/content/test/tabview/browser_tabview_group.js @@ -4,18 +4,16 @@ function test() { waitForExplicitFinish(); - window.addEventListener("tabviewshown", onTabViewWindowLoaded, false); - TabView.toggle(); + showTabView(onTabViewWindowLoaded); } let originalGroupItem = null; let originalTab = null; function onTabViewWindowLoaded() { - window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false); ok(TabView.isVisible(), "Tab View is visible"); - let contentWindow = document.getElementById("tab-view").contentWindow; + let contentWindow = TabView.getContentWindow(); is(contentWindow.GroupItems.groupItems.length, 1, "There is one group item on startup"); originalGroupItem = contentWindow.GroupItems.groupItems[0]; @@ -58,19 +56,7 @@ function testGroupItemWithTabItem(contentWindow) { let groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200); let tabItemCount = 0; - let onTabViewHidden = function() { - window.removeEventListener("tabviewhidden", onTabViewHidden, false); - - is(groupItem.getChildren().length, ++tabItemCount, - "The number of children in new tab group is increased by 1"); - - ok(!TabView.isVisible(), "Tab View is hidden because we just opened a tab"); - - TabView.toggle(); - }; let onTabViewShown = function() { - window.removeEventListener("tabviewshown", onTabViewShown, false); - let tabItem = groupItem.getChild(groupItem.getChildren().length - 1); ok(tabItem, "Tab item exists"); @@ -85,19 +71,12 @@ function testGroupItemWithTabItem(contentWindow) { ok(tabItemClosed, "The tab item is closed"); is(groupItem.getChildren().length, --tabItemCount, "The number of children in new tab group is decreased by 1"); - + ok(TabView.isVisible(), "Tab View is still shown"); // Now there should only be one tab left, so we need to hide TabView // and go into that tab. is(gBrowser.tabs.length, 1, "There is only one tab left"); - - let endGame = function() { - window.removeEventListener("tabviewhidden", endGame, false); - ok(!TabView.isVisible(), "Tab View is hidden"); - finish(); - }; - window.addEventListener("tabviewhidden", endGame, false); // after the last selected tabitem is closed, there would be not active // tabitem on the UI so we set the active tabitem before toggling the @@ -106,7 +85,11 @@ function testGroupItemWithTabItem(contentWindow) { ok(tabItems[0], "A tab item exists"); contentWindow.UI.setActive(tabItems[0]); - TabView.toggle(); + hideTabView(function() { + ok(!TabView.isVisible(), "Tab View is hidden"); + + closeGroupItem(groupItem, finish); + }); }); // remove the tab item. The code detects mousedown and mouseup so we stimulate here @@ -115,15 +98,14 @@ function testGroupItemWithTabItem(contentWindow) { EventUtils.sendMouseEvent({ type: "mousedown" }, closeButton[0], contentWindow); EventUtils.sendMouseEvent({ type: "mouseup" }, closeButton[0], contentWindow); - - TabView.toggle(); }; - window.addEventListener("tabviewhidden", onTabViewHidden, false); - window.addEventListener("tabviewshown", onTabViewShown, false); - - // click on the + button - let newTabButton = groupItem.container.getElementsByClassName("newTabButton"); - ok(newTabButton[0], "New tab button exists"); - EventUtils.synthesizeMouse(newTabButton[0], 1, 1, {}, contentWindow); + whenTabViewIsHidden(function() { + is(groupItem.getChildren().length, ++tabItemCount, + "The number of children in new tab group is increased by 1"); + + ok(!TabView.isVisible(), "Tab View is hidden because we just opened a tab"); + showTabView(onTabViewShown); + }); + groupItem.newTab(); } diff --git a/browser/base/content/test/tabview/browser_tabview_multiwindow_search.js b/browser/base/content/test/tabview/browser_tabview_multiwindow_search.js index e4a41a747f3e..74e7ba4eea5e 100644 --- a/browser/base/content/test/tabview/browser_tabview_multiwindow_search.js +++ b/browser/base/content/test/tabview/browser_tabview_multiwindow_search.js @@ -8,16 +8,14 @@ function test() { let windowOne = openDialog(location, "", "chrome,all,dialog=no", "data:text/html,"); let windowTwo; - windowOne.addEventListener("load", function() { - windowOne.removeEventListener("load", arguments.callee, false); - windowOne.gBrowser.selectedBrowser.addEventListener("load", function() { - windowOne.gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true); + whenWindowLoaded(windowOne, function () { + windowOne.gBrowser.selectedBrowser.addEventListener("load", function onLoad() { + windowOne.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true); windowTwo = openDialog(location, "", "chrome,all,dialog=no", "http://mochi.test:8888/"); - windowTwo.addEventListener("load", function() { - windowTwo.removeEventListener("load", arguments.callee, false); - windowTwo.gBrowser.selectedBrowser.addEventListener("load", function() { - windowTwo.gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true); + whenWindowLoaded(windowTwo, function () { + windowTwo.gBrowser.selectedBrowser.addEventListener("load", function onLoad() { + windowTwo.gBrowser.selectedBrowser.removeEventListener("load", onLoad, true); newWindows = [ windowOne, windowTwo ]; @@ -26,9 +24,9 @@ function test() { ok(!TabView.isVisible(), "Tab View is hidden"); TabView.toggle(); }, true); - }, false); + }); }, true); - }, false); + }); } function onTabViewWindowLoaded() { diff --git a/browser/base/content/test/tabview/browser_tabview_startup_transitions.js b/browser/base/content/test/tabview/browser_tabview_startup_transitions.js index 7bfd34fc0421..a57e29466892 100644 --- a/browser/base/content/test/tabview/browser_tabview_startup_transitions.js +++ b/browser/base/content/test/tabview/browser_tabview_startup_transitions.js @@ -31,21 +31,26 @@ function test() { let transitioned = 0; let initCallback = function() { - tabViewWindow = win.TabView._window; + tabViewWindow = win.TabView.getContentWindow(); function onTransitionEnd(event) { transitioned++; info(transitioned); } tabViewWindow.document.addEventListener("transitionend", onTransitionEnd, false); - showTabView(function() { + // don't use showTabView() here because we only want to check whether + // zoom out animation happens. Other animations would happen before + // the callback as waitForFocus() was added to showTabView() in head.js + let onTabViewShown = function() { + tabViewWindow.removeEventListener("tabviewshown", onTabViewShown, false); + tabViewWindow.document.removeEventListener("transitionend", onTransitionEnd, false); + ok(!transitioned, "There should be no transitions"); - tabViewWindow.document.removeEventListener( - "transitionend", onTransitionEnd, false); - finish(); - }, win); + }; + tabViewWindow.addEventListener("tabviewshown", onTabViewShown, false); + win.TabView.toggle(); }; win.TabView._initFrame(initCallback); diff --git a/browser/base/content/test/tabview/browser_tabview_undo_group.js b/browser/base/content/test/tabview/browser_tabview_undo_group.js index d1dafaf12fe6..35c6e0d43904 100644 --- a/browser/base/content/test/tabview/browser_tabview_undo_group.js +++ b/browser/base/content/test/tabview/browser_tabview_undo_group.js @@ -4,45 +4,33 @@ function test() { waitForExplicitFinish(); - window.addEventListener("tabviewshown", onTabViewWindowLoaded, false); - TabView.toggle(); + registerCleanupFunction(function() { + while (gBrowser.tabs[1]) + gBrowser.removeTab(gBrowser.tabs[1]); + hideTabView(function() {}); + }); + showTabView(onTabViewWindowLoaded); } function onTabViewWindowLoaded() { - window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false); ok(TabView.isVisible(), "Tab View is visible"); - let contentWindow = document.getElementById("tab-view").contentWindow; + let contentWindow = TabView.getContentWindow(); + + registerCleanupFunction(function() { + let groupItem = contentWindow.GroupItems.groupItem(groupItemId); + if (groupItem) + closeGroupItem(groupItem, function() {}); + }); // create a group item - let box = new contentWindow.Rect(20, 400, 300, 300); - let groupItem = new contentWindow.GroupItem([], { bounds: box }); - - // create a tab item in the new group - let onTabViewHidden = function() { - window.removeEventListener("tabviewhidden", onTabViewHidden, false); - - ok(!TabView.isVisible(), "Tab View is hidden because we just opened a tab"); - // show tab view - TabView.toggle(); - }; - let onTabViewShown = function() { - window.removeEventListener("tabviewshown", onTabViewShown, false); - - is(groupItem.getChildren().length, 1, "The new group has a tab item"); - // start the tests - waitForFocus(function() { - testUndoGroup(contentWindow, groupItem); - }, contentWindow); - }; - window.addEventListener("tabviewhidden", onTabViewHidden, false); - window.addEventListener("tabviewshown", onTabViewShown, false); - - // click on the + button - let newTabButton = groupItem.container.getElementsByClassName("newTabButton"); - ok(newTabButton[0], "New tab button exists"); - - EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow); + let groupItem = createGroupItemWithBlankTabs(window, 300, 300, 400, 1); + groupItemId = groupItem.id; + is(groupItem.getChildren().length, 1, "The new group has a tab item"); + // start the tests + waitForFocus(function() { + testUndoGroup(contentWindow, groupItem); + }, contentWindow); } function testUndoGroup(contentWindow, groupItem) { @@ -113,13 +101,6 @@ function testCloseUndoGroup(contentWindow, groupItem) { let theGroupItem = contentWindow.GroupItems.groupItem(groupItem.id); ok(!theGroupItem, "The group item doesn't exists"); - let endGame = function() { - window.removeEventListener("tabviewhidden", endGame, false); - ok(!TabView.isVisible(), "Tab View is hidden"); - finish(); - }; - window.addEventListener("tabviewhidden", endGame, false); - // after the last selected tabitem is closed, there would be not active // tabitem on the UI so we set the active tabitem before toggling the // visibility of tabview @@ -127,7 +108,10 @@ function testCloseUndoGroup(contentWindow, groupItem) { ok(tabItems[0], "A tab item exists"); contentWindow.UI.setActive(tabItems[0]); - TabView.toggle(); + hideTabView(function() { + ok(!TabView.isVisible(), "Tab View is hidden"); + finish(); + }); }); let closeButton = groupItem.container.getElementsByClassName("close"); diff --git a/browser/base/content/test/tabview/head.js b/browser/base/content/test/tabview/head.js index 187f5ff13fb1..7629e8e6b050 100644 --- a/browser/base/content/test/tabview/head.js +++ b/browser/base/content/test/tabview/head.js @@ -32,6 +32,9 @@ function createGroupItemWithTabs(win, width, height, padding, urls, animate) { ok(newItem.container, "Created element "+t+":"+newItem.container); ++t; }); + // to set one of tabItem to be active since we load tabs into a group + // in a non-standard flow. + contentWindow.UI.setActive(groupItem); return groupItem; } @@ -133,11 +136,13 @@ function showTabView(callback, win) { win = win || window; if (win.TabView.isVisible()) { - callback(); + waitForFocus(callback, win); return; } - whenTabViewIsShown(callback, win); + whenTabViewIsShown(function() { + waitForFocus(callback, win); + }, win); win.TabView.show(); } @@ -163,8 +168,8 @@ function whenTabViewIsHidden(callback, win) { return; } - win.addEventListener('tabviewhidden', function () { - win.removeEventListener('tabviewhidden', arguments.callee, false); + win.addEventListener('tabviewhidden', function onHidden() { + win.removeEventListener('tabviewhidden', onHidden, false); callback(); }, false); } @@ -178,8 +183,8 @@ function whenTabViewIsShown(callback, win) { return; } - win.addEventListener('tabviewshown', function () { - win.removeEventListener('tabviewshown', arguments.callee, false); + win.addEventListener('tabviewshown', function onShown() { + win.removeEventListener('tabviewshown', onShown, false); callback(); }, false); } diff --git a/browser/base/content/test/tabview/test_bug599626.html b/browser/base/content/test/tabview/test_bug599626.html deleted file mode 100644 index 590276e6aada..000000000000 --- a/browser/base/content/test/tabview/test_bug599626.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - Test page - - diff --git a/browser/base/content/test/test_wyciwyg_copying.html b/browser/base/content/test/test_wyciwyg_copying.html new file mode 100644 index 000000000000..3a8c3a150804 --- /dev/null +++ b/browser/base/content/test/test_wyciwyg_copying.html @@ -0,0 +1,13 @@ + + + + + + diff --git a/browser/base/content/urlbarBindings.xml b/browser/base/content/urlbarBindings.xml index ca4134e519ef..2278e5f7b5c6 100644 --- a/browser/base/content/urlbarBindings.xml +++ b/browser/base/content/urlbarBindings.xml @@ -327,6 +327,11 @@ gBrowser.loadURIWithFlags(url, flags, null, null, postData); } + // Focus the content area before triggering loads, since if the load + // occurs in a new tab, we want focus to be restored to the content + // area when the current tab is re-selected. + gBrowser.selectedBrowser.focus(); + if (aTriggeringEvent instanceof MouseEvent) { // We have a mouse event (from the go button), so use the standard // UI link behaviors @@ -335,18 +340,12 @@ loadCurrent(); } else { this.handleRevert(); - content.focus(); openUILinkIn(url, where, { allowThirdPartyFixup: true, postData: postData }); } - return; - } - - if (aTriggeringEvent && - aTriggeringEvent.altKey && - !isTabEmpty(gBrowser.selectedTab)) { + } else if (aTriggeringEvent && aTriggeringEvent.altKey && + !isTabEmpty(gBrowser.selectedTab)) { this.handleRevert(); - content.focus(); gBrowser.loadOneTab(url, { postData: postData, inBackground: false, @@ -356,8 +355,6 @@ } else { loadCurrent(); } - - gBrowser.selectedBrowser.focus(); ]]> @@ -513,6 +510,10 @@ return selectedVal; let uri = gBrowser.currentURI; + // Only copy exposable URIs + try { + uri = Cc["@mozilla.org/docshell/urifixup;1"].getService(Ci.nsIURIFixup).createExposableURI(uri); + } catch (ex) {} // If the entire URL is selected, just use the actual loaded URI. if (inputVal == selectedVal) { diff --git a/browser/components/sessionstore/src/nsSessionStore.js b/browser/components/sessionstore/src/nsSessionStore.js index cddf1115570b..7b958a175713 100644 --- a/browser/components/sessionstore/src/nsSessionStore.js +++ b/browser/components/sessionstore/src/nsSessionStore.js @@ -128,6 +128,8 @@ const TAB_EVENTS = ["TabOpen", "TabClose", "TabSelect", "TabShow", "TabHide", Cu.import("resource://gre/modules/XPCOMUtils.jsm"); Cu.import("resource://gre/modules/Services.jsm"); +// debug.js adds NS_ASSERT. cf. bug 669196 +Cu.import("resource://gre/modules/debug.js"); XPCOMUtils.defineLazyGetter(this, "NetUtil", function() { Cu.import("resource://gre/modules/NetUtil.jsm"); @@ -1669,10 +1671,31 @@ SessionStoreService.prototype = { tabData.index = history.index + 1; } else if (history && history.count > 0) { - for (var j = 0; j < history.count; j++) { - let entry = this._serializeHistoryEntry(history.getEntryAtIndex(j, false), - aFullData, aTab.pinned); - tabData.entries.push(entry); + try { + for (var j = 0; j < history.count; j++) { + let entry = this._serializeHistoryEntry(history.getEntryAtIndex(j, false), + aFullData, aTab.pinned); + tabData.entries.push(entry); + } + // If we make it through the for loop, then we're ok and we should clear + // any indicator of brokenness. + delete aTab.__SS_broken_history; + } + catch (ex) { + // In some cases, getEntryAtIndex will throw. This seems to be due to + // history.count being higher than it should be. By doing this in a + // try-catch, we'll update history to where it breaks, assert for + // non-release builds, and still save sessionstore.js. We'll track if + // we've shown the assert for this tab so we only show it once. + // cf. bug 669196. + if (!aTab.__SS_broken_history) { + // First Focus the window & tab we're having trouble with. + aTab.ownerDocument.defaultView.focus(); + aTab.ownerDocument.defaultView.gBrowser.selectedTab = aTab; + NS_ASSERT(false, "SessionStore failed gathering complete history " + + "for the focused window/tab. See bug 669196."); + aTab.__SS_broken_history = true; + } } tabData.index = history.index + 1; diff --git a/browser/installer/removed-files.in b/browser/installer/removed-files.in index 6d75dea38498..2fdba68e707b 100644 --- a/browser/installer/removed-files.in +++ b/browser/installer/removed-files.in @@ -992,7 +992,6 @@ xpicleanup@BIN_SUFFIX@ modules/services-sync/type_records/prefs.js modules/services-sync/type_records/tabs.js modules/services-sync/util.js - modules/SpatialNavigation.js modules/stylePanel.jsm modules/tabview/AllTabs.jsm modules/tabview/groups.jsm diff --git a/browser/locales/en-US/chrome/browser/tabview.properties b/browser/locales/en-US/chrome/browser/tabview.properties index 534872ac8495..7097a36731e3 100644 --- a/browser/locales/en-US/chrome/browser/tabview.properties +++ b/browser/locales/en-US/chrome/browser/tabview.properties @@ -1,4 +1,3 @@ -tabview.groupItem.newTabButton=New tab tabview.groupItem.defaultName=Name this tab group… tabview.groupItem.undoCloseGroup=Undo Close Group tabview.search.otherWindowTabs=Tabs from other windows diff --git a/browser/themes/gnomestripe/browser/browser.css b/browser/themes/gnomestripe/browser/browser.css index 59a4d9435011..4f349d3af2ff 100644 --- a/browser/themes/gnomestripe/browser/browser.css +++ b/browser/themes/gnomestripe/browser/browser.css @@ -1959,3 +1959,8 @@ panel[dimmed="true"] { outline: 1px dashed rgba(255,255,255,0.5); outline-offset: -1px; } + +#highlighter-veil-transparentbox[locked] { + box-shadow: 0 0 0 1px black; + outline-color: white; +} diff --git a/browser/themes/gnomestripe/browser/jar.mn b/browser/themes/gnomestripe/browser/jar.mn index 0471acd9cbcb..0a4c56793da0 100644 --- a/browser/themes/gnomestripe/browser/jar.mn +++ b/browser/themes/gnomestripe/browser/jar.mn @@ -79,7 +79,6 @@ browser.jar: skin/classic/browser/tabbrowser/tab-overflow-border.png (tabbrowser/tab-overflow-border.png) skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png) skin/classic/browser/tabview/edit-light.png (tabview/edit-light.png) - skin/classic/browser/tabview/new-tab.png (tabview/new-tab.png) skin/classic/browser/tabview/search.png (tabview/search.png) skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png) skin/classic/browser/tabview/tabview.png (tabview/tabview.png) diff --git a/browser/themes/gnomestripe/browser/tabview/new-tab.png b/browser/themes/gnomestripe/browser/tabview/new-tab.png deleted file mode 100644 index b7150d63e751..000000000000 Binary files a/browser/themes/gnomestripe/browser/tabview/new-tab.png and /dev/null differ diff --git a/browser/themes/gnomestripe/browser/tabview/tabview.css b/browser/themes/gnomestripe/browser/tabview/tabview.css index f7272a03f493..2a2a1acd7c9a 100644 --- a/browser/themes/gnomestripe/browser/tabview/tabview.css +++ b/browser/themes/gnomestripe/browser/tabview/tabview.css @@ -190,7 +190,7 @@ html[dir=rtl] .stack-trayed .tab-title { ----------------------------------*/ .groupItem { - cursor: move; + cursor: pointer; border: 1px solid rgba(230,230,230,1); background-color: window; background-image: -moz-linear-gradient(rgba(255,255,255,.3),rgba(255,255,255,.1)); @@ -385,25 +385,6 @@ html[dir=rtl] .guideTrench { /* Other ----------------------------------*/ -.newTabButton { - width: 16px; - height: 15px; - bottom: 10px; - left: 10px; - cursor: pointer; - opacity: .3; - background-image: url(chrome://browser/skin/tabview/new-tab.png); -} - -html[dir=rtl] .newTabButton { - left: auto; - right: 10px; -} - -.newTabButton:hover { - opacity: 1; -} - .active { box-shadow: 5px 5px 3px rgba(0,0,0,.5); } @@ -421,6 +402,7 @@ html[dir=rtl] .acceptsDrop { } .titlebar { + cursor: move; font-size: 12px; height: 18px; } diff --git a/browser/themes/pinstripe/browser/browser.css b/browser/themes/pinstripe/browser/browser.css index 4d4639c03b56..bb88ba8c47d3 100644 --- a/browser/themes/pinstripe/browser/browser.css +++ b/browser/themes/pinstripe/browser/browser.css @@ -2533,3 +2533,8 @@ panel[dimmed="true"] { outline: 1px dashed rgba(255,255,255,0.5); outline-offset: -1px; } + +#highlighter-veil-transparentbox[locked] { + box-shadow: 0 0 0 1px black; + outline-color: white; +} diff --git a/browser/themes/pinstripe/browser/jar.mn b/browser/themes/pinstripe/browser/jar.mn index 223cab38e93f..6db3556f25db 100644 --- a/browser/themes/pinstripe/browser/jar.mn +++ b/browser/themes/pinstripe/browser/jar.mn @@ -117,7 +117,6 @@ browser.jar: skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png) skin/classic/browser/tabview/close.png (tabview/close.png) skin/classic/browser/tabview/edit-light.png (tabview/edit-light.png) - skin/classic/browser/tabview/new-tab.png (tabview/new-tab.png) skin/classic/browser/tabview/search.png (tabview/search.png) skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png) skin/classic/browser/tabview/tabview.png (tabview/tabview.png) diff --git a/browser/themes/pinstripe/browser/tabview/new-tab.png b/browser/themes/pinstripe/browser/tabview/new-tab.png deleted file mode 100644 index b7150d63e751..000000000000 Binary files a/browser/themes/pinstripe/browser/tabview/new-tab.png and /dev/null differ diff --git a/browser/themes/pinstripe/browser/tabview/tabview.css b/browser/themes/pinstripe/browser/tabview/tabview.css index d5b939b3aace..76cdb2df2784 100644 --- a/browser/themes/pinstripe/browser/tabview/tabview.css +++ b/browser/themes/pinstripe/browser/tabview/tabview.css @@ -191,7 +191,7 @@ html[dir=rtl] .stack-trayed .tab-title { ----------------------------------*/ .groupItem { - cursor: move; + cursor: pointer; background-color: rgb(240,240,240); border-radius: 0.4em; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.6); @@ -376,25 +376,6 @@ html[dir=rtl] .guideTrench { /* Other ----------------------------------*/ -.newTabButton { - width: 16px; - height: 15px; - bottom: 10px; - left: 10px; - cursor: pointer; - opacity: .3; - background-image: url(chrome://browser/skin/tabview/new-tab.png); -} - -html[dir=rtl] .newTabButton { - left: auto; - right: 10px; -} - -.newTabButton:hover { - opacity: 1; -} - .active { box-shadow: 5px 5px 3px rgba(0,0,0,.5); } @@ -412,6 +393,7 @@ html[dir=rtl] .acceptsDrop { } .titlebar { + cursor: move; font-size: 12px; height: 18px; } diff --git a/browser/themes/winstripe/browser/Toolbar-inverted.png b/browser/themes/winstripe/browser/Toolbar-inverted.png new file mode 100644 index 000000000000..5c5881d51490 Binary files /dev/null and b/browser/themes/winstripe/browser/Toolbar-inverted.png differ diff --git a/browser/themes/winstripe/browser/browser-aero.css b/browser/themes/winstripe/browser/browser-aero.css index 864bdb39cb88..9f2a76370506 100644 --- a/browser/themes/winstripe/browser/browser-aero.css +++ b/browser/themes/winstripe/browser/browser-aero.css @@ -13,9 +13,9 @@ #appmenu-button { border-width: 2px; - -moz-border-left-colors: rgba(255,255,255,.5) rgba(83,42,6,.9); - -moz-border-bottom-colors: rgba(255,255,255,.5) rgba(83,42,6,.9); - -moz-border-right-colors: rgba(255,255,255,.5) rgba(83,42,6,.9); + -moz-border-left-colors: @appMenuButtonBorderColor@; + -moz-border-bottom-colors: @appMenuButtonBorderColor@; + -moz-border-right-colors: @appMenuButtonBorderColor@; margin-bottom: 1px; /* compensate white outer border */ box-shadow: 0 1px 0 rgba(255,255,255,.25) inset, 0 0 2px 1px rgba(255,255,255,.25) inset; @@ -138,6 +138,13 @@ border-right-style: none !important; } + #toolbar-menubar :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon:not(:-moz-lwtheme), + #TabsToolbar[tabsontop=true] :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon:not(:-moz-lwtheme), + #navigator-toolbox[tabsontop=false] > #nav-bar :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon:not(:-moz-lwtheme), + #nav-bar + #customToolbars + #PersonalToolbar[collapsed=true] + #TabsToolbar[tabsontop=false]:last-child :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon:not(:-moz-lwtheme) { + list-style-image: url("chrome://browser/skin/Toolbar-inverted.png"); + } + /* Vertical toolbar border */ #main-window[sizemode=normal] #navigator-toolbox::after, #main-window[sizemode=normal] #navigator-toolbox[tabsontop=true] > toolbar:not(#toolbar-menubar):not(#TabsToolbar), diff --git a/browser/themes/winstripe/browser/browser.css b/browser/themes/winstripe/browser/browser.css index a06051af263b..4abc6ca0e77b 100644 --- a/browser/themes/winstripe/browser/browser.css +++ b/browser/themes/winstripe/browser/browser.css @@ -57,6 +57,17 @@ %define bgTabTexture -moz-linear-gradient(transparent, hsla(0,0%,45%,.1) 1px, hsla(0,0%,32%,.2) 80%, hsla(0,0%,0%,.2)) %define bgTabTextureHover -moz-linear-gradient(hsla(0,0%,100%,.3) 1px, hsla(0,0%,75%,.2) 80%, hsla(0,0%,60%,.2)) %define navbarTextboxCustomBorder border-color: rgba(0,0,0,.32); +%define navbarLargeIcons #navigator-toolbox[iconsize=large][mode=icons] > #nav-bar + +%ifdef MOZ_OFFICIAL_BRANDING +%define appMenuButtonBorderColor rgba(255,255,255,.5) rgba(83,42,6,.9) +%else +%if MOZ_UPDATE_CHANNEL == aurora +%define appMenuButtonBorderColor hsla(0,0%,100%,.5) hsla(214,89%,21%,.9) +%else +%define appMenuButtonBorderColor hsla(0,0%,100%,.5) hsla(210,59%,13%,.9) +%endif +%endif #menubar-items { -moz-box-orient: vertical; /* for flex hack */ @@ -133,13 +144,10 @@ #appmenu-button { -moz-appearance: none; - background: -moz-linear-gradient(rgb(247,182,82), rgb(215,98,10) 95%); background-clip: padding-box; border-radius: 0 0 4px 4px; - border: 1px solid rgba(83,42,6,.9); + border: 1px solid; border-top: none; - box-shadow: 0 1px 0 rgba(255,255,255,.25) inset, - 0 0 0 1px rgba(255,255,255,.25) inset; color: white; text-shadow: 0 0 1px rgba(0,0,0,.7), 0 1px 1.5px rgba(0,0,0,.5); @@ -162,20 +170,85 @@ } %endif -#main-window[privatebrowsingmode=temporary] #appmenu-button { - background-image: -moz-linear-gradient(rgb(153,38,211), rgb(105,19,163) 95%); - border-color: rgba(43,8,65,.9); +#appmenu-button:hover:active, +#appmenu-button[open] { + border-radius: 0; } +%ifdef MOZ_OFFICIAL_BRANDING +#appmenu-button { + background-image: -moz-linear-gradient(rgb(247,182,82), rgb(215,98,10) 95%); + border-color: rgba(83,42,6,.9); + box-shadow: 0 1px 0 rgba(255,255,255,.25) inset, + 0 0 0 1px rgba(255,255,255,.25) inset; +} #appmenu-button:hover:not(:active):not([open]) { background-image: -moz-radial-gradient(center bottom, farthest-side, rgba(252,240,89,.5) 10%, rgba(252,240,89,0) 70%), -moz-radial-gradient(center bottom, farthest-side, rgb(236,133,0), rgba(255,229,172,0)), -moz-linear-gradient(rgb(246,170,69), rgb(209,74,0) 95%); border-color: rgba(83,42,6,.9); box-shadow: 0 1px 0 rgba(255,255,255,.1) inset, - 0 0 1.5px 1px rgba(250,234,169,.7) inset, + 0 0 2px 1px rgba(250,234,169,.7) inset, 0 -1px 0 rgba(250,234,169,.5) inset; } +#appmenu-button:hover:active, +#appmenu-button[open] { + background-image: -moz-linear-gradient(rgb(246,170,69), rgb(209,74,0) 95%); + box-shadow: 0 2px 3px rgba(0,0,0,.4) inset, + 0 1px 1px rgba(0,0,0,.2) inset; +} +%else +%if MOZ_UPDATE_CHANNEL == aurora +#appmenu-button { + background-image: -moz-linear-gradient(hsl(208,99%,37%), hsl(214,90%,23%) 95%); + border-color: hsla(214,89%,21%,.9); + box-shadow: 0 1px 0 hsla(205,100%,72%,.2) inset, + 0 0 2px 1px hsla(205,100%,72%,.25) inset; +} +#appmenu-button:hover:not(:active):not([open]) { + background-image: -moz-radial-gradient(center bottom, farthest-side, hsla(202,100%,85%,.5) 10%, hsla(202,100%,85%,0) 70%), + -moz-radial-gradient(center bottom, farthest-side, hsla(205,100%,72%,.7), hsla(205,100%,72%,0)), + -moz-linear-gradient(hsl(208,98%,34%), hsl(213,87%,20%) 95%); + border-color: hsla(214,89%,21%,.9); + box-shadow: 0 1px 0 hsla(205,100%,72%,.15) inset, + 0 0 2px 1px hsla(205,100%,72%,.5) inset, + 0 -1px 0 hsla(205,100%,72%,.2) inset; +} +#appmenu-button:hover:active, +#appmenu-button[open] { + background-image: -moz-linear-gradient(hsl(208,95%,30%), hsl(214,85%,17%) 95%); + box-shadow: 0 2px 3px rgba(0,0,0,.4) inset, + 0 1px 1px rgba(0,0,0,.2) inset; +} +%else +#appmenu-button { + background-image: -moz-linear-gradient(hsl(211,33%,32%), hsl(209,53%,10%) 95%); + border-color: hsla(210,59%,13%,.9); + box-shadow: 0 1px 0 hsla(210,48%,90%,.15) inset, + 0 0 2px 1px hsla(211,65%,85%,.15) inset; +} +#appmenu-button:hover:not(:active):not([open]) { + background-image: -moz-radial-gradient(center bottom, farthest-side, hsla(210,48%,90%,.5) 10%, hsla(210,48%,90%,0) 70%), + -moz-radial-gradient(center bottom, farthest-side, hsla(211,70%,83%,.5), hsla(211,70%,83%,0)), + -moz-linear-gradient(hsl(211,33%,32%), hsl(209,53%,10%) 95%); + border-color: hsla(210,59%,13%,.9); + box-shadow: 0 1px 0 hsla(210,48%,90%,.15) inset, + 0 0 2px 1px hsla(210,48%,90%,.4) inset, + 0 -1px 0 hsla(210,48%,90%,.2) inset; +} +#appmenu-button:hover:active, +#appmenu-button[open] { + background-image: -moz-linear-gradient(hsl(211,33%,26%), hsl(209,53%,6%) 95%); + box-shadow: 0 2px 3px rgba(0,0,0,.4) inset, + 0 1px 1px rgba(0,0,0,.2) inset; +} +%endif +%endif + +#main-window[privatebrowsingmode=temporary] #appmenu-button { + background-image: -moz-linear-gradient(rgb(153,38,211), rgb(105,19,163) 95%); + border-color: rgba(43,8,65,.9); +} #main-window[privatebrowsingmode=temporary] #appmenu-button:hover:not(:active):not([open]) { background-image: -moz-radial-gradient(center bottom, farthest-side, rgba(240,193,255,.5) 10%, rgba(240,193,255,0) 70%), @@ -187,14 +260,6 @@ 0 -1px 0 rgba(240,193,255,.5) inset; } -#appmenu-button:hover:active, -#appmenu-button[open] { - background-image: -moz-linear-gradient(rgb(246,170,69), rgb(209,74,0) 95%); - border-radius: 0; - box-shadow: 0 2px 3px rgba(0,0,0,.4) inset, - 0 1px 1px rgba(0,0,0,.2) inset; -} - #main-window[privatebrowsingmode=temporary] #appmenu-button:hover:active, #main-window[privatebrowsingmode=temporary] #appmenu-button[open] { background-image: -moz-linear-gradient(rgb(144,20,207), rgb(95,0,158) 95%); @@ -582,6 +647,10 @@ menuitem.bookmark-item { list-style-image: url("chrome://browser/skin/Toolbar.png"); } +.toolbarbutton-1:-moz-lwtheme-brighttext { + list-style-image: url("chrome://browser/skin/Toolbar-inverted.png"); +} + .toolbarbutton-1:not([type="menu-button"]) { -moz-box-orient: vertical; } @@ -596,19 +665,18 @@ menuitem.bookmark-item { counter-reset: smallicons; } -#navigator-toolbox[iconsize=small] > #nav-bar { - padding-top: 1px; - padding-bottom: 1px; -} - -#navigator-toolbox[iconsize=large][mode=icons] > #nav-bar { +@navbarLargeIcons@ { -moz-padding-start: 0; -moz-padding-end: 2px; } -#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button, -#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker, -#nav-bar .toolbarbutton-1 { +@navbarLargeIcons@ :-moz-any(@primaryToolbarButtons@):not(#alltabs-button):not(#tabview-button):not(#new-tab-button) > .toolbarbutton-icon { + list-style-image: url("chrome://browser/skin/Toolbar.png") !important; +} + +@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button, +@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker, +@navbarLargeIcons@ .toolbarbutton-1 { -moz-appearance: none; padding: 1px 5px; background: rgba(151,152,153,.05) @@ -624,14 +692,12 @@ menuitem.bookmark-item { text-shadow: 0 0 2px white; } -#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker, -#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button, -#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar .toolbarbutton-1 { +@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker { padding-left: 3px; padding-right: 3px; } -#nav-bar .toolbarbutton-1[type="menu-button"] { +@navbarLargeIcons@ .toolbarbutton-1[type="menu-button"] { -moz-appearance: none; padding: 0; background: none !important; @@ -639,44 +705,39 @@ menuitem.bookmark-item { box-shadow: none !important; } -#nav-bar .toolbarbutton-1 { +@navbarLargeIcons@ .toolbarbutton-1 { margin: 1px 3px; } -#navigator-toolbox[iconsize="small"][mode="icons"] > #nav-bar .toolbarbutton-1 { - margin-left: 2px; - margin-right: 2px; -} - -#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker { +@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker { -moz-border-start-style: none; } -#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(ltr), -#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(rtl) { +@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(ltr), +@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(rtl) { border-top-right-radius: 0; border-bottom-right-radius: 0; } -#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(rtl), -#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(ltr) { +@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:-moz-locale-dir(rtl), +@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker:-moz-locale-dir(ltr) { border-top-left-radius: 0; border-bottom-left-radius: 0; } -#nav-bar .toolbarbutton-1[disabled="true"] { +@navbarLargeIcons@ .toolbarbutton-1[disabled="true"] { opacity: .4; } -#nav-bar .toolbarbutton-1[disabled="true"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon, -#nav-bar .toolbarbutton-1[disabled="true"] > .toolbarbutton-icon { +@navbarLargeIcons@ .toolbarbutton-1[disabled="true"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon, +@navbarLargeIcons@ .toolbarbutton-1[disabled="true"] > .toolbarbutton-icon { opacity: 1; } -#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):not(:active):hover, -#nav-bar .toolbarbutton-1:not([open="true"]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]), -#nav-bar .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):not([checked="true"]):not([open="true"]):not(:active):hover, -#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not([disabled="true"]):not([open]):not(:active):hover > .toolbarbutton-icon { +@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):not(:active):hover, +@navbarLargeIcons@ .toolbarbutton-1:not([open="true"]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]), +@navbarLargeIcons@ .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):not([checked="true"]):not([open="true"]):not(:active):hover, +@navbarLargeIcons@ #back-button:not([disabled="true"]):not([open]):not(:active):hover > .toolbarbutton-icon { background-color: hsla(190,60%,70%,.5); border-color: hsla(190,50%,65%,.8) hsla(190,50%,50%,.8) hsla(190,50%,40%,.8); box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset, @@ -687,12 +748,12 @@ menuitem.bookmark-item { box-shadow .3s ease-in; } -#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):hover:active, -#nav-bar .toolbarbutton-1:hover:active > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]), -#nav-bar .toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker, -#nav-bar .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):hover:active, -#nav-bar .toolbarbutton-1:not([type="menu-button"])[checked="true"], -#nav-bar .toolbarbutton-1[open="true"] { +@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button:not([disabled="true"]):hover:active, +@navbarLargeIcons@ .toolbarbutton-1:hover:active > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]), +@navbarLargeIcons@ .toolbarbutton-1[open="true"] > .toolbarbutton-menubutton-dropmarker, +@navbarLargeIcons@ .toolbarbutton-1:not([type="menu-button"]):not([disabled="true"]):hover:active, +@navbarLargeIcons@ .toolbarbutton-1:not([type="menu-button"])[checked="true"], +@navbarLargeIcons@ .toolbarbutton-1[open="true"] { background-color: transparent; border-color: rgba(0,0,0,.65) rgba(0,0,0,.55) rgba(0,0,0,.5); box-shadow: 0 0 6.5px rgba(0,0,0,.4) inset, @@ -701,7 +762,7 @@ menuitem.bookmark-item { text-shadow: none; } -#nav-bar .toolbarbutton-1[checked="true"]:not(:active):hover { +@navbarLargeIcons@ .toolbarbutton-1[checked="true"]:not(:active):hover { background-color: rgba(90%,90%,90%,.4); -moz-transition: background-color .4s; } @@ -711,8 +772,8 @@ menuitem.bookmark-item { -moz-margin-end: 0; } -#nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon, -#nav-bar .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-icon { +@navbarLargeIcons@ .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon, +@navbarLargeIcons@ .toolbarbutton-1:not(:-moz-any(@primaryToolbarButtons@)) > .toolbarbutton-icon { margin: 1px; } @@ -764,37 +825,31 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button { -moz-image-region: rect(0, 36px, 18px, 18px); } -#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button { - -moz-image-region: rect(18px, 20px, 38px, 0); -} - #back-button:-moz-locale-dir(rtl) > .toolbarbutton-icon, #forward-button:-moz-locale-dir(rtl), #forward-button:-moz-locale-dir(rtl) > .toolbarbutton-text { -moz-transform: scaleX(-1); } -#nav-bar #back-button { - -moz-margin-end: 0 !important; -} - -#nav-bar #forward-button { +@navbarLargeIcons@ #forward-button { border-left-style: none; -moz-margin-start: 0 !important; } -#nav-bar #back-button:-moz-locale-dir(ltr) { +@navbarLargeIcons@ #back-button:-moz-locale-dir(ltr) { border-top-right-radius: 0; border-bottom-right-radius: 0; } -#nav-bar #back-button:-moz-locale-dir(rtl), -#nav-bar #forward-button { +@navbarLargeIcons@ #back-button:-moz-locale-dir(rtl), +@navbarLargeIcons@ #forward-button { border-top-left-radius: 0; border-bottom-left-radius: 0; } -#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button { +@navbarLargeIcons@ #back-button { + -moz-image-region: rect(18px, 20px, 38px, 0); + -moz-margin-end: 0 !important; margin: -5px 0; padding-top: 0; padding-bottom: 0; @@ -808,11 +863,11 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button { box-shadow: none; } -#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:-moz-locale-dir(rtl) { +@navbarLargeIcons@ #back-button:-moz-locale-dir(rtl) { border-radius: 10000px 0 0 10000px; } -#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button > .toolbarbutton-icon { +@navbarLargeIcons@ #back-button > .toolbarbutton-icon { border-radius: 10000px; padding: 5px; border: none; @@ -825,7 +880,7 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button { 0 1px 1px rgba(0,0,0,.3); } -#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not([disabled="true"]):not([open="true"]):not(:active):hover > .toolbarbutton-icon { +@navbarLargeIcons@ #back-button:not([disabled="true"]):not([open="true"]):not(:active):hover > .toolbarbutton-icon { box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset, 0 0 0 2px rgba(255,255,255,.1) inset, 0 0 0 1px hsla(190,50%,40%,.3), @@ -834,16 +889,16 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button { 0 0 5px 1px hsl(190,90%,80%); } -#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button:not([disabled="true"]):hover:active > .toolbarbutton-icon, -#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #back-button[open="true"] > .toolbarbutton-icon { +@navbarLargeIcons@ #back-button:not([disabled="true"]):hover:active > .toolbarbutton-icon, +@navbarLargeIcons@ #back-button[open="true"] > .toolbarbutton-icon { box-shadow: 0 0 6.5px rgba(0,0,0,.4) inset, 0 0 2px rgba(0,0,0,.4) inset, 0 0 0 1px rgba(0,0,0,.65), 0 2px 0 rgba(255,255,255,.4); } -#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar[currentset*="unified-back-forward-button"], -#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar:not([currentset]) { +@navbarLargeIcons@[currentset*="unified-back-forward-button"], +@navbarLargeIcons@:not([currentset]) { padding-top: 3px; padding-bottom: 5px; } @@ -853,7 +908,7 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button { padding-top: 5px; } -#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button { +@navbarLargeIcons@ #forward-button { /*mask: url(keyhole-forward-mask.svg#mask); XXX: this regresses twinopen */ mask: url(chrome://browser/content/browser.xul#winstripe-keyhole-forward-mask); -moz-margin-start: -6px !important; @@ -861,7 +916,7 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button { padding-right: 3px; } -#navigator-toolbox[iconsize="large"][mode="icons"] > #nav-bar #forward-button:not([disabled="true"]):not(:active):hover { +@navbarLargeIcons@ #forward-button:not([disabled="true"]):not(:active):hover { /*mask: url(keyhole-forward-mask.svg#mask-hover);*/ mask: url(chrome://browser/content/browser.xul#winstripe-keyhole-forward-mask-hover); /* Don't animate the box shadow, as the blur and spread radii affect the mask. */ @@ -895,6 +950,9 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button { #home-button.bookmark-item { list-style-image: url("chrome://browser/skin/Toolbar.png"); } +#home-button.bookmark-item:-moz-lwtheme-brighttext { + list-style-image: url("chrome://browser/skin/Toolbar-inverted.png"); +} #home-button { -moz-image-region: rect(0, 90px, 18px, 72px); } @@ -969,6 +1027,10 @@ toolbar[mode="full"] .toolbarbutton-1 > .toolbarbutton-menubutton-button { list-style-image: url("chrome://browser/skin/Toolbar.png"); } +#bookmarks-menu-button.bookmark-item:-moz-lwtheme-brighttext { + list-style-image: url("chrome://browser/skin/Toolbar-inverted.png"); +} + #bookmarks-menu-button.toolbarbutton-1 { -moz-box-orient: horizontal; } @@ -2458,3 +2520,8 @@ panel[dimmed="true"] { outline: 1px dashed rgba(255,255,255,0.5); outline-offset: -1px; } + +#highlighter-veil-transparentbox[locked] { + box-shadow: 0 0 0 1px black; + outline-color: white; +} diff --git a/browser/themes/winstripe/browser/jar.mn b/browser/themes/winstripe/browser/jar.mn index 119fc0fa8fe3..b87d7fdceff2 100644 --- a/browser/themes/winstripe/browser/jar.mn +++ b/browser/themes/winstripe/browser/jar.mn @@ -35,6 +35,7 @@ browser.jar: skin/classic/browser/reload-stop-go.png skin/classic/browser/Secure24.png (Secure24.png) skin/classic/browser/Toolbar.png (Toolbar.png) + skin/classic/browser/Toolbar-inverted.png skin/classic/browser/Go-arrow.png (Go-arrow.png) * skin/classic/browser/searchbar.css (searchbar.css) skin/classic/browser/section_collapsed.png @@ -96,7 +97,6 @@ browser.jar: skin/classic/browser/tabview/close.png (tabview/close.png) skin/classic/browser/tabview/edit-light.png (tabview/edit-light.png) skin/classic/browser/tabview/grain.png (tabview/grain.png) - skin/classic/browser/tabview/new-tab.png (tabview/new-tab.png) skin/classic/browser/tabview/search.png (tabview/search.png) skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png) skin/classic/browser/tabview/tabview.png (tabview/tabview.png) @@ -149,6 +149,7 @@ browser.jar: skin/classic/aero/browser/reload-stop-go.png skin/classic/aero/browser/Secure24.png (Secure24-aero.png) skin/classic/aero/browser/Toolbar.png + skin/classic/aero/browser/Toolbar-inverted.png skin/classic/aero/browser/Go-arrow.png (Go-arrow-aero.png) * skin/classic/aero/browser/searchbar.css (searchbar.css) skin/classic/aero/browser/section_collapsed.png @@ -211,7 +212,6 @@ browser.jar: skin/classic/aero/browser/tabview/close.png (tabview/close.png) skin/classic/aero/browser/tabview/edit-light.png (tabview/edit-light.png) skin/classic/aero/browser/tabview/grain.png (tabview/grain.png) - skin/classic/aero/browser/tabview/new-tab.png (tabview/new-tab.png) skin/classic/aero/browser/tabview/search.png (tabview/search.png) skin/classic/aero/browser/tabview/stack-expander.png (tabview/stack-expander.png) skin/classic/aero/browser/tabview/tabview.png (tabview/tabview.png) diff --git a/browser/themes/winstripe/browser/tabview/new-tab.png b/browser/themes/winstripe/browser/tabview/new-tab.png deleted file mode 100644 index b7150d63e751..000000000000 Binary files a/browser/themes/winstripe/browser/tabview/new-tab.png and /dev/null differ diff --git a/browser/themes/winstripe/browser/tabview/tabview.css b/browser/themes/winstripe/browser/tabview/tabview.css index 712f971745a5..f0e436cf2bf4 100644 --- a/browser/themes/winstripe/browser/tabview/tabview.css +++ b/browser/themes/winstripe/browser/tabview/tabview.css @@ -204,7 +204,7 @@ html[dir=rtl] .tab.focus { ----------------------------------*/ .groupItem { - cursor: move; + cursor: pointer; background-color: #E0EAF5; border-radius: 0.4em; box-shadow: @@ -398,25 +398,6 @@ html[dir=rtl] .guideTrench { /* Other ----------------------------------*/ -.newTabButton { - width: 16px; - height: 15px; - bottom: 10px; - left: 10px; - cursor: pointer; - opacity: .3; - background-image: url(chrome://browser/skin/tabview/new-tab.png); -} - -html[dir=rtl] .newTabButton { - left: auto; - right: 10px; -} - -.newTabButton:hover { - opacity: 1; -} - .active { box-shadow: 5px 5px 3px rgba(0,0,0,.5); } @@ -434,6 +415,7 @@ html[dir=rtl] .acceptsDrop { } .titlebar { + cursor: move; font-size: 12px; height: 18px; } diff --git a/build/Makefile.in b/build/Makefile.in index dcb4bf4408e6..0c056e70e418 100644 --- a/build/Makefile.in +++ b/build/Makefile.in @@ -102,6 +102,7 @@ GARBAGE += leaktest.py libs:: $(_LEAKTEST_FILES) $(INSTALL) $^ $(_LEAKTEST_DIR) +ifdef MOZ_VALGRIND _VALGRIND_DIR = $(DEPTH)/_valgrind GARBAGE_DIRS += $(_VALGRIND_DIR) @@ -112,6 +113,7 @@ _VALGRIND_FILES = \ libs:: $(_VALGRIND_FILES) $(INSTALL) $^ $(_VALGRIND_DIR) +endif ifdef ENABLE_TESTS libs:: $(topsrcdir)/tools/rb/fix_stack_using_bpsyms.py diff --git a/build/autoconf/config.sub b/build/autoconf/config.sub index 3fad4d748241..1c035c931168 100755 --- a/build/autoconf/config.sub +++ b/build/autoconf/config.sub @@ -1433,7 +1433,7 @@ case $os in os=-dicos ;; -android*) - os=android + os=-android ;; -none) ;; diff --git a/build/mobile/devicemanagerADB.py b/build/mobile/devicemanagerADB.py index cedc0c93ae06..819bdec99172 100644 --- a/build/mobile/devicemanagerADB.py +++ b/build/mobile/devicemanagerADB.py @@ -96,6 +96,8 @@ class DeviceManagerADB(DeviceManager): # contains symbolic links, the links are pushed, rather than the linked # files; we push file-by-file to get around this limitation try: + if (not self.dirExists(remoteDir)): + self.mkDirs(remoteDir+"/x") for root, dirs, files in os.walk(localDir): relRoot = os.path.relpath(root, localDir) for file in files: diff --git a/build/pgo/profileserver.py b/build/pgo/profileserver.py index e098177740ad..2542f19ab488 100644 --- a/build/pgo/profileserver.py +++ b/build/pgo/profileserver.py @@ -64,24 +64,11 @@ if __name__ == '__main__': from optparse import OptionParser automation = Automation() - parser = OptionParser(usage='OBJDIR=path/to/objdir python %prog [NUM_RUNS]') + parser = OptionParser() addCommonOptions(parser) options, args = parser.parse_args() - if not os.getenv('OBJDIR'): - parser.error('Please specify the OBJDIR environment variable.') - - if not args: - num_runs = 1 - else: - try: - num_runs = int(args[0]) - except: - parser.error('NUM_RUNS argument must be an integer.') - if num_runs < 1: - parser.error('NUM_RUNS must be greater than zero.') - debuggerInfo = getDebuggerInfo(".", options.debugger, options.debuggerArgs, options.debuggerInteractive) @@ -91,21 +78,16 @@ if __name__ == '__main__': t.start() automation.setServerInfo("localhost", PORT) + automation.initializeProfile(PROFILE_DIRECTORY) browserEnv = automation.environment() browserEnv["XPCOM_DEBUG_BREAK"] = "warn" browserEnv["MOZ_JAR_LOG_DIR"] = MOZ_JAR_LOG_DIR url = "http://localhost:%d/index.html" % PORT appPath = os.path.join(SCRIPT_DIR, automation.DEFAULT_APP) - - for i in range(0, num_runs): - if num_runs != 1: - print "Starting profiling run %d of %d" % (i + 1, num_runs) - automation.initializeProfile(PROFILE_DIRECTORY) - status = automation.runApp(url, browserEnv, appPath, PROFILE_DIRECTORY, {}, - debuggerInfo=debuggerInfo, - # the profiling HTML doesn't output anything, - # so let's just run this without a timeout - timeout = None) - if status != 0: - sys.exit(status) + status = automation.runApp(url, browserEnv, appPath, PROFILE_DIRECTORY, {}, + debuggerInfo=debuggerInfo, + # the profiling HTML doesn't output anything, + # so let's just run this without a timeout + timeout = None) + sys.exit(status) diff --git a/build/pymake/pymake/command.py b/build/pymake/pymake/command.py index 439baf3e5702..ea66325cb13b 100644 --- a/build/pymake/pymake/command.py +++ b/build/pymake/pymake/command.py @@ -105,9 +105,13 @@ class _MakeContext(object): makeflags=self.makeflags, makeoverrides=self.overrides, workdir=self.workdir, - context=self.context, env=self.env, makelevel=self.makelevel, - targets=self.targets, keepgoing=self.options.keepgoing, - silent=self.options.silent) + context=self.context, + env=self.env, + makelevel=self.makelevel, + targets=self.targets, + keepgoing=self.options.keepgoing, + silent=self.options.silent, + justprint=self.options.justprint) self.restarts += 1 @@ -189,6 +193,9 @@ def main(args, env, cwd, cb): dest="printdir", default=True) op.add_option('-s', '--silent', action="store_true", dest="silent", default=False) + op.add_option('-n', '--just-print', '--dry-run', '--recon', + action="store_true", + dest="justprint", default=False) options, arguments1 = op.parse_args(parsemakeflags(env)) options, arguments2 = op.parse_args(args, values=options) @@ -215,6 +222,9 @@ def main(args, env, cwd, cb): shortflags.append('s') options.printdir = False + if options.justprint: + shortflags.append('n') + loglevel = logging.WARNING if options.verbose: loglevel = logging.DEBUG diff --git a/build/pymake/pymake/data.py b/build/pymake/pymake/data.py index c9bee448a97a..869c2e4e4962 100644 --- a/build/pymake/pymake/data.py +++ b/build/pymake/pymake/data.py @@ -1212,13 +1212,13 @@ def getcommandsforrule(rule, target, makefile, prerequisites, stem): cstring = c.resolvestr(makefile, v) for cline in splitcommand(cstring): cline, isHidden, isRecursive, ignoreErrors, isNative = findmodifiers(cline) - if isHidden or makefile.silent: + if (isHidden or makefile.silent) and not makefile.justprint: echo = None else: echo = "%s$ %s" % (c.loc, cline) if not isNative: yield _CommandWrapper(cline, ignoreErrors=ignoreErrors, env=env, cwd=makefile.workdir, loc=c.loc, context=makefile.context, - echo=echo) + echo=echo, justprint=makefile.justprint) else: f, s, e = v.get("PYCOMMANDPATH", True) if e: @@ -1226,7 +1226,8 @@ def getcommandsforrule(rule, target, makefile, prerequisites, stem): yield _NativeWrapper(cline, ignoreErrors=ignoreErrors, env=env, cwd=makefile.workdir, loc=c.loc, context=makefile.context, - echo=echo, pycommandpath=e) + echo=echo, justprint=makefile.justprint, + pycommandpath=e) class Rule(object): """ @@ -1372,7 +1373,7 @@ class Makefile(object): def __init__(self, workdir=None, env=None, restarts=0, make=None, makeflags='', makeoverrides='', makelevel=0, context=None, targets=(), keepgoing=False, - silent=False): + silent=False, justprint=False): self.defaulttarget = None if env is None: @@ -1387,6 +1388,7 @@ class Makefile(object): self._targets = {} self.keepgoing = keepgoing self.silent = silent + self.justprint = justprint self._patternvariables = [] # of (pattern, variables) self.implicitrules = [] self.parsingfinished = False diff --git a/build/pymake/pymake/implicit.py b/build/pymake/pymake/implicit.py index 85e9ee0914d6..d73895cab703 100644 --- a/build/pymake/pymake/implicit.py +++ b/build/pymake/pymake/implicit.py @@ -1,14 +1,14 @@ -""" -Implicit variables; perhaps in the future this will also include some implicit -rules, at least match-anything cancellation rules. -""" - -variables = { - 'MKDIR': '%pymake.builtins mkdir', - 'RM': '%pymake.builtins rm -f', - 'SLEEP': '%pymake.builtins sleep', - 'TOUCH': '%pymake.builtins touch', - '.LIBPATTERNS': 'lib%.so lib%.a', - '.PYMAKE': '1', - } - +""" +Implicit variables; perhaps in the future this will also include some implicit +rules, at least match-anything cancellation rules. +""" + +variables = { + 'MKDIR': '%pymake.builtins mkdir', + 'RM': '%pymake.builtins rm -f', + 'SLEEP': '%pymake.builtins sleep', + 'TOUCH': '%pymake.builtins touch', + '.LIBPATTERNS': 'lib%.so lib%.a', + '.PYMAKE': '1', + } + diff --git a/build/pymake/pymake/process.py b/build/pymake/pymake/process.py index 62a8b6be6d12..a7a29c81a074 100644 --- a/build/pymake/pymake/process.py +++ b/build/pymake/pymake/process.py @@ -14,18 +14,20 @@ if sys.platform=='win32': _log = logging.getLogger('pymake.process') -_blacklist = re.compile(r'[$><;*?[{~`|&]|\\\n') +_escapednewlines = re.compile(r'\\\n') +_blacklist = re.compile(r'[$><;*?[{~`|&]') def clinetoargv(cline): """ If this command line can safely skip the shell, return an argv array. @returns argv, badchar """ - m = _blacklist.search(cline) + str = _escapednewlines.sub('', cline) + m = _blacklist.search(str) if m is not None: return None, m.group(0) - args = shlex.split(cline, comments=True) + args = shlex.split(str, comments=True) if len(args) and args[0].find('=') != -1: return None, '=' @@ -40,7 +42,7 @@ shellwords = (':', '.', 'break', 'cd', 'continue', 'exec', 'exit', 'export', 'printf', 'read', 'shopt', 'source', 'type', 'typeset', 'ulimit', 'unalias', 'set') -def call(cline, env, cwd, loc, cb, context, echo): +def call(cline, env, cwd, loc, cb, context, echo, justprint=False): #TODO: call this once up-front somewhere and save the result? shell, msys = util.checkmsyscompat() @@ -60,7 +62,8 @@ def call(cline, env, cwd, loc, cb, context, echo): if len(cline) > 3 and cline[1] == ':' and cline[2] == '/': cline = '/' + cline[0] + cline[2:] cline = [shell, "-c", cline] - context.call(cline, shell=not msys, env=env, cwd=cwd, cb=cb, echo=echo) + context.call(cline, shell=not msys, env=env, cwd=cwd, cb=cb, echo=echo, + justprint=justprint) return if not len(argv): @@ -81,12 +84,13 @@ def call(cline, env, cwd, loc, cb, context, echo): else: executable = None - context.call(argv, executable=executable, shell=False, env=env, cwd=cwd, cb=cb, echo=echo) + context.call(argv, executable=executable, shell=False, env=env, cwd=cwd, cb=cb, + echo=echo, justprint=justprint) -def call_native(module, method, argv, env, cwd, loc, cb, context, echo, +def call_native(module, method, argv, env, cwd, loc, cb, context, echo, justprint=False, pycommandpath=None): context.call_native(module, method, argv, env=env, cwd=cwd, cb=cb, - echo=echo, pycommandpath=pycommandpath) + echo=echo, justprint=justprint, pycommandpath=pycommandpath) def statustoresult(status): """ @@ -242,36 +246,32 @@ class ParallelContext(object): assert self.jcount > 1 or not len(self.pending), "Serial execution error defering %r %r %r: currently pending %r" % (cb, args, kwargs, self.pending) self.pending.append((cb, args, kwargs)) - def _docall(self, argv, executable, shell, env, cwd, cb, echo): + def _docall_generic(self, pool, job, cb, echo, justprint): if echo is not None: print echo - job = PopenJob(argv, executable=executable, shell=shell, env=env, cwd=cwd) - self.threadpool.apply_async(job_runner, args=(job,), callback=job.get_callback(ParallelContext._condition)) + processcb = job.get_callback(ParallelContext._condition) + if justprint: + processcb(0) + else: + pool.apply_async(job_runner, args=(job,), callback=processcb) self.running.append((job, cb)) - def _docallnative(self, module, method, argv, env, cwd, cb, echo, - pycommandpath=None): - if echo is not None: - print echo - job = PythonJob(module, method, argv, env, cwd, pycommandpath) - self.processpool.apply_async(job_runner, args=(job,), callback=job.get_callback(ParallelContext._condition)) - self.running.append((job, cb)) - - def call(self, argv, shell, env, cwd, cb, echo, executable=None): + def call(self, argv, shell, env, cwd, cb, echo, justprint=False, executable=None): """ Asynchronously call the process """ - self.defer(self._docall, argv, executable, shell, env, cwd, cb, echo) + job = PopenJob(argv, executable=executable, shell=shell, env=env, cwd=cwd) + self.defer(self._docall_generic, self.threadpool, job, cb, echo, justprint) def call_native(self, module, method, argv, env, cwd, cb, - echo, pycommandpath=None): + echo, justprint=False, pycommandpath=None): """ Asynchronously call the native function """ - self.defer(self._docallnative, module, method, argv, env, cwd, cb, - echo, pycommandpath) + job = PythonJob(module, method, argv, env, cwd, pycommandpath) + self.defer(self._docall_generic, self.processpool, job, cb, echo, justprint) @staticmethod def _waitany(condition): diff --git a/build/pymake/tests/justprint-native.mk b/build/pymake/tests/justprint-native.mk new file mode 100644 index 000000000000..580e402e979b --- /dev/null +++ b/build/pymake/tests/justprint-native.mk @@ -0,0 +1,28 @@ +## $(TOUCH) and $(RM) are native commands in pymake. +## Test that pymake --just-print just prints them. + +ifndef TOUCH +TOUCH = touch +endif + +all: + $(RM) justprint-native-file1.txt + $(TOUCH) justprint-native-file2.txt + $(MAKE) --just-print -f $(TESTPATH)/justprint-native.mk justprint_target > justprint.log +# make --just-print shouldn't have actually done anything. + test ! -f justprint-native-file1.txt + test -f justprint-native-file2.txt +# but it should have printed each command + grep -q 'touch justprint-native-file1.txt' justprint.log + grep -q 'rm -f justprint-native-file2.txt' justprint.log + grep -q 'this string is "unlikely to appear in the log by chance"' justprint.log +# tidy up + $(RM) justprint-native-file2.txt + @echo TEST-PASS + +justprint_target: + $(TOUCH) justprint-native-file1.txt + $(RM) justprint-native-file2.txt + this string is "unlikely to appear in the log by chance" + +.PHONY: justprint_target diff --git a/build/pymake/tests/justprint.mk b/build/pymake/tests/justprint.mk new file mode 100644 index 000000000000..be11ba8deca9 --- /dev/null +++ b/build/pymake/tests/justprint.mk @@ -0,0 +1,5 @@ +#T commandline: ['-n'] + +all: + false # without -n, we wouldn't get past this + TEST-PASS # heh diff --git a/build/pymake/tests/mkdir-fail.mk b/build/pymake/tests/mkdir-fail.mk index 1772af0e81f6..b05734aa90ec 100644 --- a/build/pymake/tests/mkdir-fail.mk +++ b/build/pymake/tests/mkdir-fail.mk @@ -1,4 +1,4 @@ -#T returncode: 1 +#T returncode: 2 all: mkdir newdir/subdir test ! -d newdir/subdir diff --git a/build/pymake/tests/newlines.mk b/build/pymake/tests/newlines.mk new file mode 100644 index 000000000000..5d8195c9498c --- /dev/null +++ b/build/pymake/tests/newlines.mk @@ -0,0 +1,30 @@ +#T gmake skip + +# Test that we handle \\\n properly + +all: dep1 dep2 dep3 + cat testfile + test `cat testfile` = "data"; + test "$$(cat results)" = "$(EXPECTED)"; + @echo TEST-PASS + +# Test that something that still needs to go to the shell works +testfile: + printf "data" \ + >>$@ + +dep1: testfile + +# Test that something that does not need to go to the shell works +dep2: + $(echo foo) \ + $(echo bar) + +export EXPECTED := some data + +CMD = %pycmd writeenvtofile +PYCOMMANDPATH = $(TESTPATH) + +dep3: + $(CMD) \ + results EXPECTED diff --git a/build/pymake/tests/runtests.py b/build/pymake/tests/runtests.py index e6f71403a5ed..b3bb663ac543 100644 --- a/build/pymake/tests/runtests.py +++ b/build/pymake/tests/runtests.py @@ -78,12 +78,15 @@ def runTest(makefile, make, logfile, options): logfd.close() if stdout.find('TEST-FAIL') != -1: + print stdout return False, "FAIL (TEST-FAIL printed)" if options['grepfor'] and stdout.find(options['grepfor']) == -1: - return False, "FAIL (%s not in output)" % options['grepfor'] + print stdout + return False, "FAIL (%s not in output)" % options['grepfor'] if options['returncode'] == 0 and stdout.find('TEST-PASS') == -1: + print stdout return False, 'FAIL (No TEST-PASS printed)' if options['returncode'] != 0: @@ -123,6 +126,7 @@ for makefile in makefiles: mdata = open(makefile) for line in mdata: + line = line.strip() m = tre.search(line) if m is None: break diff --git a/build/pymake/tests/vpath2.mk b/build/pymake/tests/vpath2.mk new file mode 100644 index 000000000000..be73ffe5c08f --- /dev/null +++ b/build/pymake/tests/vpath2.mk @@ -0,0 +1,18 @@ +VPATH = foo bar + +$(shell \ +mkdir bar; touch bar/test.source; \ +sleep 2; \ +mkdir foo; touch foo/tfile1; \ +touch bar/tfile2 bar/tfile3 bar/test.objtest; \ +) + +all: tfile1 tfile2 tfile3 test.objtest test.source + test "$^" = "foo/tfile1 bar/tfile2 bar/tfile3 bar/test.objtest bar/test.source" + @echo TEST-PASS + +tfile3: test.objtest + +%.objtest: %.source + test "$<" = bar/test.source + test "$@" = test.objtest diff --git a/build/tests/test.py b/build/tests/test.py index 686954d93787..13c188f0678a 100755 --- a/build/tests/test.py +++ b/build/tests/test.py @@ -86,7 +86,11 @@ def main(args=sys.argv[1:]): parser.add_option('--report-first', dest='report_first', default=False, action='store_true', help="report the first error only (all tests will still run)") + parser.add_option('-q', '--quiet', dest='quiet', + default=False, action='store_true', + help="minimize output") options, args = parser.parse_args(args) + quiet = options.__dict__.pop('quiet') # run the tests results = run_tests(**options.__dict__) @@ -99,6 +103,12 @@ def main(args=sys.argv[1:]): break if failed: sys.exit(1) # error + if not quiet: + # print results + print "manifestparser.py: All tests pass!" + for test in sorted(results.keys()): + result = results[test] + print "%s: failed=%s, attempted=%s" % (test, result[0], result[1]) if __name__ == '__main__': main() diff --git a/build/unix/check_debug_ranges.py b/build/unix/check_debug_ranges.py new file mode 100644 index 000000000000..b63273a82815 --- /dev/null +++ b/build/unix/check_debug_ranges.py @@ -0,0 +1,93 @@ +# ***** BEGIN LICENSE BLOCK ***** +# Version: MPL 1.1/GPL 2.0/LGPL 2.1 +# +# The contents of this file are subject to the Mozilla Public License Version +# 1.1 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# http://www.mozilla.org/MPL/ +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +# for the specific language governing rights and limitations under the +# License. +# +# The Original Code is mozilla.org +# +# The Initial Developer of the Original Code is +# the Mozilla Foundation +# Portions created by the Initial Developer are Copyright (C) 2011 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mike Hommey +# +# Alternatively, the contents of this file may be used under the terms of +# either the GNU General Public License Version 2 or later (the "GPL"), or +# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), +# in which case the provisions of the GPL or the LGPL are applicable instead +# of those above. If you wish to allow use of your version of this file only +# under the terms of either the GPL or the LGPL, and not to allow others to +# use your version of this file under the terms of the MPL, indicate your +# decision by deleting the provisions above and replace them with the notice +# and other provisions required by the GPL or the LGPL. If you do not delete +# the provisions above, a recipient may use your version of this file under +# the terms of any one of the MPL, the GPL or the LGPL. +# +# ***** END LICENSE BLOCK ***** + +# This script returns the number of items for the DW_AT_ranges corresponding +# to a given compilation unit. This is used as a helper to find a bug in some +# versions of GNU ld. + +import subprocess +import sys +import re + +def get_range_for(compilation_unit, debug_info): + '''Returns the range offset for a given compilation unit + in a given debug_info.''' + name = ranges = '' + search_cu = False + for nfo in debug_info.splitlines(): + if 'DW_TAG_compile_unit' in nfo: + search_cu = True + elif 'DW_TAG_' in nfo or not nfo.strip(): + if name == compilation_unit: + return int(ranges, 0) + name = ranges = '' + search_cu = False + if search_cu: + if 'DW_AT_name' in nfo: + name = nfo.rsplit(None, 1)[1] + elif 'DW_AT_ranges' in nfo: + ranges = nfo.rsplit(None, 1)[1] + return None + +def get_range_length(range, debug_ranges): + '''Returns the number of items in the range starting at the + given offset.''' + length = 0 + for line in debug_ranges.splitlines(): + m = re.match('\s*([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+([0-9a-fA-F]+)', line) + if m and int(m.group(1), 0) == range: + length += 1 + return length + +def main(bin, compilation_unit): + p = subprocess.Popen(['objdump', '-W', bin], stdout = subprocess.PIPE, stderr = subprocess.PIPE) + (out, err) = p.communicate() + sections = re.split('\n(Contents of the|The section) ', out) + debug_info = [s for s in sections if s.startswith('.debug_info')] + debug_ranges = [s for s in sections if s.startswith('.debug_ranges')] + if not debug_ranges or not debug_info: + return 0 + + range = get_range_for(compilation_unit, debug_info[0]) + if range is not None: + return get_range_length(range, debug_ranges[0]) + + return -1 + + +if __name__ == '__main__': + print main(*sys.argv[1:]) diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index 3a7d903e212b..ca75bcf36691 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -91,7 +91,6 @@ #include "nsIURIFixup.h" #include "nsCDefaultURIFixup.h" #include "nsIChromeRegistry.h" -#include "nsPrintfCString.h" #include "nsIContentSecurityPolicy.h" #include "nsIAsyncVerifyRedirectCallback.h" #include "mozilla/Preferences.h" @@ -3325,41 +3324,6 @@ nsScriptSecurityManager::Observe(nsISupports* aObject, const char* aTopic, return rv; } -/////////////////////////////////// -// Default ObjectPrincipalFinder // -/////////////////////////////////// - -// The default JSSecurityCallbacks::findObjectPrincipals is necessary since -// scripts run (and ask for object principals) during startup before -// nsJSRuntime::Init() has been called (which resets findObjectPrincipals). - -// Defined NS_EXPORT for linkage with debug-only assert in xpcshell -NS_EXPORT JSPrincipals * -NS_DefaultObjectPrincipalFinder(JSContext *cx, JSObject *obj) -{ - nsScriptSecurityManager *ssm = nsScriptSecurityManager::GetScriptSecurityManager(); - if (!ssm) { - return nsnull; - } - - nsCOMPtr principal; - nsresult rv = ssm->GetObjectPrincipal(cx, obj, getter_AddRefs(principal)); - if (NS_FAILED(rv) || !principal) { - return nsnull; - } - - JSPrincipals *jsPrincipals = nsnull; - principal->GetJSPrincipals(cx, &jsPrincipals); - - // nsIPrincipal::GetJSPrincipals() returns a strong reference to the - // JS principals, but the caller of this function expects a weak - // reference. So we need to release here. - - JSPRINCIPALS_DROP(cx, jsPrincipals); - - return jsPrincipals; -} - ///////////////////////////////////////////// // Constructor, Destructor, Initialization // ///////////////////////////////////////////// @@ -3432,7 +3396,7 @@ nsresult nsScriptSecurityManager::Init() static JSSecurityCallbacks securityCallbacks = { CheckObjectAccess, NULL, - NS_DefaultObjectPrincipalFinder, + NULL, ContentSecurityPolicyPermitsJSAction }; diff --git a/caps/src/nsSystemPrincipal.cpp b/caps/src/nsSystemPrincipal.cpp index a77bdb26b9cd..e70bd55de689 100644 --- a/caps/src/nsSystemPrincipal.cpp +++ b/caps/src/nsSystemPrincipal.cpp @@ -86,6 +86,8 @@ nsSystemPrincipal::Release() // Methods implementing nsIPrincipal // /////////////////////////////////////// +#define SYSTEM_PRINCIPAL_SPEC "[System Principal]" + NS_IMETHODIMP nsSystemPrincipal::GetPreferences(char** aPrefName, char** aID, char** aSubjectName, @@ -195,7 +197,7 @@ nsSystemPrincipal::GetURI(nsIURI** aURI) NS_IMETHODIMP nsSystemPrincipal::GetOrigin(char** aOrigin) { - *aOrigin = ToNewCString(NS_LITERAL_CSTRING("[System Principal]")); + *aOrigin = ToNewCString(NS_LITERAL_CSTRING(SYSTEM_PRINCIPAL_SPEC)); return *aOrigin ? NS_OK : NS_ERROR_OUT_OF_MEMORY; } @@ -308,11 +310,6 @@ nsSystemPrincipal::nsSystemPrincipal() { } -// Don't rename the system principal! -// The JS engine (NewCompartment) relies on this name. -// XXX: bug 669123 will fix this hack. -#define SYSTEM_PRINCIPAL_SPEC "[System Principal]" - nsresult nsSystemPrincipal::Init(JSPrincipals **jsprin) { diff --git a/config/Makefile.in b/config/Makefile.in index 3aefcd92e3c6..ce1c424d35fb 100644 --- a/config/Makefile.in +++ b/config/Makefile.in @@ -56,9 +56,7 @@ else HOST_CSRCS = nsinstall.c pathsub.c endif -PLSRCS = nfspwd.pl - -TARGETS = $(HOST_PROGRAM) $(PLSRCS:.pl=) $(SIMPLE_PROGRAMS) +TARGETS = $(HOST_PROGRAM) $(SIMPLE_PROGRAMS) ifndef CROSS_COMPILE ifdef USE_ELF_DYNSTR_GC diff --git a/config/config.mk b/config/config.mk index a764a6d31bc8..37b1b47beb97 100644 --- a/config/config.mk +++ b/config/config.mk @@ -163,6 +163,13 @@ MKDIR ?= mkdir SLEEP ?= sleep TOUCH ?= touch +ifndef .PYMAKE +PYTHONPATH = $(PYTHON) $(topsrcdir)/config/pythonpath.py +else +PYCOMMANDPATH += $(topsrcdir)/config +PYTHONPATH = %pythonpath main +endif + # determine debug-related options _DEBUG_CFLAGS := _DEBUG_LDFLAGS := @@ -384,7 +391,6 @@ MY_RULES := $(DEPTH)/config/myrules.mk # Default command macros; can be overridden in .mk. # CCC = $(CXX) -NFSPWD = $(CONFIG_TOOLS)/nfspwd PURIFY = purify $(PURIFYOPTIONS) QUANTIFY = quantify $(QUANTIFYOPTIONS) ifdef CROSS_COMPILE @@ -677,27 +683,24 @@ endif # NSINSTALL_BIN ifeq (,$(CROSS_COMPILE)$(filter-out WINNT OS2, $(OS_ARCH))) INSTALL = $(NSINSTALL) else -ifeq ($(NSDISTMODE),copy) -# copy files, but preserve source mtime -INSTALL = $(NSINSTALL) -t -else -ifeq ($(NSDISTMODE),absolute_symlink) -# install using absolute symbolic links -ifeq ($(OS_ARCH),Darwin) -INSTALL = $(NSINSTALL) -L $(PWD) -else -INSTALL = $(NSINSTALL) -L `$(NFSPWD)` -endif # Darwin -else -# install using relative symbolic links -INSTALL = $(NSINSTALL) -R -endif # absolute_symlink -endif # copy + +# This isn't laid out as conditional directives so that NSDISTMODE can be +# target-specific. +INSTALL = $(if $(filter copy, $(NSDISTMODE)), $(NSINSTALL) -t, $(if $(filter absolute_symlink, $(NSDISTMODE)), $(NSINSTALL) -L $(PWD), $(NSINSTALL) -R)) + endif # WINNT/OS2 # Use nsinstall in copy mode to install files on the system SYSINSTALL = $(NSINSTALL) -t +# Directory nsinstall. Windows and OS/2 nsinstall can't recursively copy +# directories. +ifneq (,$(filter WINNT os2-emx,$(HOST_OS_ARCH))) +DIR_INSTALL = $(PYTHON) $(topsrcdir)/config/nsinstall.py +else +DIR_INSTALL = $(INSTALL) +endif # WINNT/OS2 + # # Localization build automation # diff --git a/config/fastcwd.pl b/config/fastcwd.pl deleted file mode 100644 index c327ccfdf2b1..000000000000 --- a/config/fastcwd.pl +++ /dev/null @@ -1,66 +0,0 @@ -#!perl5 -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -sub fastcwd { - local($odev, $oino, $cdev, $cino, $tdev, $tino); - local(@path, $path); - local(*DIR); - - ($cdev, $cino) = stat('.'); - for (;;) { - ($odev, $oino) = ($cdev, $cino); - chdir('..'); - ($cdev, $cino) = stat('.'); - last if $odev == $cdev && $oino == $cino; - opendir(DIR, '.'); - for (;;) { - $_ = readdir(DIR); - next if $_ eq '.'; - next if $_ eq '..'; - - last unless $_; - ($tdev, $tino) = lstat($_); - last unless $tdev != $odev || $tino != $oino; - } - closedir(DIR); - unshift(@path, $_); - } - chdir($path = '/' . join('/', @path)); - $path; -} -1; diff --git a/config/nfspwd.pl b/config/nfspwd.pl deleted file mode 100644 index 2f0e4fb80472..000000000000 --- a/config/nfspwd.pl +++ /dev/null @@ -1,50 +0,0 @@ -#! perl -# -# ***** BEGIN LICENSE BLOCK ***** -# Version: MPL 1.1/GPL 2.0/LGPL 2.1 -# -# The contents of this file are subject to the Mozilla Public License Version -# 1.1 (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# http://www.mozilla.org/MPL/ -# -# Software distributed under the License is distributed on an "AS IS" basis, -# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License -# for the specific language governing rights and limitations under the -# License. -# -# The Original Code is mozilla.org code. -# -# The Initial Developer of the Original Code is -# Netscape Communications Corporation. -# Portions created by the Initial Developer are Copyright (C) 1998 -# the Initial Developer. All Rights Reserved. -# -# Contributor(s): -# -# Alternatively, the contents of this file may be used under the terms of -# either of the GNU General Public License Version 2 or later (the "GPL"), -# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), -# in which case the provisions of the GPL or the LGPL are applicable instead -# of those above. If you wish to allow use of your version of this file only -# under the terms of either the GPL or the LGPL, and not to allow others to -# use your version of this file under the terms of the MPL, indicate your -# decision by deleting the provisions above and replace them with the notice -# and other provisions required by the GPL or the LGPL. If you do not delete -# the provisions above, a recipient may use your version of this file under -# the terms of any one of the MPL, the GPL or the LGPL. -# -# ***** END LICENSE BLOCK ***** - -require "fastcwd.pl"; - -$_ = &fastcwd; -if (m@^/[uh]/@o || s@^/tmp_mnt/@/@o) { - print("$_\n"); -} elsif ((($user, $rest) = m@^/usr/people/(\w+)/(.*)@o) - && readlink("/u/$user") eq "/usr/people/$user") { - print("/u/$user/$rest\n"); -} else { - chop($host = `hostname`); - print("/h/$host$_\n"); -} diff --git a/config/pythonpath.py b/config/pythonpath.py index 7785fb58e0e9..c96c9f8aa722 100644 --- a/config/pythonpath.py +++ b/config/pythonpath.py @@ -2,41 +2,51 @@ Run a python script, adding extra directories to the python path. """ -import sys, os -def usage(): - print >>sys.stderr, "pythonpath.py -I directory script.py [args...]" - sys.exit(150) +def main(args): + def usage(): + print >>sys.stderr, "pythonpath.py -I directory script.py [args...]" + sys.exit(150) -paths = [] + paths = [] -while True: - try: - arg = sys.argv[1] - except IndexError: - usage() - - if arg == '-I': - del sys.argv[1] + while True: try: - path = sys.argv.pop(1) + arg = args[0] except IndexError: usage() - paths.append(path) - continue + if arg == '-I': + args.pop(0) + try: + path = args.pop(0) + except IndexError: + usage() - if arg.startswith('-I'): - path = sys.argv.pop(1)[2:] - paths.append(path) - continue + paths.append(path) + continue - break + if arg.startswith('-I'): + paths.append(args.pop(0)[2:]) + continue -sys.argv.pop(0) -script = sys.argv[0] + break -sys.path[0:0] = [os.path.dirname(script)] + paths -__name__ = '__main__' -__file__ = script -execfile(script) + script = args[0] + + sys.path[0:0] = [os.path.dirname(script)] + paths + sys.argv = args + sys.argc = len(args) + + frozenglobals['__name__'] = '__main__' + frozenglobals['__file__'] = script + + execfile(script, frozenglobals) + +# Freeze scope here ... why this makes things work I have no idea ... +frozenglobals = globals() + +import sys, os + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/config/rules.mk b/config/rules.mk index 638d32b8765c..5199098aaa46 100644 --- a/config/rules.mk +++ b/config/rules.mk @@ -125,16 +125,8 @@ ifndef relativesrcdir $(error Must define relativesrcdir when defining XPCSHELL_TESTS.) endif -# Test file installation -ifneq (,$(filter WINNT os2-emx,$(HOST_OS_ARCH))) -# Windows and OS/2 nsinstall can't recursively copy directories, so use nsinstall.py -TEST_INSTALLER = $(PYTHON) $(topsrcdir)/config/nsinstall.py -else -TEST_INSTALLER = $(INSTALL) -endif - define _INSTALL_TESTS -$(TEST_INSTALLER) $(wildcard $(srcdir)/$(dir)/*) $(testxpcobjdir)/$(relativesrcdir)/$(dir) +$(DIR_INSTALL) $(wildcard $(srcdir)/$(dir)/*) $(testxpcobjdir)/$(relativesrcdir)/$(dir) endef # do not remove the blank line! @@ -390,7 +382,7 @@ ifndef MOZ_AUTO_DEPS ifneq (,$(OBJS)$(XPIDLSRCS)$(SIMPLE_PROGRAMS)) MDDEPFILES = $(addprefix $(MDDEPDIR)/,$(OBJS:.$(OBJ_SUFFIX)=.pp)) ifndef NO_GEN_XPT -MDDEPFILES += $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.xpt)) +MDDEPFILES += $(addprefix $(MDDEPDIR)/,$(XPIDLSRCS:.idl=.h.pp) $(XPIDLSRCS:.idl=.xpt.pp)) endif endif endif @@ -1538,9 +1530,17 @@ $(XPIDL_GEN_DIR)/.done: # don't depend on $(XPIDL_GEN_DIR), because the modification date changes # with any addition to the directory, regenerating all .h files -> everything. -$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_COMPILE) $(XPIDL_GEN_DIR)/.done +XPIDL_DEPS = \ + $(topsrcdir)/xpcom/idl-parser/header.py \ + $(topsrcdir)/xpcom/idl-parser/xpidl.py \ + $(NULL) + +$(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done $(REPORT_BUILD) - $(ELOG) $(XPIDL_COMPILE) -m header -w $(XPIDL_FLAGS) -o $(XPIDL_GEN_DIR)/$* $(_VPATH_SRCS) + $(PYTHONPATH) \ + -I$(topsrcdir)/other-licenses/ply \ + -I$(topsrcdir)/xpcom/idl-parser \ + $(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(topsrcdir)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@ @if test -n "$(findstring $*.h, $(EXPORTS))"; \ then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi @@ -1549,7 +1549,7 @@ ifndef NO_GEN_XPT # into $(XPIDL_MODULE).xpt and export it to $(FINAL_TARGET)/components. $(XPIDL_GEN_DIR)/%.xpt: %.idl $(XPIDL_COMPILE) $(XPIDL_GEN_DIR)/.done $(REPORT_BUILD) - $(ELOG) $(XPIDL_COMPILE) -m typelib -w $(XPIDL_FLAGS) -e $@ -d $(MDDEPDIR)/$*.pp $(_VPATH_SRCS) + $(ELOG) $(XPIDL_COMPILE) -m typelib -w $(XPIDL_FLAGS) -e $@ -d $(MDDEPDIR)/$(@F).pp $(_VPATH_SRCS) # no need to link together if XPIDLSRCS contains only XPIDL_MODULE ifneq ($(XPIDL_MODULE).idl,$(strip $(XPIDLSRCS))) diff --git a/config/system-headers b/config/system-headers index 94e827944ac2..41a939ac80c0 100644 --- a/config/system-headers +++ b/config/system-headers @@ -204,7 +204,6 @@ ctime ctype.h curl/curl.h curl/easy.h -curl/types.h curses.h cxxabi.h DateTimeUtils.h diff --git a/configure.in b/configure.in index b3d943b1ec04..b63a95734a5a 100644 --- a/configure.in +++ b/configure.in @@ -269,6 +269,12 @@ MOZ_ARG_WITH_STRING(android-platform, location of platform dir, default NDK/build/platforms/android-5/arch-arm], android_platform=$withval) +MOZ_ARG_ENABLE_BOOL(android-libstdcxx, +[ --enable-android-libstdcxx + use GNU libstdc++ instead of STLPort for NDK >= 5], + MOZ_ANDROID_LIBSTDCXX=1, + MOZ_ANDROID_LIBSTDCXX= ) + case "$target" in arm-linux*-android*|*-linuxandroid*) android_tool_prefix="arm-linux-androideabi" @@ -314,12 +320,21 @@ case "$target" in RANLIB="$android_toolchain"/bin/"$android_tool_prefix"-ranlib STRIP="$android_toolchain"/bin/"$android_tool_prefix"-strip - if test -e "$android_ndk/sources/cxx-stl/stlport/libs/armeabi-v7a/libstlport_static.a" ; then + if test -n "$MOZ_ANDROID_LIBSTDCXX" ; then + if test ! -e "$android_ndk/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/libstdc++.a" ; then + AC_MSG_ERROR([Cannot find path to libstdc++ (NDK version >= 5?)]) + fi + STLPORT_CPPFLAGS="-I$android_ndk/sources/cxx-stl/gnu-libstdc++/include -I$android_ndk/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a/include -D_GLIBCXX_PERMIT_BACKWARD_HASH" + STLPORT_LDFLAGS="-L$android_ndk/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a" + STLPORT_LIBS="-lstdc++" + elif test -e "$android_ndk/sources/cxx-stl/stlport/libs/armeabi-v7a/libstlport_static.a" ; then STLPORT_CPPFLAGS="-I$android_ndk/sources/cxx-stl/stlport/stlport" - STLPORT_LDFLAGS="-L$android_ndk/sources/cxx-stl/stlport/libs/armeabi-v7a/ -lstlport_static" + STLPORT_LDFLAGS="-L$android_ndk/sources/cxx-stl/stlport/libs/armeabi-v7a/" + STLPORT_LIBS="-lstlport_static" elif test -e "$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/armeabi-v7a/libstlport_static.a" ; then STLPORT_CPPFLAGS="-I$android_ndk/sources/cxx-stl/stlport/stlport" - STLPORT_LDFLAGS="-L$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/armeabi-v7a -lstlport_static" + STLPORT_LDFLAGS="-L$android_ndk/tmp/ndk-digit/build/install/sources/cxx-stl/stlport/libs/armeabi-v7a" + STLPORT_LIBS="-lstlport_static" elif test "$target" != "arm-android-eabi"; then dnl fail if we're not building with NDKr4 AC_MSG_ERROR([Couldn't find path to stlport in the android ndk]) @@ -328,13 +343,13 @@ case "$target" in CPPFLAGS="-I$android_platform/usr/include $STLPORT_CPPFLAGS $CPPFLAGS" CFLAGS="-mandroid -I$android_platform/usr/include -fno-short-enums -fno-exceptions $CFLAGS" CXXFLAGS="-mandroid -I$android_platform/usr/include -fno-short-enums -fno-exceptions $CXXFLAGS" - LIBS="$LIBS $STLPORT_LDFLAGS" + LIBS="$LIBS $STLPORT_LIBS" dnl Add -llog by default, since we use it all over the place. dnl Add --allow-shlib-undefined, because libGLESv2 links to an dnl undefined symbol (present on the hardware, just not in the dnl NDK.) - LDFLAGS="-mandroid -L$android_platform/usr/lib -L$android_ndk/sources/cxx-stl/gnu-libstdc++/libs/armeabi-v7a -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform -llog -Wl,--allow-shlib-undefined $LDFLAGS" + LDFLAGS="-mandroid $STLPORT_LDFLAGS -L$android_platform/usr/lib -Wl,-rpath-link=$android_platform/usr/lib --sysroot=$android_platform -llog -Wl,--allow-shlib-undefined $LDFLAGS" dnl prevent cross compile section from using these flags as host flags if test -z "$HOST_CPPFLAGS" ; then @@ -987,7 +1002,10 @@ AC_SUBST(NSINSTALL_BIN) MOZ_PATH_PROG(DOXYGEN, doxygen, :) MOZ_PATH_PROG(AUTOCONF, autoconf, :) -MOZ_PATH_PROG(UNZIP, unzip, :) +MOZ_PATH_PROGS(UNZIP, unzip) +if test -z "$UNZIP" -o "$UNZIP" = ":"; then + AC_MSG_ERROR([unzip not found in \$PATH]) +fi MOZ_PATH_PROGS(ZIP, zip) if test -z "$ZIP" -o "$ZIP" = ":"; then AC_MSG_ERROR([zip not found in \$PATH]) @@ -1549,10 +1567,8 @@ if test "$GNU_CC"; then MKCSHLIB='$(CC) $(CFLAGS) $(DSO_PIC_CFLAGS) $(DSO_LDOPTS) -Wl,-h,$@ -o $@' DSO_LDOPTS='-shared' if test "$GCC_USE_GNU_LD"; then - # Don't allow undefined symbols in libraries, and remove dead symbols - DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs -Wl,--gc-sections" - CFLAGS="$CFLAGS -ffunction-sections -fdata-sections" - CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections" + # Don't allow undefined symbols in libraries + DSO_LDOPTS="$DSO_LDOPTS -Wl,-z,defs" fi WARNINGS_AS_ERRORS='-Werror' DSO_CFLAGS='' @@ -1826,7 +1842,9 @@ if test -n "$MOZ_VALGRIND"; then AC_MSG_ERROR( [--enable-valgrind specified but Valgrind is not installed])) AC_DEFINE(MOZ_VALGRIND) + MOZ_VALGRIND=1 fi +AC_SUBST(MOZ_VALGRIND) dnl ======================================================== dnl jprof @@ -6136,7 +6154,7 @@ if test -n "$MOZ_ANGLE"; then fi if test -n "`echo $MOZ_DIRECTX_SDK_REG_KEY | grep 'February 2010'`" ; then - AC_MSG_WARN([Found the February 2010 DirectX SDK. This is too old. We now require the June 2010 DirectX SDK, or newer.]) + AC_MSG_ERROR([Found the February 2010 DirectX SDK. This is too old. We now require the June 2010 DirectX SDK, or newer. Upgrade your SDK or to explicitly build without ANGLE, reconfigure with --disable-angle.]) else MOZ_DIRECTX_SDK_PATH=`reg query "$MOZ_DIRECTX_SDK_REG_KEY" //v InstallPath | grep REG_SZ | sed 's/.*\([[a-zA-Z]]\)\\:\\\\/\\1\\:\\\\/'` fi @@ -6151,8 +6169,7 @@ if test -n "$MOZ_ANGLE"; then fi if test -z "$MOZ_ANGLE" ; then - AC_MSG_WARN([Couldn't find the DirectX SDK, needed for ANGLE. Please install it (June 2010 or newer). To explicitly build without ANGLE, reconfigure with --disable-angle.]) - AC_MSG_WARN([This will become an error in the future.]) + AC_MSG_ERROR([Couldn't find the DirectX SDK, needed for ANGLE. Please install it (June 2010 or newer). To explicitly build without ANGLE, reconfigure with --disable-angle.]) fi if test -n "$MOZ_ANGLE" ; then @@ -6160,9 +6177,7 @@ if test -n "$MOZ_ANGLE"; then MOZ_D3DX9_VERSION=`dumpbin //headers "$MOZ_DIRECTX_SDK_PATH"/lib/$MOZ_DIRECTX_SDK_CPU_SUFFIX/d3dx9.lib | egrep d3dx9_[[0-9]][[0-9]]\.dll | head -n1 | sed 's/.*\([[0-9]][[0-9]]\).*/\\1/g'` if test -z "$MOZ_D3DX9_VERSION" ; then - MOZ_ANGLE= - AC_MSG_WARN([Couldn't determine the D3DX9 version! Disabling ANGLE.]) - AC_MSG_WARN([This will become an error in the future.]) + AC_MSG_ERROR([Couldn't determine the D3DX9 version, needed for ANGLE. To explicitly build without ANGLE, reconfigure with --disable-angle.]) fi if test -n "$MOZ_ANGLE" ; then @@ -7298,6 +7313,38 @@ if test -n "$MOZ_DEBUG" -o -n "$MOZ_DEBUG_SYMBOLS"; then export MOZ_DEBUG_SYMBOLS fi +dnl ======================================================== +dnl = Automatically remove dead symbols +dnl ======================================================== + +if test "$GNU_CC" -a "$GCC_USE_GNU_LD" -a -n "$MOZ_DEBUG_FLAGS"; then + dnl See bug 670659 + AC_CACHE_CHECK([whether removing dead symbols breaks debugging], + GC_SECTIONS_BREAKS_DEBUG_RANGES, + [echo 'int foo() {return 42;}' \ + 'int bar() {return 1;}' \ + 'int main() {return foo();}' > conftest.${ac_ext} + if AC_TRY_COMMAND([${CC-cc} -o conftest.${ac_objext} $CFLAGS $MOZ_DEBUG_FLAGS -ffunction-sections -c conftest.${ac_ext} 1>&2]) && + AC_TRY_COMMAND([${CC-cc} -o conftest${ac_exeext} $LDFLAGS $MOZ_DEBUG_FLAGS -Wl,--gc-sections conftest.${ac_objext} $LIBS 1>&2]) && + test -s conftest${ac_exeext} -a -s conftest.${ac_objext}; then + if test "`$PYTHON "$_topsrcdir"/build/unix/check_debug_ranges.py conftest.${ac_objext} conftest.${ac_ext}`" = \ + "`$PYTHON "$_topsrcdir"/build/unix/check_debug_ranges.py conftest${ac_exeext} conftest.${ac_ext}`"; then + GC_SECTIONS_BREAKS_DEBUG_RANGES=no + else + GC_SECTIONS_BREAKS_DEBUG_RANGES=yes + fi + else + dnl We really don't expect to get here, but just in case + AC_ERROR([couldn't compile a simple C file]) + fi + rm -rf conftest*]) + if test "$GC_SECTIONS_BREAKS_DEBUG_RANGES" = no; then + DSO_LDOPTS="$DSO_LDOPTS -Wl,--gc-sections" + CFLAGS="$CFLAGS -ffunction-sections -fdata-sections" + CXXFLAGS="$CXXFLAGS -ffunction-sections -fdata-sections" + fi +fi + dnl ======================================================== dnl = Disable any treating of compile warnings as errors dnl ======================================================== diff --git a/content/base/public/nsContentUtils.h b/content/base/public/nsContentUtils.h index 1ec6753e50f8..a9b7f9d78ae7 100644 --- a/content/base/public/nsContentUtils.h +++ b/content/base/public/nsContentUtils.h @@ -79,13 +79,13 @@ static fp_except_t oldmask = fpsetmask(~allmask); #include "mozilla/AutoRestore.h" #include "nsINode.h" #include "nsHashtable.h" +#include "nsIDOMNode.h" struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error! class nsIDOMScriptObjectFactory; class nsIXPConnect; class nsIContent; -class nsIDOMNode; class nsIDOMKeyEvent; class nsIDocument; class nsIDocumentObserver; @@ -122,7 +122,6 @@ struct JSRuntime; class nsIUGenCategory; class nsIWidget; class nsIDragSession; -class nsPIDOMWindow; class nsIPresShell; class nsIXPConnectJSObjectHolder; #ifdef MOZ_XTF diff --git a/content/base/public/nsDOMFile.h b/content/base/public/nsDOMFile.h index 351898eba774..691a848d4ad4 100644 --- a/content/base/public/nsDOMFile.h +++ b/content/base/public/nsDOMFile.h @@ -46,6 +46,7 @@ #include "nsIDOMFileError.h" #include "nsIInputStream.h" #include "nsIJSNativeInitializer.h" +#include "nsIMutable.h" #include "nsCOMArray.h" #include "nsCOMPtr.h" #include "mozilla/AutoRestore.h" @@ -66,21 +67,22 @@ class nsIBlobBuilder; nsresult NS_NewBlobBuilder(nsISupports* *aSupports); class nsDOMFileBase : public nsIDOMFile, - public nsIXHRSendable + public nsIXHRSendable, + public nsIMutable { public: nsDOMFileBase(const nsAString& aName, const nsAString& aContentType, PRUint64 aLength) - : mIsFile(true), mContentType(aContentType), mName(aName), - mStart(0), mLength(aLength) + : mIsFile(true), mImmutable(false), mContentType(aContentType), + mName(aName), mStart(0), mLength(aLength) { // Ensure non-null mContentType by default mContentType.SetIsVoid(PR_FALSE); } nsDOMFileBase(const nsAString& aContentType, PRUint64 aLength) - : mIsFile(false), mContentType(aContentType), + : mIsFile(false), mImmutable(false), mContentType(aContentType), mStart(0), mLength(aLength) { // Ensure non-null mContentType by default @@ -89,7 +91,7 @@ public: nsDOMFileBase(const nsAString& aContentType, PRUint64 aStart, PRUint64 aLength) - : mIsFile(false), mContentType(aContentType), + : mIsFile(false), mImmutable(false), mContentType(aContentType), mStart(aStart), mLength(aLength) { NS_ASSERTION(aLength != PR_UINT64_MAX, @@ -108,6 +110,7 @@ public: NS_DECL_NSIDOMBLOB NS_DECL_NSIDOMFILE NS_DECL_NSIXHRSENDABLE + NS_DECL_NSIMUTABLE protected: bool IsSizeUnknown() @@ -116,6 +119,7 @@ protected: } bool mIsFile; + bool mImmutable; nsString mContentType; nsString mName; @@ -186,6 +190,7 @@ protected: mCacheToken(aOther->mCacheToken) { NS_ASSERTION(mFile, "must have file"); + mImmutable = aOther->mImmutable; } virtual already_AddRefed CreateSlice(PRUint64 aStart, PRUint64 aLength, @@ -230,6 +235,7 @@ protected: mDataOwner(aOther->mDataOwner) { NS_ASSERTION(mDataOwner && mDataOwner->mData, "must have data"); + mImmutable = aOther->mImmutable; } virtual already_AddRefed CreateSlice(PRUint64 aStart, PRUint64 aLength, diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 9fcec4368247..631647b7a0b6 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -69,6 +69,7 @@ #include "nsIAnimationFrameListener.h" #include "nsEventStates.h" #include "nsIStructuredCloneContainer.h" +#include "nsDOMMemoryReporter.h" class nsIContent; class nsPresContext; @@ -149,6 +150,7 @@ public: NS_DECLARE_STATIC_IID_ACCESSOR(NS_IDOCUMENT_IID) NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW + NS_DECL_DOM_MEMORY_REPORTER_SIZEOF #ifdef MOZILLA_INTERNAL_API nsIDocument() @@ -1531,8 +1533,6 @@ public: #undef DEPRECATED_OPERATION void WarnOnceAbout(DeprecatedOperations aOperation); - PRInt64 SizeOf() const; - private: PRUint32 mWarnedAbout; diff --git a/content/base/src/CSPUtils.jsm b/content/base/src/CSPUtils.jsm index 6db4ee651bac..13cb7e8abaed 100644 --- a/content/base/src/CSPUtils.jsm +++ b/content/base/src/CSPUtils.jsm @@ -126,7 +126,7 @@ function CSPPolicyURIListener(policyURI, docRequest, csp) { this._policy = ""; // contents fetched from policyURI this._wrapper = null; // nsIScriptableInputStream this._docURI = docRequest.QueryInterface(Components.interfaces.nsIChannel) - .originalURI; // parent document URI (to be used as 'self') + .URI; // parent document URI (to be used as 'self') } CSPPolicyURIListener.prototype = { diff --git a/content/base/src/ThirdPartyUtil.cpp b/content/base/src/ThirdPartyUtil.cpp index d8fc6c5e9ff5..b195af9f48e6 100644 --- a/content/base/src/ThirdPartyUtil.cpp +++ b/content/base/src/ThirdPartyUtil.cpp @@ -286,23 +286,29 @@ ThirdPartyUtil::IsThirdPartyChannel(nsIChannel* aChannel, ourWin->GetParent(getter_AddRefs(parentWin)); NS_ENSURE_TRUE(parentWin, NS_ERROR_INVALID_ARG); - if (SameCOMIdentity(ourWin, parentWin)) { - // Check whether this is the document channel for this window (representing - // a load of a new page). This covers the case of a freshly kicked-off load - // (e.g. the user typing something in the location bar, or clicking on a - // bookmark), where the window's URI hasn't yet been set, and will be bogus. - // This is a bit of a nasty hack, but we will hopefully flag these channels - // better later. - nsLoadFlags flags; - rv = aChannel->GetLoadFlags(&flags); - NS_ENSURE_SUCCESS(rv, rv); + // Check whether this is the document channel for this window (representing a + // load of a new page). In that situation we want to avoid comparing + // channelURI to ourWin, since what's in ourWin right now will be replaced as + // the channel loads. This covers the case of a freshly kicked-off load + // (e.g. the user typing something in the location bar, or clicking on a + // bookmark), where the window's URI hasn't yet been set, and will be bogus. + // It also covers situations where a subframe is navigated to someting that + // is same-origin with all its ancestors. This is a bit of a nasty hack, but + // we will hopefully flag these channels better later. + nsLoadFlags flags; + rv = aChannel->GetLoadFlags(&flags); + NS_ENSURE_SUCCESS(rv, rv); - if (flags & nsIChannel::LOAD_DOCUMENT_URI) { + if (flags & nsIChannel::LOAD_DOCUMENT_URI) { + if (SameCOMIdentity(ourWin, parentWin)) { // We only need to compare aURI to the channel URI -- the window's will be // bogus. We already know the answer. *aResult = false; return NS_OK; } + + // Make sure to still compare to ourWin's ancestors + ourWin = parentWin; } // Check the window hierarchy. This covers most cases for an ordinary page diff --git a/content/base/src/contentSecurityPolicy.js b/content/base/src/contentSecurityPolicy.js index 2c45e79c11dc..4ba5ac541550 100644 --- a/content/base/src/contentSecurityPolicy.js +++ b/content/base/src/contentSecurityPolicy.js @@ -68,7 +68,6 @@ function ContentSecurityPolicy() { this._policy._allowInlineScripts = true; this._policy._allowEval = true; - this._requestHeaders = []; this._request = ""; this._docRequest = null; CSPdebug("CSP POLICY INITED TO 'default-src *'"); @@ -211,13 +210,6 @@ ContentSecurityPolicy.prototype = { var reqVersion = internalChannel.getRequestVersion(reqMaj, reqMin); this._request += " HTTP/" + reqMaj.value + "." + reqMin.value; } - - // grab the request headers - var self = this; - aChannel.visitRequestHeaders({ - visitHeader: function(aHeader, aValue) { - self._requestHeaders.push(aHeader + ": " + aValue); - }}); }, /* ........ Methods .............. */ @@ -270,21 +262,13 @@ ContentSecurityPolicy.prototype = { // { // csp-report: { // request: "GET /index.html HTTP/1.1", - // request-headers: "Host: example.com - // User-Agent: ... - // ...", // blocked-uri: "...", // violated-directive: "..." // } // } - var strHeaders = ""; - for (let i in this._requestHeaders) { - strHeaders += this._requestHeaders[i] + "\n"; - } var report = { 'csp-report': { 'request': this._request, - 'request-headers': strHeaders, 'blocked-uri': (blockedUri instanceof Ci.nsIURI ? blockedUri.asciiSpec : blockedUri), 'violated-directive': violatedDirective diff --git a/content/base/src/nsCommentNode.cpp b/content/base/src/nsCommentNode.cpp index f4f9eda7b966..a8afba4aeba6 100644 --- a/content/base/src/nsCommentNode.cpp +++ b/content/base/src/nsCommentNode.cpp @@ -43,6 +43,7 @@ #include "nsGenericDOMDataNode.h" #include "nsCOMPtr.h" #include "nsIDocument.h" +#include "nsDOMMemoryReporter.h" class nsCommentNode : public nsGenericDOMDataNode, public nsIDOMComment @@ -60,6 +61,10 @@ public: // nsIDOMCharacterData NS_FORWARD_NSIDOMCHARACTERDATA(nsGenericDOMDataNode::) + // DOM Memory Reporter participant. + NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsCommentNode, + nsGenericDOMDataNode) + // nsIDOMComment // Empty interface diff --git a/content/base/src/nsContentList.h b/content/base/src/nsContentList.h index c74684567c4b..015635b96e9a 100644 --- a/content/base/src/nsContentList.h +++ b/content/base/src/nsContentList.h @@ -56,7 +56,7 @@ #include "nsCycleCollectionParticipant.h" #include "nsWrapperCache.h" #include "nsCRT.h" -#include "mozilla/dom/Element.h" +#include "nsHashKeys.h" // Magic namespace id that means "match all namespaces". This is // negative so it won't collide with actual namespace constants. @@ -74,6 +74,11 @@ typedef PRBool (*nsContentListMatchFunc)(nsIContent* aContent, typedef void (*nsContentListDestroyFunc)(void* aData); class nsIDocument; +namespace mozilla { +namespace dom { +class Element; +} +} class nsBaseContentList : public nsINodeList diff --git a/content/base/src/nsContentSink.cpp b/content/base/src/nsContentSink.cpp index e09ff33db984..fcb2fdf0830c 100644 --- a/content/base/src/nsContentSink.cpp +++ b/content/base/src/nsContentSink.cpp @@ -557,13 +557,6 @@ nsContentSink::DoProcessLinkHeader() ProcessLinkHeader(nsnull, value); } -static const PRUnichar kSemiCh = PRUnichar(';'); -static const PRUnichar kCommaCh = PRUnichar(','); -static const PRUnichar kEqualsCh = PRUnichar('='); -static const PRUnichar kLessThanCh = PRUnichar('<'); -static const PRUnichar kGreaterThanCh = PRUnichar('>'); - - // check whether the Link header field applies to the context resource // see @@ -642,22 +635,31 @@ nsContentSink::ProcessLinkHeader(nsIContent* aElement, end = start; last = end - 1; + PRBool needsUnescape = PR_FALSE; + // look for semicolon or comma - while (*end != kNullCh && *end != kSemiCh && *end != kCommaCh) { + while (*end != kNullCh && *end != kSemicolon && *end != kComma) { PRUnichar ch = *end; - if (ch == kApostrophe || ch == kQuote || ch == kLessThanCh) { + if (ch == kApostrophe || ch == kQuote || ch == kLessThan) { // quoted string - PRUnichar quote = *end; - if (quote == kLessThanCh) { - quote = kGreaterThanCh; + PRUnichar quote = ch; + if (quote == kLessThan) { + quote = kGreaterThan; } - + + needsUnescape = (ch == kQuote); + PRUnichar* closeQuote = (end + 1); // seek closing quote while (*closeQuote != kNullCh && quote != *closeQuote) { + // in quoted-string, "\" is an escape character + if (needsUnescape && *closeQuote == kBackSlash && *(closeQuote + 1) != kNullCh) { + ++closeQuote; + } + ++closeQuote; } @@ -671,14 +673,14 @@ nsContentSink::ProcessLinkHeader(nsIContent* aElement, ch = *(end + 1); - if (ch != kNullCh && ch != kSemiCh && ch != kCommaCh) { + if (ch != kNullCh && ch != kSemicolon && ch != kComma) { // end string here *(++end) = kNullCh; ch = *(end + 1); // keep going until semi or comma - while (ch != kNullCh && ch != kSemiCh && ch != kCommaCh) { + while (ch != kNullCh && ch != kSemicolon && ch != kComma) { ++end; ch = *end; @@ -697,7 +699,7 @@ nsContentSink::ProcessLinkHeader(nsIContent* aElement, *end = kNullCh; if (start < end) { - if ((*start == kLessThanCh) && (*last == kGreaterThanCh)) { + if ((*start == kLessThan) && (*last == kGreaterThan)) { *last = kNullCh; if (href.IsEmpty()) { // first one wins @@ -707,7 +709,7 @@ nsContentSink::ProcessLinkHeader(nsIContent* aElement, } else { PRUnichar* equals = start; - while ((*equals != kNullCh) && (*equals != kEqualsCh)) { + while ((*equals != kNullCh) && (*equals != kEqual)) { equals++; } @@ -727,6 +729,21 @@ nsContentSink::ProcessLinkHeader(nsIContent* aElement, value++; } + if (needsUnescape) { + // unescape in-place + PRUnichar* unescaped = value; + PRUnichar *src = value; + + while (*src != kNullCh) { + if (*src == kBackSlash && *(src + 1) != kNullCh) { + src++; + } + *unescaped++ = *src++; + } + + *unescaped = kNullCh; + } + if (attr.LowerCaseEqualsLiteral("rel")) { if (rel.IsEmpty()) { rel = value; @@ -759,7 +776,7 @@ nsContentSink::ProcessLinkHeader(nsIContent* aElement, } } - if (endCh == kCommaCh) { + if (endCh == kComma) { // hit a comma, process what we've got so far href.Trim(" \t\n\r\f"); // trim HTML5 whitespace diff --git a/content/base/src/nsCopySupport.cpp b/content/base/src/nsCopySupport.cpp index 3bd37fd41e42..683be5796549 100644 --- a/content/base/src/nsCopySupport.cpp +++ b/content/base/src/nsCopySupport.cpp @@ -79,6 +79,8 @@ #include "nsContentUtils.h" #include "nsContentCID.h" +#include "mozilla/dom/Element.h" + nsresult NS_NewDomSelection(nsISelection **aDomSelection); static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID); diff --git a/content/base/src/nsDOMFile.cpp b/content/base/src/nsDOMFile.cpp index ededcc26d2df..d4169f32d8fc 100644 --- a/content/base/src/nsDOMFile.cpp +++ b/content/base/src/nsDOMFile.cpp @@ -143,6 +143,7 @@ NS_INTERFACE_MAP_BEGIN(nsDOMFileBase) NS_INTERFACE_MAP_ENTRY(nsIDOMBlob) NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIDOMFile, mIsFile) NS_INTERFACE_MAP_ENTRY(nsIXHRSendable) + NS_INTERFACE_MAP_ENTRY(nsIMutable) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(File, mIsFile) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO_CONDITIONAL(Blob, !mIsFile) NS_INTERFACE_MAP_END @@ -313,6 +314,35 @@ nsDOMFileBase::GetSendInfo(nsIInputStream** aBody, return NS_OK; } +NS_IMETHODIMP +nsDOMFileBase::GetMutable(PRBool* aMutable) +{ + *aMutable = !mImmutable; + return NS_OK; +} + +NS_IMETHODIMP +nsDOMFileBase::SetMutable(PRBool aMutable) +{ + nsresult rv = NS_OK; + + NS_ENSURE_ARG(!mImmutable || !aMutable); + + if (!mImmutable && !aMutable) { + // Force the content type and size to be cached + nsString dummyString; + rv = this->GetType(dummyString); + NS_ENSURE_SUCCESS(rv, rv); + + PRUint64 dummyInt; + rv = this->GetSize(&dummyInt); + NS_ENSURE_SUCCESS(rv, rv); + } + + mImmutable = !aMutable; + return rv; +} + //////////////////////////////////////////////////////////////////////////// // nsDOMFileFile implementation @@ -413,6 +443,9 @@ nsDOMFileFile::Initialize(nsISupports* aOwner, { nsresult rv; + NS_ASSERTION(!mImmutable, "Something went wrong ..."); + NS_ENSURE_TRUE(!mImmutable, NS_ERROR_UNEXPECTED); + if (!nsContentUtils::IsCallerChrome()) { return NS_ERROR_DOM_SECURITY_ERR; // Real short trip } diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 252d32ee14de..9bca208b4960 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -8383,3 +8383,11 @@ nsIDocument::SizeOf() const return size; } +PRInt64 +nsDocument::SizeOf() const +{ + PRInt64 size = MemoryReporter::GetBasicSize(this); + size += mAttrStyleSheet ? mAttrStyleSheet->SizeOf() : 0; + return size; +} + diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 27762d877bd4..a79106d62772 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -499,6 +499,7 @@ public: typedef mozilla::dom::Element Element; NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_DOM_MEMORY_REPORTER_SIZEOF using nsINode::GetScriptTypeID; diff --git a/content/base/src/nsDocumentEncoder.cpp b/content/base/src/nsDocumentEncoder.cpp index 425926110195..7b2eb98a0079 100644 --- a/content/base/src/nsDocumentEncoder.cpp +++ b/content/base/src/nsDocumentEncoder.cpp @@ -82,6 +82,7 @@ #include "nsTArray.h" #include "nsIFrame.h" #include "nsStringBuffer.h" +#include "mozilla/dom/Element.h" nsresult NS_NewDomSelection(nsISelection **aDomSelection); diff --git a/content/base/src/nsFrameLoader.cpp b/content/base/src/nsFrameLoader.cpp index 8205e292d92d..2f4bd5a05443 100644 --- a/content/base/src/nsFrameLoader.cpp +++ b/content/base/src/nsFrameLoader.cpp @@ -1628,8 +1628,6 @@ nsFrameLoader::GetWindowDimensions(nsRect& aRect) nsCOMPtr parentAsItem(do_QueryInterface(parentAsWebNav)); - NS_ASSERTION(mIsTopLevelContent, "Outer dimensions must be taken only from TopLevel content"); - nsCOMPtr parentOwner; if (NS_FAILED(parentAsItem->GetTreeOwner(getter_AddRefs(parentOwner))) || !parentOwner) { diff --git a/content/base/src/nsFrameLoader.h b/content/base/src/nsFrameLoader.h index 63cdca3071e6..d8e2148252e2 100644 --- a/content/base/src/nsFrameLoader.h +++ b/content/base/src/nsFrameLoader.h @@ -53,8 +53,8 @@ #include "nsAutoPtr.h" #include "nsFrameMessageManager.h" #include "Layers.h" +#include "nsIContent.h" -class nsIContent; class nsIURI; class nsSubDocumentFrame; class nsIView; diff --git a/content/base/src/nsGenericDOMDataNode.cpp b/content/base/src/nsGenericDOMDataNode.cpp index bf3f9624dc72..c1332111aec2 100644 --- a/content/base/src/nsGenericDOMDataNode.cpp +++ b/content/base/src/nsGenericDOMDataNode.cpp @@ -67,7 +67,7 @@ #include "pldhash.h" #include "prprf.h" -namespace css = mozilla::css; +using namespace mozilla; nsGenericDOMDataNode::nsGenericDOMDataNode(already_AddRefed aNodeInfo) : nsIContent(aNodeInfo) @@ -1065,3 +1065,13 @@ nsGenericDOMDataNode::GetClassAttributeName() const { return nsnull; } + +PRInt64 +nsGenericDOMDataNode::SizeOf() const +{ + PRInt64 size = dom::MemoryReporter::GetBasicSize(this); + size += mText.SizeOf() - sizeof(mText); + return size; +} + diff --git a/content/base/src/nsGenericDOMDataNode.h b/content/base/src/nsGenericDOMDataNode.h index d341123431df..07c341c7aa52 100644 --- a/content/base/src/nsGenericDOMDataNode.h +++ b/content/base/src/nsGenericDOMDataNode.h @@ -51,6 +51,7 @@ #include "nsGenericElement.h" #include "nsCycleCollectionParticipant.h" #include "nsContentUtils.h" +#include "nsDOMMemoryReporter.h" #ifdef MOZ_SMIL #include "nsISMILAttr.h" @@ -84,6 +85,8 @@ class nsGenericDOMDataNode : public nsIContent public: NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_DOM_MEMORY_REPORTER_SIZEOF + nsGenericDOMDataNode(already_AddRefed aNodeInfo); virtual ~nsGenericDOMDataNode(); diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 7ab2d0480d0b..097ce8c2a4b3 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -1226,24 +1226,20 @@ nsGenericElement::UpdateEditableState(PRBool aNotify) { nsIContent *parent = GetParent(); - PRBool oldEditable = IsEditable(); SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE)); - PRBool newEditable = IsEditable(); - if (oldEditable != newEditable) { - if (aNotify) { - UpdateState(aNotify); + if (aNotify) { + UpdateState(aNotify); + } else { + // Avoid calling UpdateState in this very common case, because + // this gets called for pretty much every single element on + // insertion into the document and UpdateState can be slow for + // some kinds of elements even when not notifying. + if (IsEditable()) { + RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY); + AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE); } else { - // Avoid calling UpdateState in this very common case, because - // this gets called for pretty much every single element on - // insertion into the document and UpdateState can be slow for - // some kinds of elements even when not notifying. - if (oldEditable) { - RemoveStatesSilently(NS_EVENT_STATE_MOZ_READWRITE); - AddStatesSilently(NS_EVENT_STATE_MOZ_READONLY); - } else { - RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY); - AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE); - } + RemoveStatesSilently(NS_EVENT_STATE_MOZ_READWRITE); + AddStatesSilently(NS_EVENT_STATE_MOZ_READONLY); } } } @@ -3592,6 +3588,7 @@ nsGenericElement::DispatchClickEvent(nsPresContext* aPresContext, nsInputEvent* aSourceEvent, nsIContent* aTarget, PRBool aFullDispatch, + PRUint32 aFlags, nsEventStatus* aStatus) { NS_PRECONDITION(aTarget, "Must have target"); @@ -3618,6 +3615,7 @@ nsGenericElement::DispatchClickEvent(nsPresContext* aPresContext, event.isControl = aSourceEvent->isControl; event.isAlt = aSourceEvent->isAlt; event.isMeta = aSourceEvent->isMeta; + event.flags = aFlags; return DispatchEvent(aPresContext, &event, aTarget, aFullDispatch, aStatus); } @@ -5038,7 +5036,7 @@ nsGenericElement::CheckHandleEventForLinksPrecondition(nsEventChainVisitor& aVis (aVisitor.mEvent->message != NS_KEY_PRESS) && (aVisitor.mEvent->message != NS_UI_ACTIVATE)) || !aVisitor.mPresContext || - (aVisitor.mEvent->flags & NS_EVENT_FLAG_PREVENT_ANCHOR_ACTIONS)) { + (aVisitor.mEvent->flags & NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS)) { return PR_FALSE; } @@ -5084,7 +5082,7 @@ nsGenericElement::PreHandleEventForLinks(nsEventChainPreVisitor& aVisitor) nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target, PR_FALSE, PR_TRUE, PR_TRUE); // Make sure any ancestor links don't also TriggerLink - aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_ANCHOR_ACTIONS; + aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS; } break; @@ -5094,7 +5092,7 @@ nsGenericElement::PreHandleEventForLinks(nsEventChainPreVisitor& aVisitor) case NS_BLUR_CONTENT: rv = LeaveLink(aVisitor.mPresContext); if (NS_SUCCEEDED(rv)) { - aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_ANCHOR_ACTIONS; + aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS; } break; @@ -5142,7 +5140,7 @@ nsGenericElement::PostHandleEventForLinks(nsEventChainPostVisitor& aVisitor) if (handler && document) { nsIFocusManager* fm = nsFocusManager::GetFocusManager(); if (fm) { - aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_ANCHOR_ACTIONS; + aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS; nsCOMPtr elem = do_QueryInterface(this); fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOUSE | nsIFocusManager::FLAG_NOSCROLL); @@ -5198,7 +5196,7 @@ nsGenericElement::PostHandleEventForLinks(nsEventChainPostVisitor& aVisitor) if (keyEvent->keyCode == NS_VK_RETURN) { nsEventStatus status = nsEventStatus_eIgnore; rv = DispatchClickEvent(aVisitor.mPresContext, keyEvent, this, - PR_FALSE, &status); + PR_FALSE, 0, &status); if (NS_SUCCEEDED(rv)) { aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; } diff --git a/content/base/src/nsGenericElement.h b/content/base/src/nsGenericElement.h index 8fa9ab247167..1bd8ac874e08 100644 --- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -523,6 +523,7 @@ public: nsInputEvent* aSourceEvent, nsIContent* aTarget, PRBool aFullDispatch, + PRUint32 aFlags, nsEventStatus* aStatus); /** diff --git a/content/base/src/nsGkAtomList.h b/content/base/src/nsGkAtomList.h index 77c30802ec09..313a5ebc3938 100644 --- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -480,7 +480,6 @@ GK_ATOM(integer, "integer") GK_ATOM(intersection, "intersection") GK_ATOM(iscontainer, "iscontainer") GK_ATOM(isempty, "isempty") -GK_ATOM(isindex, "isindex") GK_ATOM(ismap, "ismap") GK_ATOM(itemid, "itemid") GK_ATOM(itemprop, "itemprop") diff --git a/content/base/src/nsImageLoadingContent.cpp b/content/base/src/nsImageLoadingContent.cpp index 6ee59eb74e23..3d3464d0a0c4 100644 --- a/content/base/src/nsImageLoadingContent.cpp +++ b/content/base/src/nsImageLoadingContent.cpp @@ -79,6 +79,7 @@ #include "nsSVGEffects.h" #include "mozAutoDocUpdate.h" +#include "mozilla/dom/Element.h" #ifdef DEBUG_chb static void PrintReqURL(imgIRequest* req) { diff --git a/content/base/src/nsImageLoadingContent.h b/content/base/src/nsImageLoadingContent.h index b38df99e0c22..5e9312327ef8 100644 --- a/content/base/src/nsImageLoadingContent.h +++ b/content/base/src/nsImageLoadingContent.h @@ -52,6 +52,7 @@ #include "nsCOMPtr.h" #include "nsContentUtils.h" #include "nsString.h" +#include "nsEventStates.h" class nsIURI; class nsIDocument; diff --git a/content/base/src/nsMappedAttributeElement.h b/content/base/src/nsMappedAttributeElement.h index 0c83ad6ad71b..176d50d7a9c9 100644 --- a/content/base/src/nsMappedAttributeElement.h +++ b/content/base/src/nsMappedAttributeElement.h @@ -46,6 +46,7 @@ #define NS_MAPPEDATTRIBUTEELEMENT_H_ #include "nsStyledElement.h" +#include "nsDOMMemoryReporter.h" class nsMappedAttributes; struct nsRuleData; @@ -65,6 +66,9 @@ protected: {} public: + NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsMappedAttributeElement, + nsMappedAttributeElementBase) + virtual nsresult BindToTree(nsIDocument* aDocument, nsIContent* aParent, nsIContent* aBindingParent, PRBool aCompileEventHandlers); diff --git a/content/base/src/nsMappedAttributes.h b/content/base/src/nsMappedAttributes.h index 7367779cd184..d402531d52ef 100644 --- a/content/base/src/nsMappedAttributes.h +++ b/content/base/src/nsMappedAttributes.h @@ -108,6 +108,12 @@ public: virtual void List(FILE* out = stdout, PRInt32 aIndent = 0) const; #endif + PRInt64 SizeOf() const { + NS_ASSERTION(mAttrCount == mBufferSize, + "mBufferSize and mAttrCount are expected to be the same."); + return sizeof(*this) - sizeof(void*) + mAttrCount * sizeof(InternalAttr); + } + private: nsMappedAttributes(const nsMappedAttributes& aCopy); ~nsMappedAttributes(); diff --git a/content/base/src/nsNodeInfo.cpp b/content/base/src/nsNodeInfo.cpp index 4a05d20f5584..e9fc75fb2c30 100644 --- a/content/base/src/nsNodeInfo.cpp +++ b/content/base/src/nsNodeInfo.cpp @@ -55,6 +55,8 @@ #include NEW_H #include "nsFixedSizeAllocator.h" #include "prprf.h" +#include "nsIDocument.h" +#include "nsGkAtoms.h" static const size_t kNodeInfoPoolSizes[] = { sizeof(nsNodeInfo) diff --git a/content/base/src/nsObjectLoadingContent.cpp b/content/base/src/nsObjectLoadingContent.cpp index 28a7abf5d719..514bfbddf7a9 100644 --- a/content/base/src/nsObjectLoadingContent.cpp +++ b/content/base/src/nsObjectLoadingContent.cpp @@ -96,6 +96,7 @@ #include "nsIContentSecurityPolicy.h" #include "nsIChannelPolicy.h" #include "nsChannelPolicy.h" +#include "mozilla/dom/Element.h" #ifdef PR_LOGGING static PRLogModuleInfo* gObjectLog = PR_NewLogModule("objlc"); diff --git a/content/base/src/nsStyledElement.h b/content/base/src/nsStyledElement.h index 6992a7519570..662498e63d85 100644 --- a/content/base/src/nsStyledElement.h +++ b/content/base/src/nsStyledElement.h @@ -48,6 +48,7 @@ #include "nsString.h" #include "nsGenericElement.h" +#include "nsDOMMemoryReporter.h" namespace mozilla { namespace css { @@ -68,6 +69,9 @@ protected: public: + NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsStyledElementNotElementCSSInlineStyle, + nsStyledElementBase) + // nsIContent interface methods virtual nsIAtom* GetClassAttributeName() const; virtual nsIAtom* GetIDAttributeName() const; @@ -115,6 +119,10 @@ protected: }; class nsStyledElement : public nsStyledElementNotElementCSSInlineStyle { +public: + NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsStyledElement, + nsStyledElementNotElementCSSInlineStyle) + protected: inline nsStyledElement(already_AddRefed aNodeInfo) : nsStyledElementNotElementCSSInlineStyle(aNodeInfo) diff --git a/content/base/src/nsTextFragment.h b/content/base/src/nsTextFragment.h index c9510fc82feb..8e0e1483a0c8 100644 --- a/content/base/src/nsTextFragment.h +++ b/content/base/src/nsTextFragment.h @@ -47,6 +47,8 @@ #include "nsString.h" #include "nsReadableUtils.h" #include "nsTraceRefcnt.h" +#include "nsDOMMemoryReporter.h" + class nsString; class nsCString; @@ -79,7 +81,7 @@ class nsCString; * This class does not have a virtual destructor therefore it is not * meant to be subclassed. */ -class nsTextFragment { +class NS_FINAL_CLASS nsTextFragment { public: static nsresult Init(); static void Shutdown(); @@ -224,6 +226,17 @@ public: PRUint32 mLength : 29; }; + /** + * Returns the size taken in memory by this text fragment. + * @return the size taken in memory by this text fragment. + */ + PRInt64 SizeOf() const + { + PRInt64 size = sizeof(*this); + size += GetLength() * Is2b() ? sizeof(*m2b) : sizeof(*m1b); + return size; + } + private: void ReleaseText(); diff --git a/content/base/src/nsTextNode.h b/content/base/src/nsTextNode.h index 5ce6a58bce7e..429b48f6e2d1 100644 --- a/content/base/src/nsTextNode.h +++ b/content/base/src/nsTextNode.h @@ -47,6 +47,7 @@ #include "nsIAttribute.h" #include "nsIDocument.h" #include "nsThreadUtils.h" +#include "nsDOMMemoryReporter.h" /** * Class used to implement DOM text nodes @@ -70,6 +71,9 @@ public: // nsIDOMText NS_FORWARD_NSIDOMTEXT(nsGenericDOMDataNode::) + // DOM Memory Reporter participant. + NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsTextNode, nsGenericDOMDataNode) + // nsINode virtual PRBool IsNodeOfType(PRUint32 aFlags) const; diff --git a/content/base/src/nsTreeWalker.cpp b/content/base/src/nsTreeWalker.cpp index 3228829a8537..2295916fc5f5 100644 --- a/content/base/src/nsTreeWalker.cpp +++ b/content/base/src/nsTreeWalker.cpp @@ -47,6 +47,8 @@ #include "nsIDOMNode.h" #include "nsIDOMNodeFilter.h" #include "nsDOMError.h" +#include "nsINode.h" +#include "nsIContent.h" #include "nsContentUtils.h" diff --git a/content/base/src/nsWebSocket.cpp b/content/base/src/nsWebSocket.cpp index 616dae3bafcc..45fc30199a60 100644 --- a/content/base/src/nsWebSocket.cpp +++ b/content/base/src/nsWebSocket.cpp @@ -1352,15 +1352,16 @@ nsWebSocket::Init(nsIPrincipal* aPrincipal, NS_ENSURE_SUCCESS(rv, rv); // Don't allow https:// to open ws:// - nsCOMPtr originURI; - PRBool originHTTPS; if (!mSecure && !Preferences::GetBool("network.websocket.allowInsecureFromHTTPS", - PR_FALSE) && - NS_SUCCEEDED(NS_NewURI(getter_AddRefs(originURI), mUTF16Origin)) && - NS_SUCCEEDED(originURI->SchemeIs("https", &originHTTPS)) && - originHTTPS) { - return NS_ERROR_DOM_SECURITY_ERR; + PR_FALSE)) { + // Confirmed we are opening plain ws:// and want to prevent this from a + // secure context (e.g. https). Check the security context of the document + // associated with this script, which is the same as associated with mOwner. + nsCOMPtr originDoc = + nsContentUtils::GetDocumentFromScriptContext(mScriptContext); + if (originDoc && originDoc->GetSecurityInfo()) + return NS_ERROR_DOM_SECURITY_ERR; } // sets the protocol diff --git a/content/canvas/src/nsCanvasRenderingContext2D.cpp b/content/canvas/src/nsCanvasRenderingContext2D.cpp index 092100cc51c3..c764f27bb189 100644 --- a/content/canvas/src/nsCanvasRenderingContext2D.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp @@ -3297,47 +3297,24 @@ nsCanvasRenderingContext2D::DrawImage(nsIDOMElement *imgElt, float a1, return NS_ERROR_INVALID_ARG; } - if (sw == 0.0 || sh == 0.0) { - // zero-sized source -- failure !? - return NS_ERROR_DOM_INDEX_SIZE_ERR; - } - if (dw == 0.0 || dh == 0.0) { // not really failure, but nothing to do -- // and noone likes a divide-by-zero return NS_OK; } - // The following check might do the validation of the float arguments: - // (!FloatValidate(sx, sy, sw, sh) || !FloatValidate(dx, dy, dw, dh)) - // but we would also need to validate some sums for overflow (e.g. sx + sw). - if (!FloatValidate(sx + sw, sy + sh, dx + dw, dy + dh)) { + if (!FloatValidate(sx, sy, sw, sh) || !FloatValidate(dx, dy, dw, dh)) { return NS_OK; } - // Handle negative sw, sh, dw and dh by flipping the rectangle over in the - // relevant direction. - if (sw < 0.0) { - sx += sw; - sw = -sw; - } - if (sh < 0.0) { - sy += sh; - sh = -sh; - } - if (dw < 0.0) { - dx += dw; - dw = -dw; - } - if (dh < 0.0) { - dy += dh; - dh = -dh; - } - - // Checking source image boundaries. - if (sx < 0 || sx + sw > (double) imgSize.width || - sy < 0 || sy + sh > (double) imgSize.height) { - return NS_ERROR_DOM_INDEX_SIZE_ERR; + // check args + if (sx < 0.0 || sy < 0.0 || + sw < 0.0 || sw > (double) imgSize.width || + sh < 0.0 || sh > (double) imgSize.height || + dw < 0.0 || dh < 0.0) + { + // XXX ERRMSG we need to report an error to developers here! (bug 329026) + return NS_ERROR_DOM_INDEX_SIZE_ERR; } matrix.Translate(gfxPoint(sx, sy)); diff --git a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp index 1fe50497e634..a4b0ee49bdf5 100644 --- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp +++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp @@ -3741,39 +3741,17 @@ nsCanvasRenderingContext2DAzure::DrawImage(nsIDOMElement *imgElt, float a1, return NS_ERROR_INVALID_ARG; } - if (sw == 0.0 || sh == 0.0) { - // zero-sized source -- failure !? - return NS_ERROR_DOM_INDEX_SIZE_ERR; - } - if (dw == 0.0 || dh == 0.0) { // not really failure, but nothing to do -- // and noone likes a divide-by-zero return NS_OK; } - // Handle negative sw, sh, dw and dh by flipping the rectangle over in the - // relevant direction. - if (sw < 0.0) { - sx += sw; - sw = -sw; - } - if (sh < 0.0) { - sy += sh; - sh = -sh; - } - if (dw < 0.0) { - dx += dw; - dw = -dw; - } - if (dh < 0.0) { - dy += dh; - dh = -dh; - } - - // Checking source image boundaries. - if (sx < 0 || sx + sw > (double) imgSize.width || - sy < 0 || sy + sh > (double) imgSize.height) { + if (sx < 0.0 || sy < 0.0 || + sw < 0.0 || sw > (double) imgSize.width || + sh < 0.0 || sh > (double) imgSize.height || + dw < 0.0 || dh < 0.0) { + // XXX - Unresolved spec issues here, for now return error. return NS_ERROR_DOM_INDEX_SIZE_ERR; } diff --git a/content/canvas/test/test_canvas.html b/content/canvas/test/test_canvas.html index 05e9f615a9f9..1416def39fd2 100644 --- a/content/canvas/test/test_canvas.html +++ b/content/canvas/test/test_canvas.html @@ -3042,38 +3042,6 @@ var _thrown = undefined; try { } - - -

Canvas test: 2d.drawImage.negativedir

-

FAIL (fallback content)

- - -

Canvas test: 2d.drawImage.negativedest

@@ -3086,6 +3054,9 @@ function test_2d_drawImage_negativedest() { var canvas = document.getElementById('c117'); var ctx = canvas.getContext('2d'); +var _thrown_outer = false; +try { + ctx.fillStyle = '#f00'; ctx.fillRect(0, 0, 100, 50); ctx.drawImage(document.getElementById('ggrr-256x256_1.png'), 100, 78, 50, 50, 0, 50, 50, -50); @@ -3101,6 +3072,11 @@ isPixel(ctx, 51,48, 0,255,0,255, 2); isPixel(ctx, 25,25, 0,255,0,255, 2); isPixel(ctx, 75,25, 0,255,0,255, 2); +} catch (e) { + _thrown_outer = true; +} +todo(!_thrown_outer, 'should not throw exception'); + } @@ -3118,6 +3094,9 @@ function test_2d_drawImage_negativesource() { var canvas = document.getElementById('c118'); var ctx = canvas.getContext('2d'); +var _thrown_outer = false; +try { + ctx.fillStyle = '#f00'; ctx.fillRect(0, 0, 100, 50); ctx.drawImage(document.getElementById('ggrr-256x256_2.png'), 100, 78, -100, 50, 0, 0, 50, 50); @@ -3133,6 +3112,11 @@ isPixel(ctx, 51,48, 0,255,0,255, 2); isPixel(ctx, 25,25, 0,255,0,255, 2); isPixel(ctx, 75,25, 0,255,0,255, 2); +} catch (e) { + _thrown_outer = true; +} +todo(!_thrown_outer, 'should not throw exception'); + } @@ -3528,10 +3512,12 @@ function test_2d_drawImage_outsidesource() { var canvas = document.getElementById('c122'); var ctx = canvas.getContext('2d'); +var _thrown_outer = false; +try { + ctx.drawImage(document.getElementById('green_7.png'), 10.5, 10.5, 89.5, 39.5, 0, 0, 100, 50); ctx.drawImage(document.getElementById('green_7.png'), 5.5, 5.5, -5.5, -5.5, 0, 0, 100, 50); ctx.drawImage(document.getElementById('green_7.png'), 100, 50, -5, -5, 0, 0, 100, 50); - var _thrown = undefined; try { ctx.drawImage(document.getElementById('red_11.png'), -0.001, 0, 100, 50, 0, 0, 100, 50); } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR"); @@ -3546,7 +3532,7 @@ var _thrown = undefined; try { } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR"); var _thrown = undefined; try { ctx.drawImage(document.getElementById('red_11.png'), 50, 0, 50.001, 50, 0, 0, 100, 50); -} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR"); +} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR"); var _thrown = undefined; try { ctx.drawImage(document.getElementById('red_11.png'), 0, 0, -5, 5, 0, 0, 100, 50); } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR"); @@ -3556,7 +3542,12 @@ var _thrown = undefined; try { var _thrown = undefined; try { ctx.drawImage(document.getElementById('red_11.png'), 110, 60, -20, -20, 0, 0, 100, 50); } catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR"); -isPixel(ctx, 50,25, 0,255,0,255, 2); +todo_isPixel(ctx, 50,25, 0,255,0,255, 2); + +} catch (e) { + _thrown_outer = true; +} +todo(!_thrown_outer, 'should not throw exception'); } @@ -3713,13 +3704,13 @@ ctx.fillStyle = '#0f0'; ctx.fillRect(0, 0, 100, 50); var _thrown = undefined; try { ctx.drawImage(document.getElementById('red_14.png'), 10, 10, 0, 1, 0, 0, 100, 50); -} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR"); +} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR"); var _thrown = undefined; try { ctx.drawImage(document.getElementById('red_14.png'), 10, 10, 1, 0, 0, 0, 100, 50); -} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR"); +} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR"); var _thrown = undefined; try { ctx.drawImage(document.getElementById('red_14.png'), 10, 10, 0, 0, 0, 0, 100, 50); -} catch (e) { _thrown = e }; ok(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR"); +} catch (e) { _thrown = e }; todo(_thrown && _thrown.code == DOMException.INDEX_SIZE_ERR, "should throw INDEX_SIZE_ERR"); isPixel(ctx, 50,25, 0,255,0,255, 2); @@ -19531,8 +19522,8 @@ ok(ctx.clip() === undefined, "ctx.clip() === undefined"); if (ctx.putImageData) { ok(ctx.putImageData(ctx.getImageData(0, 0, 1, 1), 0, 0) === undefined, "ctx.putImageData(ctx.getImageData(0, 0, 1, 1), 0, 0) === undefined"); } -ok(ctx.drawImage(document.getElementById('yellow_11.png'), 0, 0, 1, 1, 0, 0, 0, 0) === undefined, "ctx.drawImage(document.getElementById('yellow_11.png'), 0, 0, 1, 1, 0, 0, 0, 0) === undefined"); -ok(ctx.drawImage(canvas, 0, 0, 1, 1, 0, 0, 0, 0) === undefined, "ctx.drawImage(canvas, 0, 0, 1, 1, 0, 0, 0, 0) === undefined"); +ok(ctx.drawImage(document.getElementById('yellow_11.png'), 0, 0, 0, 0, 0, 0, 0, 0) === undefined, "ctx.drawImage(document.getElementById('yellow_11.png'), 0, 0, 0, 0, 0, 0, 0, 0) === undefined"); +ok(ctx.drawImage(canvas, 0, 0, 0, 0, 0, 0, 0, 0) === undefined, "ctx.drawImage(canvas, 0, 0, 0, 0, 0, 0, 0, 0) === undefined"); ok(ctx.createLinearGradient(0, 0, 0, 0).addColorStop(0, 'white') === undefined, "ctx.createLinearGradient(0, 0, 0, 0).addColorStop(0, 'white') === undefined"); @@ -21922,11 +21913,6 @@ function runTests() { } catch (e) { ok(false, "unexpected exception thrown in: test_2d_drawImage_incomplete"); } - try { - test_2d_drawImage_negativedir(); - } catch (e) { - ok(false, "unexpected exception thrown in: test_2d_drawImage_negativedir"); - } try { test_2d_drawImage_negativedest(); } catch (e) { diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 12e75cb78837..4e567d54319e 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -3228,6 +3228,16 @@ nsGenericHTMLFrameElement::CopyInnerTo(nsGenericElement* aDest) const return rv; } +PRInt64 +nsGenericHTMLFrameElement::SizeOf() const +{ + PRInt64 size = MemoryReporter::GetBasicSize(this); + // TODO: need to implement SizeOf() in nsFrameLoader, bug 672539. + size += mFrameLoader ? sizeof(*mFrameLoader.get()) : 0; + return size; +} + //---------------------------------------------------------------------- nsresult diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index 2fb072beeddb..a26af6187957 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -46,6 +46,7 @@ #include "nsFrameLoader.h" #include "nsGkAtoms.h" #include "nsContentCreatorFunctions.h" +#include "nsDOMMemoryReporter.h" class nsIDOMAttr; class nsIDOMEventListener; @@ -81,6 +82,9 @@ public: "Unexpected namespace"); } + NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsGenericHTMLElement, + nsGenericHTMLElementBase) + /** Typesafe, non-refcounting cast from nsIContent. Cheaper than QI. **/ static nsGenericHTMLElement* FromContent(nsIContent *aContent) { @@ -820,6 +824,9 @@ public: nsGenericHTMLFormElement(already_AddRefed aNodeInfo); virtual ~nsGenericHTMLFormElement(); + NS_DECL_AND_IMPL_DOM_MEMORY_REPORTER_SIZEOF(nsGenericHTMLFormElement, + nsGenericHTMLElement) + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); virtual PRBool IsNodeOfType(PRUint32 aFlags) const; @@ -1006,6 +1013,8 @@ public: } virtual ~nsGenericHTMLFrameElement(); + NS_DECL_DOM_MEMORY_REPORTER_SIZEOF + // nsISupports NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr); @@ -1535,7 +1544,6 @@ NS_DECLARE_NS_NEW_HTML_ELEMENT_AS_SHARED(Html) NS_DECLARE_NS_NEW_HTML_ELEMENT(IFrame) NS_DECLARE_NS_NEW_HTML_ELEMENT(Image) NS_DECLARE_NS_NEW_HTML_ELEMENT(Input) -NS_DECLARE_NS_NEW_HTML_ELEMENT(IsIndex) NS_DECLARE_NS_NEW_HTML_ELEMENT(LI) NS_DECLARE_NS_NEW_HTML_ELEMENT(Label) NS_DECLARE_NS_NEW_HTML_ELEMENT(Legend) diff --git a/content/html/content/src/nsHTMLButtonElement.cpp b/content/html/content/src/nsHTMLButtonElement.cpp index e8334c6ded8d..6523fbd541a7 100644 --- a/content/html/content/src/nsHTMLButtonElement.cpp +++ b/content/html/content/src/nsHTMLButtonElement.cpp @@ -392,7 +392,7 @@ nsHTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor) if (fm) fm->SetFocus(this, nsIFocusManager::FLAG_BYMOUSE | nsIFocusManager::FLAG_NOSCROLL); - aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_ANCHOR_ACTIONS; + aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS; } else if (static_cast(aVisitor.mEvent)->button == nsMouseEvent::eMiddleButton || static_cast(aVisitor.mEvent)->button == diff --git a/content/html/content/src/nsHTMLLabelElement.cpp b/content/html/content/src/nsHTMLLabelElement.cpp index 993795451105..766c9052dc5f 100644 --- a/content/html/content/src/nsHTMLLabelElement.cpp +++ b/content/html/content/src/nsHTMLLabelElement.cpp @@ -181,7 +181,9 @@ nsHTMLLabelElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor) (!NS_IS_MOUSE_LEFT_CLICK(aVisitor.mEvent) && aVisitor.mEvent->message != NS_MOUSE_BUTTON_DOWN) || aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault || - !aVisitor.mPresContext) { + !aVisitor.mPresContext || + // Don't handle the event if it's already been handled by another label + (aVisitor.mEvent->flags & NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS)) { return NS_OK; } @@ -256,8 +258,11 @@ nsHTMLLabelElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor) // will actually create a new event. DispatchClickEvent(aVisitor.mPresContext, static_cast(aVisitor.mEvent), - content, PR_FALSE, &status); + content, PR_FALSE, + NS_EVENT_FLAG_PREVENT_MULTIPLE_ACTIONS, &status); // Do we care about the status this returned? I don't think we do... + // Don't run another