diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml index 5108827f51e..e995702841f 100644 --- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -1459,7 +1459,8 @@ aTab.removeAttribute("fadein"); setTimeout(function (tab, tabbrowser) { - if (tab.parentNode) { + if (tab.parentNode && + window.getComputedStyle(tab).maxWidth == "0.1px") { NS_ASSERT(false, "Giving up waiting for the tab closing animation to finish (bug 608589)"); tabbrowser._endRemoveTab(tab); } diff --git a/browser/base/content/tabview/search.js b/browser/base/content/tabview/search.js index 0b8af0eed51..0cc4b94528e 100644 --- a/browser/base/content/tabview/search.js +++ b/browser/base/content/tabview/search.js @@ -336,7 +336,7 @@ SearchEventHandlerClass.prototype = { iQ("#searchbutton").mousedown(function() { self.initiatedBy = "buttonclick"; - ensureSearchShown(null); + ensureSearchShown(); self.switchToInMode(); }); @@ -347,30 +347,37 @@ SearchEventHandlerClass.prototype = { // ---------- // Function: beforeSearchKeyHandler - // Handles all keypresses before the search interface is brought up. + // Handles all keydown before the search interface is brought up. beforeSearchKeyHandler: function (event) { // Only match reasonable text-like characters for quick search. - // TODO: Also include funky chars. Bug 593904 - if (!String.fromCharCode(event.which).match(/[a-zA-Z0-9]/) || event.altKey || - event.ctrlKey || event.metaKey) + if (event.altKey || event.ctrlKey || event.metaKey) return; + if ((event.keyCode > 0 && event.keyCode <= event.DOM_VK_DELETE) || + event.keyCode == event.DOM_VK_CONTEXT_MENU || + event.keyCode == event.DOM_VK_SLEEP || + (event.keyCode >= event.DOM_VK_F1 && + event.keyCode <= event.DOM_VK_SCROLL_LOCK) || + event.keyCode == event.DOM_VK_META) { + return; + } + // If we are already in an input field, allow typing as normal. if (event.target.nodeName == "INPUT") return; this.switchToInMode(); - this.initiatedBy = "keypress"; - ensureSearchShown(event); + this.initiatedBy = "keydown"; + ensureSearchShown(); }, // ---------- // Function: inSearchKeyHandler - // Handles all keypresses while search mode. + // Handles all keydown while search mode. inSearchKeyHandler: function (event) { let term = iQ("#searchbox").val(); if ((event.keyCode == event.DOM_VK_ESCAPE) || - (event.keyCode == event.DOM_VK_BACK_SPACE && term.length <= 1 && this.initiatedBy == "keypress")) { + (event.keyCode == event.DOM_VK_BACK_SPACE && term.length <= 1 && this.initiatedBy == "keydown")) { hideSearch(event); return; } @@ -396,9 +403,9 @@ SearchEventHandlerClass.prototype = { switchToBeforeMode: function switchToBeforeMode() { let self = this; if (this.currentHandler) - iQ(window).unbind("keypress", this.currentHandler); + iQ(window).unbind("keydown", this.currentHandler); this.currentHandler = function(event) self.beforeSearchKeyHandler(event); - iQ(window).keypress(this.currentHandler); + iQ(window).keydown(this.currentHandler); }, // ---------- @@ -408,9 +415,9 @@ SearchEventHandlerClass.prototype = { switchToInMode: function switchToInMode() { let self = this; if (this.currentHandler) - iQ(window).unbind("keypress", this.currentHandler); + iQ(window).unbind("keydown", this.currentHandler); this.currentHandler = function(event) self.inSearchKeyHandler(event); - iQ(window).keypress(this.currentHandler); + iQ(window).keydown(this.currentHandler); } }; @@ -534,7 +541,7 @@ function performSearch() { matcher.doSearch(TabHandlers.onMatch, TabHandlers.onUnmatch, TabHandlers.onOther); } -function ensureSearchShown(event){ +function ensureSearchShown(){ var $search = iQ("#search"); var $searchShade = iQ("#searchshade"); var $searchbox = iQ("#searchbox"); @@ -546,17 +553,13 @@ function ensureSearchShown(event){ var mainWindow = gWindow.document.getElementById("main-window"); mainWindow.setAttribute("activetitlebarcolor", "#717171"); - // Marshal the focusing, otherwise you end up with - // a race condition where only sometimes would the - // first keystroke be registered by the search box. - // When you marshal it never gets registered, so we - // manually - setTimeout(function focusSearch() { - $searchbox[0].focus(); - $searchbox[0].val = '0'; - if (event != null) - $searchbox.val(String.fromCharCode(event.charCode)); + $searchbox[0].focus(); + $searchbox[0].val = '0'; + // NOTE: when this function is called by keydown handler, next keypress + // event or composition events of IME will be fired on the focused editor. + + setTimeout(function dispatchTabViewSearchEnabledEvent() { let newEvent = document.createEvent("Events"); newEvent.initEvent("tabviewsearchenabled", false, false); dispatchEvent(newEvent); diff --git a/browser/base/content/test/tabview/browser_tabview_bug595191.js b/browser/base/content/test/tabview/browser_tabview_bug595191.js index e4bc3d06600..d89501a823b 100644 --- a/browser/base/content/test/tabview/browser_tabview_bug595191.js +++ b/browser/base/content/test/tabview/browser_tabview_bug595191.js @@ -79,7 +79,7 @@ function escapeTest(contentWindow) { } contentWindow.addEventListener("tabviewsearchdisabled", onSearchDisabled, false); - EventUtils.synthesizeKey("VK_ESCAPE", { type: "keypress" }, contentWindow); + EventUtils.synthesizeKey("VK_ESCAPE", { }, contentWindow); } function toggleTabViewTest(contentWindow) { diff --git a/browser/themes/winstripe/browser/browser.css b/browser/themes/winstripe/browser/browser.css index 8160f5695d1..65c0cccda84 100644 --- a/browser/themes/winstripe/browser/browser.css +++ b/browser/themes/winstripe/browser/browser.css @@ -159,6 +159,14 @@ } } +%ifndef WINSTRIPE_AERO +@media all and (-moz-windows-default-theme) { + #main-window[sizemode="normal"] #appmenu-button { + margin-bottom: 5px; + } +} +%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); diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 3ed5616b636..d73da133c7b 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -285,6 +285,9 @@ public: * Get/Set the base target of a link in a document. */ virtual void GetBaseTarget(nsAString &aBaseTarget) = 0; + void SetBaseTarget(const nsString& aBaseTarget) { + mBaseTarget = aBaseTarget; + } /** * Return a standard name for the document's character set. @@ -1746,6 +1749,9 @@ protected: // The session history entry in which we're currently bf-cached. Non-null // if and only if we're currently in the bfcache. nsISHEntry* mSHEntry; + + // Our base target. + nsString mBaseTarget; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIDocument, NS_IDOCUMENT_IID) diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 67ee808b560..c1ad82a8208 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -2966,19 +2966,7 @@ nsDocument::SetBaseURI(nsIURI* aURI) void nsDocument::GetBaseTarget(nsAString &aBaseTarget) { - aBaseTarget.Truncate(); - Element* head = GetHeadElement(); - if (!head) { - return; - } - - for (ChildIterator iter(head); !iter.IsDone(); iter.Next()) { - nsIContent* child = iter; - if (child->NodeInfo()->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) && - child->GetAttr(kNameSpaceID_None, nsGkAtoms::target, aBaseTarget)) { - return; - } - } + aBaseTarget = mBaseTarget; } void diff --git a/content/base/src/nsDocument.h b/content/base/src/nsDocument.h index 7b1b3a971f0..f757f82b0be 100644 --- a/content/base/src/nsDocument.h +++ b/content/base/src/nsDocument.h @@ -1165,8 +1165,6 @@ protected: nsCOMPtr mScriptEventManager; - nsString mBaseTarget; - // Our update nesting level PRUint32 mUpdateNestLevel; diff --git a/content/base/src/nsXMLHttpRequest.cpp b/content/base/src/nsXMLHttpRequest.cpp index 381e2897e0d..7bb470466f6 100644 --- a/content/base/src/nsXMLHttpRequest.cpp +++ b/content/base/src/nsXMLHttpRequest.cpp @@ -1655,7 +1655,6 @@ nsXMLHttpRequest::OpenRequest(const nsACString& method, const nsAString& password) { NS_ENSURE_ARG(!method.IsEmpty()); - NS_ENSURE_ARG(!url.IsEmpty()); NS_ENSURE_TRUE(mPrincipal, NS_ERROR_NOT_INITIALIZED); diff --git a/content/base/test/Makefile.in b/content/base/test/Makefile.in index 0a2e83f8a22..232a9f6cb27 100644 --- a/content/base/test/Makefile.in +++ b/content/base/test/Makefile.in @@ -455,6 +455,7 @@ _TEST_FILES2 = \ test_bug590771.html \ test_bug622117.html \ test_bug622246.html \ + test_bug484396.html \ $(NULL) # This test fails on the Mac for some reason diff --git a/content/base/test/test_bug484396.html b/content/base/test/test_bug484396.html new file mode 100644 index 00000000000..058e2882c27 --- /dev/null +++ b/content/base/test/test_bug484396.html @@ -0,0 +1,49 @@ + + + + + Test for Bug 484396 + + + + + +Mozilla Bug 484396 +

+ +
+
+
+ + diff --git a/content/base/test/test_bug515401.html b/content/base/test/test_bug515401.html index a3ee50aede8..6f3c4b3f45d 100644 --- a/content/base/test/test_bug515401.html +++ b/content/base/test/test_bug515401.html @@ -108,13 +108,13 @@ head.insertBefore(basehref0, head.firstChild); verifyBase("base6/", "insert base with href before existing"); // Insert base as grandchild of head -var baseerr = document.createElement("base"); -baseerr.href = "baseerr/"; +var basehref3 = document.createElement("base"); +basehref3.href = "base7/"; var tmp = document.createElement("head"); -tmp.appendChild(baseerr); +tmp.appendChild(basehref3); head.insertBefore(tmp, head.firstChild); -verifyBase("base6/", "inserted base as grandchild of head"); -is(baseerr.parentNode.parentNode, head, "base got inserted correctly"); +verifyBase("base7/", "inserted base as grandchild of head at the beginning of head"); +is(basehref3.parentNode.parentNode, head, "base got inserted correctly"); // Remove secondary bases var tmp, tmp2; @@ -124,7 +124,7 @@ for (tmp = head.firstChild; tmp = tmp.nextSibling; tmp) { head.removeChild(tmp); tmp = tmp2; } - verifyBase("base6/", "remove unneeded base"); + verifyBase("base7/", "remove unneeded base"); } // Remove head @@ -132,8 +132,8 @@ document.documentElement.removeChild(head); verifyBase("", "removed head"); // Insert base in body -document.body.insertBefore(baseerr, document.body.firstChild); -verifyBase("", "inserted base in body"); +document.body.insertBefore(basehref3, document.body.firstChild); +verifyBase("base7/", "inserted base in body"); diff --git a/content/canvas/src/CustomQS_Canvas2D.h b/content/canvas/src/CustomQS_Canvas2D.h index f7eadc07dfe..72a91ecbd41 100644 --- a/content/canvas/src/CustomQS_Canvas2D.h +++ b/content/canvas/src/CustomQS_Canvas2D.h @@ -349,9 +349,12 @@ nsIDOMCanvasRenderingContext2D_PutImageData(JSContext *cx, uintN argc, jsval *vp hasDirtyRect = PR_TRUE; } - if (!JS_GetProperty(cx, dataObject, "data", tv.jsval_addr()) || - JSVAL_IS_PRIMITIVE(tv.jsval_value())) + if (!JS_GetProperty(cx, dataObject, "data", tv.jsval_addr())) return JS_FALSE; + + if (JSVAL_IS_PRIMITIVE(tv.jsval_value())) + return xpc_qsThrow(cx, NS_ERROR_DOM_TYPE_MISMATCH_ERR); + darray = JSVAL_TO_OBJECT(tv.jsval_value()); js::AutoValueRooter tsrc_tvr(cx); diff --git a/content/canvas/test/Makefile.in b/content/canvas/test/Makefile.in index 6c7dceb529e..5b72c37d1b3 100644 --- a/content/canvas/test/Makefile.in +++ b/content/canvas/test/Makefile.in @@ -81,6 +81,7 @@ _TEST_FILES_0 = \ test_2d.composite.uncovered.image.source-out.html \ test_mozGetAsFile.html \ test_canvas_strokeStyle_getter.html \ + test_bug613794.html \ $(NULL) ifneq (1_Linux,$(MOZ_SUITE)_$(OS_ARCH)) diff --git a/content/canvas/test/test_bug613794.html b/content/canvas/test/test_bug613794.html new file mode 100644 index 00000000000..830ea6ea5c3 --- /dev/null +++ b/content/canvas/test/test_bug613794.html @@ -0,0 +1,56 @@ + + + + + Test for Bug 613794 + + + + + +Mozilla Bug 613794 +

+ +
+
+
+ + diff --git a/content/html/content/src/nsHTMLButtonElement.cpp b/content/html/content/src/nsHTMLButtonElement.cpp index f50b0dc8f3a..a580b6fafa5 100644 --- a/content/html/content/src/nsHTMLButtonElement.cpp +++ b/content/html/content/src/nsHTMLButtonElement.cpp @@ -447,7 +447,7 @@ nsHTMLButtonElement::PostHandleEvent(nsEventChainPostVisitor& aVisitor) if (fm) fm->SetFocus(this, nsIFocusManager::FLAG_BYMOUSE | nsIFocusManager::FLAG_NOSCROLL); - aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault; + aVisitor.mEvent->flags |= NS_EVENT_FLAG_PREVENT_ANCHOR_ACTIONS; } else if (static_cast(aVisitor.mEvent)->button == nsMouseEvent::eMiddleButton || static_cast(aVisitor.mEvent)->button == diff --git a/content/html/content/src/nsHTMLSharedElement.cpp b/content/html/content/src/nsHTMLSharedElement.cpp index 8f017c36f70..a81c0b13751 100644 --- a/content/html/content/src/nsHTMLSharedElement.cpp +++ b/content/html/content/src/nsHTMLSharedElement.cpp @@ -377,18 +377,14 @@ nsHTMLSharedElement::IsAttributeMapped(const nsIAtom* aAttribute) const return nsGenericHTMLElement::IsAttributeMapped(aAttribute); } -void -SetBaseURIUsingFirstBaseWithHref(nsIContent* aHead, nsIContent* aMustMatch) +static void +SetBaseURIUsingFirstBaseWithHref(nsIDocument* aDocument, nsIContent* aMustMatch) { - NS_PRECONDITION(aHead && aHead->GetOwnerDoc() && - aHead->GetOwnerDoc()->GetHeadElement() == aHead, - "Bad head"); + NS_PRECONDITION(aDocument, "Need a document!"); - nsIDocument* doc = aHead->GetOwnerDoc(); - - for (nsINode::ChildIterator iter(aHead); !iter.IsDone(); iter.Next()) { - nsIContent* child = iter; - if (child->NodeInfo()->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) && + for (nsIContent* child = aDocument->GetFirstChild(); child; + child = child->GetNextNode()) { + if (child->IsHTML(nsGkAtoms::base) && child->HasAttr(kNameSpaceID_None, nsGkAtoms::href)) { if (aMustMatch && child != aMustMatch) { return; @@ -400,18 +396,43 @@ SetBaseURIUsingFirstBaseWithHref(nsIContent* aHead, nsIContent* aMustMatch) nsCOMPtr newBaseURI; nsContentUtils::NewURIWithDocumentCharset( - getter_AddRefs(newBaseURI), href, doc, doc->GetDocumentURI()); + getter_AddRefs(newBaseURI), href, aDocument, + aDocument->GetDocumentURI()); // Try to set our base URI. If that fails, try to set base URI to null - nsresult rv = doc->SetBaseURI(newBaseURI); + nsresult rv = aDocument->SetBaseURI(newBaseURI); if (NS_FAILED(rv)) { - doc->SetBaseURI(nsnull); + aDocument->SetBaseURI(nsnull); } return; } } - doc->SetBaseURI(nsnull); + aDocument->SetBaseURI(nsnull); +} + +static void +SetBaseTargetUsingFirstBaseWithTarget(nsIDocument* aDocument, + nsIContent* aMustMatch) +{ + NS_PRECONDITION(aDocument, "Need a document!"); + + for (nsIContent* child = aDocument->GetFirstChild(); child; + child = child->GetNextNode()) { + if (child->IsHTML(nsGkAtoms::base) && + child->HasAttr(kNameSpaceID_None, nsGkAtoms::target)) { + if (aMustMatch && child != aMustMatch) { + return; + } + + nsString target; + child->GetAttr(kNameSpaceID_None, nsGkAtoms::target, target); + aDocument->SetBaseTarget(target); + return; + } + } + + aDocument->SetBaseTarget(EmptyString()); } nsresult @@ -425,15 +446,16 @@ nsHTMLSharedElement::SetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, // If the href attribute of a tag is changing, we may need to update // the document's base URI, which will cause all the links on the page to be - // re-resolved given the new base. - nsIContent* head; - if (mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) && - aName == nsGkAtoms::href && + // re-resolved given the new base. If the target attribute is changing, we + // similarly need to change the base target. + if (mNodeInfo->Equals(nsGkAtoms::base) && aNameSpaceID == kNameSpaceID_None && - IsInDoc() && - (head = GetParent()) && - head == GetOwnerDoc()->GetHeadElement()) { - SetBaseURIUsingFirstBaseWithHref(head, this); + IsInDoc()) { + if (aName == nsGkAtoms::href) { + SetBaseURIUsingFirstBaseWithHref(GetCurrentDoc(), this); + } else if (aName == nsGkAtoms::target) { + SetBaseTargetUsingFirstBaseWithTarget(GetCurrentDoc(), this); + } } return NS_OK; @@ -448,15 +470,15 @@ nsHTMLSharedElement::UnsetAttr(PRInt32 aNameSpaceID, nsIAtom* aName, // If we're the first with an href and our href attribute is being // unset, then we're no longer the first with an href, and we need to - // find the new one. - nsIContent* head; - if (mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) && - aName == nsGkAtoms::href && + // find the new one. Similar for target. + if (mNodeInfo->Equals(nsGkAtoms::base) && aNameSpaceID == kNameSpaceID_None && - IsInDoc() && - (head = GetParent()) && - head == GetOwnerDoc()->GetHeadElement()) { - SetBaseURIUsingFirstBaseWithHref(head, nsnull); + IsInDoc()) { + if (aName == nsGkAtoms::href) { + SetBaseURIUsingFirstBaseWithHref(GetCurrentDoc(), nsnull); + } else if (aName == nsGkAtoms::target) { + SetBaseTargetUsingFirstBaseWithTarget(GetCurrentDoc(), nsnull); + } } return NS_OK; @@ -472,14 +494,16 @@ nsHTMLSharedElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, aCompileEventHandlers); NS_ENSURE_SUCCESS(rv, rv); - // The document stores a pointer to its first element, which we may + // The document stores a pointer to its base URI and base target, which we may // need to update here. - if (mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) && - HasAttr(kNameSpaceID_None, nsGkAtoms::href) && - aDocument && aParent && - aDocument->GetHeadElement() == aParent) { - - SetBaseURIUsingFirstBaseWithHref(aParent, this); + if (mNodeInfo->Equals(nsGkAtoms::base) && + aDocument) { + if (HasAttr(kNameSpaceID_None, nsGkAtoms::href)) { + SetBaseURIUsingFirstBaseWithHref(aDocument, this); + } + if (HasAttr(kNameSpaceID_None, nsGkAtoms::target)) { + SetBaseTargetUsingFirstBaseWithTarget(aDocument, this); + } } return NS_OK; @@ -488,27 +512,18 @@ nsHTMLSharedElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent, void nsHTMLSharedElement::UnbindFromTree(PRBool aDeep, PRBool aNullParent) { - nsIDocument* doc; - nsIContent* parent; - PRBool inHeadBase = mNodeInfo->Equals(nsGkAtoms::base, kNameSpaceID_XHTML) && - (doc = GetCurrentDoc()) && - (parent = GetParent()) && - parent->NodeInfo()->Equals(nsGkAtoms::head, - kNameSpaceID_XHTML); + nsIDocument* doc = GetCurrentDoc(); nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent); // If we're removing a from a document, we may need to update the - // document's record of the first base node. - if (inHeadBase) { - // We might have gotten here as a result of the being removed - // from the document. In that case we need to call SetBaseURI(nsnull) - Element* head = doc->GetHeadElement(); - if (head) { - SetBaseURIUsingFirstBaseWithHref(head, nsnull); + // document's base URI and base target + if (doc && mNodeInfo->Equals(nsGkAtoms::base)) { + if (HasAttr(kNameSpaceID_None, nsGkAtoms::href)) { + SetBaseURIUsingFirstBaseWithHref(doc, nsnull); } - else { - doc->SetBaseURI(nsnull); + if (HasAttr(kNameSpaceID_None, nsGkAtoms::target)) { + SetBaseTargetUsingFirstBaseWithTarget(doc, nsnull); } } } diff --git a/content/html/content/test/Makefile.in b/content/html/content/test/Makefile.in index c3ae3f247cc..a95c3ecc816 100644 --- a/content/html/content/test/Makefile.in +++ b/content/html/content/test/Makefile.in @@ -250,6 +250,7 @@ _TEST_FILES = \ test_bug601030.html \ test_bug610687.html \ test_bug618948.html \ + test_bug623291.html \ $(NULL) libs:: $(_TEST_FILES) diff --git a/content/html/content/test/test_bug623291.html b/content/html/content/test/test_bug623291.html new file mode 100644 index 00000000000..b0af6efc56b --- /dev/null +++ b/content/html/content/test/test_bug623291.html @@ -0,0 +1,47 @@ + + + + + Test for Bug 623291 + + + + + + +Mozilla Bug 623291 +

+ + + + +
+
+
+ + diff --git a/docshell/base/nsDSURIContentListener.cpp b/docshell/base/nsDSURIContentListener.cpp index e3a851fe628..357f9d2da78 100644 --- a/docshell/base/nsDSURIContentListener.cpp +++ b/docshell/base/nsDSURIContentListener.cpp @@ -146,6 +146,12 @@ nsDSURIContentListener::DoContent(const char* aContentType, } rv = mDocShell->CreateContentViewer(aContentType, request, aContentHandler); + + if (rv == NS_ERROR_REMOTE_XUL) { + request->Cancel(rv); + return NS_OK; + } + if (NS_FAILED(rv)) { // it's okay if we don't know how to handle the content return NS_OK; diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index ff6b8673191..ac0ab89cf89 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -3922,6 +3922,36 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI, // Bad Content Encoding. error.AssignLiteral("contentEncodingError"); break; + case NS_ERROR_REMOTE_XUL: + { + error.AssignLiteral("remoteXUL"); + + /** + * We want to set an hardcoded messageStr which uses the + * brandShortName. + */ + nsCOMPtr stringBundleService = + mozilla::services::GetStringBundleService(); + if (!stringBundleService) { + return NS_ERROR_FAILURE; + } + + nsCOMPtr brandBundle; + rv = stringBundleService->CreateBundle(kBrandBundleURL, + getter_AddRefs(brandBundle)); + NS_ENSURE_SUCCESS(rv, rv); + + nsXPIDLString brandName; + rv = brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(), + getter_Copies(brandName)); + + // We could use something like nsTextFormatter::smprintf. + messageStr.AssignLiteral("This page uses an unsupported technology " + "that is no longer available in "); + messageStr.Append(brandName); + messageStr.AppendLiteral("."); + break; + } case NS_ERROR_UNSAFE_CONTENT_TYPE: // Channel refused to load from an unrecognized content type. error.AssignLiteral("unsafeContentType"); @@ -6253,6 +6283,7 @@ nsDocShell::EndPageLoad(nsIWebProgress * aProgress, aStatus == NS_ERROR_MALWARE_URI || aStatus == NS_ERROR_PHISHING_URI || aStatus == NS_ERROR_UNSAFE_CONTENT_TYPE || + aStatus == NS_ERROR_REMOTE_XUL || NS_ERROR_GET_MODULE(aStatus) == NS_ERROR_MODULE_SECURITY) { DisplayLoadError(aStatus, url, nsnull, aChannel); } @@ -7292,7 +7323,7 @@ nsDocShell::CreateContentViewer(const char *aContentType, aContentHandler, getter_AddRefs(viewer)); if (NS_FAILED(rv)) - return NS_ERROR_FAILURE; + return rv; // Notify the current document that it is about to be unloaded!! // @@ -7474,14 +7505,14 @@ nsDocShell::NewContentViewerObj(const char *aContentType, // Now create an instance of the content viewer // nsLayoutDLF makes the determination if it should be a "view-source" instead of "view" - NS_ENSURE_SUCCESS(docLoaderFactory->CreateInstance("view", - aOpenedChannel, - aLoadGroup, aContentType, - static_cast(this), - nsnull, - aContentHandler, - aViewer), - NS_ERROR_FAILURE); + nsresult rv = docLoaderFactory->CreateInstance("view", + aOpenedChannel, + aLoadGroup, aContentType, + static_cast(this), + nsnull, + aContentHandler, + aViewer); + NS_ENSURE_SUCCESS(rv, rv); (*aViewer)->SetContainer(static_cast(this)); return NS_OK; diff --git a/docshell/base/nsDocShellEnumerator.cpp b/docshell/base/nsDocShellEnumerator.cpp index bd30defbc54..2866457382f 100644 --- a/docshell/base/nsDocShellEnumerator.cpp +++ b/docshell/base/nsDocShellEnumerator.cpp @@ -70,9 +70,11 @@ NS_IMETHODIMP nsDocShellEnumerator::GetNext(nsISupports **outCurItem) if (mCurIndex >= mItemArray.Length()) { return NS_ERROR_FAILURE; } - + // post-increment is important here - return CallQueryInterface(mItemArray[mCurIndex++], outCurItem); + nsCOMPtr item = do_QueryReferent(mItemArray[mCurIndex++], &rv); + item.forget(outCurItem); + return rv; } /* boolean hasMoreElements (); */ @@ -91,14 +93,14 @@ NS_IMETHODIMP nsDocShellEnumerator::HasMoreElements(PRBool *outHasMore) nsresult nsDocShellEnumerator::GetEnumerationRootItem(nsIDocShellTreeItem * *aEnumerationRootItem) { NS_ENSURE_ARG_POINTER(aEnumerationRootItem); - *aEnumerationRootItem = mRootItem; - NS_IF_ADDREF(*aEnumerationRootItem); + nsCOMPtr item = do_QueryReferent(mRootItem); + item.forget(aEnumerationRootItem); return NS_OK; } nsresult nsDocShellEnumerator::SetEnumerationRootItem(nsIDocShellTreeItem * aEnumerationRootItem) { - mRootItem = aEnumerationRootItem; + mRootItem = do_GetWeakReference(aEnumerationRootItem); ClearState(); return NS_OK; } @@ -142,14 +144,15 @@ nsresult nsDocShellEnumerator::ClearState() return NS_OK; } -nsresult nsDocShellEnumerator::BuildDocShellArray(nsTArray& inItemArray) +nsresult nsDocShellEnumerator::BuildDocShellArray(nsTArray& inItemArray) { NS_ENSURE_TRUE(mRootItem, NS_ERROR_NOT_INITIALIZED); inItemArray.Clear(); - return BuildArrayRecursive(mRootItem, inItemArray); + nsCOMPtr item = do_QueryReferent(mRootItem); + return BuildArrayRecursive(item, inItemArray); } -nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray) +nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray) { nsresult rv; nsCOMPtr itemAsNode = do_QueryInterface(inItem, &rv); @@ -160,7 +163,7 @@ nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* if ((mDocShellType == nsIDocShellTreeItem::typeAll) || (NS_SUCCEEDED(inItem->GetItemType(&itemType)) && (itemType == mDocShellType))) { - if (!inItemArray.AppendElement(inItem)) + if (!inItemArray.AppendElement(do_GetWeakReference(inItem))) return NS_ERROR_OUT_OF_MEMORY; } @@ -182,7 +185,7 @@ nsresult nsDocShellForwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* } -nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray) +nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray) { nsresult rv; nsCOMPtr itemAsNode = do_QueryInterface(inItem, &rv); @@ -207,7 +210,7 @@ nsresult nsDocShellBackwardsEnumerator::BuildArrayRecursive(nsIDocShellTreeItem* if ((mDocShellType == nsIDocShellTreeItem::typeAll) || (NS_SUCCEEDED(inItem->GetItemType(&itemType)) && (itemType == mDocShellType))) { - if (!inItemArray.AppendElement(inItem)) + if (!inItemArray.AppendElement(do_GetWeakReference(inItem))) return NS_ERROR_OUT_OF_MEMORY; } diff --git a/docshell/base/nsDocShellEnumerator.h b/docshell/base/nsDocShellEnumerator.h index e95aa876f19..eba22137e97 100644 --- a/docshell/base/nsDocShellEnumerator.h +++ b/docshell/base/nsDocShellEnumerator.h @@ -43,6 +43,8 @@ #include "nsCOMPtr.h" #include "nsTArray.h" +#include "nsIWeakReference.h" +#include "nsIWeakReferenceUtils.h" class nsIDocShellTreeItem; @@ -98,14 +100,14 @@ protected: nsresult EnsureDocShellArray(); nsresult ClearState(); - nsresult BuildDocShellArray(nsTArray& inItemArray); - virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray) = 0; + nsresult BuildDocShellArray(nsTArray& inItemArray); + virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray) = 0; protected: - nsIDocShellTreeItem* mRootItem; // weak ref! + nsWeakPtr mRootItem; // weak ref! - nsTArray mItemArray; // flattened list of items with matching type + nsTArray mItemArray; // flattened list of items with matching type PRUint32 mCurIndex; PRInt32 mDocShellType; // only want shells of this type @@ -126,7 +128,7 @@ public: protected: - virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray); + virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray); }; @@ -140,6 +142,6 @@ public: } protected: - virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray); + virtual nsresult BuildArrayRecursive(nsIDocShellTreeItem* inItem, nsTArray& inItemArray); }; diff --git a/docshell/resources/content/netError.xhtml b/docshell/resources/content/netError.xhtml index 4846134726d..901141f7987 100644 --- a/docshell/resources/content/netError.xhtml +++ b/docshell/resources/content/netError.xhtml @@ -186,6 +186,12 @@ showSecuritySection(); } + if (err == "remoteXUL") { + // Remove the "Try again" button for remote XUL errors given that + // it is useless. + document.getElementById("errorTryAgain").style.display = "none"; + } + if (err == "cspFrameAncestorBlocked") { // Remove the "Try again" button for CSP frame ancestors violation, since it's // almost certainly useless. (Bug 553180) @@ -322,6 +328,7 @@

&nssBadCert.title;

&malwareBlocked.title;

&cspFrameAncestorBlocked.title;

+

Remote XUL

&generic.longDesc;
@@ -345,6 +352,7 @@
&nssBadCert.longDesc2;
&malwareBlocked.longDesc;
&cspFrameAncestorBlocked.longDesc;
+
  • Please contact the website owners to inform them of this problem.
diff --git a/dom/plugins/PluginInstanceChild.cpp b/dom/plugins/PluginInstanceChild.cpp index 1554a6e7b71..d71dc1c3219 100644 --- a/dom/plugins/PluginInstanceChild.cpp +++ b/dom/plugins/PluginInstanceChild.cpp @@ -2544,7 +2544,6 @@ PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect, if (mMaemoImageRendering && aSurface->GetType() == gfxASurface::SurfaceTypeImage) { aSurface->Flush(); - mPendingPluginCall = PR_TRUE; gfxImageSurface* image = static_cast(aSurface); NPImageExpose imgExp; imgExp.depth = gfxUtils::ImageFormatToDepth(image->Format()); @@ -2577,14 +2576,12 @@ PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect, exposeEvent.major_code = 0; exposeEvent.minor_code = 0; mPluginIface->event(&mData, reinterpret_cast(&exposeEvent)); - mPendingPluginCall = PR_FALSE; return; } #endif NS_ASSERTION(aSurface->GetType() == gfxASurface::SurfaceTypeXlib, "Non supported platform surface type"); - mPendingPluginCall = true; NPEvent pluginEvent; XGraphicsExposeEvent& exposeEvent = pluginEvent.xgraphicsexpose; exposeEvent.type = GraphicsExpose; @@ -2601,7 +2598,6 @@ PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect, exposeEvent.major_code = 0; exposeEvent.minor_code = 0; mPluginIface->event(&mData, reinterpret_cast(&exposeEvent)); - mPendingPluginCall = false; return; #endif @@ -2609,8 +2605,6 @@ PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect, NS_ASSERTION(SharedDIBSurface::IsSharedDIBSurface(aSurface), "Expected (SharedDIB) image surface."); - mPendingPluginCall = true; - // This rect is in the window coordinate space. aRect is in the plugin // coordinate space. RECT rect = { @@ -2627,7 +2621,6 @@ PluginInstanceChild::PaintRectToPlatformSurface(const nsIntRect& aRect, ::SetViewportOrgEx((HDC) mWindow.window, -mWindow.x, -mWindow.y, NULL); mPluginIface->event(&mData, reinterpret_cast(&paintEvent)); - mPendingPluginCall = false; return; #endif @@ -2737,6 +2730,9 @@ PluginInstanceChild::ShowPluginFrame() return false; } + AutoRestore pending(mPendingPluginCall); + mPendingPluginCall = true; + if (!EnsureCurrentBuffer()) { return false; } diff --git a/embedding/components/printingui/src/win/nsPrintDialogUtil.cpp b/embedding/components/printingui/src/win/nsPrintDialogUtil.cpp index 355bc110562..8355795ff08 100644 --- a/embedding/components/printingui/src/win/nsPrintDialogUtil.cpp +++ b/embedding/components/printingui/src/win/nsPrintDialogUtil.cpp @@ -872,11 +872,6 @@ ShowNativePrintDialog(HWND aHWnd, } } - NS_ASSERTION(!printerName.IsEmpty(), "We have to have a printer name"); - if (printerName.IsEmpty()) { - return NS_ERROR_FAILURE; - } - // Now create a DEVNAMES struct so the the dialog is initialized correctly. PRUint32 len = printerName.Length(); diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index 8d9f36599b1..c800d7ce770 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -691,6 +691,43 @@ gfxWindowsPlatform::WindowsOSVersion() return winVersion; } +void +gfxWindowsPlatform::GetDLLVersion(PRUnichar *aDLLPath, nsAString& aVersion) +{ + DWORD versInfoSize, vers[4] = {0}; + // version info not available case + aVersion.Assign(NS_LITERAL_STRING("0.0.0.0")); + versInfoSize = GetFileVersionInfoSizeW(aDLLPath, NULL); + nsAutoTArray versionInfo; + + if (!versionInfo.AppendElements(PRUint32(versInfoSize))) { + return; + } + if (!GetFileVersionInfoW(aDLLPath, NULL, versInfoSize, + LPBYTE(versionInfo.Elements()))) { + return; + } + + UINT len; + VS_FIXEDFILEINFO *fileInfo; + if (!VerQueryValue(LPBYTE(versionInfo.Elements()), TEXT("\\"), + (LPVOID *)&fileInfo , &len)) { + return; + } + + DWORD fileVersMS = fileInfo->dwFileVersionMS; + DWORD fileVersLS = fileInfo->dwFileVersionLS; + + vers[0] = HIWORD(fileVersMS); + vers[1] = LOWORD(fileVersMS); + vers[2] = HIWORD(fileVersLS); + vers[3] = LOWORD(fileVersLS); + + char buf[256]; + sprintf(buf, "%d.%d.%d.%d", vers[0], vers[1], vers[2], vers[3]); + aVersion.Assign(NS_ConvertUTF8toUTF16(buf)); +} + void gfxWindowsPlatform::FontsPrefsChanged(nsIPrefBranch *aPrefBranch, const char *aPref) { diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h index 5e3b9ff76af..f963c24acdb 100644 --- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -227,6 +227,8 @@ public: static PRInt32 WindowsOSVersion(); + static void GetDLLVersion(PRUnichar *aDLLPath, nsAString& aVersion); + virtual void FontsPrefsChanged(nsIPrefBranch *aPrefBranch, const char *aPref); #ifdef CAIRO_HAS_DWRITE_FONT diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp index 767731d986b..24bd56d9fd6 100644 --- a/layout/base/nsCSSFrameConstructor.cpp +++ b/layout/base/nsCSSFrameConstructor.cpp @@ -8791,9 +8791,29 @@ nsCSSFrameConstructor::ReplicateFixedFrames(nsPageContentFrame* aParentFrame) nsIFrame* prevPlaceholder = mPresShell->FrameManager()->GetPlaceholderFrameFor(fixed); if (prevPlaceholder && nsLayoutUtils::IsProperAncestorFrame(prevCanvasFrame, prevPlaceholder)) { - nsresult rv = ConstructFrame(state, fixed->GetContent(), - canvasFrame, fixedPlaceholders); - NS_ENSURE_SUCCESS(rv, rv); + // We want to use the same style as the primary style frame for + // our content + nsIContent* content = fixed->GetContent(); + nsStyleContext* styleContext = + nsLayoutUtils::GetStyleFrame(content->GetPrimaryFrame())-> + GetStyleContext(); + FrameConstructionItemList items; + AddFrameConstructionItemsInternal(state, content, canvasFrame, + content->Tag(), + content->GetNameSpaceID(), + PR_TRUE, + styleContext, + ITEM_ALLOW_XBL_BASE | + ITEM_ALLOW_PAGE_BREAK, + items); + for (FCItemIterator iter(items); !iter.IsDone(); iter.Next()) { + NS_ASSERTION(iter.item().DesiredParentType() == + GetParentType(canvasFrame), + "This is not going to work"); + nsresult rv = + ConstructFramesFromItem(state, iter, canvasFrame, fixedPlaceholders); + NS_ENSURE_SUCCESS(rv, rv); + } } } diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index efd130be42d..5d32095e3a1 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -2288,7 +2288,7 @@ nsCSSRendering::PaintBackgroundWithSC(nsPresContext* aPresContext, currentBackgroundClip = bg->BottomLayer().mClip; isSolidBorder = (aFlags & PAINTBG_WILL_PAINT_BORDER) && IsOpaqueBorder(aBorder); - if (isSolidBorder) + if (isSolidBorder && currentBackgroundClip == NS_STYLE_BG_CLIP_BORDER) currentBackgroundClip = NS_STYLE_BG_CLIP_PADDING; SetupBackgroundClip(ctx, currentBackgroundClip, aForFrame, aBorderArea, aDirtyRect, haveRoundedCorners, diff --git a/layout/build/nsContentDLF.cpp b/layout/build/nsContentDLF.cpp index bc364a2d64b..67dda37f53e 100644 --- a/layout/build/nsContentDLF.cpp +++ b/layout/build/nsContentDLF.cpp @@ -281,8 +281,11 @@ nsContentDLF::CreateInstance(const char* aCommand, // Try XUL typeIndex = 0; while (gXULTypes[typeIndex]) { - if (0 == PL_strcmp(gXULTypes[typeIndex++], aContentType) && - MayUseXULXBL(aChannel)) { + if (0 == PL_strcmp(gXULTypes[typeIndex++], aContentType)) { + if (!MayUseXULXBL(aChannel)) { + return NS_ERROR_REMOTE_XUL; + } + return CreateXULDocument(aCommand, aChannel, aLoadGroup, aContentType, aContainer, diff --git a/layout/printing/nsPrintObject.cpp b/layout/printing/nsPrintObject.cpp index 61caf9cee43..86814d6e6d4 100644 --- a/layout/printing/nsPrintObject.cpp +++ b/layout/printing/nsPrintObject.cpp @@ -44,14 +44,15 @@ #include "nsGkAtoms.h" #include "nsComponentManagerUtils.h" #include "nsIDocShellTreeItem.h" - +#include "nsIBaseWindow.h" + //--------------------------------------------------- //-- nsPrintObject Class Impl //--------------------------------------------------- nsPrintObject::nsPrintObject() : mContent(nsnull), mFrameType(eFrame), mParent(nsnull), mHasBeenPrinted(PR_FALSE), mDontPrint(PR_TRUE), mPrintAsIs(PR_FALSE), - mSharedPresShell(PR_FALSE), mInvisible(PR_FALSE), + mSharedPresShell(PR_FALSE), mInvisible(PR_FALSE), mDidCreateDocShell(PR_FALSE), mShrinkRatio(1.0), mZoomRatio(1.0) { } @@ -65,6 +66,12 @@ nsPrintObject::~nsPrintObject() } DestroyPresentation(); + if (mDidCreateDocShell && mDocShell) { + nsCOMPtr baseWin(do_QueryInterface(mDocShell)); + if (baseWin) { + baseWin->Destroy(); + } + } mDocShell = nsnull; mTreeOwner = nsnull; // mTreeOwner must be released after mDocShell; } @@ -86,6 +93,7 @@ nsPrintObject::Init(nsIDocShell* aDocShell, nsIDOMDocument* aDoc, // Create a container docshell for printing. mDocShell = do_CreateInstance("@mozilla.org/docshell;1"); NS_ENSURE_TRUE(mDocShell, NS_ERROR_OUT_OF_MEMORY); + mDidCreateDocShell = PR_TRUE; nsCOMPtr newItem = do_QueryInterface(mDocShell); newItem->SetItemType(itemType); newItem->SetTreeOwner(mTreeOwner); diff --git a/layout/printing/nsPrintObject.h b/layout/printing/nsPrintObject.h index a57839db7d4..6521e8a5cc5 100644 --- a/layout/printing/nsPrintObject.h +++ b/layout/printing/nsPrintObject.h @@ -89,6 +89,7 @@ public: PRPackedBool mSharedPresShell; PRPackedBool mInvisible; // Indicates PO is set to not visible by CSS PRPackedBool mPrintPreview; + PRPackedBool mDidCreateDocShell; float mShrinkRatio; float mZoomRatio; diff --git a/layout/reftests/backgrounds/background-clip-2-ref.html b/layout/reftests/backgrounds/background-clip-2-ref.html new file mode 100644 index 00000000000..15b521ae0e6 --- /dev/null +++ b/layout/reftests/backgrounds/background-clip-2-ref.html @@ -0,0 +1,12 @@ + + + +
+
+
+
+ + diff --git a/layout/reftests/backgrounds/background-clip-2.html b/layout/reftests/backgrounds/background-clip-2.html new file mode 100644 index 00000000000..2a10493d91e --- /dev/null +++ b/layout/reftests/backgrounds/background-clip-2.html @@ -0,0 +1,12 @@ + + + +
+
+ + diff --git a/layout/reftests/backgrounds/reftest.list b/layout/reftests/backgrounds/reftest.list index f60abb5c5e4..367014bc87b 100644 --- a/layout/reftests/backgrounds/reftest.list +++ b/layout/reftests/backgrounds/reftest.list @@ -27,6 +27,7 @@ == background-redraw-237766.html background-redraw-237766-ref.html == background-clip-1.html background-clip-1-ref.html +== background-clip-2.html background-clip-2-ref.html == background-size-auto-auto.html background-size-auto-ref.html == background-size-auto.html background-size-auto-ref.html diff --git a/layout/reftests/printing/577450-1-ref.html b/layout/reftests/printing/577450-1-ref.html new file mode 100644 index 00000000000..ac75351151b --- /dev/null +++ b/layout/reftests/printing/577450-1-ref.html @@ -0,0 +1,8 @@ + + + +
Big green text
+ +
+ + diff --git a/layout/reftests/printing/577450-1.html b/layout/reftests/printing/577450-1.html new file mode 100644 index 00000000000..a30c84ef32a --- /dev/null +++ b/layout/reftests/printing/577450-1.html @@ -0,0 +1,8 @@ + + + +
Big green text
+ +
+ + diff --git a/layout/reftests/printing/reftest.list b/layout/reftests/printing/reftest.list index 615d87ecb35..234ad055db4 100644 --- a/layout/reftests/printing/reftest.list +++ b/layout/reftests/printing/reftest.list @@ -9,3 +9,4 @@ == test-async-print.html 272830-1-ref.html == 129941-1a.html 129941-1-ref.html == 129941-1b.html 129941-1-ref.html +== 577450-1.html 577450-1-ref.html diff --git a/modules/plugin/base/src/nsPluginTags.cpp b/modules/plugin/base/src/nsPluginTags.cpp index 65bef582252..2301444078b 100644 --- a/modules/plugin/base/src/nsPluginTags.cpp +++ b/modules/plugin/base/src/nsPluginTags.cpp @@ -285,7 +285,7 @@ static nsresult ConvertToUTF8(nsIUnicodeDecoder *aUnicodeDecoder, nsresult nsPluginTag::EnsureMembersAreUTF8() { -#ifdef XP_WIN +#if defined(XP_WIN) || defined(XP_MACOSX) return NS_OK; #else nsresult rv; diff --git a/modules/plugin/base/src/nsPluginsDirDarwin.cpp b/modules/plugin/base/src/nsPluginsDirDarwin.cpp index 3387c1bd47a..3736d7fc53a 100644 --- a/modules/plugin/base/src/nsPluginsDirDarwin.cpp +++ b/modules/plugin/base/src/nsPluginsDirDarwin.cpp @@ -124,12 +124,27 @@ PRBool nsPluginsDir::IsPluginFile(nsIFile* file) // Caller is responsible for freeing returned buffer. static char* CFStringRefToUTF8Buffer(CFStringRef cfString) { - int bufferLength = ::CFStringGetLength(cfString) + 1; - char* newBuffer = static_cast(NS_Alloc(bufferLength)); - if (newBuffer && !::CFStringGetCString(cfString, newBuffer, bufferLength, kCFStringEncodingUTF8)) { - NS_Free(newBuffer); - newBuffer = nsnull; + const char* buffer = ::CFStringGetCStringPtr(cfString, kCFStringEncodingUTF8); + if (buffer) { + return PL_strdup(buffer); } + + int bufferLength = + ::CFStringGetMaximumSizeForEncoding(::CFStringGetLength(cfString), + kCFStringEncodingUTF8) + 1; + char* newBuffer = static_cast(NS_Alloc(bufferLength)); + if (!newBuffer) { + return nsnull; + } + + if (!::CFStringGetCString(cfString, newBuffer, bufferLength, + kCFStringEncodingUTF8)) { + NS_Free(newBuffer); + return nsnull; + } + + newBuffer = static_cast(NS_Realloc(newBuffer, + PL_strlen(newBuffer) + 1)); return newBuffer; } diff --git a/modules/plugin/test/mochitest/Makefile.in b/modules/plugin/test/mochitest/Makefile.in index 223dde90885..b5a0fbbdc3a 100644 --- a/modules/plugin/test/mochitest/Makefile.in +++ b/modules/plugin/test/mochitest/Makefile.in @@ -129,8 +129,6 @@ _MOCHICHROME_FILES += \ $(NULL) endif -# Temporarily disable the tests on Linux, see bug 573290 and bug 583591. -ifneq ($(OS_ARCH),Linux) ifdef MOZ_CRASHREPORTER _MOCHICHROME_FILES += \ test_crash_notify.xul \ @@ -138,7 +136,6 @@ _MOCHICHROME_FILES += \ test_crash_submit.xul \ $(NULL) endif -endif ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT)) _MOCHICHROME_FILES += \ diff --git a/netwerk/base/public/nsNetError.h b/netwerk/base/public/nsNetError.h index ccc7d06e7e7..b00a777632f 100644 --- a/netwerk/base/public/nsNetError.h +++ b/netwerk/base/public/nsNetError.h @@ -240,6 +240,14 @@ #define NS_ERROR_UNSAFE_CONTENT_TYPE \ NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 74) +/** + * The request failed because the user tried to access to a remote XUL document + * from a website that is not in its white-list. + */ +#define NS_ERROR_REMOTE_XUL \ + NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 75) + + /****************************************************************************** * FTP specific error codes: * diff --git a/parser/html/nsHtml5TreeBuilderCppSupplement.h b/parser/html/nsHtml5TreeBuilderCppSupplement.h index 9bd4793dea8..9d91b9b9f4f 100644 --- a/parser/html/nsHtml5TreeBuilderCppSupplement.h +++ b/parser/html/nsHtml5TreeBuilderCppSupplement.h @@ -149,9 +149,7 @@ nsHtml5TreeBuilder::createElement(PRInt32 aNamespace, nsIAtom* aName, nsHtml5Htm if (url) { mSpeculativeLoadQueue.AppendElement()->InitManifest(*url); } - } else if (nsHtml5Atoms::base == aName && - (mode == NS_HTML5TREE_BUILDER_IN_HEAD || - mode == NS_HTML5TREE_BUILDER_AFTER_HEAD)) { + } else if (nsHtml5Atoms::base == aName) { nsString* url = aAttributes->getValue(nsHtml5AttributeName::ATTR_HREF); if (url) { diff --git a/testing/mochitest/tests/SimpleTest/EventUtils.js b/testing/mochitest/tests/SimpleTest/EventUtils.js index de525c30736..365c4cb751a 100644 --- a/testing/mochitest/tests/SimpleTest/EventUtils.js +++ b/testing/mochitest/tests/SimpleTest/EventUtils.js @@ -299,6 +299,81 @@ function synthesizeMouseScroll(aTarget, aOffsetX, aOffsetY, aEvent, aWindow) } } +function _computeKeyCodeFromChar(aChar) +{ + if (aChar.length != 1) { + return 0; + } + const nsIDOMKeyEvent = Components.interfaces.nsIDOMKeyEvent; + if (aChar >= 'a' && aChar <= 'z') { + return nsIDOMKeyEvent.DOM_VK_A + aChar.charCodeAt(0) - 'a'.charCodeAt(0); + } + if (aChar >= 'A' && aChar <= 'Z') { + return nsIDOMKeyEvent.DOM_VK_A + aChar.charCodeAt(0) - 'A'.charCodeAt(0); + } + if (aChar >= '0' && aChar <= '9') { + return nsIDOMKeyEvent.DOM_VK_0 + aChar.charCodeAt(0) - '0'.charCodeAt(0); + } + // returns US keyboard layout's keycode + switch (aChar) { + case '~': + case '`': + return nsIDOMKeyEvent.DOM_VK_BACK_QUOTE; + case '!': + return nsIDOMKeyEvent.DOM_VK_1; + case '@': + return nsIDOMKeyEvent.DOM_VK_2; + case '#': + return nsIDOMKeyEvent.DOM_VK_3; + case '$': + return nsIDOMKeyEvent.DOM_VK_4; + case '%': + return nsIDOMKeyEvent.DOM_VK_5; + case '^': + return nsIDOMKeyEvent.DOM_VK_6; + case '&': + return nsIDOMKeyEvent.DOM_VK_7; + case '*': + return nsIDOMKeyEvent.DOM_VK_8; + case '(': + return nsIDOMKeyEvent.DOM_VK_9; + case ')': + return nsIDOMKeyEvent.DOM_VK_0; + case '-': + case '_': + return nsIDOMKeyEvent.DOM_VK_SUBTRACT; + case '+': + case '=': + return nsIDOMKeyEvent.DOM_VK_EQUALS; + case '{': + case '[': + return nsIDOMKeyEvent.DOM_VK_OPEN_BRACKET; + case '}': + case ']': + return nsIDOMKeyEvent.DOM_VK_CLOSE_BRACKET; + case '|': + case '\\': + return nsIDOMKeyEvent.DOM_VK_BACK_SLASH; + case ':': + case ';': + return nsIDOMKeyEvent.DOM_VK_SEMICOLON; + case '\'': + case '"': + return nsIDOMKeyEvent.DOM_VK_QUOTE; + case '<': + case ',': + return nsIDOMKeyEvent.DOM_VK_COMMA; + case '>': + case '.': + return nsIDOMKeyEvent.DOM_VK_PERIOD; + case '?': + case '/': + return nsIDOMKeyEvent.DOM_VK_SLASH; + default: + return 0; + } +} + /** * Synthesize a key event. It is targeted at whatever would be targeted by an * actual keypress by the user, typically the focused element. @@ -327,20 +402,24 @@ function synthesizeKey(aKey, aEvent, aWindow) var keyCode = 0, charCode = 0; if (aKey.indexOf("VK_") == 0) keyCode = KeyEvent["DOM_" + aKey]; - else + else { charCode = aKey.charCodeAt(0); + keyCode = _computeKeyCodeFromChar(aKey.charAt(0)); + } var modifiers = _parseModifiers(aEvent); - if (aEvent.type) { - utils.sendKeyEvent(aEvent.type, keyCode, charCode, modifiers); - } - else { + if (aEvent.type == "keypress") { + utils.sendKeyEvent(aEvent.type, charCode ? 0 : keyCode, + charCode, modifiers); + } else if (aEvent.type) { + utils.sendKeyEvent(aEvent.type, keyCode, 0, modifiers); + } else { var keyDownDefaultHappened = - utils.sendKeyEvent("keydown", keyCode, charCode, modifiers); - utils.sendKeyEvent("keypress", keyCode, charCode, modifiers, - !keyDownDefaultHappened); - utils.sendKeyEvent("keyup", keyCode, charCode, modifiers); + utils.sendKeyEvent("keydown", keyCode, 0, modifiers); + utils.sendKeyEvent("keypress", charCode ? 0 : keyCode, charCode, + modifiers, !keyDownDefaultHappened); + utils.sendKeyEvent("keyup", keyCode, 0, modifiers); } } } diff --git a/toolkit/components/commandlines/src/nsCommandLine.cpp b/toolkit/components/commandlines/src/nsCommandLine.cpp index e4008d1b8ec..79de9e6c3c3 100644 --- a/toolkit/components/commandlines/src/nsCommandLine.cpp +++ b/toolkit/components/commandlines/src/nsCommandLine.cpp @@ -58,7 +58,7 @@ #include "nsXPCOMCID.h" #include "plstr.h" -#ifdef XP_MACOSX +#ifdef MOZ_WIDGET_COCOA #include #include "nsILocalFileMac.h" #elif defined(XP_WIN) @@ -287,7 +287,7 @@ nsCommandLine::ResolveFile(const nsAString& aArgument, nsIFile* *aResult) nsresult rv; -#if defined(XP_MACOSX) +#if defined(MOZ_WIDGET_COCOA) nsCOMPtr lfm (do_QueryInterface(mWorkingDir)); NS_ENSURE_TRUE(lfm, NS_ERROR_NO_INTERFACE); diff --git a/toolkit/components/places/tests/bookmarks/test_393498.js b/toolkit/components/places/tests/bookmarks/test_393498.js index 24de9d47b68..1e39177fdd9 100644 --- a/toolkit/components/places/tests/bookmarks/test_393498.js +++ b/toolkit/components/places/tests/bookmarks/test_393498.js @@ -82,9 +82,9 @@ function run_test() { bmsvc.DEFAULT_INDEX, ""); do_check_true(observer.itemChangedProperty == null); - // We set lastModified 1us in the past to workaround a timing bug on + // We set lastModified in the past to workaround a timing bug on // virtual machines, see bug 427142 for details. - var newDate = Date.now() * 1000 - 1; + var newDate = (Date.now() - 10) * 1000; bmsvc.setItemDateAdded(bookmarkId, newDate); // test notification do_check_eq(observer._itemChangedProperty, "dateAdded"); @@ -129,7 +129,7 @@ function run_test() { // test live update of lastModified caused by other changes: // We set lastModified in the past to workaround timers resolution, // see bug 427142 for details. - var pastDate = Date.now() * 1000 - 20000; + var pastDate = (Date.now() - 10) * 1000; bmsvc.setItemLastModified(bookmarkId, pastDate); // set title (causing update of last modified) var oldLastModified = bmsvc.getItemLastModified(bookmarkId); diff --git a/toolkit/content/aboutSupport.js b/toolkit/content/aboutSupport.js index 3e3f3d1e75b..64613d6ee3e 100644 --- a/toolkit/content/aboutSupport.js +++ b/toolkit/content/aboutSupport.js @@ -233,12 +233,16 @@ function populateGraphicsSection() { ])); var dwEnabled = false; + var dwriteEnabledStr = dwEnabled.toString(); + var dwriteVersion; try { dwEnabled = gfxInfo.DWriteEnabled; + dwriteVersion = gfxInfo.DWriteVersion; + dwriteEnabledStr = dwEnabled.toString() + " (" + dwriteVersion + ")"; } catch(e) {} trGraphics.push(createParentElement("tr", [ createHeader(bundle.GetStringFromName("directWriteEnabled")), - createElement("td", dwEnabled), + createElement("td", dwriteEnabledStr), ])); var webglrenderer; diff --git a/toolkit/crashreporter/Makefile.in b/toolkit/crashreporter/Makefile.in index 6e518490458..ba0f31989dd 100644 --- a/toolkit/crashreporter/Makefile.in +++ b/toolkit/crashreporter/Makefile.in @@ -122,10 +122,7 @@ EXTRA_JS_MODULES = \ $(NULL) ifdef ENABLE_TESTS -# Temporarily disable the tests on Linux, see bug 573290 and bug 583591 -ifneq ($(OS_ARCH),Linux) TOOL_DIRS = test endif -endif include $(topsrcdir)/config/rules.mk diff --git a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h index a80a5efd0f7..f3f7767711f 100644 --- a/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h +++ b/toolkit/crashreporter/google-breakpad/src/google_breakpad/processor/minidump.h @@ -79,7 +79,9 @@ #ifndef GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__ #define GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__ +#ifndef _WIN32 #include +#endif #include #include diff --git a/toolkit/crashreporter/google-breakpad/src/processor/logging.cc b/toolkit/crashreporter/google-breakpad/src/processor/logging.cc index 8842df35c1f..c58fb8dd21c 100644 --- a/toolkit/crashreporter/google-breakpad/src/processor/logging.cc +++ b/toolkit/crashreporter/google-breakpad/src/processor/logging.cc @@ -44,13 +44,21 @@ namespace google_breakpad { +#ifdef _WIN32 +#define snprintf _snprintf +#endif + LogStream::LogStream(std::ostream &stream, Severity severity, const char *file, int line) : stream_(stream) { time_t clock; time(&clock); struct tm tm_struct; +#ifdef _WIN32 + localtime_s(&tm_struct, &clock); +#else localtime_r(&clock, &tm_struct); +#endif char time_string[20]; strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", &tm_struct); diff --git a/toolkit/crashreporter/google-breakpad/src/processor/logging.h b/toolkit/crashreporter/google-breakpad/src/processor/logging.h index b638ff5890f..642506d5d6c 100644 --- a/toolkit/crashreporter/google-breakpad/src/processor/logging.h +++ b/toolkit/crashreporter/google-breakpad/src/processor/logging.h @@ -68,6 +68,15 @@ namespace google_breakpad { +// These are defined in Microsoft headers. +#ifdef SEVERITY_ERROR +#undef SEVERITY_ERROR +#endif + +#ifdef ERROR +#undef ERROR +#endif + class LogStream { public: enum Severity { diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc index 1e3f3a43ed7..9736c6dd1d6 100644 --- a/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc +++ b/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc @@ -40,14 +40,15 @@ #include #include #include -#include + #ifdef _WIN32 #include typedef SSIZE_T ssize_t; -#define open _open -#define read _read -#define lseek _lseek +#define PRIx64 "llx" +#define PRIx32 "lx" +#define snprintf _snprintf #else // _WIN32 +#include #define O_BINARY 0 #endif // _WIN32 @@ -1101,7 +1102,7 @@ void MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) { descriptor_ = descriptor; valid_ = descriptor && descriptor_->memory.data_size <= - numeric_limits::max() - + numeric_limits::max() - descriptor_->start_of_memory_range; } @@ -3688,7 +3689,11 @@ void Minidump::Print() { printf(" stream_directory_rva = 0x%x\n", header_.stream_directory_rva); printf(" checksum = 0x%x\n", header_.checksum); struct tm timestruct; +#ifdef _WIN32 + gmtime_s(×truct, reinterpret_cast(&header_.time_date_stamp)); +#else gmtime_r(reinterpret_cast(&header_.time_date_stamp), ×truct); +#endif char timestr[20]; strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", ×truct); printf(" time_date_stamp = 0x%x %s\n", header_.time_date_stamp, diff --git a/toolkit/crashreporter/nsExceptionHandler.cpp b/toolkit/crashreporter/nsExceptionHandler.cpp index ecebfc93b02..f7fdb3e0471 100644 --- a/toolkit/crashreporter/nsExceptionHandler.cpp +++ b/toolkit/crashreporter/nsExceptionHandler.cpp @@ -209,10 +209,6 @@ static AnnotationTable* crashReporterAPIData_Hash; static nsCString* crashReporterAPIData = nsnull; static nsCString* notesField = nsnull; -#if defined(XP_WIN) -static HMODULE dbghelp = NULL; -#endif - #if defined(MOZ_IPC) // OOP crash reporting static CrashGenerationServer* crashServer; // chrome process has this @@ -723,17 +719,23 @@ nsresult SetExceptionHandler(nsILocalFile* aXREDirectory, #ifdef XP_WIN // Try to determine what version of dbghelp.dll we're using. - // MinidumpWithFullMemoryInfo is only available in 6.2 or newer. - dbghelp = LoadLibraryW(L"dbghelp.dll"); + // MinidumpWithFullMemoryInfo is only available in 6.1.x or newer. MINIDUMP_TYPE minidump_type = MiniDumpNormal; - if (dbghelp) { - typedef LPAPI_VERSION (WINAPI *ImagehlpApiVersionPtr)(void); - ImagehlpApiVersionPtr imagehlp_api_version = - (ImagehlpApiVersionPtr)GetProcAddress(dbghelp, "ImagehlpApiVersion"); - if (imagehlp_api_version) { - LPAPI_VERSION api_version = imagehlp_api_version(); - if (api_version->MajorVersion > 6 || - (api_version->MajorVersion == 6 && api_version->MinorVersion > 1)) { + DWORD version_size = GetFileVersionInfoSizeW(L"dbghelp.dll", NULL); + if (version_size > 0) { + std::vector buffer(version_size); + if (GetFileVersionInfoW(L"dbghelp.dll", + 0, + version_size, + &buffer[0])) { + UINT len; + VS_FIXEDFILEINFO* file_info; + VerQueryValue(&buffer[0], L"\\", (void**)&file_info, &len); + WORD major = HIWORD(file_info->dwFileVersionMS), + minor = LOWORD(file_info->dwFileVersionMS), + revision = HIWORD(file_info->dwFileVersionLS); + if (major > 6 || (major == 6 && minor > 1) || + (major == 6 && minor == 1 && revision >= 7600)) { minidump_type = MiniDumpWithFullMemoryInfo; } } @@ -1028,12 +1030,6 @@ nsresult UnsetExceptionHandler() { delete gExceptionHandler; -#if defined(XP_WIN) - if (dbghelp) { - FreeLibrary(dbghelp); - } -#endif - // do this here in the unlikely case that we succeeded in allocating // our strings but failed to allocate gExceptionHandler. if (crashReporterAPIData_Hash) { diff --git a/toolkit/crashreporter/test/CrashTestUtils.jsm b/toolkit/crashreporter/test/CrashTestUtils.jsm new file mode 100644 index 00000000000..62287c3ff71 --- /dev/null +++ b/toolkit/crashreporter/test/CrashTestUtils.jsm @@ -0,0 +1,42 @@ +var EXPORTED_SYMBOLS = ["CrashTestUtils"]; + +let CrashTestUtils = { + // These will be defined using ctypes APIs below. + crash: null, + lockDir: null, + dumpHasStream: null, + + // Constants for crash() + // Keep these in sync with nsTestCrasher.cpp! + CRASH_INVALID_POINTER_DEREF: 0, + CRASH_PURE_VIRTUAL_CALL: 1, + CRASH_RUNTIMEABORT: 2, + + // Constants for dumpHasStream() + // From google_breakpad/common/minidump_format.h + MD_THREAD_LIST_STREAM: 3, + MD_MEMORY_INFO_LIST_STREAM: 16 +}; + +// Grab APIs from the testcrasher shared library +Components.utils.import("resource://gre/modules/ctypes.jsm"); +let dir = __LOCATION__.parent; +let file = dir.clone(); +file.append(ctypes.libraryName("testcrasher")); +let lib = ctypes.open(file.path); +CrashTestUtils.crash = lib.declare("Crash", + ctypes.default_abi, + ctypes.void_t, + ctypes.int16_t); + +CrashTestUtils.lockDir = lib.declare("LockDir", + ctypes.default_abi, + ctypes.voidptr_t, // nsILocalFile* + ctypes.voidptr_t); // nsISupports* + + +CrashTestUtils.dumpHasStream = lib.declare("DumpHasStream", + ctypes.default_abi, + ctypes.bool, + ctypes.char.ptr, + ctypes.uint32_t); diff --git a/toolkit/crashreporter/test/Makefile.in b/toolkit/crashreporter/test/Makefile.in index 147116c42ec..86b557f852a 100644 --- a/toolkit/crashreporter/test/Makefile.in +++ b/toolkit/crashreporter/test/Makefile.in @@ -47,16 +47,26 @@ MODULE = crashreporter_test XPCSHELL_TESTS = unit LIBRARY_NAME = testcrasher -IS_COMPONENT = 1 NO_DIST_INSTALL = 1 -XPIDLSRCS = nsITestCrasher.idl +VPATH += \ + $(srcdir)/../google-breakpad/src/processor/ \ + $(srcdir)/../google-breakpad/src/common/ \ + $(NULL) CPPSRCS = \ nsTestCrasher.cpp \ + dumputils.cpp \ + basic_code_modules.cc \ + logging.cc \ + minidump.cc \ + pathname_stripper.cc \ $(NULL) -LOCAL_INCLUDES += -I$(XPIDL_GEN_DIR) +LOCAL_INCLUDES += \ + -I$(XPIDL_GEN_DIR) \ + -I$(srcdir)/../google-breakpad/src/ \ + $(NULL) EXTRA_DSO_LIBS += xpcom EXTRA_DSO_LDOPTS += $(LIBS_DIR) $(MOZ_COMPONENT_LIBS) @@ -76,11 +86,11 @@ EXTRA_DSO_LDOPTS += $(EXTRA_DSO_LIBS) $(XPCOM_LIBS) endif -EXTRA_PP_COMPONENTS = testcrasher.manifest +EXTRA_JS_MODULES = CrashTestUtils.jsm include $(topsrcdir)/config/rules.mk -DEFINES += -DSHARED_LIBRARY=$(SHARED_LIBRARY) +DEFINES += -DSHARED_LIBRARY=$(SHARED_LIBRARY) -DNOMINMAX ifneq (mobile,$(MOZ_BUILD_APP)) _BROWSER_FILES = \ @@ -95,7 +105,6 @@ libs:: $(_BROWSER_FILES) $(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)/browser endif -libs:: $(SHARED_LIBRARY) $(XPIDL_GEN_DIR)/$(XPIDL_MODULE).xpt - $(NSINSTALL) -D $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/components - $(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/components - $(PYTHON) $(topsrcdir)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $(srcdir)/testcrasher.manifest > $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/components/testcrasher.manifest +libs:: $(SHARED_LIBRARY) $(EXTRA_JS_MODULES) + $(INSTALL) $^ $(DEPTH)/_tests/xpcshell/$(relativesrcdir)/unit/ + diff --git a/toolkit/crashreporter/test/dumputils.cpp b/toolkit/crashreporter/test/dumputils.cpp new file mode 100644 index 00000000000..d2d186c878e --- /dev/null +++ b/toolkit/crashreporter/test/dumputils.cpp @@ -0,0 +1,19 @@ +#include "google_breakpad/processor/minidump.h" +#include "nscore.h" + +using namespace google_breakpad; + +extern "C" +NS_EXPORT bool +DumpHasStream(const char* dump_file, u_int32_t stream_type) +{ + Minidump dump(dump_file); + if (!dump.Read()) + return false; + + u_int32_t length; + if (!dump.SeekToStreamType(stream_type, &length) || length == 0) + return false; + + return true; +} diff --git a/toolkit/crashreporter/test/nsITestCrasher.idl b/toolkit/crashreporter/test/nsITestCrasher.idl deleted file mode 100644 index 803f14cb415..00000000000 --- a/toolkit/crashreporter/test/nsITestCrasher.idl +++ /dev/null @@ -1,21 +0,0 @@ -#include "nsISupports.idl" - -interface nsILocalFile; - -[scriptable, uuid(95464a04-6949-46cb-b621-d167790704a0)] -interface nsITestCrasher : nsISupports -{ - void crash(in short how); - - /** - * Lock a directory using XRE_LockProfileDirectory. - * - * @param directory The directory to lock - * @return An opaque lock object. - */ - nsISupports lockDir(in nsILocalFile directory); - - const short CRASH_INVALID_POINTER_DEREF = 0; - const short CRASH_PURE_VIRTUAL_CALL = 1; - const short CRASH_RUNTIMEABORT = 2; -}; diff --git a/toolkit/crashreporter/test/nsTestCrasher.cpp b/toolkit/crashreporter/test/nsTestCrasher.cpp index 6f0684ac046..e7fdc92ac03 100644 --- a/toolkit/crashreporter/test/nsTestCrasher.cpp +++ b/toolkit/crashreporter/test/nsTestCrasher.cpp @@ -1,23 +1,5 @@ -#include "nsServiceManagerUtils.h" -#include "nsIComponentManager.h" -#include "nsITestCrasher.h" +#include "nscore.h" #include "nsXULAppAPI.h" -#include "mozilla/ModuleUtils.h" - -class nsTestCrasher : public nsITestCrasher -{ -public: - NS_DECL_ISUPPORTS - NS_DECL_NSITESTCRASHER - - nsTestCrasher() {} - -private: - ~nsTestCrasher() {}; -}; - - -NS_IMPL_ISUPPORTS1(nsTestCrasher, nsITestCrasher) /* * This pure virtual call example is from MSDN @@ -49,59 +31,39 @@ void PureVirtualCall() B b; } -/* void crash (); */ -NS_IMETHODIMP nsTestCrasher::Crash(PRInt16 how) +// Keep these in sync with CrashTestUtils.jsm! +const PRInt16 CRASH_INVALID_POINTER_DEREF = 0; +const PRInt16 CRASH_PURE_VIRTUAL_CALL = 1; +const PRInt16 CRASH_RUNTIMEABORT = 2; + +extern "C" NS_EXPORT +void Crash(PRInt16 how) { switch (how) { - case nsITestCrasher::CRASH_INVALID_POINTER_DEREF: { + case CRASH_INVALID_POINTER_DEREF: { volatile int* foo = (int*)0x42; *foo = 0; // not reached break; } - case nsITestCrasher::CRASH_PURE_VIRTUAL_CALL: { + case CRASH_PURE_VIRTUAL_CALL: { PureVirtualCall(); // not reached break; } - case nsITestCrasher::CRASH_RUNTIMEABORT: { + case CRASH_RUNTIMEABORT: { NS_RUNTIMEABORT("Intentional crash"); break; } default: - return NS_ERROR_INVALID_ARG; + break; } - return NS_OK; } -/* nsISupports LockDir (in nsILocalFile directory); */ -NS_IMETHODIMP nsTestCrasher::LockDir(nsILocalFile *directory, - nsISupports **_retval NS_OUTPARAM) +extern "C" NS_EXPORT +nsISupports* LockDir(nsILocalFile *directory) { - return XRE_LockProfileDirectory(directory, _retval); + nsISupports* lockfile = nsnull; + XRE_LockProfileDirectory(directory, &lockfile); + return lockfile; } - -// 54afce51-38d7-4df0-9750-2f90f9ffbca2 -#define NS_TESTCRASHER_CID \ -{ 0x54afce51, 0x38d7, 0x4df0, {0x97, 0x50, 0x2f, 0x90, 0xf9, 0xff, 0xbc, 0xa2} } - -NS_GENERIC_FACTORY_CONSTRUCTOR(nsTestCrasher) -NS_DEFINE_NAMED_CID(NS_TESTCRASHER_CID); - -static const mozilla::Module::CIDEntry kTestCrasherCIDs[] = { - { &kNS_TESTCRASHER_CID, false, NULL, nsTestCrasherConstructor }, - { NULL } -}; - -static const mozilla::Module::ContractIDEntry kTestCrasherContracts[] = { - { "@mozilla.org/testcrasher;1", &kNS_TESTCRASHER_CID }, - { NULL } -}; - -static const mozilla::Module kTestCrasherModule = { - mozilla::Module::kVersion, - kTestCrasherCIDs, - kTestCrasherContracts -}; - -NSMODULE_DEFN(nsTestCrasherModule) = &kTestCrasherModule; diff --git a/toolkit/crashreporter/test/testcrasher.manifest b/toolkit/crashreporter/test/testcrasher.manifest deleted file mode 100644 index 81580059c0a..00000000000 --- a/toolkit/crashreporter/test/testcrasher.manifest +++ /dev/null @@ -1,3 +0,0 @@ -#filter substitution -binary-component @SHARED_LIBRARY@ -interfaces crashreporter_test.xpt diff --git a/toolkit/crashreporter/test/unit/crasher_subprocess_head.js b/toolkit/crashreporter/test/unit/crasher_subprocess_head.js index b6d211d57d7..5df06164ad0 100644 --- a/toolkit/crashreporter/test/unit/crasher_subprocess_head.js +++ b/toolkit/crashreporter/test/unit/crasher_subprocess_head.js @@ -7,9 +7,12 @@ let crashReporter = .getService(Components.interfaces.nsICrashReporter); crashReporter.enabled = true; crashReporter.minidumpPath = cwd; -let cd = cwd.clone(); -cd.append("components"); -cd.append("testcrasher.manifest"); -Components.manager instanceof Components.interfaces.nsIComponentRegistrar; -Components.manager.autoRegister(cd); -let crashType = Components.interfaces.nsITestCrasher.CRASH_INVALID_POINTER_DEREF; + +let ios = Components.classes["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService); +let protocolHandler = ios.getProtocolHandler("resource") + .QueryInterface(Components.interfaces.nsIResProtocolHandler); +let curDirURI = ios.newFileURI(cwd); +protocolHandler.setSubstitution("test", curDirURI); +Components.utils.import("resource://test/CrashTestUtils.jsm"); +let crashType = CrashTestUtils.CRASH_INVALID_POINTER_DEREF; diff --git a/toolkit/crashreporter/test/unit/crasher_subprocess_tail.js b/toolkit/crashreporter/test/unit/crasher_subprocess_tail.js index 96a285becbd..63aa3ab26b2 100644 --- a/toolkit/crashreporter/test/unit/crasher_subprocess_tail.js +++ b/toolkit/crashreporter/test/unit/crasher_subprocess_tail.js @@ -1,3 +1,2 @@ // now actually crash -let crasher = Components.classes["@mozilla.org/testcrasher;1"].createInstance(Components.interfaces.nsITestCrasher); -crasher.crash(crashType); +CrashTestUtils.crash(crashType); diff --git a/toolkit/crashreporter/test/unit/head_crashreporter.js b/toolkit/crashreporter/test/unit/head_crashreporter.js index 44a76cb72a7..f2aa0de52cc 100644 --- a/toolkit/crashreporter/test/unit/head_crashreporter.js +++ b/toolkit/crashreporter/test/unit/head_crashreporter.js @@ -22,7 +22,7 @@ * @param canReturnZero * If true, the subprocess may return with a zero exit code. * Certain types of crashes may not cause the process to - * exit with an error. + * exit with an error. */ function do_crash(setup, callback, canReturnZero) { @@ -81,6 +81,14 @@ function do_crash(setup, callback, canReturnZero) let extrafile = minidump.clone(); extrafile.leafName = extrafile.leafName.slice(0, -4) + ".extra"; + + // Just in case, don't let these files linger. + do_register_cleanup(function() { + if (minidump.exists()) + minidump.remove(false); + if (extrafile.exists()) + extrafile.remove(false); + }); do_check_true(extrafile.exists()); let extra = parseKeyValuePairsFromFile(extrafile); @@ -129,3 +137,6 @@ function parseKeyValuePairsFromFile(file) { fstream.close(); return parseKeyValuePairs(contents); } + +// Import binary APIs via js-ctypes. +Components.utils.import("resource://test/CrashTestUtils.jsm"); diff --git a/toolkit/crashreporter/test/unit/test_crash_purevirtual.js b/toolkit/crashreporter/test/unit/test_crash_purevirtual.js index 15f8c57bcc6..6746aca2954 100644 --- a/toolkit/crashreporter/test/unit/test_crash_purevirtual.js +++ b/toolkit/crashreporter/test/unit/test_crash_purevirtual.js @@ -13,7 +13,7 @@ function run_test() // Try crashing with a pure virtual call do_crash(function() { - crashType = Components.interfaces.nsITestCrasher.CRASH_PURE_VIRTUAL_CALL; + crashType = CrashTestUtils.CRASH_PURE_VIRTUAL_CALL; crashReporter.annotateCrashReport("TestKey", "TestValue"); }, function(mdump, extra) { diff --git a/toolkit/crashreporter/test/unit/test_crash_runtimeabort.js b/toolkit/crashreporter/test/unit/test_crash_runtimeabort.js index d828ff4fb64..3099c59c577 100644 --- a/toolkit/crashreporter/test/unit/test_crash_runtimeabort.js +++ b/toolkit/crashreporter/test/unit/test_crash_runtimeabort.js @@ -1,13 +1,13 @@ function run_test() { if (!("@mozilla.org/toolkit/crash-reporter;1" in Components.classes)) { - dump("INFO | test_crash_purevirtual.js | Can't test crashreporter in a non-libxul build.\n"); + dump("INFO | test_crash_runtimeabort.js | Can't test crashreporter in a non-libxul build.\n"); return; } // Try crashing with a runtime abort do_crash(function() { - crashType = Components.interfaces.nsITestCrasher.CRASH_RUNTIMEABORT; + crashType = CrashTestUtils.CRASH_RUNTIMEABORT; crashReporter.annotateCrashReport("TestKey", "TestValue"); }, function(mdump, extra) { diff --git a/toolkit/crashreporter/test/unit/test_crashreporter_crash.js b/toolkit/crashreporter/test/unit/test_crashreporter_crash.js index 70e432d6d5f..b1689b6f4b1 100644 --- a/toolkit/crashreporter/test/unit/test_crashreporter_crash.js +++ b/toolkit/crashreporter/test/unit/test_crashreporter_crash.js @@ -5,12 +5,24 @@ function run_test() return; } + var is_win7_or_newer = false; + var ph = Components.classes["@mozilla.org/network/protocol;1?name=http"] + .getService(Components.interfaces.nsIHttpProtocolHandler); + var match = ph.userAgent.match(/Windows NT (\d+).(\d+)/); + if (match && (parseInt(match[1]) > 6 || + parseInt(match[1]) == 6 && parseInt(match[2]) >= 1)) { + is_win7_or_newer = true; + } + // try a basic crash do_crash(null, function(mdump, extra) { do_check_true(mdump.exists()); do_check_true(mdump.fileSize > 0); do_check_true('StartupTime' in extra); do_check_true('CrashTime' in extra); + do_check_true(CrashTestUtils.dumpHasStream(mdump.path, CrashTestUtils.MD_THREAD_LIST_STREAM)); + if (is_win7_or_newer) + do_check_true(CrashTestUtils.dumpHasStream(mdump.path, CrashTestUtils.MD_MEMORY_INFO_LIST_STREAM)); }); // check setting some basic data diff --git a/toolkit/crashreporter/test/unit/test_crashreporter_crash_profile_lock.js b/toolkit/crashreporter/test/unit/test_crashreporter_crash_profile_lock.js index 877c6b0485a..78492ea5de8 100644 --- a/toolkit/crashreporter/test/unit/test_crashreporter_crash_profile_lock.js +++ b/toolkit/crashreporter/test/unit/test_crashreporter_crash_profile_lock.js @@ -16,8 +16,7 @@ function run_test() let dir = Components.classes["@mozilla.org/file/local;1"] .createInstance(Components.interfaces.nsILocalFile); dir.initWithPath(profd); - let mycrasher = Components.classes["@mozilla.org/testcrasher;1"].createInstance(Components.interfaces.nsITestCrasher); - let lock = mycrasher.lockDir(dir); + let lock = CrashTestUtils.lockDir(dir); // when we crash, the lock file should be cleaned up }, function(mdump, extra) { diff --git a/widget/public/nsIGfxInfo.idl b/widget/public/nsIGfxInfo.idl index 670cb573899..c065ee2e870 100644 --- a/widget/public/nsIGfxInfo.idl +++ b/widget/public/nsIGfxInfo.idl @@ -40,7 +40,7 @@ /* NOTE: this interface is completely undesigned, not stable and likely to change */ -[scriptable, uuid(d2bfa0fd-8f73-4660-9609-f999680243b1)] +[scriptable, uuid(5c5de1e7-f7f4-46b4-9ced-03ab1f869eaf)] interface nsIGfxInfo : nsISupports { /* @@ -48,6 +48,7 @@ interface nsIGfxInfo : nsISupports */ readonly attribute boolean D2DEnabled; readonly attribute boolean DWriteEnabled; + readonly attribute DOMString DWriteVersion; /** * The name of the display adapter. diff --git a/widget/src/android/GfxInfo.cpp b/widget/src/android/GfxInfo.cpp index f06126ce255..0a7b6232ca0 100644 --- a/widget/src/android/GfxInfo.cpp +++ b/widget/src/android/GfxInfo.cpp @@ -71,6 +71,13 @@ GfxInfo::GetDWriteEnabled(PRBool *aEnabled) return NS_ERROR_FAILURE; } +/* readonly attribute DOMString DWriteVersion; */ +NS_IMETHODIMP +GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion) +{ + return NS_ERROR_FAILURE; +} + void GfxInfo::Init() { diff --git a/widget/src/cocoa/GfxInfo.mm b/widget/src/cocoa/GfxInfo.mm index 7e27acd8ee2..3f4eeffb2e6 100644 --- a/widget/src/cocoa/GfxInfo.mm +++ b/widget/src/cocoa/GfxInfo.mm @@ -106,6 +106,13 @@ GfxInfo::GetDWriteEnabled(PRBool *aEnabled) return NS_ERROR_FAILURE; } +/* readonly attribute DOMString DWriteVersion; */ +NS_IMETHODIMP +GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion) +{ + return NS_ERROR_FAILURE; +} + /* readonly attribute DOMString adapterDescription; */ NS_IMETHODIMP GfxInfo::GetAdapterDescription(nsAString & aAdapterDescription) diff --git a/widget/src/gtk2/nsGtkIMModule.cpp b/widget/src/gtk2/nsGtkIMModule.cpp index f8231c195af..c46158d6537 100644 --- a/widget/src/gtk2/nsGtkIMModule.cpp +++ b/widget/src/gtk2/nsGtkIMModule.cpp @@ -363,7 +363,8 @@ nsGtkIMModule::OnBlurWindow(nsWindow* aWindow) } PRBool -nsGtkIMModule::OnKeyEvent(nsWindow* aCaller, GdkEventKey* aEvent) +nsGtkIMModule::OnKeyEvent(nsWindow* aCaller, GdkEventKey* aEvent, + PRBool aKeyDownEventWasSent /* = PR_FALSE */) { NS_PRECONDITION(aEvent, "aEvent must be non-null"); @@ -372,8 +373,8 @@ nsGtkIMModule::OnKeyEvent(nsWindow* aCaller, GdkEventKey* aEvent) } PR_LOG(gGtkIMLog, PR_LOG_ALWAYS, - ("GtkIMModule(%p): OnKeyEvent, aCaller=%p", - this, aCaller)); + ("GtkIMModule(%p): OnKeyEvent, aCaller=%p, aKeyDownEventWasSent=%s", + this, aCaller, aKeyDownEventWasSent ? "TRUE" : "FALSE")); PR_LOG(gGtkIMLog, PR_LOG_ALWAYS, (" aEvent: type=%s, keyval=0x%X, unicode=0x%X", aEvent->type == GDK_KEY_PRESS ? "GDK_KEY_PRESS" : @@ -394,6 +395,7 @@ nsGtkIMModule::OnKeyEvent(nsWindow* aCaller, GdkEventKey* aEvent) return PR_FALSE; } + mKeyDownEventWasSent = aKeyDownEventWasSent; mFilterKeyEvent = PR_TRUE; mProcessingKeyEvent = aEvent; gboolean isFiltered = gtk_im_context_filter_keypress(im, aEvent); @@ -1040,13 +1042,16 @@ nsGtkIMModule::DispatchCompositionStart() mCompositionStart = selection.mReply.mOffset; - if (mProcessingKeyEvent && mProcessingKeyEvent->type == GDK_KEY_PRESS) { + if (mProcessingKeyEvent && !mKeyDownEventWasSent && + mProcessingKeyEvent->type == GDK_KEY_PRESS) { // If this composition is started by a native keydown event, we need to // dispatch our keydown event here (before composition start). nsCOMPtr kungFuDeathGrip = mLastFocusedWindow; PRBool isCancelled; mLastFocusedWindow->DispatchKeyDownEvent(mProcessingKeyEvent, &isCancelled); + PR_LOG(gGtkIMLog, PR_LOG_ALWAYS, + (" keydown event is dispatched")); if (static_cast(kungFuDeathGrip.get())->IsDestroyed() || kungFuDeathGrip != mLastFocusedWindow) { PR_LOG(gGtkIMLog, PR_LOG_ALWAYS, diff --git a/widget/src/gtk2/nsGtkIMModule.h b/widget/src/gtk2/nsGtkIMModule.h index 2f5ff551e6a..c07ecbf5b71 100644 --- a/widget/src/gtk2/nsGtkIMModule.h +++ b/widget/src/gtk2/nsGtkIMModule.h @@ -89,6 +89,10 @@ public: nsGtkIMModule(nsWindow* aOwnerWindow); ~nsGtkIMModule(); + // "Enabled" means the users can use all IMEs. + // I.e., the focus is in the normal editors. + PRBool IsEnabled(); + // OnFocusWindow is a notification that aWindow is going to be focused. void OnFocusWindow(nsWindow* aWindow); // OnBlurWindow is a notification that aWindow is going to be unfocused. @@ -103,7 +107,8 @@ public: // filtered by IME. Otherwise, this returns FALSE. // NOTE: When the keypress event starts composition, this returns TRUE but // this dispatches keydown event before compositionstart event. - PRBool OnKeyEvent(nsWindow* aWindow, GdkEventKey* aEvent); + PRBool OnKeyEvent(nsWindow* aWindow, GdkEventKey* aEvent, + PRBool aKeyDownEventWasSent = PR_FALSE); // IME related nsIWidget methods. nsresult ResetInputState(nsWindow* aCaller); @@ -179,6 +184,12 @@ protected: // another content (nsIContent). Don't refer this value directly, use // ShouldIgnoreNativeCompositionEvent(). PRPackedBool mIgnoreNativeCompositionEvent; + // mKeyDownEventWasSent is used by OnKeyEvent() and + // DispatchCompositionStart(). DispatchCompositionStart() dispatches + // a keydown event if the composition start is caused by a native + // keypress event. If this is true, the keydown event has been dispatched. + // Then, DispatchCompositionStart() doesn't dispatch keydown event. + PRPackedBool mKeyDownEventWasSent; // sLastFocusedModule is a pointer to the last focused instance of this // class. When a instance is destroyed and sLastFocusedModule refers it, @@ -219,10 +230,6 @@ protected: // state. So, this means *current* IM context. GtkIMContext* GetContext(); - // "Enabled" means the users can use all IMEs. - // I.e., the focus is in the normal editors. - PRBool IsEnabled(); - // "Editable" means the users can input characters. They may be not able to // use IMEs but they can use dead keys. // I.e., the focus is in the normal editors or the password editors or diff --git a/widget/src/gtk2/nsWindow.cpp b/widget/src/gtk2/nsWindow.cpp index 45622e6f5e8..db377b0e0f3 100644 --- a/widget/src/gtk2/nsWindow.cpp +++ b/widget/src/gtk2/nsWindow.cpp @@ -3014,8 +3014,12 @@ nsWindow::OnKeyPressEvent(GtkWidget *aWidget, GdkEventKey *aEvent) // if we are in the middle of composing text, XIM gets to see it // before mozilla does. - if (mIMModule && mIMModule->OnKeyEvent(this, aEvent)) { - return TRUE; + PRBool IMEWasEnabled = PR_FALSE; + if (mIMModule) { + IMEWasEnabled = mIMModule->IsEnabled(); + if (mIMModule->OnKeyEvent(this, aEvent)) { + return TRUE; + } } nsEventStatus status; @@ -3039,6 +3043,17 @@ nsWindow::OnKeyPressEvent(GtkWidget *aWidget, GdkEventKey *aEvent) return TRUE; } + // If a keydown event handler causes to enable IME, i.e., it moves + // focus from IME unusable content to IME usable editor, we should + // send the native key event to IME for the first input on the editor. + if (!IMEWasEnabled && mIMModule && mIMModule->IsEnabled()) { + // Notice our keydown event was already dispatched. This prevents + // unnecessary DOM keydown event in the editor. + if (mIMModule->OnKeyEvent(this, aEvent, PR_TRUE)) { + return TRUE; + } + } + // Don't pass modifiers as NS_KEY_PRESS events. // TODO: Instead of selectively excluding some keys from NS_KEY_PRESS events, // we should instead selectively include (as per MSDN spec; no official diff --git a/widget/src/windows/GfxInfo.cpp b/widget/src/windows/GfxInfo.cpp index 37973a8068c..ff593926eb5 100644 --- a/widget/src/windows/GfxInfo.cpp +++ b/widget/src/windows/GfxInfo.cpp @@ -74,6 +74,14 @@ GfxInfo::GetDWriteEnabled(PRBool *aEnabled) return NS_OK; } +/* readonly attribute DOMString DWriteVersion; */ +NS_IMETHODIMP +GfxInfo::GetDWriteVersion(nsAString & aDwriteVersion) +{ + gfxWindowsPlatform::GetPlatform()->GetDLLVersion(L"dwrite.dll", aDwriteVersion); + return NS_OK; +} + /* XXX: GfxInfo doesn't handle multiple GPUs. We should try to do that. Bug #591057 */ static nsresult GetKeyValue(const WCHAR* keyLocation, const WCHAR* keyName, nsAString& destString, int type) diff --git a/widget/src/windows/nsWindow.cpp b/widget/src/windows/nsWindow.cpp index bb113bb13d3..bdfaf14afb9 100644 --- a/widget/src/windows/nsWindow.cpp +++ b/widget/src/windows/nsWindow.cpp @@ -316,6 +316,8 @@ PRUint32 nsWindow::sOOPPPluginFocusEvent = RegisterWindowMessageW(kOOPPPluginFocusEventId); #endif +MSG nsWindow::sRedirectedKeyDown; + /************************************************************** * * SECTION: globals variables @@ -460,6 +462,8 @@ nsWindow::nsWindow() : nsBaseWidget() nsUXThemeData::InitTitlebarInfo(); // Init theme data nsUXThemeData::UpdateNativeThemeInfo(); + + ForgetRedirectedKeyDownMessage(); } // !sInstanceCount mIdleService = nsnull; @@ -5322,6 +5326,11 @@ PRBool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam, #endif case WM_SETFOCUS: + // If previous focused window isn't ours, it must have received the + // redirected message. So, we should forget it. + if (!IsOurProcessWindow(HWND(wParam))) { + ForgetRedirectedKeyDownMessage(); + } if (sJustGotActivate) { result = DispatchFocusToTopLevelWindow(NS_ACTIVATE); } @@ -5880,6 +5889,25 @@ void nsWindow::PostSleepWakeNotification(const char* aNotification) } #endif +// RemoveNextCharMessage() should be called by WM_KEYDOWN or WM_SYSKEYDOWM +// message handler. If there is no WM_(SYS)CHAR message for it, this +// method does nothing. +// NOTE: WM_(SYS)CHAR message is posted by TranslateMessage() API which is +// called in message loop. So, WM_(SYS)KEYDOWN message should have +// WM_(SYS)CHAR message in the queue if the keydown event causes character +// input. + +/* static */ +void nsWindow::RemoveNextCharMessage(HWND aWnd) +{ + MSG msg; + if (::PeekMessageW(&msg, aWnd, + WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE | PM_NOYIELD) && + (msg.message == WM_CHAR || msg.message == WM_SYSCHAR)) { + ::GetMessageW(&msg, aWnd, msg.message, msg.message); + } +} + LRESULT nsWindow::ProcessCharMessage(const MSG &aMsg, PRBool *aEventDispatched) { NS_PRECONDITION(aMsg.message == WM_CHAR || aMsg.message == WM_SYSCHAR, @@ -5941,6 +5969,12 @@ LRESULT nsWindow::ProcessKeyDownMessage(const MSG &aMsg, NS_PRECONDITION(aMsg.message == WM_KEYDOWN || aMsg.message == WM_SYSKEYDOWN, "message is not keydown event"); + // If this method doesn't call OnKeyDown(), this method must clean up the + // redirected message information itself. For more information, see above + // comment of AutoForgetRedirectedKeyDownMessage struct definition in + // nsWindow.h. + AutoForgetRedirectedKeyDownMessage forgetRedirectedMessage(this, aMsg); + nsModifierKeyState modKeyState; // Note: the original code passed (HIWORD(lParam)) to OnKeyDown as @@ -5962,6 +5996,9 @@ LRESULT nsWindow::ProcessKeyDownMessage(const MSG &aMsg, nsIMM32Handler::NotifyEndStatusChange(); } else if (!nsIMM32Handler::IsComposingOn(this)) { result = OnKeyDown(aMsg, modKeyState, aEventDispatched, nsnull); + // OnKeyDown cleaned up the redirected message information itself, so, + // we should do nothing. + forgetRedirectedMessage.mCancel = PR_TRUE; } #ifndef WINCE @@ -6673,6 +6710,14 @@ UINT nsWindow::MapFromNativeToDOM(UINT aNativeKeyCode) return aNativeKeyCode; } +/* static */ +PRBool nsWindow::IsRedirectedKeyDownMessage(const MSG &aMsg) +{ + return (aMsg.message == WM_KEYDOWN || aMsg.message == WM_SYSKEYDOWN) && + (sRedirectedKeyDown.message == aMsg.message && + GetScanCode(sRedirectedKeyDown.lParam) == GetScanCode(aMsg.lParam)); +} + /** * nsWindow::OnKeyDown peeks into the message queue and pulls out * WM_CHAR messages for processing. During testing we don't want to @@ -6686,14 +6731,15 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg, PRBool *aEventDispatched, nsFakeCharMessage* aFakeCharMessage) { - UINT virtualKeyCode = aMsg.wParam; + UINT virtualKeyCode = + aMsg.wParam != VK_PROCESSKEY ? aMsg.wParam : ::ImmGetVirtualKey(mWnd); #ifndef WINCE - gKbdLayout.OnKeyDown (virtualKeyCode); + gKbdLayout.OnKeyDown(virtualKeyCode); #endif // Use only DOMKeyCode for XP processing. - // Use aVirtualKeyCode for gKbdLayout and native processing. + // Use virtualKeyCode for gKbdLayout and native processing. UINT DOMKeyCode = nsIMM32Handler::IsComposingOn(this) ? virtualKeyCode : MapFromNativeToDOM(virtualKeyCode); @@ -6701,10 +6747,71 @@ LRESULT nsWindow::OnKeyDown(const MSG &aMsg, //printf("In OnKeyDown virt: %d\n", DOMKeyCode); #endif - PRBool noDefault = - DispatchKeyEvent(NS_KEY_DOWN, 0, nsnull, DOMKeyCode, &aMsg, aModKeyState); - if (aEventDispatched) - *aEventDispatched = PR_TRUE; + static PRBool sRedirectedKeyDownEventPreventedDefault = PR_FALSE; + PRBool noDefault; + if (aFakeCharMessage || !IsRedirectedKeyDownMessage(aMsg)) { + HIMC oldIMC = mOldIMC; + noDefault = + DispatchKeyEvent(NS_KEY_DOWN, 0, nsnull, DOMKeyCode, &aMsg, aModKeyState); + if (aEventDispatched) { + *aEventDispatched = PR_TRUE; + } + + // If IMC wasn't associated to the window but is associated it now (i.e., + // focus is moved from a non-editable editor to an editor by keydown + // event handler), WM_CHAR and WM_SYSCHAR shouldn't cause first character + // inputting if IME is opened. But then, we should redirect the native + // keydown message to IME. + // However, note that if focus has been already moved to another + // application, we shouldn't redirect the message to it because the keydown + // message is processed by us, so, nobody shouldn't process it. + HWND focusedWnd = ::GetFocus(); + if (!noDefault && !aFakeCharMessage && oldIMC && !mOldIMC && focusedWnd && + !PluginHasFocus()) { + RemoveNextCharMessage(focusedWnd); + + INPUT keyinput; + keyinput.type = INPUT_KEYBOARD; + keyinput.ki.wVk = aMsg.wParam; + keyinput.ki.wScan = GetScanCode(aMsg.lParam); + keyinput.ki.dwFlags = KEYEVENTF_SCANCODE; + if (IsExtendedScanCode(aMsg.lParam)) { + keyinput.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY; + } + keyinput.ki.time = 0; + keyinput.ki.dwExtraInfo = NULL; + + sRedirectedKeyDownEventPreventedDefault = noDefault; + sRedirectedKeyDown = aMsg; + + ::SendInput(1, &keyinput, sizeof(keyinput)); + + // Return here. We shouldn't dispatch keypress event for this WM_KEYDOWN. + // If it's needed, it will be dispatched after next (redirected) + // WM_KEYDOWN. + return PR_TRUE; + } + + if (mOnDestroyCalled) { + // If this was destroyed by the keydown event handler, we shouldn't + // dispatch keypress event on this window. + return PR_TRUE; + } + } else { + noDefault = sRedirectedKeyDownEventPreventedDefault; + // If this is redirected keydown message, we have dispatched the keydown + // event already. + if (aEventDispatched) { + *aEventDispatched = PR_TRUE; + } + } + + ForgetRedirectedKeyDownMessage(); + + // If the key was processed by IME, we shouldn't dispatch keypress event. + if (aMsg.wParam == VK_PROCESSKEY) { + return noDefault; + } // If we won't be getting a WM_CHAR, WM_SYSCHAR or WM_DEADCHAR, synthesize a keypress // for almost all keys @@ -7408,14 +7515,19 @@ void nsWindow::OnSettingsChange(WPARAM wParam, LPARAM lParam) nsWindowGfx::OnSettingsChangeGfx(wParam); } -static PRBool IsOurProcessWindow(HWND aHWND) +/* static */ +PRBool nsWindow::IsOurProcessWindow(HWND aHWND) { + if (!aHWND) { + return PR_FALSE; + } DWORD processId = 0; ::GetWindowThreadProcessId(aHWND, &processId); return processId == ::GetCurrentProcessId(); } -static HWND FindOurProcessWindow(HWND aHWND) +/* static */ +HWND nsWindow::FindOurProcessWindow(HWND aHWND) { for (HWND wnd = ::GetParent(aHWND); wnd; wnd = ::GetParent(wnd)) { if (IsOurProcessWindow(wnd)) { diff --git a/widget/src/windows/nsWindow.h b/widget/src/windows/nsWindow.h index ba1581513f9..b8a0b24e1bd 100644 --- a/widget/src/windows/nsWindow.h +++ b/widget/src/windows/nsWindow.h @@ -336,6 +336,8 @@ protected: return mTransparencyMode == eTransparencyGlass || mTransparencyMode == eTransparencyBorderlessGlass; } + PRBool IsOurProcessWindow(HWND aHWND); + HWND FindOurProcessWindow(HWND aHWND); /** * Event processing helpers @@ -346,6 +348,7 @@ protected: PRBool DispatchStandardEvent(PRUint32 aMsg); PRBool DispatchCommandEvent(PRUint32 aEventCommand); void RelayMouseEvent(UINT aMsg, WPARAM wParam, LPARAM lParam); + static void RemoveNextCharMessage(HWND aWnd); void RemoveMessageAndDispatchPluginEvent(UINT aFirstMsg, UINT aLastMsg); static MSG InitMSG(UINT aMessage, WPARAM wParam, LPARAM lParam); virtual PRBool ProcessMessage(UINT msg, WPARAM &wParam, @@ -368,6 +371,19 @@ protected: LRESULT* aRetValue, PRBool& aQuitProcessing); PRInt32 ClientMarginHitTestPoint(PRInt32 mx, PRInt32 my); + static WORD GetScanCode(LPARAM aLParam) + { + return (aLParam >> 16) & 0xFF; + } + static PRBool IsExtendedScanCode(LPARAM aLParam) + { + return (aLParam & 0x1000000) != 0; + } + static PRBool IsRedirectedKeyDownMessage(const MSG &aMsg); + static void ForgetRedirectedKeyDownMessage() + { + sRedirectedKeyDown.message = WM_NULL; + } /** * Event handlers @@ -608,6 +624,45 @@ protected: static HINSTANCE sAccLib; static LPFNLRESULTFROMOBJECT sLresultFromObject; #endif // ACCESSIBILITY + + // sRedirectedKeyDown is WM_KEYDOWN message or WM_SYSKEYDOWN message which + // was reirected to SendInput() API by OnKeyDown(). + static MSG sRedirectedKeyDown; + + // If a window receives WM_KEYDOWN message or WM_SYSKEYDOWM message which is + // redirected message, OnKeyDowm() prevents to dispatch NS_KEY_DOWN event + // because it has been dispatched before the message was redirected. + // However, in some cases, ProcessKeyDownMessage() doesn't call OnKeyDown(). + // Then, ProcessKeyDownMessage() needs to forget the redirected message and + // remove WM_CHAR message or WM_SYSCHAR message for the redirected keydown + // message. AutoForgetRedirectedKeyDownMessage struct is a helper struct + // for doing that. This must be created in stack. + struct AutoForgetRedirectedKeyDownMessage + { + AutoForgetRedirectedKeyDownMessage(nsWindow* aWindow, const MSG &aMsg) : + mCancel(!nsWindow::IsRedirectedKeyDownMessage(aMsg)), + mWindow(aWindow), mMsg(aMsg) + { + } + + ~AutoForgetRedirectedKeyDownMessage() + { + if (mCancel) { + return; + } + // Prevent unnecessary keypress event + if (!mWindow->mOnDestroyCalled) { + nsWindow::RemoveNextCharMessage(mWindow->mWnd); + } + // Foreget the redirected message + nsWindow::ForgetRedirectedKeyDownMessage(); + } + + PRBool mCancel; + nsCOMPtr mWindow; + const MSG &mMsg; + }; + }; /** diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp index f2c0262a3b6..16d167a9994 100644 --- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -994,8 +994,6 @@ struct nsCycleCollector nsPurpleBuffer mPurpleBuf; - nsCOMPtr mListener; - void RegisterRuntime(PRUint32 langID, nsCycleCollectionLanguageRuntime *rt); nsCycleCollectionLanguageRuntime * GetRuntime(PRUint32 langID); @@ -1407,7 +1405,7 @@ private: PtrInfo *mCurrPi; nsCycleCollectionLanguageRuntime **mRuntimes; // weak, from nsCycleCollector nsCString mNextEdgeName; - nsCOMPtr mListener; + nsICycleCollectorListener *mListener; public: GCGraphBuilder(GCGraph &aGraph, @@ -2499,7 +2497,6 @@ void nsCycleCollector::CleanupAfterCollection() { mWhiteNodes = nsnull; - mListener = nsnull; mCollectionInProgress = PR_FALSE; #ifdef XP_OS2 @@ -2527,14 +2524,6 @@ nsCycleCollector::Collect(PRUint32 aTryCollections, if (!PrepareForCollection(&whiteNodes)) return 0; -#ifdef DEBUG_CC - nsCOMPtr tempListener; - if (!aListener && mParams.mDrawGraphs) { - tempListener = new nsCycleCollectorLogger(); - aListener = tempListener; - } -#endif - PRUint32 totalCollections = 0; while (aTryCollections > totalCollections) { // Synchronous cycle collection. Always force a JS GC as well. @@ -3285,7 +3274,7 @@ nsCycleCollector_DEBUG_wasFreed(nsISupports *n) class nsCycleCollectorRunner : public nsRunnable { nsCycleCollector *mCollector; - nsCOMPtr mListener; + nsICycleCollectorListener *mListener; Mutex mLock; CondVar mRequest; CondVar mReply; @@ -3330,6 +3319,7 @@ public: nsCycleCollectorRunner(nsCycleCollector *collector) : mCollector(collector), + mListener(nsnull), mLock("cycle collector lock"), mRequest(mLock, "cycle collector request condvar"), mReply(mLock, "cycle collector reply condvar"), @@ -3469,9 +3459,16 @@ PRUint32 nsCycleCollector_collect(nsICycleCollectorListener *aListener) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); + nsCOMPtr listener(aListener); +#ifdef DEBUG_CC + if (!aListener && sCollector.mParams.mDrawGraphs) { + listener = new nsCycleCollectorLogger(); + } +#endif + if (sCollectorRunner) - return sCollectorRunner->Collect(aListener); - return sCollector ? sCollector->Collect(1, aListener) : 0; + return sCollectorRunner->Collect(listener); + return sCollector ? sCollector->Collect(1, listener) : 0; } void diff --git a/xpcom/glue/nsTObserverArray.h b/xpcom/glue/nsTObserverArray.h index b919aa89b53..0235cbf8b4d 100644 --- a/xpcom/glue/nsTObserverArray.h +++ b/xpcom/glue/nsTObserverArray.h @@ -41,6 +41,16 @@ #include "nsTArray.h" +/** + * An array of observers. Like a normal array, but supports iterators that are + * stable even if the array is modified during iteration. + * The template parameter T is the observer type the array will hold; + * N is the number of built-in storage slots that come with the array. + * NOTE: You probably want to use nsTObserverArray, unless you specifically + * want built-in storage. See below. + * @see nsTObserverArray, nsTArray + */ + class NS_COM_GLUE nsTObserverArray_base { public: typedef PRUint32 index_type; @@ -90,16 +100,6 @@ class NS_COM_GLUE nsTObserverArray_base { mutable Iterator_base* mIterators; }; -/** - * An array of observers. Like a normal array, but supports iterators that are - * stable even if the array is modified during iteration. - * The template parameter T is the observer type the array will hold; - * N is the number of built-in storage slots that come with the array. - * NOTE: You probably want to use nsTObserverArray, unless you specifically - * want built-in storage. See below. - * @see nsTObserverArray, nsTArray - */ - template class nsAutoTObserverArray : protected nsTObserverArray_base { public: diff --git a/xpcom/tests/unit/test_nsIProcess.js b/xpcom/tests/unit/test_nsIProcess.js index 318804990f4..8beb854165f 100644 --- a/xpcom/tests/unit/test_nsIProcess.js +++ b/xpcom/tests/unit/test_nsIProcess.js @@ -249,13 +249,13 @@ function test_kill_2() process.kill(); } catch (e) { } - } - // We need to ensure that we process any events on the main thread - - // this allow threads to clean up properly and avoid out of memory - // errors during the test. - while (thread.hasPendingEvents()) - thread.processNextEvent(false); + // We need to ensure that we process any events on the main thread - + // this allow threads to clean up properly and avoid out of memory + // errors during the test. + while (thread.hasPendingEvents()) + thread.processNextEvent(false); + } } function run_test() {