diff --git a/accessible/src/atk/nsHTMLLinkAccessibleWrap.cpp b/accessible/src/atk/nsHTMLLinkAccessibleWrap.cpp index c4ff646291c9..0a94cc7c4807 100644 --- a/accessible/src/atk/nsHTMLLinkAccessibleWrap.cpp +++ b/accessible/src/atk/nsHTMLLinkAccessibleWrap.cpp @@ -89,10 +89,7 @@ NS_IMETHODIMP nsHTMLLinkAccessibleWrap::GetURI(PRInt32 i, nsIURI **aURI) nsCOMPtr link(do_QueryInterface(mLinkContent)); if (link) { - nsXPIDLCString hrefValue; - if (NS_SUCCEEDED(link->GetHrefUTF8(getter_Copies(hrefValue)))) { - return NS_NewURI(aURI, hrefValue, nsnull, nsnull); - } + return link->GetHrefURI(aURI); } return NS_ERROR_FAILURE; diff --git a/content/base/src/nsGenericElement.cpp b/content/base/src/nsGenericElement.cpp index 76c40b6e958e..7f0f88582f05 100644 --- a/content/base/src/nsGenericElement.cpp +++ b/content/base/src/nsGenericElement.cpp @@ -3115,29 +3115,16 @@ nsGenericElement::LeaveLink(nsIPresContext* aPresContext) nsresult nsGenericElement::TriggerLink(nsIPresContext* aPresContext, nsLinkVerb aVerb, - nsIURI* aBaseURL, - const nsAString& aURLSpec, + nsIURI* aOriginURI, + nsIURI* aLinkURI, const nsAFlatString& aTargetSpec, PRBool aClick) { + NS_PRECONDITION(aLinkURI, "No link URI"); nsCOMPtr handler; nsresult rv = aPresContext->GetLinkHandler(getter_AddRefs(handler)); if (NS_FAILED(rv) || !handler) return rv; - // Resolve url to an absolute url - nsCOMPtr targetURI; - nsCAutoString docCharset; - if (mDocument && - NS_SUCCEEDED(mDocument->GetDocumentCharacterSet(docCharset))) { - rv = NS_NewURI(getter_AddRefs(targetURI), aURLSpec, - docCharset.get(), aBaseURL); - } else { - rv = NS_NewURI(getter_AddRefs(targetURI), aURLSpec, nsnull, aBaseURL); - } - - NS_ENSURE_SUCCESS(rv, rv); - - // Now pass on absolute url to the click handler if (aClick) { nsresult proceed = NS_OK; // Check that this page is allowed to load this URI. @@ -3145,17 +3132,15 @@ nsGenericElement::TriggerLink(nsIPresContext* aPresContext, do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_SUCCEEDED(rv)) proceed = - securityManager->CheckLoadURI(aBaseURL, targetURI, + securityManager->CheckLoadURI(aOriginURI, aLinkURI, nsIScriptSecurityManager::STANDARD); // Only pass off the click event if the script security manager // says it's ok. if (NS_SUCCEEDED(proceed)) - handler->OnLinkClick(this, aVerb, targetURI, - aTargetSpec.get()); + handler->OnLinkClick(this, aVerb, aLinkURI, aTargetSpec.get()); } else { - handler->OnOverLink(this, targetURI, - aTargetSpec.get()); + handler->OnOverLink(this, aLinkURI, aTargetSpec.get()); } return rv; } diff --git a/content/base/src/nsGenericElement.h b/content/base/src/nsGenericElement.h index b81d1f8bb55b..5c417c1bbab8 100644 --- a/content/base/src/nsGenericElement.h +++ b/content/base/src/nsGenericElement.h @@ -535,19 +535,22 @@ public: const nsAString& aValue); /** - * Load a link, putting together the proper URL from the pieces given. + * Trigger a link with uri aLinkURI. If aClick is false, this triggers a + * mouseover on the link, otherwise it triggers a load, after doing a + * security check. * @param aPresContext the pres context. * @param aVerb how the link will be loaded (replace page, new window, etc.) - * @param aBaseURL the base URL to start with (content.baseURL, may be null) - * @param aURLSpec the URL of the link (may be relative) - * @param aTargetSpec the target (like target=, may be null) + * @param aOriginURI the URI the request originates from. Used as the origin + * uri for a CheckLoadURI call. + * @param aLinkURI the URI of the link + * @param aTargetSpec the target (like target=, may be empty) * @param aClick whether this was a click or not (if false, it assumes you * just hovered over the link) */ nsresult TriggerLink(nsIPresContext* aPresContext, nsLinkVerb aVerb, - nsIURI* aBaseURL, - const nsAString& aURLSpec, + nsIURI* aOriginURI, + nsIURI* aLinkURI, const nsAFlatString& aTargetSpec, PRBool aClick); /** diff --git a/content/base/src/nsStyleLinkElement.cpp b/content/base/src/nsStyleLinkElement.cpp index f2b88b308842..4026fc1c7ca5 100644 --- a/content/base/src/nsStyleLinkElement.cpp +++ b/content/base/src/nsStyleLinkElement.cpp @@ -207,19 +207,20 @@ nsStyleLinkElement::UpdateStyleSheet(nsIDocument *aOldDocument, return NS_OK; } - nsAutoString url; + nsCOMPtr uri; PRBool isInline; + GetStyleSheetURL(&isInline, getter_AddRefs(uri)); - GetStyleSheetURL(&isInline, url); + if (mStyleSheet && !isInline && uri) { + nsCOMPtr oldURI; - nsCOMPtr styleSheet(do_QueryInterface(mStyleSheet)); - - if (styleSheet && !isInline) { - nsAutoString oldHref; - - styleSheet->GetHref(oldHref); - if (oldHref.Equals(url)) { - return NS_OK; // We already loaded this stylesheet + mStyleSheet->GetURL(*getter_AddRefs(oldURI)); + if (oldURI) { + PRBool equal; + nsresult rv = oldURI->Equals(uri, &equal); + if (NS_SUCCEEDED(rv) && equal) { + return NS_OK; // We already loaded this stylesheet + } } } @@ -228,7 +229,7 @@ nsStyleLinkElement::UpdateStyleSheet(nsIDocument *aOldDocument, mStyleSheet = nsnull; } - if (url.IsEmpty() && !isInline) { + if (!uri && !isInline) { return NS_OK; // If href is empty and this is not inline style then just bail } @@ -241,17 +242,6 @@ nsStyleLinkElement::UpdateStyleSheet(nsIDocument *aOldDocument, return NS_OK; } - nsCOMPtr uri; - nsresult rv = NS_OK; - - if (!isInline) { - rv = NS_NewURI(getter_AddRefs(uri), url); - - if (NS_FAILED(rv)) { - return NS_OK; // The URL is bad, move along, don't propagate the error (for now) - } - } - nsCOMPtr htmlContainer(do_QueryInterface(doc)); nsCOMPtr loader; @@ -286,6 +276,7 @@ nsStyleLinkElement::UpdateStyleSheet(nsIDocument *aOldDocument, } PRBool doneLoading; + nsresult rv = NS_OK; if (isInline) { PRInt32 count; thisContent->ChildCount(count); diff --git a/content/base/src/nsStyleLinkElement.h b/content/base/src/nsStyleLinkElement.h index b22addc9a25c..325c9ca8dfd3 100644 --- a/content/base/src/nsStyleLinkElement.h +++ b/content/base/src/nsStyleLinkElement.h @@ -57,7 +57,7 @@ public: protected: virtual void GetStyleSheetURL(PRBool* aIsInline, - nsAString& aUrl) = 0; + nsIURI** aURI) = 0; virtual void GetStyleSheetInfo(nsAString& aTitle, nsAString& aType, nsAString& aMedia, diff --git a/content/html/content/public/nsILink.h b/content/html/content/public/nsILink.h index eaebb9ac45d8..de6b0e527b51 100644 --- a/content/html/content/public/nsILink.h +++ b/content/html/content/public/nsILink.h @@ -42,6 +42,8 @@ #include "nsISupports.h" #include "nsILinkHandler.h" // definition of nsLinkState +class nsIURI; + // IID for the nsILink interface #define NS_ILINK_IID \ { 0xa904ac22, 0x28fa, 0x4812, \ @@ -76,18 +78,14 @@ public: NS_IMETHOD SetLinkState(nsLinkState aState) = 0; /** - * Get a pointer to the UTF-8 encoded canonical URL (i.e., fully - * resolved to the base URL) that this link element points to. The - * buffer returned has been allocated for and should be deleted by - * the caller. + * Get a pointer to the fully href URI (fully resolved and canonicalized, + * since it's an nsIURI object). * - * @param aBuf [out] A pointer to be filled in with a pointer to a - * null-terminated string containing the canonical URL. - * If the element has no HREF attribute, it is set to - * nsnull. - * @return NS_OK if the out pointer is filled in + * @param aURI [out] A pointer to be filled in with a pointer to the URI + * If the element has no HREF attribute, it is set to nsnull. + * @return NS_OK if the out pointer is filled in (possibly with nsnull) */ - NS_IMETHOD GetHrefUTF8(char** aBuf) = 0; + NS_IMETHOD GetHrefURI(nsIURI** aURI) = 0; }; diff --git a/content/html/content/src/nsGenericHTMLElement.cpp b/content/html/content/src/nsGenericHTMLElement.cpp index 54ada59bbf88..25e0a4f031a3 100644 --- a/content/html/content/src/nsGenericHTMLElement.cpp +++ b/content/html/content/src/nsGenericHTMLElement.cpp @@ -1467,17 +1467,12 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsIPresContext* aPresContext, // nsILink interface to get a canonified URL that has been // correctly escaped and URL-encoded for the document's charset. - nsXPIDLCString hrefCStr; - GetHrefUTF8ForAnchors(getter_Copies(hrefCStr)); + nsCOMPtr hrefURI; + GetHrefURIForAnchors(getter_AddRefs(hrefURI)); // Only bother to handle the mouse event if there was an href // specified. - if (hrefCStr) { - NS_ConvertUTF8toUCS2 href(hrefCStr); - // Strip off any unneeded CF/LF (for Bug 52119) - // It can't be done in the parser because of Bug 15204 - href.StripChars("\r\n"); - + if (hrefURI) { switch (aEvent->message) { case NS_MOUSE_LEFT_BUTTON_DOWN: { @@ -1527,7 +1522,7 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsIPresContext* aPresContext, break; // let the click go through so we can handle it in JS/XUL } - ret = TriggerLink(aPresContext, eLinkVerb_Replace, baseURL, href, + ret = TriggerLink(aPresContext, eLinkVerb_Replace, baseURL, hrefURI, target, PR_TRUE); *aEventStatus = nsEventStatus_eConsumeDoDefault; @@ -1577,8 +1572,8 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsIPresContext* aPresContext, if (target.IsEmpty()) { GetBaseTarget(target); } - ret = TriggerLink(aPresContext, eLinkVerb_Replace, - baseURL, href, target, PR_FALSE); + ret = TriggerLink(aPresContext, eLinkVerb_Replace, baseURL, + hrefURI, target, PR_FALSE); } break; @@ -1598,7 +1593,7 @@ nsGenericHTMLElement::HandleDOMEventForAnchors(nsIPresContext* aPresContext, } nsresult -nsGenericHTMLElement::GetHrefUTF8ForAnchors(char** aHref) +nsGenericHTMLElement::GetHrefURIForAnchors(nsIURI** aURI) { // This is used by the three nsILink implementations and // nsHTMLStyleElement. @@ -1608,29 +1603,21 @@ nsGenericHTMLElement::GetHrefUTF8ForAnchors(char** aHref) if (NS_CONTENT_ATTR_HAS_VALUE == GetAttr(kNameSpaceID_None, nsHTMLAtoms::href, relURLSpec)) { - // Clean up any leading or trailing whitespace - relURLSpec.Trim(" \t\n\r"); - // Get base URL. nsCOMPtr baseURL; GetBaseURL(getter_AddRefs(baseURL)); - if (baseURL) { - // Get absolute URL. - nsCAutoString buf; - NS_MakeAbsoluteURIWithCharset(buf, relURLSpec, mDocument, baseURL, - nsHTMLUtils::IOService, - nsHTMLUtils::CharsetMgr); - *aHref = ToNewCString(buf); - } - else { - // Absolute URL is same as relative URL. - *aHref = ToNewUTF8String(relURLSpec); + // Get absolute URL. + nsCAutoString buf; + nsresult rv = NS_NewURIWithDocumentCharset(aURI, relURLSpec, mDocument, + baseURL); + if (NS_FAILED(rv)) { + *aURI = nsnull; } } else { // Absolute URL is null to say we have no HREF. - *aHref = nsnull; + *aURI = nsnull; } return NS_OK; diff --git a/content/html/content/src/nsGenericHTMLElement.h b/content/html/content/src/nsGenericHTMLElement.h index cb63d011787a..d44403616e72 100644 --- a/content/html/content/src/nsGenericHTMLElement.h +++ b/content/html/content/src/nsGenericHTMLElement.h @@ -217,7 +217,7 @@ public: // Used by A, AREA, LINK, and STYLE. // Callers must hold a reference to nsHTMLUtils's global reference count. - nsresult GetHrefUTF8ForAnchors(char** aHref); + nsresult GetHrefURIForAnchors(nsIURI** aURI); // Implementation for nsIHTMLContent NS_IMETHOD SetHTMLAttribute(nsIAtom* aAttribute, const nsHTMLValue& aValue, diff --git a/content/html/content/src/nsHTMLAnchorElement.cpp b/content/html/content/src/nsHTMLAnchorElement.cpp index ce213285f815..187df3944dc3 100644 --- a/content/html/content/src/nsHTMLAnchorElement.cpp +++ b/content/html/content/src/nsHTMLAnchorElement.cpp @@ -106,7 +106,7 @@ public: // nsILink NS_IMETHOD GetLinkState(nsLinkState &aState); NS_IMETHOD SetLinkState(nsLinkState aState); - NS_IMETHOD GetHrefUTF8(char** aBuf); + NS_IMETHOD GetHrefURI(nsIURI** aURI); NS_IMETHOD SetDocument(nsIDocument* aDocument, PRBool aDeep, PRBool aCompileEventHandlers); @@ -164,12 +164,12 @@ NS_NewHTMLAnchorElement(nsIHTMLContent** aInstancePtrResult, nsHTMLAnchorElement::nsHTMLAnchorElement() : mLinkState(eLinkState_Unknown) { - nsHTMLUtils::AddRef(); // for GetHrefUTF8 + nsHTMLUtils::AddRef(); // for GetHrefURI } nsHTMLAnchorElement::~nsHTMLAnchorElement() { - nsHTMLUtils::Release(); // for GetHrefUTF8 + nsHTMLUtils::Release(); // for GetHrefURI } @@ -357,13 +357,17 @@ nsHTMLAnchorElement::HandleDOMEvent(nsIPresContext* aPresContext, NS_IMETHODIMP nsHTMLAnchorElement::GetHref(nsAString& aValue) { - nsXPIDLCString buf; - nsresult rv = GetHrefUTF8(getter_Copies(buf)); - if (NS_FAILED(rv)) return rv; + nsCOMPtr uri; + nsresult rv = GetHrefURI(getter_AddRefs(uri)); + if (NS_FAILED(rv)) + return rv; - CopyUTF8toUTF16(buf, aValue); + nsCAutoString spec; + if (uri) { + uri->GetSpec(spec); + } + CopyUTF8toUTF16(spec, aValue); - // NS_IMPL_STRING_ATTR does nothing where we have (buf == null) return NS_OK; } @@ -660,9 +664,9 @@ nsHTMLAnchorElement::SetLinkState(nsLinkState aState) } NS_IMETHODIMP -nsHTMLAnchorElement::GetHrefUTF8(char** aBuf) +nsHTMLAnchorElement::GetHrefURI(nsIURI** aURI) { - return GetHrefUTF8ForAnchors(aBuf); + return GetHrefURIForAnchors(aURI); } NS_IMETHODIMP diff --git a/content/html/content/src/nsHTMLAreaElement.cpp b/content/html/content/src/nsHTMLAreaElement.cpp index fd3dfd812147..8e6de3e8a333 100644 --- a/content/html/content/src/nsHTMLAreaElement.cpp +++ b/content/html/content/src/nsHTMLAreaElement.cpp @@ -83,7 +83,7 @@ public: // nsILink NS_IMETHOD GetLinkState(nsLinkState &aState); NS_IMETHOD SetLinkState(nsLinkState aState); - NS_IMETHOD GetHrefUTF8(char** aBuf); + NS_IMETHOD GetHrefURI(nsIURI** aURI); NS_IMETHOD StringToAttribute(nsIAtom* aAttribute, const nsAString& aValue, @@ -140,12 +140,12 @@ NS_NewHTMLAreaElement(nsIHTMLContent** aInstancePtrResult, nsHTMLAreaElement::nsHTMLAreaElement() : mLinkState(eLinkState_Unknown) { - nsHTMLUtils::AddRef(); // for GetHrefUTF8 + nsHTMLUtils::AddRef(); // for GetHrefURI } nsHTMLAreaElement::~nsHTMLAreaElement() { - nsHTMLUtils::Release(); // for GetHrefUTF8 + nsHTMLUtils::Release(); // for GetHrefURI } NS_IMPL_ADDREF_INHERITED(nsHTMLAreaElement, nsGenericElement) @@ -273,14 +273,14 @@ nsHTMLAreaElement::RemoveFocus(nsIPresContext* aPresContext) NS_IMETHODIMP nsHTMLAreaElement::GetHref(nsAString& aValue) { - char *buf; - nsresult rv = GetHrefUTF8(&buf); + nsCOMPtr uri; + nsresult rv = GetHrefURI(getter_AddRefs(uri)); if (NS_FAILED(rv)) return rv; - if (buf) { - aValue.Assign(NS_ConvertASCIItoUCS2(buf)); - nsCRT::free(buf); + if (uri) { + nsCAutoString spec; + uri->GetSpec(spec); + CopyUTF8toUTF16(spec, aValue); } - // NS_IMPL_STRING_ATTR does nothing where we have (buf == null) return NS_OK; } @@ -571,7 +571,7 @@ nsHTMLAreaElement::SetLinkState(nsLinkState aState) } NS_IMETHODIMP -nsHTMLAreaElement::GetHrefUTF8(char** aBuf) +nsHTMLAreaElement::GetHrefURI(nsIURI** aURI) { - return GetHrefUTF8ForAnchors(aBuf); + return GetHrefURIForAnchors(aURI); } diff --git a/content/html/content/src/nsHTMLLinkElement.cpp b/content/html/content/src/nsHTMLLinkElement.cpp index 4730df7f76e0..961428ec3ed7 100644 --- a/content/html/content/src/nsHTMLLinkElement.cpp +++ b/content/html/content/src/nsHTMLLinkElement.cpp @@ -86,7 +86,7 @@ public: // nsILink NS_IMETHOD GetLinkState(nsLinkState &aState); NS_IMETHOD SetLinkState(nsLinkState aState); - NS_IMETHOD GetHrefUTF8(char** aBuf); + NS_IMETHOD GetHrefURI(nsIURI** aURI); NS_IMETHOD SetDocument(nsIDocument* aDocument, PRBool aDeep, PRBool aCompileEventHandlers) { @@ -186,7 +186,7 @@ public: protected: virtual void GetStyleSheetURL(PRBool* aIsInline, - nsAString& aUrl); + nsIURI** aURI); virtual void GetStyleSheetInfo(nsAString& aTitle, nsAString& aType, nsAString& aMedia, @@ -226,12 +226,12 @@ NS_NewHTMLLinkElement(nsIHTMLContent** aInstancePtrResult, nsHTMLLinkElement::nsHTMLLinkElement() : mLinkState(eLinkState_Unknown) { - nsHTMLUtils::AddRef(); // for GetHrefUTF8 + nsHTMLUtils::AddRef(); // for GetHrefURI } nsHTMLLinkElement::~nsHTMLLinkElement() { - nsHTMLUtils::Release(); // for GetHrefUTF8 + nsHTMLUtils::Release(); // for GetHrefURI } @@ -320,16 +320,15 @@ NS_IMPL_STRING_ATTR(nsHTMLLinkElement, Type, type) NS_IMETHODIMP nsHTMLLinkElement::GetHref(nsAString& aValue) { - char *buf; - nsresult rv = GetHrefUTF8(&buf); + nsCOMPtr uri; + nsresult rv = GetHrefURI(getter_AddRefs(uri)); if (NS_FAILED(rv)) return rv; - if (buf) { - aValue.Assign(NS_ConvertUTF8toUCS2(buf)); - nsCRT::free(buf); + if (uri) { + nsCAutoString spec; + uri->GetSpec(spec); + CopyUTF8toUTF16(spec, aValue); } - // NS_IMPL_STRING_ATTR does nothing where we have (buf == null) - return NS_OK; } @@ -375,17 +374,17 @@ nsHTMLLinkElement::SetLinkState(nsLinkState aState) } NS_IMETHODIMP -nsHTMLLinkElement::GetHrefUTF8(char** aBuf) +nsHTMLLinkElement::GetHrefURI(nsIURI** aURI) { - return GetHrefUTF8ForAnchors(aBuf); + return GetHrefURIForAnchors(aURI); } void nsHTMLLinkElement::GetStyleSheetURL(PRBool* aIsInline, - nsAString& aUrl) + nsIURI** aURI) { *aIsInline = PR_FALSE; - GetHref(aUrl); + GetHrefURIForAnchors(aURI); return; } diff --git a/content/html/content/src/nsHTMLStyleElement.cpp b/content/html/content/src/nsHTMLStyleElement.cpp index f00368dbcf54..2c3e183d8800 100644 --- a/content/html/content/src/nsHTMLStyleElement.cpp +++ b/content/html/content/src/nsHTMLStyleElement.cpp @@ -168,7 +168,7 @@ public: protected: void GetStyleSheetURL(PRBool* aIsInline, - nsAString& aUrl); + nsIURI** aURI); void GetStyleSheetInfo(nsAString& aTitle, nsAString& aType, nsAString& aMedia, @@ -204,12 +204,12 @@ NS_NewHTMLStyleElement(nsIHTMLContent** aInstancePtrResult, nsHTMLStyleElement::nsHTMLStyleElement() { - nsHTMLUtils::AddRef(); // for GetHrefUTF8ForAnchors + nsHTMLUtils::AddRef(); // for GetHrefURIForAnchors } nsHTMLStyleElement::~nsHTMLStyleElement() { - nsHTMLUtils::Release(); // for GetHrefUTF8ForAnchors + nsHTMLUtils::Release(); // for GetHrefURIForAnchors } @@ -314,9 +314,9 @@ nsHTMLStyleElement::SetInnerHTML(const nsAString& aInnerHTML) void nsHTMLStyleElement::GetStyleSheetURL(PRBool* aIsInline, - nsAString& aUrl) + nsIURI** aURI) { - aUrl.Truncate(); + *aURI = nsnull; *aIsInline = !HasAttr(kNameSpaceID_None, nsHTMLAtoms::src); if (*aIsInline) { return; @@ -328,12 +328,7 @@ nsHTMLStyleElement::GetStyleSheetURL(PRBool* aIsInline, return; } - char *buf; - GetHrefUTF8ForAnchors(&buf); - if (buf) { - aUrl.Assign(NS_ConvertUTF8toUCS2(buf)); - nsCRT::free(buf); - } + GetHrefURIForAnchors(aURI); return; } diff --git a/content/html/style/src/nsStyleUtil.cpp b/content/html/style/src/nsStyleUtil.cpp index 903db3e8750b..7def156cbfc4 100644 --- a/content/html/style/src/nsStyleUtil.cpp +++ b/content/html/style/src/nsStyleUtil.cpp @@ -595,15 +595,14 @@ PRBool nsStyleUtil::IsHTMLLink(nsIContent *aContent, nsIAtom *aTag, nsIPresConte // if there is no link, then this anchor is not really a linkpseudo. // bug=23209 - nsXPIDLCString href; - link->GetHrefUTF8(getter_Copies(href)); + nsCOMPtr hrefURI; + link->GetHrefURI(getter_AddRefs(hrefURI)); - if (href) { - nsILinkHandler *linkHandler = nsnull; - aPresContext->GetLinkHandler(&linkHandler); + if (hrefURI) { + nsCOMPtr linkHandler; + aPresContext->GetLinkHandler(getter_AddRefs(linkHandler)); if (linkHandler) { - linkHandler->GetLinkState(href, linkState); - NS_RELEASE(linkHandler); + linkHandler->GetLinkState(hrefURI, linkState); } else { // no link handler? then all links are unvisited @@ -665,16 +664,14 @@ PRBool nsStyleUtil::IsSimpleXlink(nsIContent *aContent, nsIPresContext *aPresCon } } - // convert here, rather than twice in NS_MakeAbsoluteURI and - // back again - nsCAutoString absHREF; - (void) NS_MakeAbsoluteURI(absHREF, NS_ConvertUCS2toUTF8(val), baseURI); + nsCOMPtr absURI; + // XXX should we make sure to get the right charset off the document? + (void) NS_NewURI(getter_AddRefs(absURI), val, nsnull, baseURI); - nsILinkHandler *linkHandler = nsnull; - aPresContext->GetLinkHandler(&linkHandler); + nsCOMPtr linkHandler; + aPresContext->GetLinkHandler(getter_AddRefs(linkHandler)); if (linkHandler) { - linkHandler->GetLinkState(absHREF, *aState); - NS_RELEASE(linkHandler); + linkHandler->GetLinkState(absURI, *aState); } else { // no link handler? then all links are unvisited diff --git a/content/shared/public/nsHTMLUtils.h b/content/shared/public/nsHTMLUtils.h index 301a63c0bf62..74896de048b1 100644 --- a/content/shared/public/nsHTMLUtils.h +++ b/content/shared/public/nsHTMLUtils.h @@ -53,19 +53,14 @@ class nsString; class nsACString; /** - * A version of NS_MakeAbsoluteURI that's savvy to document character - * set encodings, and will recode a relative spec in the specified - * charset and URL-escape it before resolving. - * - * XXXdarin this should really return a nsIURI + * A version of NS_NewURI that's savvy to document character + * set encodings */ nsresult -NS_MakeAbsoluteURIWithCharset(nsACString &aResult, - const nsString& aSpec, - nsIDocument* aDocument, - nsIURI* aBaseURI = nsnull, - nsIIOService* aIOService = nsnull, - nsICharsetConverterManager* aConvMgr = nsnull); +NS_NewURIWithDocumentCharset(nsIURI** aResult, + const nsString& aSpec, + nsIDocument* aDocument, + nsIURI* aBaseURI); class nsHTMLUtils { diff --git a/content/shared/src/nsHTMLUtils.cpp b/content/shared/src/nsHTMLUtils.cpp index 1227f56a801a..f2fb02de5329 100644 --- a/content/shared/src/nsHTMLUtils.cpp +++ b/content/shared/src/nsHTMLUtils.cpp @@ -58,49 +58,21 @@ static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID); nsresult -NS_MakeAbsoluteURIWithCharset(nsACString &aResult, - const nsString& aSpec, - nsIDocument* aDocument, - nsIURI* aBaseURI, - nsIIOService* aIOService, - nsICharsetConverterManager* aConvMgr) +NS_NewURIWithDocumentCharset(nsIURI** aResult, + const nsString& aSpec, + nsIDocument* aDocument, + nsIURI* aBaseURI) { - // Initialize aResult in case of tragedy - aResult.Truncate(); - - // Sanity - NS_PRECONDITION(aBaseURI != nsnull, "no base URI"); - if (! aBaseURI) - return NS_ERROR_FAILURE; - - // This gets the relative spec after gyrating it through all the - // necessary encodings and escaping. - - if (IsASCII(aSpec)) { - // If it's ASCII, then just copy the characters - return aBaseURI->Resolve(NS_LossyConvertUCS2toASCII(aSpec), aResult); - } - - nsCOMPtr absURI; - nsresult rv; - - nsCAutoString originCharset; // XXX why store charset as UCS2? + NS_PRECONDITION(aResult, "Null out param"); + NS_PRECONDITION(aBaseURI, "Must have a base URI"); + + nsCAutoString originCharset; if (aDocument && NS_FAILED(aDocument->GetDocumentCharacterSet(originCharset))) originCharset.Truncate(); - // URI can't be encoded in UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32-LE, - // UTF-32LE, UTF-32BE (yet?). Truncate it and leave it to default (UTF-8) - if (originCharset[0] == 'U' && - originCharset[1] == 'T' && - originCharset[2] == 'F') - originCharset.Truncate(); - - rv = nsHTMLUtils::IOService->NewURI(NS_ConvertUCS2toUTF8(aSpec), - originCharset.get(), - aBaseURI, getter_AddRefs(absURI)); - if (NS_FAILED(rv)) return rv; - - return absURI->GetSpec(aResult); + return nsHTMLUtils::IOService->NewURI(NS_ConvertUCS2toUTF8(aSpec), + originCharset.get(), + aBaseURI, aResult); } diff --git a/content/xml/content/src/nsXMLElement.cpp b/content/xml/content/src/nsXMLElement.cpp index 6e039d63d663..c970b8c31a64 100644 --- a/content/xml/content/src/nsXMLElement.cpp +++ b/content/xml/content/src/nsXMLElement.cpp @@ -40,8 +40,10 @@ #include "nsXMLElement.h" #include "nsHTMLAtoms.h" #include "nsLayoutAtoms.h" +#include "nsHTMLUtils.h" #include "nsIDocument.h" #include "nsIAtom.h" +#include "nsNetUtil.h" #include "nsIEventListenerManager.h" #include "nsIDocShell.h" #include "nsIEventStateManager.h" @@ -97,10 +99,12 @@ NS_NewXMLElement(nsIContent** aInstancePtrResult, nsINodeInfo *aNodeInfo) nsXMLElement::nsXMLElement() : mIsLink(PR_FALSE) { + nsHTMLUtils::AddRef(); // for NS_NewURIWithDocumentCharset } nsXMLElement::~nsXMLElement() { + nsHTMLUtils::Release(); // for NS_NewURIWithDocumentCharset } @@ -143,17 +147,6 @@ NS_IMPL_ADDREF_INHERITED(nsXMLElement, nsGenericElement) NS_IMPL_RELEASE_INHERITED(nsXMLElement, nsGenericElement) -static inline nsresult MakeURI(const nsACString &aSpec, nsIURI *aBase, nsIURI **aURI) -{ - nsresult rv; - static NS_DEFINE_CID(ioServCID,NS_IOSERVICE_CID); - nsCOMPtr service(do_GetService(ioServCID, &rv)); - if (NS_FAILED(rv)) - return rv; - - return service->NewURI(aSpec,nsnull,aBase,aURI); -} - NS_IMETHODIMP nsXMLElement::GetXMLBaseURI(nsIURI **aURI) { @@ -176,14 +169,12 @@ nsXMLElement::GetXMLBaseURI(nsIURI **aURI) // The complex looking if above is to make sure that we do not erroneously // think a value of "./this:that" would have a scheme of "./that" - NS_ConvertUCS2toUTF8 str(value); - - rv = MakeURI(str, nsnull, aURI); + rv = NS_NewURIWithDocumentCharset(aURI, value, mDocument, nsnull); if (NS_FAILED(rv)) break; if (!base.IsEmpty()) { // XXXdarin base is always empty - CopyUTF16toUTF8(base, str); + NS_ConvertUTF16toUTF8 str(base); nsCAutoString resolvedStr; rv = (*aURI)->Resolve(str, resolvedStr); if (NS_FAILED(rv)) break; @@ -224,7 +215,7 @@ nsXMLElement::GetXMLBaseURI(nsIURI **aURI) *aURI = docBase.get(); NS_IF_ADDREF(*aURI); // nsCOMPtr releases this once } else { - rv = MakeURI(NS_ConvertUCS2toUTF8(base), docBase, aURI); + rv = NS_NewURIWithDocumentCharset(aURI, base, mDocument, docBase); } } @@ -319,15 +310,13 @@ static nsresult DocShellToPresContext(nsIDocShell *aShell, } -static nsresult CheckLoadURI(nsIURI *aBaseURI, const nsAString& aURI, - nsIURI **aAbsURI) +static nsresult CheckLoadURI(const nsString& aSpec, nsIURI *aBaseURI, + nsIDocument* aDocument, nsIURI **aAbsURI) { - NS_ConvertUCS2toUTF8 str(aURI); - *aAbsURI = nsnull; nsresult rv; - rv = MakeURI(str, aBaseURI, aAbsURI); + rv = NS_NewURIWithDocumentCharset(aAbsURI, aSpec, aDocument, aBaseURI); if (NS_SUCCEEDED(rv)) { nsCOMPtr securityManager = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); @@ -449,12 +438,12 @@ nsXMLElement::MaybeTriggerAutoLink(nsIDocShell *aShell) value); if (rv == NS_CONTENT_ATTR_HAS_VALUE && !value.IsEmpty()) { nsCOMPtr uri; - rv = CheckLoadURI(base,value,getter_AddRefs(uri)); + rv = CheckLoadURI(value, base, mDocument, getter_AddRefs(uri)); if (NS_SUCCEEDED(rv)) { nsCOMPtr pc; - rv = DocShellToPresContext(aShell,getter_AddRefs(pc)); + rv = DocShellToPresContext(aShell, getter_AddRefs(pc)); if (NS_SUCCEEDED(rv)) { - rv = TriggerLink(pc, verb, base, value, + rv = TriggerLink(pc, verb, base, uri, NS_LITERAL_STRING(""), PR_TRUE); return SpecialAutoLoadReturn(rv,verb); @@ -506,7 +495,6 @@ nsXMLElement::HandleDOMEvent(nsIPresContext* aPresContext, break; // let the click go through so we can handle it in JS/XUL } nsAutoString show, href, target; - nsIURI* baseURL = nsnull; nsLinkVerb verb = eLinkVerb_Undefined; // basically means same as replace nsGenericContainerElement::GetAttr(kNameSpaceID_XLink, nsHTMLAtoms::href, @@ -539,12 +527,16 @@ nsXMLElement::HandleDOMEvent(nsIPresContext* aPresContext, verb = eLinkVerb_Embed; } - GetXMLBaseURI(&baseURL); + nsCOMPtr baseURL; + GetXMLBaseURI(getter_AddRefs(baseURL)); + nsCOMPtr uri; + ret = NS_NewURIWithDocumentCharset(getter_AddRefs(uri), href, + mDocument, baseURL); + if (NS_SUCCEEDED(ret)) { + ret = TriggerLink(aPresContext, verb, baseURL, uri, target, + PR_TRUE); + } - ret = TriggerLink(aPresContext, verb, baseURL, href, target, - PR_TRUE); - - NS_IF_RELEASE(baseURL); *aEventStatus = nsEventStatus_eConsumeDoDefault; } } @@ -586,7 +578,6 @@ nsXMLElement::HandleDOMEvent(nsIPresContext* aPresContext, case NS_MOUSE_ENTER_SYNTH: { nsAutoString href, target; - nsIURI* baseURL = nsnull; nsGenericContainerElement::GetAttr(kNameSpaceID_XLink, nsHTMLAtoms::href, href); @@ -595,12 +586,17 @@ nsXMLElement::HandleDOMEvent(nsIPresContext* aPresContext, break; } - GetXMLBaseURI(&baseURL); + nsCOMPtr baseURL; + GetXMLBaseURI(getter_AddRefs(baseURL)); - ret = TriggerLink(aPresContext, eLinkVerb_Replace, baseURL, href, - target, PR_FALSE); + nsCOMPtr uri; + ret = NS_NewURIWithDocumentCharset(getter_AddRefs(uri), href, + mDocument, baseURL); + if (NS_SUCCEEDED(ret)) { + ret = TriggerLink(aPresContext, eLinkVerb_Replace, baseURL, uri, + target, PR_FALSE); + } - NS_IF_RELEASE(baseURL); *aEventStatus = nsEventStatus_eConsumeDoDefault; } break; diff --git a/content/xml/content/src/nsXMLStylesheetPI.cpp b/content/xml/content/src/nsXMLStylesheetPI.cpp index fbda72d10b3a..54948131c60f 100644 --- a/content/xml/content/src/nsXMLStylesheetPI.cpp +++ b/content/xml/content/src/nsXMLStylesheetPI.cpp @@ -71,7 +71,7 @@ public: protected: void GetStyleSheetURL(PRBool* aIsInline, - nsAString& aUrl); + nsIURI** aURI); void GetStyleSheetInfo(nsAString& aTitle, nsAString& aType, nsAString& aMedia, @@ -157,10 +157,10 @@ nsXMLStylesheetPI::GetCharset(nsAString& aCharset) void nsXMLStylesheetPI::GetStyleSheetURL(PRBool* aIsInline, - nsAString& aUrl) + nsIURI** aURI) { *aIsInline = PR_FALSE; - aUrl.Truncate(); + *aURI = nsnull; nsAutoString href; GetAttrValue(NS_LITERAL_STRING("href"), href); @@ -169,10 +169,12 @@ nsXMLStylesheetPI::GetStyleSheetURL(PRBool* aIsInline, } nsCOMPtr url, baseURL; + nsCAutoString charset; if (mDocument) { mDocument->GetBaseURL(getter_AddRefs(baseURL)); + mDocument->GetDocumentCharacterSet(charset); } - NS_MakeAbsoluteURI(aUrl, href, baseURL); + NS_NewURI(aURI, href, charset.get(), baseURL); } void diff --git a/docshell/base/nsWebShell.cpp b/docshell/base/nsWebShell.cpp index 43ff63e6863e..b17755b34747 100644 --- a/docshell/base/nsWebShell.cpp +++ b/docshell/base/nsWebShell.cpp @@ -757,86 +757,26 @@ nsWebShell::OnLeaveLink() return rv; } -nsresult -nsWebShell::NormalizeURI(nsACString& aURLSpec) -{ - nsIURI *uri = nsnull; - nsCAutoString scheme; - nsresult rv = mIOService->ExtractScheme(aURLSpec, scheme); - if (NS_FAILED(rv)) return rv; - - // keep tempUri up here to keep it in scope - nsCOMPtr tempUri; - - // used to avoid extra work later - PRBool clearUri(PR_TRUE); - - if (scheme.Equals(NS_LITERAL_CSTRING("http"))) { - if (mCachedHttpUrl) - rv = mCachedHttpUrl->SetSpec(aURLSpec); - else - rv = NS_NewURI(getter_AddRefs(mCachedHttpUrl), aURLSpec); - - uri = mCachedHttpUrl; - } - - else if (scheme.Equals(NS_LITERAL_CSTRING("https"))) { - if (mCachedHttpsUrl) - rv = mCachedHttpsUrl->SetSpec(aURLSpec); - else - rv = NS_NewURI(getter_AddRefs(mCachedHttpsUrl), aURLSpec); - - uri = mCachedHttpsUrl; - } - - else if (scheme.Equals(NS_LITERAL_CSTRING("ftp"))) { - if (mCachedFtpUrl) - rv = mCachedFtpUrl->SetSpec(aURLSpec); - else - rv = NS_NewURI(getter_AddRefs(mCachedFtpUrl), aURLSpec); - - uri = mCachedFtpUrl; - } else { - rv = NS_NewURI(getter_AddRefs(tempUri), aURLSpec); - uri = tempUri; - clearUri = PR_FALSE; - } - - // covers all above failures - if (NS_FAILED(rv)) return rv; - - rv = uri->GetSpec(aURLSpec); - - // clear out the old spec, for security reasons - old data should - // not be floating around in cached URIs! - // (but avoid doing extra work if we're just destroying the uri) - if (clearUri) - uri->SetSpec(NS_LITERAL_CSTRING("")); - - return rv; -} - NS_IMETHODIMP -nsWebShell::GetLinkState(const nsACString& aLinkURI, nsLinkState& aState) +nsWebShell::GetLinkState(nsIURI* aLinkURI, nsLinkState& aState) { + if (!aLinkURI) { + // No uri means not a link + aState = eLinkState_NotLink; + return NS_OK; + } + aState = eLinkState_Unvisited; // no history, leave state unchanged if (!mGlobalHistory) return NS_OK; - - // default to the given URI - nsCAutoString resolvedPath(aLinkURI); - nsresult rv; - // get the cached IO service - if (!mIOService) - mIOService = do_GetService(NS_IOSERVICE_CONTRACTID, &rv); - - NormalizeURI(resolvedPath); + nsCAutoString spec; + aLinkURI->GetSpec(spec); PRBool isVisited; - NS_ENSURE_SUCCESS(mGlobalHistory->IsVisited(resolvedPath.get(), &isVisited), + NS_ENSURE_SUCCESS(mGlobalHistory->IsVisited(spec.get(), &isVisited), NS_ERROR_FAILURE); if (isVisited) aState = eLinkState_Visited; diff --git a/docshell/base/nsWebShell.h b/docshell/base/nsWebShell.h index 66b18d5285de..731902fa9e96 100644 --- a/docshell/base/nsWebShell.h +++ b/docshell/base/nsWebShell.h @@ -87,7 +87,7 @@ public: nsIURI* aURI, const PRUnichar* aTargetSpec); NS_IMETHOD OnLeaveLink(); - NS_IMETHOD GetLinkState(const nsACString& aLinkURI, nsLinkState& aState); + NS_IMETHOD GetLinkState(nsIURI* aLinkURI, nsLinkState& aState); NS_IMETHOD Create(); NS_IMETHOD Destroy(); @@ -117,8 +117,6 @@ protected: nsIChannel* channel, nsresult aStatus); - nsresult NormalizeURI(nsACString& aURLSpec); - PRThread *mThread; nsIWebShellContainer* mContainer; @@ -134,17 +132,6 @@ protected: nsIStreamListener** aResult); nsCOMPtr mCommandManager; - - // cached io service for NS_NewURI - nsCOMPtr mIOService; - - // these are specifically cached for these - // protocols, because we're optimizing for link coloring - - // most links are http, https, or ftp - nsCOMPtr mCachedHttpUrl; - nsCOMPtr mCachedHttpsUrl; - nsCOMPtr mCachedFtpUrl; - #ifdef DEBUG private: diff --git a/layout/style/nsStyleUtil.cpp b/layout/style/nsStyleUtil.cpp index 903db3e8750b..7def156cbfc4 100644 --- a/layout/style/nsStyleUtil.cpp +++ b/layout/style/nsStyleUtil.cpp @@ -595,15 +595,14 @@ PRBool nsStyleUtil::IsHTMLLink(nsIContent *aContent, nsIAtom *aTag, nsIPresConte // if there is no link, then this anchor is not really a linkpseudo. // bug=23209 - nsXPIDLCString href; - link->GetHrefUTF8(getter_Copies(href)); + nsCOMPtr hrefURI; + link->GetHrefURI(getter_AddRefs(hrefURI)); - if (href) { - nsILinkHandler *linkHandler = nsnull; - aPresContext->GetLinkHandler(&linkHandler); + if (hrefURI) { + nsCOMPtr linkHandler; + aPresContext->GetLinkHandler(getter_AddRefs(linkHandler)); if (linkHandler) { - linkHandler->GetLinkState(href, linkState); - NS_RELEASE(linkHandler); + linkHandler->GetLinkState(hrefURI, linkState); } else { // no link handler? then all links are unvisited @@ -665,16 +664,14 @@ PRBool nsStyleUtil::IsSimpleXlink(nsIContent *aContent, nsIPresContext *aPresCon } } - // convert here, rather than twice in NS_MakeAbsoluteURI and - // back again - nsCAutoString absHREF; - (void) NS_MakeAbsoluteURI(absHREF, NS_ConvertUCS2toUTF8(val), baseURI); + nsCOMPtr absURI; + // XXX should we make sure to get the right charset off the document? + (void) NS_NewURI(getter_AddRefs(absURI), val, nsnull, baseURI); - nsILinkHandler *linkHandler = nsnull; - aPresContext->GetLinkHandler(&linkHandler); + nsCOMPtr linkHandler; + aPresContext->GetLinkHandler(getter_AddRefs(linkHandler)); if (linkHandler) { - linkHandler->GetLinkState(absHREF, *aState); - NS_RELEASE(linkHandler); + linkHandler->GetLinkState(absURI, *aState); } else { // no link handler? then all links are unvisited diff --git a/netwerk/base/src/nsStandardURL.cpp b/netwerk/base/src/nsStandardURL.cpp index be763e2ec3c9..eed77249c0c9 100644 --- a/netwerk/base/src/nsStandardURL.cpp +++ b/netwerk/base/src/nsStandardURL.cpp @@ -2264,8 +2264,14 @@ nsStandardURL::Init(PRUint32 urlType, else mOriginCharset = charset; - // an empty charset implies UTF-8 - if (mOriginCharset.EqualsIgnoreCase("UTF-8")) + // URI can't be encoded in UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32-LE, + // UTF-32LE, UTF-32BE (yet?). Truncate mOriginCharset if it starts with + // "utf" (since an empty mOriginCharset implies UTF-8, this is safe even if + // mOriginCharset is UTF-8). + if (mOriginCharset.Length() >= 3 && + (mOriginCharset[0] == 'U' || mOriginCharset[0] == 'u') && + (mOriginCharset[1] == 'T' || mOriginCharset[1] == 't') && + (mOriginCharset[2] == 'F' || mOriginCharset[2] == 'f')) mOriginCharset.Truncate(); if (baseURI) { diff --git a/webshell/public/nsILinkHandler.h b/webshell/public/nsILinkHandler.h index 74524877fb4f..db9de1cf7f1d 100644 --- a/webshell/public/nsILinkHandler.h +++ b/webshell/public/nsILinkHandler.h @@ -138,7 +138,7 @@ public: /** * Get the state of a link to a given absolute URL */ - NS_IMETHOD GetLinkState(const nsACString& aLinkURI, nsLinkState& aState) = 0; + NS_IMETHOD GetLinkState(nsIURI* aLinkURI, nsLinkState& aState) = 0; }; #endif /* nsILinkHandler_h___ */