diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index a347aad853b..e03bd3ce6d8 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -44,7 +44,7 @@ #include "nsIScriptObjectPrincipal.h" #include "nsIScriptContext.h" #include "nsIURL.h" -#include "nsIJARURI.h" +#include "nsINestedURI.h" #include "nspr.h" #include "nsJSPrincipals.h" #include "nsSystemPrincipal.h" @@ -266,18 +266,10 @@ nsScriptSecurityManager::SecurityCompareURIs(nsIURI* aSourceURI, return NS_OK; } - // If either uri is a jar URI, get the base URI - nsCOMPtr jarURI; - nsCOMPtr sourceBaseURI(aSourceURI); - while((jarURI = do_QueryInterface(sourceBaseURI))) - { - jarURI->GetJARFile(getter_AddRefs(sourceBaseURI)); - } - nsCOMPtr targetBaseURI(aTargetURI); - while((jarURI = do_QueryInterface(targetBaseURI))) - { - jarURI->GetJARFile(getter_AddRefs(targetBaseURI)); - } + // If either URI is a nested URI, get the base URI + nsCOMPtr sourceBaseURI = NS_GetInnermostURI(aSourceURI); + + nsCOMPtr targetBaseURI = NS_GetInnermostURI(aTargetURI); if (!sourceBaseURI || !targetBaseURI) return NS_ERROR_FAILURE; @@ -1184,38 +1176,18 @@ nsScriptSecurityManager::GetBaseURIScheme(nsIURI* aURI, nsresult rv; + // Get the innermost URI + nsCOMPtr uri = NS_GetInnermostURI(aURI); + //-- get the source scheme - rv = aURI->GetScheme(aScheme); + rv = uri->GetScheme(aScheme); if (NS_FAILED(rv)) return rv; - //-- If aURI is a view-source URI, drill down to the base URI - if (aScheme.EqualsLiteral("view-source")) - { - nsCAutoString path; - rv = aURI->GetPath(path); - if (NS_FAILED(rv)) return rv; - nsCOMPtr innerURI; - rv = NS_NewURI(getter_AddRefs(innerURI), path, nsnull, nsnull, - sIOService); - if (NS_FAILED(rv)) return rv; - return nsScriptSecurityManager::GetBaseURIScheme(innerURI, aScheme); - } - - //-- If aURI is a jar URI, drill down again - nsCOMPtr jarURI = do_QueryInterface(aURI); - if (jarURI) - { - nsCOMPtr innerURI; - jarURI->GetJARFile(getter_AddRefs(innerURI)); - if (!innerURI) return NS_ERROR_FAILURE; - return nsScriptSecurityManager::GetBaseURIScheme(innerURI, aScheme); - } - //-- if aURI is an about uri, distinguish 'safe' and 'unsafe' about URIs if(aScheme.EqualsLiteral("about")) { nsCAutoString path; - rv = NS_GetAboutModuleName(aURI, path); + rv = NS_GetAboutModuleName(uri, path); NS_ENSURE_SUCCESS(rv, rv); if (path.EqualsLiteral("blank") || path.EqualsLiteral("mozilla") || @@ -1895,7 +1867,15 @@ NS_IMETHODIMP nsScriptSecurityManager::GetCodebasePrincipal(nsIURI *aURI, nsIPrincipal **result) { - nsresult rv; + PRBool noContext; + nsresult rv = + NS_URIChainHasFlags(aURI, + nsIProtocolHandler::URI_HAS_NO_SECURITY_CONTEXT, + &noContext); + if (NS_FAILED(rv) || noContext) { + return CallCreateInstance(NS_NULLPRINCIPAL_CONTRACTID, result); + } + nsCOMPtr principal; rv = CreateCodebasePrincipal(aURI, getter_AddRefs(principal)); if (NS_FAILED(rv)) return rv; diff --git a/content/xul/document/public/nsIXULPrototypeCache.h b/content/xul/document/public/nsIXULPrototypeCache.h index 4a791174f02..47907ede753 100644 --- a/content/xul/document/public/nsIXULPrototypeCache.h +++ b/content/xul/document/public/nsIXULPrototypeCache.h @@ -129,7 +129,7 @@ const char XUL_FASTLOAD_FILE_BASENAME[] = "XUL"; // Increase the subtractor when changing version, say when changing the // (opaque to FastLoad code) format of JS script, function, regexp, etc. // XDR serializations. -#define XUL_FASTLOAD_FILE_VERSION (0xfeedbeef - 10) +#define XUL_FASTLOAD_FILE_VERSION (0xfeedbeef - 11) #define XUL_SERIALIZATION_BUFFER_SIZE (64 * 1024) #define XUL_DESERIALIZATION_BUFFER_SIZE (8 * 1024) diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index ce87388cb67..1168a9d95c2 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -123,6 +123,7 @@ #include "nsISHistoryListener.h" #include "nsIWindowWatcher.h" #include "nsIObserver.h" +#include "nsINestedURI.h" // Editor-related #include "nsIEditingSession.h" @@ -6812,7 +6813,8 @@ nsDocShell::DoURILoad(nsIURI * aURI, } } // - // Set the owner of the channel - only for javascript and data channels. + // Set the owner of the channel, but only for channels that can't + // provide their own security context. // // XXX: Is seems wrong that the owner is ignored - even if one is // supplied) unless the URI is javascript or data. @@ -6820,17 +6822,14 @@ nsDocShell::DoURILoad(nsIURI * aURI, // passing in. In particular, see the code and comments in LoadURI // where we get the current document principal as the owner if called // from chrome. That would be very wrong if this code changed - // anything but javascript: and data: + // anything but channels that can't provide their own security context! // // (Currently chrome URIs set the owner when they are created! // So setting a NULL owner would be bad!) // - PRBool isJSOrData = PR_FALSE; - aURI->SchemeIs("javascript", &isJSOrData); - if (!isJSOrData) { - aURI->SchemeIs("data", &isJSOrData); - } - if (isJSOrData) { + PRBool inherit; + rv = URIInheritsSecurityContext(aURI, &inherit); + if (NS_SUCCEEDED(rv) && inherit) { channel->SetOwner(aOwner); } @@ -7599,7 +7598,6 @@ nsDocShell::AddToSessionHistory(nsIURI * aURI, NS_IMETHODIMP nsDocShell::LoadHistoryEntry(nsISHEntry * aEntry, PRUint32 aLoadType) { - nsresult rv; nsCOMPtr uri; nsCOMPtr postData; nsCOMPtr referrerURI; @@ -7614,18 +7612,15 @@ nsDocShell::LoadHistoryEntry(nsISHEntry * aEntry, PRUint32 aLoadType) NS_ERROR_FAILURE); NS_ENSURE_SUCCESS(aEntry->GetContentType(contentType), NS_ERROR_FAILURE); - PRBool isJavaScript, isViewSource, isData; // Calling CreateAboutBlankContentViewer can set mOSHE to null, and if // that's the only thing holding a ref to aEntry that will cause aEntry to // die while we're loading it. So hold a strong ref to aEntry here, just // in case. nsCOMPtr kungFuDeathGrip(aEntry); - if ((NS_SUCCEEDED(uri->SchemeIs("javascript", &isJavaScript)) && - isJavaScript) || - (NS_SUCCEEDED(uri->SchemeIs("view-source", &isViewSource)) && - isViewSource) || - (NS_SUCCEEDED(uri->SchemeIs("data", &isData)) && isData)) { - // We're loading a javascript: or data: URL from session + PRBool inherit; + nsresult rv = URIInheritsSecurityContext(uri, &inherit); + if (NS_FAILED(rv) || inherit) { + // We're loading a URL that inherits a security context from session // history. Replace the current document with about:blank to // prevent anything from the current document from leaking // into any JavaScript code in the URL. @@ -8679,3 +8674,14 @@ nsDocShell::Observe(nsISupports *aSubject, const char *aTopic, } return rv; } + +/* static */ +nsresult +nsDocShell::URIInheritsSecurityContext(nsIURI* aURI, PRBool* aResult) +{ + // Need to add explicit check for about:blank here too, in the + // future. See bug 332182. + return NS_URIChainHasFlags(aURI, + nsIProtocolHandler::URI_HAS_NO_SECURITY_CONTEXT, + aResult); +} diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h index f85bade539d..0fe918d010a 100644 --- a/docshell/base/nsDocShell.h +++ b/docshell/base/nsDocShell.h @@ -462,6 +462,9 @@ protected: // Call BeginRestore(nsnull, PR_FALSE) for each child of this shell. nsresult BeginRestoreChildren(); + // Check whether aURI should inherit our security context + static nsresult URIInheritsSecurityContext(nsIURI* aURI, PRBool* aResult); + protected: // Override the parent setter from nsDocLoader virtual nsresult SetDocLoaderParent(nsDocLoader * aLoader); diff --git a/docshell/base/nsWebShell.cpp b/docshell/base/nsWebShell.cpp index 5554df324ae..8f3cd4a4a97 100644 --- a/docshell/base/nsWebShell.cpp +++ b/docshell/base/nsWebShell.cpp @@ -703,19 +703,15 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent, nsCOMPtr node(do_QueryInterface(aContent)); NS_ENSURE_TRUE(node, NS_ERROR_UNEXPECTED); - PRBool isJS = PR_FALSE; - PRBool isData = PR_FALSE; - - aURI->SchemeIs("javascript", &isJS); - aURI->SchemeIs("data", &isData); - - if (isJS || isData) { + PRBool inherit; + nsresult rv = URIInheritsSecurityContext(aURI, &inherit); + if (NS_FAILED(rv) || inherit) { nsCOMPtr sourceDoc = aContent->GetDocument(); if (!sourceDoc) { // The source is in a 'zombie' document, or not part of a - // document any more. Don't let it execute any javascript in the - // new document. + // document any more. Don't let it perform loads in this docshell. + // XXXbz why only for the inherit case? return NS_OK; } @@ -725,8 +721,8 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent, NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE); if (presShell->GetDocument() != sourceDoc) { - // The source is not in the current document, don't let it - // execute any javascript in the current document. + // The source is not in the current document, don't let it load anything + // that would inherit the principals of the current document. return NS_OK; } @@ -765,7 +761,6 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent, *aRequest = nsnull; } - nsresult rv; switch(aVerb) { case eLinkVerb_New: NS_ASSERTION(target.IsEmpty(), "Losing window name information"); diff --git a/dom/src/jsurl/nsJSProtocolHandler.cpp b/dom/src/jsurl/nsJSProtocolHandler.cpp index 99b7498937b..e10d130d2de 100644 --- a/dom/src/jsurl/nsJSProtocolHandler.cpp +++ b/dom/src/jsurl/nsJSProtocolHandler.cpp @@ -800,7 +800,7 @@ nsJSProtocolHandler::GetDefaultPort(PRInt32 *result) NS_IMETHODIMP nsJSProtocolHandler::GetProtocolFlags(PRUint32 *result) { - *result = URI_NORELATIVE | URI_NOAUTH; + *result = URI_NORELATIVE | URI_NOAUTH | URI_HAS_NO_SECURITY_CONTEXT; return NS_OK; } diff --git a/modules/libjar/nsIJARURI.idl b/modules/libjar/nsIJARURI.idl index ed78aff8da6..0728027164d 100644 --- a/modules/libjar/nsIJARURI.idl +++ b/modules/libjar/nsIJARURI.idl @@ -47,14 +47,14 @@ * * The nsIURL methods operate on the part of the spec. */ -[scriptable, uuid(c7e410d3-85f2-11d3-9f63-006008a6efe9)] +[scriptable, uuid(d2746619-1724-4f42-8ca8-dacaf1b269d6)] interface nsIJARURI : nsIURL { /** * Returns the root URI (the one for the actual JAR file) for this JAR * (e.g., http://www.big.com/blue.jar). */ - attribute nsIURI JARFile; + readonly attribute nsIURI JARFile; /** * Returns the entry specified for this JAR URI (e.g., "ocean.html"). This diff --git a/modules/libjar/nsJARURI.cpp b/modules/libjar/nsJARURI.cpp index a4bd4d1a382..50ce35ad92f 100644 --- a/modules/libjar/nsJARURI.cpp +++ b/modules/libjar/nsJARURI.cpp @@ -73,6 +73,7 @@ NS_INTERFACE_MAP_BEGIN(nsJARURI) NS_INTERFACE_MAP_ENTRY(nsIJARURI) NS_INTERFACE_MAP_ENTRY(nsISerializable) NS_INTERFACE_MAP_ENTRY(nsIClassInfo) + NS_INTERFACE_MAP_ENTRY(nsINestedURI) // see nsJARURI::Equals if (aIID.Equals(NS_GET_IID(nsJARURI))) foundInterface = NS_REINTERPRET_CAST(nsISupports*, this); @@ -318,6 +319,8 @@ nsJARURI::SetSpecWithBase(const nsACString &aSpec, nsIURI* aBaseURL) aBaseURL, getter_AddRefs(mJARFile)); if (NS_FAILED(rv)) return rv; + NS_TryToSetImmutable(mJARFile); + // skip over any extra '/' chars while (*delim_end == '/') ++delim_end; @@ -500,6 +503,8 @@ nsJARURI::Clone(nsIURI **result) rv = mJARFile->Clone(getter_AddRefs(newJARFile)); if (NS_FAILED(rv)) return rv; + NS_TryToSetImmutable(newJARFile); + nsCOMPtr newJAREntryURI; rv = mJAREntry->Clone(getter_AddRefs(newJAREntryURI)); if (NS_FAILED(rv)) return rv; @@ -759,16 +764,7 @@ nsJARURI::GetRelativeSpec(nsIURI* uriToCompare, nsACString& relativeSpec) NS_IMETHODIMP nsJARURI::GetJARFile(nsIURI* *jarFile) { - *jarFile = mJARFile; - NS_ADDREF(*jarFile); - return NS_OK; -} - -NS_IMETHODIMP -nsJARURI::SetJARFile(nsIURI* jarFile) -{ - mJARFile = jarFile; - return NS_OK; + return GetInnerURI(jarFile); } NS_IMETHODIMP @@ -790,3 +786,16 @@ nsJARURI::SetJAREntry(const nsACString &entryPath) } //////////////////////////////////////////////////////////////////////////////// + +NS_IMETHODIMP +nsJARURI::GetInnerURI(nsIURI **uri) +{ + return NS_EnsureSafeToReturn(mJARFile, uri); +} + +NS_IMETHODIMP +nsJARURI::GetInnermostURI(nsIURI** uri) +{ + return NS_ImplGetInnermostURI(this, uri); +} + diff --git a/modules/libjar/nsJARURI.h b/modules/libjar/nsJARURI.h index 5b45ace5641..93c073046d4 100644 --- a/modules/libjar/nsJARURI.h +++ b/modules/libjar/nsJARURI.h @@ -44,6 +44,7 @@ #include "nsIClassInfo.h" #include "nsCOMPtr.h" #include "nsString.h" +#include "nsINestedURI.h" #define NS_THIS_JARURI_IMPL_CID \ { /* 9a55f629-730b-4d08-b75b-fa7d9570a691 */ \ @@ -64,7 +65,10 @@ } -class nsJARURI : public nsIJARURI, nsISerializable, nsIClassInfo +class nsJARURI : public nsIJARURI, + public nsISerializable, + public nsIClassInfo, + public nsINestedURI { public: NS_DECL_ISUPPORTS @@ -73,6 +77,7 @@ public: NS_DECL_NSIJARURI NS_DECL_NSISERIALIZABLE NS_DECL_NSICLASSINFO + NS_DECL_NSINESTEDURI NS_DECLARE_STATIC_IID_ACCESSOR(NS_THIS_JARURI_IMPL_CID) diff --git a/netwerk/base/public/Makefile.in b/netwerk/base/public/Makefile.in index ef2e8974f9f..8ffcb10416b 100644 --- a/netwerk/base/public/Makefile.in +++ b/netwerk/base/public/Makefile.in @@ -102,6 +102,7 @@ XPIDLSRCS = \ nsISyncStreamListener.idl \ nsIUnicharStreamLoader.idl \ nsIStandardURL.idl \ + nsINestedURI.idl \ nsIURLParser.idl \ nsIURIChecker.idl \ nsISecurityEventSink.idl \ diff --git a/netwerk/base/public/nsINestedURI.idl b/netwerk/base/public/nsINestedURI.idl new file mode 100644 index 00000000000..1d74f966114 --- /dev/null +++ b/netwerk/base/public/nsINestedURI.idl @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Boris Zbarsky (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +interface nsIURI; + +/** + * nsINestedURI is an interface that must be implemented by any nsIURI + * implementation which has an "inner" URI that it actually gets data + * from. + */ +[scriptable, uuid(6de2c874-796c-46bf-b57f-0d7bd7d6cab0)] +interface nsINestedURI : nsISupports +{ + /** + * The inner URI for this nested URI. This must not return null if the + * getter succeeds; URIs that have no inner must not QI to this interface. + * Dynamically changing whether there is an inner URI is not allowed. + * + * Modifying the returned URI must not in any way modify the nested URI; this + * means the returned URI must be either immutable or a clone. + */ + readonly attribute nsIURI innerURI; + + /** + * The innermost URI for this nested URI. This must not return null if the + * getter succeeds. This is equivalent to repeatedly calling innerURI while + * the returned URI QIs to nsINestedURI. + * + * Modifying the returned URI must not in any way modify the nested URI; this + * means the returned URI must be either immutable or a clone. + */ + readonly attribute nsIURI innermostURI; +}; diff --git a/netwerk/base/public/nsINetUtil.idl b/netwerk/base/public/nsINetUtil.idl index f1d055ac433..eb0396426bc 100644 --- a/netwerk/base/public/nsINetUtil.idl +++ b/netwerk/base/public/nsINetUtil.idl @@ -39,10 +39,12 @@ #include "nsISupports.idl" +interface nsIURI; + /** * nsINetUtil provides various network-related utility methods. */ -[scriptable, uuid(e379f39e-80bd-4ac5-a35a-27e7739f837d)] +[scriptable, uuid(4a1f4ab4-d527-4606-b0f7-53a27f20804c)] interface nsINetUtil : nsISupports { /** @@ -77,4 +79,28 @@ interface nsINetUtil : nsISupports * escape a string with %00-style escaping */ ACString escapeString(in ACString aString, in unsigned long aEscapeType); + + /** + * Test whether the given URI's handler has the given protocol flags. + * + * @param aURI the URI in question + * @param aFlags the flags we're testing for. + * + * @return whether the protocol handler for aURI has all the flags + * in aFlags. + */ + boolean protocolHasFlags(in nsIURI aURI, in unsigned long aFlag); + + /** + * Test whether the protocol handler for this URI or that for any of + * its inner URIs has the given protocol flags. This will QI aURI to + * nsINestedURI and walk the nested URI chain. + * + * @param aURI the URI in question + * @param aFlags the flags we're testing for. + * + * @return whether any of the protocol handlers involved have all the flags + * in aFlags. + */ + boolean URIChainHasFlags(in nsIURI aURI, in unsigned long aFlags); }; diff --git a/netwerk/base/public/nsIProtocolHandler.idl b/netwerk/base/public/nsIProtocolHandler.idl index da6612c522c..72e469aadad 100644 --- a/netwerk/base/public/nsIProtocolHandler.idl +++ b/netwerk/base/public/nsIProtocolHandler.idl @@ -134,6 +134,13 @@ interface nsIProtocolHandler : nsISupports */ const unsigned long URI_NOAUTH = (1<<1); + /** + * The URIs for this protocol have no inherent security context. That is, + * it's not possible to decide what a document loaded from one of these + * URIs should be allowed to do. + */ + const unsigned long URI_HAS_NO_SECURITY_CONTEXT = (1<<4); + /** * This protocol handler can be proxied via a proxy (socks or http) * (e.g., irc, smtp, http, etc.). If the protocol supports transparent diff --git a/netwerk/base/public/nsIStandardURL.idl b/netwerk/base/public/nsIStandardURL.idl index d669c02c9e7..c0135e12487 100644 --- a/netwerk/base/public/nsIStandardURL.idl +++ b/netwerk/base/public/nsIStandardURL.idl @@ -37,7 +37,7 @@ * * ***** END LICENSE BLOCK ***** */ -#include "nsISupports.idl" +#include "nsIMutable.idl" interface nsIURI; @@ -49,8 +49,8 @@ interface nsIURI; * * @status UNDER_REVIEW */ -[scriptable, uuid(8793370a-311f-11d4-9876-00c04fa0cf4a)] -interface nsIStandardURL : nsISupports +[scriptable, uuid(babd6cca-ebe7-4329-967c-d6b9e33caa81)] +interface nsIStandardURL : nsIMutable { /** * blah:foo/bar => blah://foo/bar @@ -101,11 +101,4 @@ interface nsIStandardURL : nsISupports in AUTF8String aSpec, in string aOriginCharset, in nsIURI aBaseURI); - - /** - * Control whether or not this URL can be modified. Protocol handlers - * can set this flag before handing out an URL to ensure that it is not - * inadvertently modified. - */ - attribute boolean mutable; }; diff --git a/netwerk/base/public/nsNetUtil.h b/netwerk/base/public/nsNetUtil.h index 184442b0b12..dd2456ca910 100644 --- a/netwerk/base/public/nsNetUtil.h +++ b/netwerk/base/public/nsNetUtil.h @@ -88,6 +88,8 @@ #include "nsINetUtil.h" #include "nsComponentManagerUtils.h" #include "nsServiceManagerUtils.h" +#include "nsINestedURI.h" +#include "nsIMutable.h" // Helper, to simplify getting the I/O service. inline const nsGetServiceByContractIDWithError @@ -1041,4 +1043,116 @@ NS_IsOffline() return offline; } +/** + * Helper functions for implementing nsINestedURI::innermostURI. + * + * Note that NS_DoImplGetInnermostURI is "private" -- call + * NS_ImplGetInnermostURI instead. + */ +inline nsresult +NS_DoImplGetInnermostURI(nsINestedURI* nestedURI, nsIURI** result) +{ + NS_PRECONDITION(nestedURI, "Must have a nested URI!"); + NS_PRECONDITION(!*result, "Must have null *result"); + + nsCOMPtr inner; + nsresult rv = nestedURI->GetInnerURI(getter_AddRefs(inner)); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr nestedInner(do_QueryInterface(inner)); + if (!nestedInner) { + // Found the innermost one + inner.swap(*result); + return NS_OK; + } + + return NS_DoImplGetInnermostURI(nestedInner, result); +} + +inline nsresult +NS_ImplGetInnermostURI(nsINestedURI* nestedURI, nsIURI** result) +{ + // Make it safe to use swap() + *result = nsnull; + + return NS_DoImplGetInnermostURI(nestedURI, result); +} + +/** + * Helper function that ensures that |result| is a URI that's safe to + * return. If |uri| is immutable, just returns it, otherwise returns + * a clone. |uri| must not be null. + */ +inline nsresult +NS_EnsureSafeToReturn(nsIURI* uri, nsIURI** result) +{ + NS_PRECONDITION(uri, "Must have a URI"); + + // Assume mutable until told otherwise + PRBool isMutable = PR_TRUE; + nsCOMPtr mutableObj(do_QueryInterface(uri)); + if (mutableObj) { + nsresult rv = mutableObj->GetMutable(&isMutable); + isMutable = NS_FAILED(rv) || isMutable; + } + + if (!isMutable) { + NS_ADDREF(*result = uri); + return NS_OK; + } + + return uri->Clone(result); +} + +/** + * Helper function that tries to set the argument URI to be immutable + */ +inline void +NS_TryToSetImmutable(nsIURI* uri) +{ + nsCOMPtr mutableObj(do_QueryInterface(uri)); + if (mutableObj) { + mutableObj->SetMutable(PR_FALSE); + } +} + +/** + * Helper function for testing whether the given URI, or any of its + * inner URIs, has all the given protocol flags. + */ +inline nsresult +NS_URIChainHasFlags(nsIURI *uri, + PRUint32 flags, + PRBool *result) +{ + nsresult rv; + nsCOMPtr util = do_GetIOService(&rv); + NS_ENSURE_SUCCESS(rv, rv); + + return util->URIChainHasFlags(uri, flags, result); +} + +/** + * Helper function for getting the innermost URI for a given URI. The return + * value could be just the object passed in if it's not a nested URI. + */ +inline already_AddRefed +NS_GetInnermostURI(nsIURI *uri) +{ + NS_PRECONDITION(uri, "Must have URI"); + + nsCOMPtr nestedURI(do_QueryInterface(uri)); + if (!nestedURI) { + NS_ADDREF(uri); + return uri; + } + + nsresult rv = nestedURI->GetInnermostURI(&uri); + if (NS_FAILED(rv)) { + return nsnull; + } + + return uri; +} + #endif // !nsNetUtil_h__ diff --git a/netwerk/base/src/nsIOService.cpp b/netwerk/base/src/nsIOService.cpp index d191f34c88a..8cba0a1b89a 100644 --- a/netwerk/base/src/nsIOService.cpp +++ b/netwerk/base/src/nsIOService.cpp @@ -1,5 +1,5 @@ -/* vim:set ts=4 sw=4 cindent et: */ /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* vim:set ts=4 sw=4 cindent et: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -67,6 +67,7 @@ #include "nsIRecyclingAllocator.h" #include "nsISocketTransport.h" #include "nsCRT.h" +#include "nsINestedURI.h" #define PORT_PREF_PREFIX "network.security.ports." #define PORT_PREF(x) PORT_PREF_PREFIX x @@ -795,6 +796,60 @@ nsIOService::ParseContentType(const nsACString &aTypeHeader, return NS_OK; } +NS_IMETHODIMP +nsIOService::ProtocolHasFlags(nsIURI *uri, + PRUint32 flags, + PRBool *result) +{ + NS_ENSURE_ARG(uri); + + *result = PR_FALSE; + nsCAutoString scheme; + nsresult rv = uri->GetScheme(scheme); + NS_ENSURE_SUCCESS(rv, rv); + + PRUint32 protocolFlags; + rv = GetProtocolFlags(scheme.get(), &protocolFlags); + + if (NS_SUCCEEDED(rv)) { + *result = (protocolFlags & flags) == flags; + } + + return rv; +} + +NS_IMETHODIMP +nsIOService::URIChainHasFlags(nsIURI *uri, + PRUint32 flags, + PRBool *result) +{ + nsresult rv = ProtocolHasFlags(uri, flags, result); + NS_ENSURE_SUCCESS(rv, rv); + + if (*result) { + return rv; + } + + // Dig deeper into the chain. Note that this is not a do/while loop to + // avoid the extra addref/release on |uri| in the common (non-nested) case. + nsCOMPtr nestedURI = do_QueryInterface(uri); + while (nestedURI) { + nsCOMPtr innerURI; + rv = nestedURI->GetInnerURI(getter_AddRefs(innerURI)); + NS_ENSURE_SUCCESS(rv, rv); + + rv = ProtocolHasFlags(innerURI, flags, result); + + if (*result) { + return rv; + } + + nestedURI = do_QueryInterface(innerURI); + } + + return rv; +} + NS_IMETHODIMP nsIOService::SetManageOfflineStatus(PRBool aManage) { PRBool wasManaged = mManageOfflineStatus; diff --git a/netwerk/base/src/nsSimpleURI.cpp b/netwerk/base/src/nsSimpleURI.cpp index 22e86b212d1..02a8d871fdd 100644 --- a/netwerk/base/src/nsSimpleURI.cpp +++ b/netwerk/base/src/nsSimpleURI.cpp @@ -61,6 +61,7 @@ static NS_DEFINE_CID(kSimpleURICID, NS_SIMPLEURI_CID); // nsSimpleURI methods: nsSimpleURI::nsSimpleURI(nsISupports* outer) + : mMutable(PR_TRUE) { NS_INIT_AGGREGATED(outer); } @@ -85,6 +86,8 @@ nsSimpleURI::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr) *aInstancePtr = NS_STATIC_CAST(nsISerializable*, this); } else if (aIID.Equals(NS_GET_IID(nsIClassInfo))) { *aInstancePtr = NS_STATIC_CAST(nsIClassInfo*, this); + } else if (aIID.Equals(NS_GET_IID(nsIMutable))) { + *aInstancePtr = NS_STATIC_CAST(nsIMutable*, this); } else { *aInstancePtr = nsnull; return NS_NOINTERFACE; @@ -101,6 +104,9 @@ nsSimpleURI::Read(nsIObjectInputStream* aStream) { nsresult rv; + rv = aStream->ReadBoolean(&mMutable); + if (NS_FAILED(rv)) return rv; + rv = aStream->ReadCString(mScheme); if (NS_FAILED(rv)) return rv; @@ -115,6 +121,9 @@ nsSimpleURI::Write(nsIObjectOutputStream* aStream) { nsresult rv; + rv = aStream->WriteBoolean(mMutable); + if (NS_FAILED(rv)) return rv; + rv = aStream->WriteStringZ(mScheme.get()); if (NS_FAILED(rv)) return rv; @@ -137,6 +146,8 @@ nsSimpleURI::GetSpec(nsACString &result) NS_IMETHODIMP nsSimpleURI::SetSpec(const nsACString &aSpec) { + NS_ENSURE_STATE(mMutable); + const nsAFlatCString& flat = PromiseFlatCString(aSpec); const char* specPtr = flat.get(); @@ -181,6 +192,8 @@ nsSimpleURI::GetScheme(nsACString &result) NS_IMETHODIMP nsSimpleURI::SetScheme(const nsACString &scheme) { + NS_ENSURE_STATE(mMutable); + mScheme = scheme; ToLowerCase(mScheme); return NS_OK; @@ -202,6 +215,8 @@ nsSimpleURI::GetUserPass(nsACString &result) NS_IMETHODIMP nsSimpleURI::SetUserPass(const nsACString &userPass) { + NS_ENSURE_STATE(mMutable); + return NS_ERROR_FAILURE; } @@ -214,6 +229,8 @@ nsSimpleURI::GetUsername(nsACString &result) NS_IMETHODIMP nsSimpleURI::SetUsername(const nsACString &userName) { + NS_ENSURE_STATE(mMutable); + return NS_ERROR_FAILURE; } @@ -226,6 +243,8 @@ nsSimpleURI::GetPassword(nsACString &result) NS_IMETHODIMP nsSimpleURI::SetPassword(const nsACString &password) { + NS_ENSURE_STATE(mMutable); + return NS_ERROR_FAILURE; } @@ -240,6 +259,8 @@ nsSimpleURI::GetHostPort(nsACString &result) NS_IMETHODIMP nsSimpleURI::SetHostPort(const nsACString &result) { + NS_ENSURE_STATE(mMutable); + return NS_ERROR_FAILURE; } @@ -254,6 +275,8 @@ nsSimpleURI::GetHost(nsACString &result) NS_IMETHODIMP nsSimpleURI::SetHost(const nsACString &host) { + NS_ENSURE_STATE(mMutable); + return NS_ERROR_FAILURE; } @@ -268,6 +291,8 @@ nsSimpleURI::GetPort(PRInt32 *result) NS_IMETHODIMP nsSimpleURI::SetPort(PRInt32 port) { + NS_ENSURE_STATE(mMutable); + return NS_ERROR_FAILURE; } @@ -281,6 +306,8 @@ nsSimpleURI::GetPath(nsACString &result) NS_IMETHODIMP nsSimpleURI::SetPath(const nsACString &path) { + NS_ENSURE_STATE(mMutable); + mPath = path; return NS_OK; } @@ -322,13 +349,21 @@ nsSimpleURI::SchemeIs(const char *i_Scheme, PRBool *o_Equals) return NS_OK; } +/* virtual */ nsSimpleURI* +nsSimpleURI::StartClone() +{ + return new nsSimpleURI(nsnull); // XXX outer? +} + NS_IMETHODIMP nsSimpleURI::Clone(nsIURI* *result) { - nsSimpleURI* url = new nsSimpleURI(nsnull); // XXX outer? + nsSimpleURI* url = StartClone(); if (url == nsnull) return NS_ERROR_OUT_OF_MEMORY; + // Note: |url| may well have mMutable false at this point, so + // don't call any setter methods. url->mScheme = mScheme; url->mPath = mPath; @@ -390,6 +425,8 @@ nsSimpleURI::GetHelperForLanguage(PRUint32 language, nsISupports **_retval) NS_IMETHODIMP nsSimpleURI::GetContractID(char * *aContractID) { + // Make sure to modify any subclasses as needed if this ever + // changes. *aContractID = nsnull; return NS_OK; } @@ -404,6 +441,8 @@ nsSimpleURI::GetClassDescription(char * *aClassDescription) NS_IMETHODIMP nsSimpleURI::GetClassID(nsCID * *aClassID) { + // Make sure to modify any subclasses as needed if this ever + // changes to not call the virtual GetClassIDNoAlloc. *aClassID = (nsCID*) nsMemory::Alloc(sizeof(nsCID)); if (!*aClassID) return NS_ERROR_OUT_OF_MEMORY; @@ -430,3 +469,23 @@ nsSimpleURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) *aClassIDNoAlloc = kSimpleURICID; return NS_OK; } + +//---------------------------------------------------------------------------- +// nsSimpleURI::nsISimpleURI +//---------------------------------------------------------------------------- +NS_IMETHODIMP +nsSimpleURI::GetMutable(PRBool *value) +{ + *value = mMutable; + return NS_OK; +} + +NS_IMETHODIMP +nsSimpleURI::SetMutable(PRBool value) +{ + NS_ENSURE_ARG(mMutable || !value); + + mMutable = value; + return NS_OK; +} + diff --git a/netwerk/base/src/nsSimpleURI.h b/netwerk/base/src/nsSimpleURI.h index 92d7be6177c..e30d8cba7b0 100644 --- a/netwerk/base/src/nsSimpleURI.h +++ b/netwerk/base/src/nsSimpleURI.h @@ -43,6 +43,7 @@ #include "nsISerializable.h" #include "nsString.h" #include "nsIClassInfo.h" +#include "nsIMutable.h" #define NS_THIS_SIMPLEURI_IMPLEMENTATION_CID \ { /* 22b8f64a-2f7b-11d3-8cd0-0060b0fc14a3 */ \ @@ -52,13 +53,17 @@ {0x8c, 0xd0, 0x00, 0x60, 0xb0, 0xfc, 0x14, 0xa3} \ } -class nsSimpleURI : public nsIURI, public nsISerializable, public nsIClassInfo +class nsSimpleURI : public nsIURI, + public nsISerializable, + public nsIClassInfo, + public nsIMutable { public: NS_DECL_AGGREGATED NS_DECL_NSIURI NS_DECL_NSISERIALIZABLE NS_DECL_NSICLASSINFO + NS_DECL_NSIMUTABLE // nsSimpleURI methods: @@ -66,8 +71,11 @@ public: virtual ~nsSimpleURI(); protected: + virtual nsSimpleURI* StartClone(); + nsCString mScheme; nsCString mPath; + PRBool mMutable; }; #endif // nsSimpleURI_h__ diff --git a/netwerk/base/src/nsStandardURL.cpp b/netwerk/base/src/nsStandardURL.cpp index ec93e9abc49..16a3ba90384 100644 --- a/netwerk/base/src/nsStandardURL.cpp +++ b/netwerk/base/src/nsStandardURL.cpp @@ -934,6 +934,7 @@ NS_INTERFACE_MAP_BEGIN(nsStandardURL) NS_INTERFACE_MAP_ENTRY(nsIStandardURL) NS_INTERFACE_MAP_ENTRY(nsISerializable) NS_INTERFACE_MAP_ENTRY(nsIClassInfo) + NS_INTERFACE_MAP_ENTRY(nsIMutable) // see nsStandardURL::Equals if (aIID.Equals(kThisImplCID)) foundInterface = NS_STATIC_CAST(nsIURI *, this); @@ -2600,6 +2601,8 @@ nsStandardURL::GetMutable(PRBool *value) NS_IMETHODIMP nsStandardURL::SetMutable(PRBool value) { + NS_ENSURE_ARG(mMutable || !value); + mMutable = value; return NS_OK; } @@ -2683,6 +2686,12 @@ nsStandardURL::Read(nsIObjectInputStream *stream) rv = NS_ReadOptionalCString(stream, mOriginCharset); if (NS_FAILED(rv)) return rv; + PRBool isMutable; + rv = stream->ReadBoolean(&isMutable); + if (NS_FAILED(rv)) return rv; + + mMutable = isMutable; + return NS_OK; } @@ -2745,6 +2754,9 @@ nsStandardURL::Write(nsIObjectOutputStream *stream) rv = NS_WriteOptionalStringZ(stream, mOriginCharset.get()); if (NS_FAILED(rv)) return rv; + rv = stream->WriteBoolean(mMutable); + if (NS_FAILED(rv)) return rv; + return NS_OK; } diff --git a/netwerk/base/src/nsStandardURL.h b/netwerk/base/src/nsStandardURL.h index a22d432a61f..a33e8da2ee4 100644 --- a/netwerk/base/src/nsStandardURL.h +++ b/netwerk/base/src/nsStandardURL.h @@ -77,6 +77,7 @@ public: NS_DECL_NSISTANDARDURL NS_DECL_NSISERIALIZABLE NS_DECL_NSICLASSINFO + NS_DECL_NSIMUTABLE nsStandardURL(PRBool aSupportsFileURL = PR_FALSE); virtual ~nsStandardURL(); diff --git a/netwerk/build/nsNetModule.cpp b/netwerk/build/nsNetModule.cpp index 3eb5310ecb8..66fbdf9e682 100644 --- a/netwerk/build/nsNetModule.cpp +++ b/netwerk/build/nsNetModule.cpp @@ -226,6 +226,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsGopherHandler) #ifdef NECKO_PROTOCOL_viewsource #include "nsViewSourceHandler.h" NS_GENERIC_FACTORY_CONSTRUCTOR(nsViewSourceHandler) +NS_GENERIC_FACTORY_CONSTRUCTOR(nsViewSourceURI) #endif #ifdef NECKO_PROTOCOL_data @@ -1133,6 +1134,11 @@ static const nsModuleComponentInfo gNetModuleInfo[] = { NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "view-source", nsViewSourceHandlerConstructor }, + { "The ViewSource URI", + NS_VIEWSOURCEURI_CID, + nsnull, + nsViewSourceURIConstructor + }, #endif #ifdef XP_WIN diff --git a/netwerk/protocol/data/src/nsDataHandler.cpp b/netwerk/protocol/data/src/nsDataHandler.cpp index dfeae3d9cc2..226e7dbbc31 100644 --- a/netwerk/protocol/data/src/nsDataHandler.cpp +++ b/netwerk/protocol/data/src/nsDataHandler.cpp @@ -89,7 +89,7 @@ nsDataHandler::GetDefaultPort(PRInt32 *result) { NS_IMETHODIMP nsDataHandler::GetProtocolFlags(PRUint32 *result) { - *result = URI_NORELATIVE | URI_NOAUTH; + *result = URI_NORELATIVE | URI_NOAUTH | URI_HAS_NO_SECURITY_CONTEXT; return NS_OK; } diff --git a/netwerk/protocol/viewsource/src/Makefile.in b/netwerk/protocol/viewsource/src/Makefile.in index 99d533340d3..39b80eb0b94 100644 --- a/netwerk/protocol/viewsource/src/Makefile.in +++ b/netwerk/protocol/viewsource/src/Makefile.in @@ -58,6 +58,8 @@ CPPSRCS = \ nsViewSourceChannel.cpp \ $(NULL) +LOCAL_INCLUDES=-I$(srcdir)/../../../base/src + # we don't want the shared lib, but we want to force the creation of a # static lib. FORCE_STATIC_LIB = 1 diff --git a/netwerk/protocol/viewsource/src/nsViewSourceHandler.cpp b/netwerk/protocol/viewsource/src/nsViewSourceHandler.cpp index c416ddebffc..d88a75051bc 100644 --- a/netwerk/protocol/viewsource/src/nsViewSourceHandler.cpp +++ b/netwerk/protocol/viewsource/src/nsViewSourceHandler.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* vim:set ts=4 sw=4 sts=4 et: */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 @@ -41,6 +41,11 @@ #include "nsViewSourceHandler.h" #include "nsViewSourceChannel.h" #include "nsNetUtil.h" +#include "nsIObjectInputStream.h" +#include "nsIObjectOutputStream.h" +#include "nsIProgrammingLanguage.h" + +#define VIEW_SOURCE "view-source" //////////////////////////////////////////////////////////////////////////////// @@ -52,7 +57,7 @@ NS_IMPL_ISUPPORTS1(nsViewSourceHandler, nsIProtocolHandler) NS_IMETHODIMP nsViewSourceHandler::GetScheme(nsACString &result) { - result.AssignLiteral("view-source"); + result.AssignLiteral(VIEW_SOURCE); return NS_OK; } @@ -76,7 +81,7 @@ nsViewSourceHandler::NewURI(const nsACString &aSpec, nsIURI *aBaseURI, nsIURI **aResult) { - nsresult rv; + *aResult = nsnull; // Extract inner URL and normalize to ASCII. This is done to properly // support IDN in cases like "view-source:http://www.szalagavató.hu/" @@ -86,10 +91,13 @@ nsViewSourceHandler::NewURI(const nsACString &aSpec, return NS_ERROR_MALFORMED_URI; nsCOMPtr innerURI; - rv = NS_NewURI(getter_AddRefs(innerURI), Substring(aSpec, colon + 1), aCharset); + nsresult rv = NS_NewURI(getter_AddRefs(innerURI), + Substring(aSpec, colon + 1), aCharset); if (NS_FAILED(rv)) return rv; + NS_TryToSetImmutable(innerURI); + nsCAutoString asciiSpec; rv = innerURI->GetAsciiSpec(asciiSpec); if (NS_FAILED(rv)) @@ -97,18 +105,23 @@ nsViewSourceHandler::NewURI(const nsACString &aSpec, // put back our scheme and construct a simple-uri wrapper - asciiSpec.Insert("view-source:", 0); + asciiSpec.Insert(VIEW_SOURCE ":", 0); - nsIURI *uri; - rv = CallCreateInstance(NS_SIMPLEURI_CONTRACTID, nsnull, &uri); + // We can't swap() from an nsRefPtr to an nsIURI**, sadly. + nsViewSourceURI* ourURI = new nsViewSourceURI(innerURI); + nsCOMPtr uri = ourURI; + if (!uri) + return NS_ERROR_OUT_OF_MEMORY; + + rv = ourURI->SetSpec(asciiSpec); if (NS_FAILED(rv)) return rv; - - rv = uri->SetSpec(asciiSpec); - if (NS_FAILED(rv)) - NS_RELEASE(uri); - else - *aResult = uri; + + // Make the URI immutable so it's impossible to get it out of sync + // with mInnerURI. + ourURI->SetMutable(PR_FALSE); + + uri.swap(*aResult); return rv; } @@ -138,3 +151,98 @@ nsViewSourceHandler::AllowPort(PRInt32 port, const char *scheme, PRBool *_retval *_retval = PR_FALSE; return NS_OK; } + +/////////////////////////////////////////////////////////////// +// nsViewSourceURI implementation + +static NS_DEFINE_CID(kViewSourceURICID, NS_VIEWSOURCEURI_CID); + +NS_IMPL_ISUPPORTS_INHERITED1(nsViewSourceURI, nsSimpleURI, nsINestedURI) + +// nsISerializable + +NS_IMETHODIMP +nsViewSourceURI::Read(nsIObjectInputStream* aStream) +{ + nsresult rv = nsSimpleURI::Read(aStream); + if (NS_FAILED(rv)) return rv; + + NS_ASSERTION(!mMutable, "How did that happen?"); + + // Our mPath is going to be ASCII; see nsViewSourceHandler::NewURI. So + // just using NS_NewURI with no charset is ok. + rv = NS_NewURI(getter_AddRefs(mInnerURI), mPath); + if (NS_FAILED(rv)) return rv; + + NS_TryToSetImmutable(mInnerURI); + + return rv; +} + +// nsINestedURI + +NS_IMETHODIMP +nsViewSourceURI::GetInnerURI(nsIURI** uri) +{ + return NS_EnsureSafeToReturn(mInnerURI, uri); +} + +NS_IMETHODIMP +nsViewSourceURI::GetInnermostURI(nsIURI** uri) +{ + return NS_ImplGetInnermostURI(this, uri); +} + +// nsIURI overrides + +NS_IMETHODIMP +nsViewSourceURI::Equals(nsIURI* other, PRBool *result) +{ + if (other) { + PRBool correctScheme; + nsresult rv = other->SchemeIs(VIEW_SOURCE, &correctScheme); + NS_ENSURE_SUCCESS(rv, rv); + + if (correctScheme) { + nsCOMPtr nest = do_QueryInterface(other); + if (nest) { + nsCOMPtr otherInner; + rv = nest->GetInnerURI(getter_AddRefs(otherInner)); + NS_ENSURE_SUCCESS(rv, rv); + + return otherInner->Equals(mInnerURI, result); + } + } + } + + *result = PR_FALSE; + return NS_OK; +} + +/* virtual */ nsSimpleURI* +nsViewSourceURI::StartClone() +{ + nsCOMPtr innerClone; + nsresult rv = mInnerURI->Clone(getter_AddRefs(innerClone)); + if (NS_FAILED(rv)) { + return nsnull; + } + + NS_TryToSetImmutable(innerClone); + + nsViewSourceURI* url = new nsViewSourceURI(innerClone); + if (url) { + url->SetMutable(PR_FALSE); + } + + return url; +} + +// nsIClassInfo overrides + +NS_IMETHODIMP +nsViewSourceURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) +{ + *aClassIDNoAlloc = kViewSourceURICID; + return NS_OK; +} diff --git a/netwerk/protocol/viewsource/src/nsViewSourceHandler.h b/netwerk/protocol/viewsource/src/nsViewSourceHandler.h index 92823510136..31b7e898924 100644 --- a/netwerk/protocol/viewsource/src/nsViewSourceHandler.h +++ b/netwerk/protocol/viewsource/src/nsViewSourceHandler.h @@ -40,6 +40,9 @@ #define nsViewSourceHandler_h___ #include "nsIProtocolHandler.h" +#include "nsCOMPtr.h" +#include "nsSimpleURI.h" +#include "nsINestedURI.h" class nsViewSourceHandler : public nsIProtocolHandler { @@ -48,4 +51,50 @@ public: NS_DECL_NSIPROTOCOLHANDLER }; +#define NS_VIEWSOURCEURI_CID \ +{ /* 2545766f-3a27-4fd1-8e88-b0886d346242 */ \ + 0x2545766f, \ + 0x3a27, \ + 0x4fd1, \ + { 0x8e, 0x88, 0xb0, 0x88, 0x6d, 0x34, 0x62, 0x42 } \ +} + +class nsViewSourceURI : public nsSimpleURI, + public nsINestedURI +{ +public: + nsViewSourceURI(nsIURI* innerURI) + : nsSimpleURI(nsnull), + mInnerURI(innerURI) + { + NS_ASSERTION(innerURI, "Must have inner URI"); + } + + // To be used by deserialization only + nsViewSourceURI() + : nsSimpleURI(nsnull) + { + } + + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_NSINESTEDURI + + // Overrides for various methods nsSimpleURI implements follow. + + // nsIURI overrides + NS_IMETHOD Equals(nsIURI* other, PRBool *result); + virtual nsSimpleURI* StartClone(); + + // nsISerializable overrides -- we can use the same Write(), but we + // need a different Read(). + NS_IMETHOD Read(nsIObjectInputStream* aStream); + + // Override the nsIClassInfo method GetClassIDNoAlloc to make sure our + // nsISerializable impl works right. + NS_IMETHOD GetClassIDNoAlloc(nsCID *aClassIDNoAlloc); + +protected: + nsCOMPtr mInnerURI; +}; + #endif /* !defined( nsViewSourceHandler_h___ ) */ diff --git a/uriloader/exthandler/nsExternalProtocolHandler.cpp b/uriloader/exthandler/nsExternalProtocolHandler.cpp index 573a39ff26b..31ede59d686 100644 --- a/uriloader/exthandler/nsExternalProtocolHandler.cpp +++ b/uriloader/exthandler/nsExternalProtocolHandler.cpp @@ -360,7 +360,7 @@ PRBool nsExternalProtocolHandler::HaveProtocolHandler(nsIURI * aURI) NS_IMETHODIMP nsExternalProtocolHandler::GetProtocolFlags(PRUint32 *aUritype) { // Make it norelative since it is a simple uri - *aUritype = URI_NORELATIVE; + *aUritype = URI_NORELATIVE | URI_NOAUTH | URI_HAS_NO_SECURITY_CONTEXT; return NS_OK; } diff --git a/xpcom/base/Makefile.in b/xpcom/base/Makefile.in index c6dab929f77..834fa0de11c 100644 --- a/xpcom/base/Makefile.in +++ b/xpcom/base/Makefile.in @@ -124,6 +124,7 @@ XPIDLSRCS = \ nsIExceptionService.idl \ nsIVersionComparator.idl \ nsIUUIDGenerator.idl \ + nsIMutable.idl \ $(NULL) ifdef GC_LEAK_DETECTOR diff --git a/xpcom/base/nsIMutable.idl b/xpcom/base/nsIMutable.idl new file mode 100644 index 00000000000..70935e229ed --- /dev/null +++ b/xpcom/base/nsIMutable.idl @@ -0,0 +1,55 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is + * Mozilla Corporation. + * Portions created by the Initial Developer are Copyright (C) 2006 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Boris Zbarsky (Original Author) + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include "nsISupports.idl" + +/** + * nsIMutable defines an interface to be implemented by objects which + * can be made immutable. + */ +[scriptable, uuid(321578d0-03c1-4d95-8821-021ac612d18d)] +interface nsIMutable : nsISupports +{ + /** + * Control whether or not this object can be modified. If the flag is + * false, no modification is allowed. Once the flag has been set to false, + * it cannot be reset back to true -- attempts to do so throw + * NS_ERROR_INVALID_ARG. + */ + attribute boolean mutable; +};