Add an interface for nested URIs (like jar:, view-source:, etc) to implement

and use it in various places.  Create null principals if asked for a codebase
principal for a codebase that doesn't have an inherent security context (eg
data: or javascript:).  Bug 334407, r=biesi,dveditz, sr=darin
This commit is contained in:
bzbarsky%mit.edu 2006-05-02 18:54:19 +00:00
Родитель 02082fc3be
Коммит fca88cd9e1
28 изменённых файлов: 676 добавлений и 111 удалений

Просмотреть файл

@ -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<nsIJARURI> jarURI;
nsCOMPtr<nsIURI> sourceBaseURI(aSourceURI);
while((jarURI = do_QueryInterface(sourceBaseURI)))
{
jarURI->GetJARFile(getter_AddRefs(sourceBaseURI));
}
nsCOMPtr<nsIURI> targetBaseURI(aTargetURI);
while((jarURI = do_QueryInterface(targetBaseURI)))
{
jarURI->GetJARFile(getter_AddRefs(targetBaseURI));
}
// If either URI is a nested URI, get the base URI
nsCOMPtr<nsIURI> sourceBaseURI = NS_GetInnermostURI(aSourceURI);
nsCOMPtr<nsIURI> 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<nsIURI> 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<nsIURI> 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<nsIJARURI> jarURI = do_QueryInterface(aURI);
if (jarURI)
{
nsCOMPtr<nsIURI> 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<nsIPrincipal> principal;
rv = CreateCodebasePrincipal(aURI, getter_AddRefs(principal));
if (NS_FAILED(rv)) return rv;

Просмотреть файл

@ -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)

Просмотреть файл

@ -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<nsIURI> uri;
nsCOMPtr<nsIInputStream> postData;
nsCOMPtr<nsIURI> 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<nsISHEntry> 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);
}

Просмотреть файл

@ -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);

Просмотреть файл

@ -703,19 +703,15 @@ nsWebShell::OnLinkClickSync(nsIContent *aContent,
nsCOMPtr<nsIDOMNode> 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<nsIDocument> 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");

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -47,14 +47,14 @@
*
* The nsIURL methods operate on the <jar-entry> 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

Просмотреть файл

@ -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<nsIURI> 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);
}

Просмотреть файл

@ -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)

Просмотреть файл

@ -102,6 +102,7 @@ XPIDLSRCS = \
nsISyncStreamListener.idl \
nsIUnicharStreamLoader.idl \
nsIStandardURL.idl \
nsINestedURI.idl \
nsIURLParser.idl \
nsIURIChecker.idl \
nsISecurityEventSink.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 <bzbarsky@mit.edu> (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;
};

Просмотреть файл

@ -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);
};

Просмотреть файл

@ -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

Просмотреть файл

@ -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;
};

Просмотреть файл

@ -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<nsIURI> inner;
nsresult rv = nestedURI->GetInnerURI(getter_AddRefs(inner));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsINestedURI> 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<nsIMutable> 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<nsIMutable> 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<nsINetUtil> 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<nsIURI>
NS_GetInnermostURI(nsIURI *uri)
{
NS_PRECONDITION(uri, "Must have URI");
nsCOMPtr<nsINestedURI> 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__

Просмотреть файл

@ -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<nsINestedURI> nestedURI = do_QueryInterface(uri);
while (nestedURI) {
nsCOMPtr<nsIURI> 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;

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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__

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -77,6 +77,7 @@ public:
NS_DECL_NSISTANDARDURL
NS_DECL_NSISERIALIZABLE
NS_DECL_NSICLASSINFO
NS_DECL_NSIMUTABLE
nsStandardURL(PRBool aSupportsFileURL = PR_FALSE);
virtual ~nsStandardURL();

Просмотреть файл

@ -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

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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<nsIURI> 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<nsViewSourceURI> to an nsIURI**, sadly.
nsViewSourceURI* ourURI = new nsViewSourceURI(innerURI);
nsCOMPtr<nsIURI> 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<nsINestedURI> nest = do_QueryInterface(other);
if (nest) {
nsCOMPtr<nsIURI> 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<nsIURI> 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;
}

Просмотреть файл

@ -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<nsIURI> mInnerURI;
};
#endif /* !defined( nsViewSourceHandler_h___ ) */

Просмотреть файл

@ -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;
}

Просмотреть файл

@ -124,6 +124,7 @@ XPIDLSRCS = \
nsIExceptionService.idl \
nsIVersionComparator.idl \
nsIUUIDGenerator.idl \
nsIMutable.idl \
$(NULL)
ifdef GC_LEAK_DETECTOR

55
xpcom/base/nsIMutable.idl Normal file
Просмотреть файл

@ -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 <bzbarsky@mit.edu> (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;
};