/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: NPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Netscape 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/NPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Travis Bogard * Pierre Phaneuf * * * 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 NPL, 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 NPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #include "nsGlobalWindow.h" #include "nsIWebShell.h" #include "nsIDocShell.h" #include "nsIDocShellLoadInfo.h" #include "nsIWebNavigation.h" #include "nsIURL.h" #include "nsIIOService.h" #include "nsIServiceManager.h" #include "nsNetUtil.h" #include "plstr.h" #include "prprf.h" #include "prmem.h" #include "nsCOMPtr.h" #include "nsJSUtils.h" #include "nsIScriptSecurityManager.h" #include "nsICodebasePrincipal.h" #include "nsIDOMWindow.h" #include "nsIDOMDocument.h" #include "nsIDocument.h" #include "nsIJSContextStack.h" #include "nsXPIDLString.h" #include "nsDOMError.h" #include "nsDOMClassInfo.h" LocationImpl::LocationImpl(nsIDocShell *aDocShell) { NS_INIT_REFCNT(); mDocShell = aDocShell; // Weak Reference } LocationImpl::~LocationImpl() { } // QueryInterface implementation for LocationImpl NS_INTERFACE_MAP_BEGIN(LocationImpl) NS_INTERFACE_MAP_ENTRY(nsIDOMNSLocation) NS_INTERFACE_MAP_ENTRY(nsIDOMLocation) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMLocation) NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Location) NS_INTERFACE_MAP_END NS_IMPL_ADDREF(LocationImpl) NS_IMPL_RELEASE(LocationImpl) NS_IMETHODIMP_(void) LocationImpl::SetDocShell(nsIDocShell *aDocShell) { mDocShell = aDocShell; // Weak Reference } nsresult LocationImpl::CheckURL(nsIURI* aURI, nsIDocShellLoadInfo** aLoadInfo) { nsresult result; // Get JSContext from stack. nsCOMPtr stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &result)); if (NS_FAILED(result)) return NS_ERROR_FAILURE; JSContext *cx; if (NS_FAILED(stack->Peek(&cx))) return NS_ERROR_FAILURE; // Get security manager. nsCOMPtr secMan(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &result)); if (NS_FAILED(result)) return NS_ERROR_FAILURE; // Check to see if URI is allowed. result = secMan->CheckLoadURIFromScript(cx, aURI); if (NS_FAILED(result)) return result; // Create load info nsCOMPtr loadInfo; mDocShell->CreateLoadInfo(getter_AddRefs(loadInfo)); NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE); // Now get the principal to use when loading the URI nsCOMPtr principal; if (NS_FAILED(secMan->GetSubjectPrincipal(getter_AddRefs(principal))) || !principal) return NS_ERROR_FAILURE; nsCOMPtr owner = do_QueryInterface(principal); loadInfo->SetOwner(owner); *aLoadInfo = loadInfo.get(); NS_ADDREF(*aLoadInfo); return NS_OK; } nsresult LocationImpl::SetURL(nsIURI* aURI) { if (mDocShell) { nsCOMPtr loadInfo; nsCOMPtr webNav(do_QueryInterface(mDocShell)); if(NS_FAILED(CheckURL(aURI, getter_AddRefs(loadInfo)))) return NS_ERROR_FAILURE; webNav->Stop(nsIWebNavigation::STOP_CONTENT); return mDocShell->LoadURI(aURI, loadInfo, nsIWebNavigation::LOAD_FLAGS_NONE); } return NS_OK; } NS_IMETHODIMP LocationImpl::GetHash(nsAWritableString& aHash) { nsAutoString href; nsresult result = NS_OK; result = GetHref(href); if (NS_SUCCEEDED(result)) { nsCOMPtr uri; result = NS_NewURI(getter_AddRefs(uri), href); if (uri) { nsCOMPtr url(do_QueryInterface(uri)); nsXPIDLCString ref; if (url) { result = url->GetRef(getter_Copies(ref)); } if (NS_SUCCEEDED(result) && ref && *ref) { aHash.Assign(NS_LITERAL_STRING("#")); aHash.Append(NS_ConvertASCIItoUCS2(ref)); } else { aHash.SetLength(0); } } } return result; } NS_IMETHODIMP LocationImpl::SetHash(const nsAReadableString& aHash) { nsAutoString href; nsresult result = NS_OK; result = GetHref(href); if (NS_SUCCEEDED(result)) { nsCOMPtr uri; result = NS_NewURI(getter_AddRefs(uri), href); if (NS_FAILED(result)) return result; nsCOMPtr url(do_QueryInterface(uri, &result)); if (url) { url->SetRef(NS_ConvertUCS2toUTF8(aHash).get()); SetURL(url); } } return result; } NS_IMETHODIMP LocationImpl::GetHost(nsAWritableString& aHost) { nsAutoString href; nsresult result = NS_OK; result = GetHref(href); if (NS_SUCCEEDED(result)) { nsCOMPtr uri; result = NS_NewURI(getter_AddRefs(uri), href); if (uri) { nsXPIDLCString host; result = uri->GetHost(getter_Copies(host)); if (NS_SUCCEEDED(result)) { PRInt32 port; CopyASCIItoUCS2(nsDependentCString(host), aHost); uri->GetPort(&port); if (port != -1) { aHost.Append(PRUnichar(':')); nsAutoString tmpHost; tmpHost.AppendInt(port); aHost.Append(tmpHost); } } } } return result; } NS_IMETHODIMP LocationImpl::SetHost(const nsAReadableString& aHost) { nsAutoString href; nsresult result = NS_OK; result = GetHref(href); if (NS_SUCCEEDED(result)) { nsCOMPtr uri; result = NS_NewURI(getter_AddRefs(uri), href); if (uri) { uri->SetHost(NS_ConvertUCS2toUTF8(aHost).get()); SetURL(uri); } } return result; } NS_IMETHODIMP LocationImpl::GetHostname(nsAWritableString& aHostname) { nsAutoString href; nsresult result = NS_OK; result = GetHref(href); if (NS_SUCCEEDED(result)) { nsCOMPtr uri; result = NS_NewURI(getter_AddRefs(uri), href); if (uri) { nsXPIDLCString host; result = uri->GetHost(getter_Copies(host)); if (NS_SUCCEEDED(result)) { CopyASCIItoUCS2(nsDependentCString(host), aHostname); } } } return result; } NS_IMETHODIMP LocationImpl::SetHostname(const nsAReadableString& aHostname) { nsAutoString href; nsresult result = NS_OK; result = GetHref(href); if (NS_SUCCEEDED(result)) { nsCOMPtr uri; result = NS_NewURI(getter_AddRefs(uri), href); if (uri) { uri->SetHost(NS_ConvertUCS2toUTF8(aHostname).get()); SetURL(uri); } } return result; } NS_IMETHODIMP LocationImpl::GetHref(nsAWritableString& aHref) { nsresult result = NS_OK; nsCOMPtr webNav(do_QueryInterface(mDocShell)); if (webNav) { nsCOMPtr uri; result = webNav->GetCurrentURI(getter_AddRefs(uri)); if (NS_SUCCEEDED(result) && uri) { nsXPIDLCString uriString; result = uri->GetSpec(getter_Copies(uriString)); if (NS_SUCCEEDED(result)) CopyASCIItoUCS2(nsDependentCString(uriString), aHref); } } return result; } NS_IMETHODIMP LocationImpl::SetHref(const nsAReadableString& aHref) { nsAutoString oldHref; nsresult rv = NS_OK; // Get JSContext from stack. nsCOMPtr stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv)); if (NS_FAILED(rv)) return NS_ERROR_FAILURE; JSContext *cx; if (NS_FAILED(stack->Peek(&cx))) return NS_ERROR_FAILURE; if (cx) { rv = SetHrefWithContext(cx, aHref, PR_FALSE); } else { rv = GetHref(oldHref); if (NS_SUCCEEDED(rv)) { nsCOMPtr oldUri; rv = NS_NewURI(getter_AddRefs(oldUri), oldHref); if (oldUri) { rv = SetHrefWithBase(aHref, oldUri, PR_FALSE); } } } return rv; } nsresult LocationImpl::SetHrefWithContext(JSContext* cx, const nsAReadableString& aHref, PRBool aReplace) { nsCOMPtr base; // Get the source of the caller nsresult result = GetSourceURL(cx, getter_AddRefs(base)); if (NS_FAILED(result)) { return result; } return SetHrefWithBase(aHref, base, aReplace); } nsresult LocationImpl::SetHrefWithBase(const nsAReadableString& aHref, nsIURI* aBase, PRBool aReplace) { nsresult result; nsCOMPtr newUri; result = NS_NewURI(getter_AddRefs(newUri), aHref, aBase); if (newUri && mDocShell) { nsCOMPtr loadInfo; nsCOMPtr webNav(do_QueryInterface(mDocShell)); nsresult rv = CheckURL(newUri, getter_AddRefs(loadInfo)); if(NS_FAILED(rv)) return rv; /* Check with the scriptContext if it is currently processing a script tag. * If so, this must be a