LCOV - code coverage report
Current view: directory - dom/base - nsLocation.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 421 0 0.0 %
Date: 2012-06-02 Functions: 39 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 sw=2 et tw=80: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Travis Bogard <travis@netscape.com>
      25                 :  *   Pierre Phaneuf <pp@ludusdesign.com>
      26                 :  *
      27                 :  * Alternatively, the contents of this file may be used under the terms of
      28                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      29                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      30                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      31                 :  * of those above. If you wish to allow use of your version of this file only
      32                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      33                 :  * use your version of this file under the terms of the MPL, indicate your
      34                 :  * decision by deleting the provisions above and replace them with the notice
      35                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      36                 :  * the provisions above, a recipient may use your version of this file under
      37                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      38                 :  *
      39                 :  * ***** END LICENSE BLOCK ***** */
      40                 : 
      41                 : #include "nsLocation.h"
      42                 : #include "nsIScriptSecurityManager.h"
      43                 : #include "nsIScriptContext.h"
      44                 : #include "nsIDocShell.h"
      45                 : #include "nsIDocShellLoadInfo.h"
      46                 : #include "nsIWebNavigation.h"
      47                 : #include "nsCDefaultURIFixup.h"
      48                 : #include "nsIURIFixup.h"
      49                 : #include "nsIURL.h"
      50                 : #include "nsIJARURI.h"
      51                 : #include "nsIIOService.h"
      52                 : #include "nsIServiceManager.h"
      53                 : #include "nsNetUtil.h"
      54                 : #include "plstr.h"
      55                 : #include "prprf.h"
      56                 : #include "prmem.h"
      57                 : #include "nsCOMPtr.h"
      58                 : #include "nsEscape.h"
      59                 : #include "nsIDOMWindow.h"
      60                 : #include "nsIDOMDocument.h"
      61                 : #include "nsIDocument.h"
      62                 : #include "nsIPresShell.h"
      63                 : #include "nsPresContext.h"
      64                 : #include "nsIJSContextStack.h"
      65                 : #include "nsXPIDLString.h"
      66                 : #include "nsDOMError.h"
      67                 : #include "nsDOMClassInfoID.h"
      68                 : #include "nsCRT.h"
      69                 : #include "nsIProtocolHandler.h"
      70                 : #include "nsReadableUtils.h"
      71                 : #include "nsITextToSubURI.h"
      72                 : #include "nsContentUtils.h"
      73                 : #include "nsJSUtils.h"
      74                 : #include "jsfriendapi.h"
      75                 : 
      76                 : static nsresult
      77               0 : GetContextFromStack(nsIJSContextStack *aStack, JSContext **aContext)
      78                 : {
      79                 :   nsCOMPtr<nsIJSContextStackIterator>
      80               0 :     iterator(do_CreateInstance("@mozilla.org/js/xpc/ContextStackIterator;1"));
      81               0 :   NS_ENSURE_TRUE(iterator, NS_ERROR_FAILURE);
      82                 : 
      83               0 :   nsresult rv = iterator->Reset(aStack);
      84               0 :   NS_ENSURE_SUCCESS(rv, rv);
      85                 : 
      86                 :   bool done;
      87               0 :   while (NS_SUCCEEDED(iterator->Done(&done)) && !done) {
      88               0 :     rv = iterator->Prev(aContext);
      89               0 :     NS_ASSERTION(NS_SUCCEEDED(rv), "Broken iterator implementation");
      90                 : 
      91                 :     // Consider a null context the end of the line.
      92               0 :     if (!*aContext) {
      93               0 :       break;
      94                 :     }
      95                 : 
      96               0 :     if (nsJSUtils::GetDynamicScriptContext(*aContext)) {
      97               0 :       return NS_OK;
      98                 :     }
      99                 :   }
     100                 : 
     101               0 :   *aContext = nsnull;
     102                 : 
     103               0 :   return NS_OK;
     104                 : }
     105                 : 
     106                 : static nsresult
     107               0 : GetDocumentCharacterSetForURI(const nsAString& aHref, nsACString& aCharset)
     108                 : {
     109               0 :   aCharset.Truncate();
     110                 : 
     111                 :   nsresult rv;
     112                 : 
     113               0 :   nsCOMPtr<nsIJSContextStack> stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv));
     114               0 :   NS_ENSURE_SUCCESS(rv, rv);
     115                 : 
     116                 :   JSContext *cx;
     117                 : 
     118               0 :   rv = GetContextFromStack(stack, &cx);
     119               0 :   NS_ENSURE_SUCCESS(rv, rv);
     120                 : 
     121               0 :   if (cx) {
     122                 :     nsCOMPtr<nsIDOMWindow> window =
     123               0 :       do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
     124               0 :     NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
     125                 : 
     126               0 :     nsCOMPtr<nsIDOMDocument> domDoc;
     127               0 :     rv = window->GetDocument(getter_AddRefs(domDoc));
     128               0 :     NS_ENSURE_SUCCESS(rv, rv);
     129                 : 
     130               0 :     nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
     131                 : 
     132               0 :     if (doc) {
     133               0 :       aCharset = doc->GetDocumentCharacterSet();
     134                 :     }
     135                 :   }
     136                 : 
     137               0 :   return NS_OK;
     138                 : }
     139                 : 
     140               0 : nsLocation::nsLocation(nsIDocShell *aDocShell)
     141                 : {
     142               0 :   mDocShell = do_GetWeakReference(aDocShell);
     143               0 : }
     144                 : 
     145               0 : nsLocation::~nsLocation()
     146                 : {
     147               0 : }
     148                 : 
     149                 : DOMCI_DATA(Location, nsLocation)
     150                 : 
     151                 : // QueryInterface implementation for nsLocation
     152               0 : NS_INTERFACE_MAP_BEGIN(nsLocation)
     153               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMLocation)
     154               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMLocation)
     155               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Location)
     156               0 : NS_INTERFACE_MAP_END
     157                 : 
     158                 : 
     159               0 : NS_IMPL_ADDREF(nsLocation)
     160               0 : NS_IMPL_RELEASE(nsLocation)
     161                 : 
     162                 : void
     163               0 : nsLocation::SetDocShell(nsIDocShell *aDocShell)
     164                 : {
     165               0 :    mDocShell = do_GetWeakReference(aDocShell);
     166               0 : }
     167                 : 
     168                 : nsIDocShell *
     169               0 : nsLocation::GetDocShell()
     170                 : {
     171               0 :   nsCOMPtr<nsIDocShell> docshell(do_QueryReferent(mDocShell));
     172               0 :   return docshell;
     173                 : }
     174                 : 
     175                 : // Try to get the the document corresponding to the given JSStackFrame.
     176                 : static already_AddRefed<nsIDocument>
     177               0 : GetFrameDocument(JSContext *cx, JSStackFrame *fp)
     178                 : {
     179               0 :   if (!cx || !fp)
     180               0 :     return nsnull;
     181                 : 
     182               0 :   JSObject* scope = JS_GetGlobalForFrame(fp);
     183               0 :   if (!scope)
     184               0 :     return nsnull;
     185                 : 
     186               0 :   JSAutoEnterCompartment ac;
     187               0 :   if (!ac.enter(cx, scope))
     188               0 :      return nsnull;
     189                 : 
     190                 :   nsCOMPtr<nsIDOMWindow> window =
     191               0 :     do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx, scope));
     192               0 :   if (!window)
     193               0 :     return nsnull;
     194                 : 
     195                 :   // If it's a window, get its document.
     196               0 :   nsCOMPtr<nsIDOMDocument> domDoc;
     197               0 :   window->GetDocument(getter_AddRefs(domDoc));
     198               0 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
     199               0 :   return doc.forget();
     200                 : }
     201                 : 
     202                 : nsresult
     203               0 : nsLocation::CheckURL(nsIURI* aURI, nsIDocShellLoadInfo** aLoadInfo)
     204                 : {
     205               0 :   *aLoadInfo = nsnull;
     206                 : 
     207               0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
     208               0 :   NS_ENSURE_TRUE(docShell, NS_ERROR_NOT_AVAILABLE);
     209                 : 
     210                 :   nsresult rv;
     211                 :   // Get JSContext from stack.
     212                 :   nsCOMPtr<nsIJSContextStack>
     213               0 :     stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv));
     214               0 :   NS_ENSURE_SUCCESS(rv, rv);
     215                 : 
     216                 :   JSContext *cx;
     217                 : 
     218               0 :   NS_ENSURE_SUCCESS(GetContextFromStack(stack, &cx), NS_ERROR_FAILURE);
     219                 : 
     220               0 :   nsCOMPtr<nsISupports> owner;
     221               0 :   nsCOMPtr<nsIURI> sourceURI;
     222                 : 
     223               0 :   if (cx) {
     224                 :     // No cx means that there's no JS running, or at least no JS that
     225                 :     // was run through code that properly pushed a context onto the
     226                 :     // context stack (as all code that runs JS off of web pages
     227                 :     // does). We won't bother with security checks in this case, but
     228                 :     // we need to create the loadinfo etc.
     229                 : 
     230                 :     // Get security manager.
     231                 :     nsCOMPtr<nsIScriptSecurityManager>
     232               0 :       secMan(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv));
     233               0 :     NS_ENSURE_SUCCESS(rv, rv);
     234                 : 
     235                 :     // Check to see if URI is allowed.
     236               0 :     rv = secMan->CheckLoadURIFromScript(cx, aURI);
     237               0 :     NS_ENSURE_SUCCESS(rv, rv);
     238                 : 
     239                 :     // Now get the principal to use when loading the URI
     240                 :     // First, get the principal and frame.
     241                 :     JSStackFrame *fp;
     242               0 :     nsIPrincipal* principal = secMan->GetCxSubjectPrincipalAndFrame(cx, &fp);
     243               0 :     NS_ENSURE_TRUE(principal, NS_ERROR_FAILURE);
     244                 : 
     245               0 :     nsCOMPtr<nsIURI> principalURI;
     246               0 :     principal->GetURI(getter_AddRefs(principalURI));
     247                 : 
     248                 :     // Make the load's referrer reflect changes to the document's URI caused by
     249                 :     // push/replaceState, if possible.  First, get the document corresponding to
     250                 :     // fp.  If the document's original URI (i.e. its URI before
     251                 :     // push/replaceState) matches the principal's URI, use the document's
     252                 :     // current URI as the referrer.  If they don't match, use the principal's
     253                 :     // URI.
     254                 : 
     255               0 :     nsCOMPtr<nsIDocument> frameDoc = GetFrameDocument(cx, fp);
     256               0 :     nsCOMPtr<nsIURI> docOriginalURI, docCurrentURI;
     257               0 :     if (frameDoc) {
     258               0 :       docOriginalURI = frameDoc->GetOriginalURI();
     259               0 :       docCurrentURI = frameDoc->GetDocumentURI();
     260                 :     }
     261                 : 
     262               0 :     bool urisEqual = false;
     263               0 :     if (docOriginalURI && docCurrentURI && principalURI) {
     264               0 :       principalURI->Equals(docOriginalURI, &urisEqual);
     265                 :     }
     266                 : 
     267               0 :     if (urisEqual) {
     268               0 :       sourceURI = docCurrentURI;
     269                 :     }
     270                 :     else {
     271               0 :       sourceURI = principalURI;
     272                 :     }
     273                 : 
     274               0 :     owner = do_QueryInterface(principal);
     275                 :   }
     276                 : 
     277                 :   // Create load info
     278               0 :   nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
     279               0 :   docShell->CreateLoadInfo(getter_AddRefs(loadInfo));
     280               0 :   NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE);
     281                 : 
     282               0 :   loadInfo->SetOwner(owner);
     283                 : 
     284               0 :   if (sourceURI) {
     285               0 :     loadInfo->SetReferrer(sourceURI);
     286                 :   }
     287                 : 
     288               0 :   loadInfo.swap(*aLoadInfo);
     289                 : 
     290               0 :   return NS_OK;
     291                 : }
     292                 : 
     293                 : nsresult
     294               0 : nsLocation::GetURI(nsIURI** aURI, bool aGetInnermostURI)
     295                 : {
     296               0 :   *aURI = nsnull;
     297                 : 
     298                 :   nsresult rv;
     299               0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
     300               0 :   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell, &rv));
     301               0 :   if (NS_FAILED(rv)) {
     302               0 :     return rv;
     303                 :   }
     304                 : 
     305               0 :   nsCOMPtr<nsIURI> uri;
     306               0 :   rv = webNav->GetCurrentURI(getter_AddRefs(uri));
     307               0 :   NS_ENSURE_SUCCESS(rv, rv);
     308                 : 
     309                 :   // It is valid for docshell to return a null URI. Don't try to fixup
     310                 :   // if this happens.
     311               0 :   if (!uri) {
     312               0 :     return NS_OK;
     313                 :   }
     314                 : 
     315               0 :   if (aGetInnermostURI) {
     316               0 :     nsCOMPtr<nsIJARURI> jarURI(do_QueryInterface(uri));
     317               0 :     while (jarURI) {
     318               0 :       jarURI->GetJARFile(getter_AddRefs(uri));
     319               0 :       jarURI = do_QueryInterface(uri);
     320                 :     }
     321                 :   }
     322                 : 
     323               0 :   NS_ASSERTION(uri, "nsJARURI screwed up?");
     324                 : 
     325               0 :   nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
     326               0 :   NS_ENSURE_SUCCESS(rv, rv);
     327                 : 
     328               0 :   return urifixup->CreateExposableURI(uri, aURI);
     329                 : }
     330                 : 
     331                 : nsresult
     332               0 : nsLocation::GetWritableURI(nsIURI** aURI)
     333                 : {
     334               0 :   *aURI = nsnull;
     335                 : 
     336               0 :   nsCOMPtr<nsIURI> uri;
     337                 : 
     338               0 :   nsresult rv = GetURI(getter_AddRefs(uri));
     339               0 :   if (NS_FAILED(rv) || !uri) {
     340               0 :     return rv;
     341                 :   }
     342                 : 
     343               0 :   return uri->Clone(aURI);
     344                 : }
     345                 : 
     346                 : nsresult
     347               0 : nsLocation::SetURI(nsIURI* aURI, bool aReplace)
     348                 : {
     349               0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
     350               0 :   if (docShell) {
     351               0 :     nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
     352               0 :     nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
     353                 : 
     354               0 :     if(NS_FAILED(CheckURL(aURI, getter_AddRefs(loadInfo))))
     355               0 :       return NS_ERROR_FAILURE;
     356                 : 
     357               0 :     if (aReplace) {
     358               0 :       loadInfo->SetLoadType(nsIDocShellLoadInfo::loadStopContentAndReplace);
     359                 :     } else {
     360               0 :       loadInfo->SetLoadType(nsIDocShellLoadInfo::loadStopContent);
     361                 :     }
     362                 : 
     363               0 :     return docShell->LoadURI(aURI, loadInfo,
     364               0 :                              nsIWebNavigation::LOAD_FLAGS_NONE, true);
     365                 :   }
     366                 : 
     367               0 :   return NS_OK;
     368                 : }
     369                 : 
     370                 : NS_IMETHODIMP
     371               0 : nsLocation::GetHash(nsAString& aHash)
     372                 : {
     373               0 :   aHash.SetLength(0);
     374                 : 
     375               0 :   nsCOMPtr<nsIURI> uri;
     376               0 :   nsresult rv = GetURI(getter_AddRefs(uri));
     377               0 :   if (NS_FAILED(rv) || !uri) {
     378               0 :     return rv;
     379                 :   }
     380                 : 
     381               0 :   nsCAutoString ref;
     382               0 :   nsAutoString unicodeRef;
     383                 : 
     384               0 :   rv = uri->GetRef(ref);
     385               0 :   if (NS_SUCCEEDED(rv)) {
     386                 :     nsCOMPtr<nsITextToSubURI> textToSubURI(
     387               0 :         do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv));
     388                 : 
     389               0 :     if (NS_SUCCEEDED(rv)) {
     390               0 :       nsCAutoString charset;
     391               0 :       uri->GetOriginCharset(charset);
     392                 :         
     393               0 :       rv = textToSubURI->UnEscapeURIForUI(charset, ref, unicodeRef);
     394                 :     }
     395                 :       
     396               0 :     if (NS_FAILED(rv)) {
     397                 :       // Oh, well.  No intl here!
     398               0 :       NS_UnescapeURL(ref);
     399               0 :       CopyASCIItoUTF16(ref, unicodeRef);
     400               0 :       rv = NS_OK;
     401                 :     }
     402                 :   }
     403                 : 
     404               0 :   if (NS_SUCCEEDED(rv) && !unicodeRef.IsEmpty()) {
     405               0 :     aHash.Assign(PRUnichar('#'));
     406               0 :     aHash.Append(unicodeRef);
     407                 :   }
     408                 : 
     409               0 :   if (aHash == mCachedHash) {
     410                 :     // Work around ShareThis stupidly polling location.hash every
     411                 :     // 5ms all the time by handing out the same exact string buffer
     412                 :     // we handed out last time.
     413               0 :     aHash = mCachedHash;
     414                 :   } else {
     415               0 :     mCachedHash = aHash;
     416                 :   }
     417                 : 
     418               0 :   return rv;
     419                 : }
     420                 : 
     421                 : NS_IMETHODIMP
     422               0 : nsLocation::SetHash(const nsAString& aHash)
     423                 : {
     424               0 :   nsCOMPtr<nsIURI> uri;
     425               0 :   nsresult rv = GetWritableURI(getter_AddRefs(uri));
     426               0 :   if (NS_FAILED(rv) || !uri) {
     427               0 :     return rv;
     428                 :   }
     429                 : 
     430               0 :   NS_ConvertUTF16toUTF8 hash(aHash);
     431               0 :   if (hash.IsEmpty() || hash.First() != PRUnichar('#')) {
     432               0 :     hash.Insert(PRUnichar('#'), 0);
     433                 :   }
     434               0 :   rv = uri->SetRef(hash);
     435               0 :   if (NS_SUCCEEDED(rv)) {
     436               0 :     SetURI(uri);
     437                 :   }
     438                 : 
     439               0 :   return rv;
     440                 : }
     441                 : 
     442                 : NS_IMETHODIMP
     443               0 : nsLocation::GetHost(nsAString& aHost)
     444                 : {
     445               0 :   aHost.Truncate();
     446                 : 
     447               0 :   nsCOMPtr<nsIURI> uri;
     448                 :   nsresult result;
     449                 : 
     450               0 :   result = GetURI(getter_AddRefs(uri), true);
     451                 : 
     452               0 :   if (uri) {
     453               0 :     nsCAutoString hostport;
     454                 : 
     455               0 :     result = uri->GetHostPort(hostport);
     456                 : 
     457               0 :     if (NS_SUCCEEDED(result)) {
     458               0 :       AppendUTF8toUTF16(hostport, aHost);
     459                 :     }
     460                 :   }
     461                 : 
     462               0 :   return NS_OK;
     463                 : }
     464                 : 
     465                 : NS_IMETHODIMP
     466               0 : nsLocation::SetHost(const nsAString& aHost)
     467                 : {
     468               0 :   nsCOMPtr<nsIURI> uri;
     469               0 :   nsresult rv = GetWritableURI(getter_AddRefs(uri));
     470                 : 
     471               0 :   if (uri) {
     472               0 :     rv = uri->SetHostPort(NS_ConvertUTF16toUTF8(aHost));
     473               0 :     if (NS_SUCCEEDED(rv)) {
     474               0 :       SetURI(uri);
     475                 :     }
     476                 :   }
     477                 : 
     478               0 :   return rv;
     479                 : }
     480                 : 
     481                 : NS_IMETHODIMP
     482               0 : nsLocation::GetHostname(nsAString& aHostname)
     483                 : {
     484               0 :   aHostname.Truncate();
     485                 : 
     486               0 :   nsCOMPtr<nsIURI> uri;
     487                 :   nsresult result;
     488                 : 
     489               0 :   result = GetURI(getter_AddRefs(uri), true);
     490                 : 
     491               0 :   if (uri) {
     492               0 :     nsCAutoString host;
     493                 : 
     494               0 :     result = uri->GetHost(host);
     495                 : 
     496               0 :     if (NS_SUCCEEDED(result)) {
     497               0 :       AppendUTF8toUTF16(host, aHostname);
     498                 :     }
     499                 :   }
     500                 : 
     501               0 :   return NS_OK;
     502                 : }
     503                 : 
     504                 : NS_IMETHODIMP
     505               0 : nsLocation::SetHostname(const nsAString& aHostname)
     506                 : {
     507               0 :   nsCOMPtr<nsIURI> uri;
     508               0 :   nsresult rv = GetWritableURI(getter_AddRefs(uri));
     509                 : 
     510               0 :   if (uri) {
     511               0 :     rv = uri->SetHost(NS_ConvertUTF16toUTF8(aHostname));
     512               0 :     if (NS_SUCCEEDED(rv)) {
     513               0 :       SetURI(uri);
     514                 :     }
     515                 :   }
     516                 : 
     517               0 :   return rv;
     518                 : }
     519                 : 
     520                 : NS_IMETHODIMP
     521               0 : nsLocation::GetHref(nsAString& aHref)
     522                 : {
     523               0 :   aHref.Truncate();
     524                 : 
     525               0 :   nsCOMPtr<nsIURI> uri;
     526                 :   nsresult result;
     527                 : 
     528               0 :   result = GetURI(getter_AddRefs(uri));
     529                 : 
     530               0 :   if (uri) {
     531               0 :     nsCAutoString uriString;
     532                 : 
     533               0 :     result = uri->GetSpec(uriString);
     534                 : 
     535               0 :     if (NS_SUCCEEDED(result)) {
     536               0 :       AppendUTF8toUTF16(uriString, aHref);
     537                 :     }
     538                 :   }
     539                 : 
     540               0 :   return result;
     541                 : }
     542                 : 
     543                 : NS_IMETHODIMP
     544               0 : nsLocation::SetHref(const nsAString& aHref)
     545                 : {
     546               0 :   nsAutoString oldHref;
     547               0 :   nsresult rv = NS_OK;
     548                 : 
     549                 :   // Get JSContext from stack.
     550                 :   nsCOMPtr<nsIJSContextStack>
     551               0 :     stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &rv));
     552                 : 
     553               0 :   if (NS_FAILED(rv))
     554               0 :     return NS_ERROR_FAILURE;
     555                 : 
     556                 :   JSContext *cx;
     557                 : 
     558               0 :   if (NS_FAILED(GetContextFromStack(stack, &cx)))
     559               0 :     return NS_ERROR_FAILURE;
     560                 : 
     561               0 :   if (cx) {
     562               0 :     rv = SetHrefWithContext(cx, aHref, false);
     563                 :   } else {
     564               0 :     rv = GetHref(oldHref);
     565                 : 
     566               0 :     if (NS_SUCCEEDED(rv)) {
     567               0 :       nsCOMPtr<nsIURI> oldUri;
     568                 : 
     569               0 :       rv = NS_NewURI(getter_AddRefs(oldUri), oldHref);
     570                 : 
     571               0 :       if (oldUri) {
     572               0 :         rv = SetHrefWithBase(aHref, oldUri, false);
     573                 :       }
     574                 :     }
     575                 :   }
     576                 : 
     577               0 :   return rv;
     578                 : }
     579                 : 
     580                 : nsresult
     581               0 : nsLocation::SetHrefWithContext(JSContext* cx, const nsAString& aHref,
     582                 :                                bool aReplace)
     583                 : {
     584               0 :   nsCOMPtr<nsIURI> base;
     585                 : 
     586                 :   // Get the source of the caller
     587               0 :   nsresult result = GetSourceBaseURL(cx, getter_AddRefs(base));
     588                 : 
     589               0 :   if (NS_FAILED(result)) {
     590               0 :     return result;
     591                 :   }
     592                 : 
     593               0 :   return SetHrefWithBase(aHref, base, aReplace);
     594                 : }
     595                 : 
     596                 : nsresult
     597               0 : nsLocation::SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
     598                 :                             bool aReplace)
     599                 : {
     600                 :   nsresult result;
     601               0 :   nsCOMPtr<nsIURI> newUri;
     602                 : 
     603               0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
     604                 : 
     605               0 :   nsCAutoString docCharset;
     606               0 :   if (NS_SUCCEEDED(GetDocumentCharacterSetForURI(aHref, docCharset)))
     607               0 :     result = NS_NewURI(getter_AddRefs(newUri), aHref, docCharset.get(), aBase);
     608                 :   else
     609               0 :     result = NS_NewURI(getter_AddRefs(newUri), aHref, nsnull, aBase);
     610                 : 
     611               0 :   if (newUri) {
     612                 :     /* Check with the scriptContext if it is currently processing a script tag.
     613                 :      * If so, this must be a <script> tag with a location.href in it.
     614                 :      * we want to do a replace load, in such a situation. 
     615                 :      * In other cases, for example if a event handler or a JS timer
     616                 :      * had a location.href in it, we want to do a normal load,
     617                 :      * so that the new url will be appended to Session History.
     618                 :      * This solution is tricky. Hopefully it isn't going to bite
     619                 :      * anywhere else. This is part of solution for bug # 39938, 72197
     620                 :      * 
     621                 :      */
     622               0 :     bool inScriptTag=false;
     623                 :     // Get JSContext from stack.
     624               0 :     nsCOMPtr<nsIJSContextStack> stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1", &result));
     625                 : 
     626               0 :     if (stack) {
     627                 :       JSContext *cx;
     628                 : 
     629               0 :       result = GetContextFromStack(stack, &cx);
     630               0 :       if (cx) {
     631                 :         nsIScriptContext *scriptContext =
     632               0 :           nsJSUtils::GetDynamicScriptContext(cx);
     633                 : 
     634               0 :         if (scriptContext) {
     635               0 :           if (scriptContext->GetProcessingScriptTag()) {
     636                 :             // Now check to make sure that the script is running in our window,
     637                 :             // since we only want to replace if the location is set by a
     638                 :             // <script> tag in the same window.  See bug 178729.
     639               0 :             nsCOMPtr<nsIScriptGlobalObject> ourGlobal(do_GetInterface(docShell));
     640               0 :             inScriptTag = (ourGlobal == scriptContext->GetGlobalObject());
     641                 :           }
     642                 :         }  
     643                 :       } //cx
     644                 :     }  // stack
     645                 : 
     646               0 :     return SetURI(newUri, aReplace || inScriptTag);
     647                 :   }
     648                 : 
     649               0 :   return result;
     650                 : }
     651                 : 
     652                 : NS_IMETHODIMP
     653               0 : nsLocation::GetPathname(nsAString& aPathname)
     654                 : {
     655               0 :   aPathname.Truncate();
     656                 : 
     657               0 :   nsCOMPtr<nsIURI> uri;
     658               0 :   nsresult result = NS_OK;
     659                 : 
     660               0 :   result = GetURI(getter_AddRefs(uri));
     661                 : 
     662               0 :   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
     663               0 :   if (url) {
     664               0 :     nsCAutoString file;
     665                 : 
     666               0 :     result = url->GetFilePath(file);
     667                 : 
     668               0 :     if (NS_SUCCEEDED(result)) {
     669               0 :       AppendUTF8toUTF16(file, aPathname);
     670                 :     }
     671                 :   }
     672                 : 
     673               0 :   return result;
     674                 : }
     675                 : 
     676                 : NS_IMETHODIMP
     677               0 : nsLocation::SetPathname(const nsAString& aPathname)
     678                 : {
     679               0 :   nsCOMPtr<nsIURI> uri;
     680               0 :   nsresult rv = GetWritableURI(getter_AddRefs(uri));
     681                 : 
     682               0 :   if (uri) {
     683               0 :     rv = uri->SetPath(NS_ConvertUTF16toUTF8(aPathname));
     684               0 :     if (NS_SUCCEEDED(rv)) {
     685               0 :       SetURI(uri);
     686                 :     }
     687                 :   }
     688                 : 
     689               0 :   return rv;
     690                 : }
     691                 : 
     692                 : NS_IMETHODIMP
     693               0 : nsLocation::GetPort(nsAString& aPort)
     694                 : {
     695               0 :   aPort.SetLength(0);
     696                 : 
     697               0 :   nsCOMPtr<nsIURI> uri;
     698               0 :   nsresult result = NS_OK;
     699                 : 
     700               0 :   result = GetURI(getter_AddRefs(uri), true);
     701                 : 
     702               0 :   if (uri) {
     703                 :     PRInt32 port;
     704               0 :     result = uri->GetPort(&port);
     705                 : 
     706               0 :     if (NS_SUCCEEDED(result) && -1 != port) {
     707               0 :       nsAutoString portStr;
     708               0 :       portStr.AppendInt(port);
     709               0 :       aPort.Append(portStr);
     710                 :     }
     711                 : 
     712                 :     // Don't propagate this exception to caller
     713               0 :     result = NS_OK;
     714                 :   }
     715                 : 
     716               0 :   return result;
     717                 : }
     718                 : 
     719                 : NS_IMETHODIMP
     720               0 : nsLocation::SetPort(const nsAString& aPort)
     721                 : {
     722               0 :   nsCOMPtr<nsIURI> uri;
     723               0 :   nsresult rv = GetWritableURI(getter_AddRefs(uri));
     724                 : 
     725               0 :   if (uri) {
     726                 :     // perhaps use nsReadingIterators at some point?
     727               0 :     NS_ConvertUTF16toUTF8 portStr(aPort);
     728               0 :     const char *buf = portStr.get();
     729               0 :     PRInt32 port = -1;
     730                 : 
     731               0 :     if (buf) {
     732               0 :       if (*buf == ':') {
     733               0 :         port = atol(buf+1);
     734                 :       }
     735                 :       else {
     736               0 :         port = atol(buf);
     737                 :       }
     738                 :     }
     739                 : 
     740               0 :     rv = uri->SetPort(port);
     741               0 :     if (NS_SUCCEEDED(rv)) {
     742               0 :       SetURI(uri);
     743                 :     }
     744                 :   }
     745                 : 
     746               0 :   return rv;
     747                 : }
     748                 : 
     749                 : NS_IMETHODIMP
     750               0 : nsLocation::GetProtocol(nsAString& aProtocol)
     751                 : {
     752               0 :   aProtocol.SetLength(0);
     753                 : 
     754               0 :   nsCOMPtr<nsIURI> uri;
     755               0 :   nsresult result = NS_OK;
     756                 : 
     757               0 :   result = GetURI(getter_AddRefs(uri));
     758                 : 
     759               0 :   if (uri) {
     760               0 :     nsCAutoString protocol;
     761                 : 
     762               0 :     result = uri->GetScheme(protocol);
     763                 : 
     764               0 :     if (NS_SUCCEEDED(result)) {
     765               0 :       CopyASCIItoUTF16(protocol, aProtocol);
     766               0 :       aProtocol.Append(PRUnichar(':'));
     767                 :     }
     768                 :   }
     769                 : 
     770               0 :   return result;
     771                 : }
     772                 : 
     773                 : NS_IMETHODIMP
     774               0 : nsLocation::SetProtocol(const nsAString& aProtocol)
     775                 : {
     776               0 :   nsCOMPtr<nsIURI> uri;
     777               0 :   nsresult rv = GetWritableURI(getter_AddRefs(uri));
     778                 : 
     779               0 :   if (uri) {
     780               0 :     rv = uri->SetScheme(NS_ConvertUTF16toUTF8(aProtocol));
     781               0 :     if (NS_SUCCEEDED(rv)) {
     782               0 :       SetURI(uri);
     783                 :     }
     784                 :   }
     785                 : 
     786               0 :   return rv;
     787                 : }
     788                 : 
     789                 : NS_IMETHODIMP
     790               0 : nsLocation::GetSearch(nsAString& aSearch)
     791                 : {
     792               0 :   aSearch.SetLength(0);
     793                 : 
     794               0 :   nsCOMPtr<nsIURI> uri;
     795               0 :   nsresult result = NS_OK;
     796                 : 
     797               0 :   result = GetURI(getter_AddRefs(uri));
     798                 : 
     799               0 :   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
     800                 : 
     801               0 :   if (url) {
     802               0 :     nsCAutoString search;
     803                 : 
     804               0 :     result = url->GetQuery(search);
     805                 : 
     806               0 :     if (NS_SUCCEEDED(result) && !search.IsEmpty()) {
     807               0 :       aSearch.Assign(PRUnichar('?'));
     808               0 :       AppendUTF8toUTF16(search, aSearch);
     809                 :     }
     810                 :   }
     811                 : 
     812               0 :   return NS_OK;
     813                 : }
     814                 : 
     815                 : NS_IMETHODIMP
     816               0 : nsLocation::SetSearch(const nsAString& aSearch)
     817                 : {
     818               0 :   nsCOMPtr<nsIURI> uri;
     819               0 :   nsresult rv = GetWritableURI(getter_AddRefs(uri));
     820                 : 
     821               0 :   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
     822               0 :   if (url) {
     823               0 :     rv = url->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
     824               0 :     if (NS_SUCCEEDED(rv)) {
     825               0 :       SetURI(uri);
     826                 :     }
     827                 :   }
     828                 : 
     829               0 :   return rv;
     830                 : }
     831                 : 
     832                 : NS_IMETHODIMP
     833               0 : nsLocation::Reload(bool aForceget)
     834                 : {
     835                 :   nsresult rv;
     836               0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
     837               0 :   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
     838               0 :   nsCOMPtr<nsPIDOMWindow> window(do_GetInterface(docShell));
     839                 : 
     840               0 :   if (window && window->IsHandlingResizeEvent()) {
     841                 :     // location.reload() was called on a window that is handling a
     842                 :     // resize event. Sites do this since Netscape 4.x needed it, but
     843                 :     // we don't, and it's a horrible experience for nothing. In stead
     844                 :     // of reloading the page, just clear style data and reflow the
     845                 :     // page since some sites may use this trick to work around gecko
     846                 :     // reflow bugs, and this should have the same effect.
     847                 : 
     848               0 :     nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
     849                 : 
     850                 :     nsIPresShell *shell;
     851                 :     nsPresContext *pcx;
     852               0 :     if (doc && (shell = doc->GetShell()) && (pcx = shell->GetPresContext())) {
     853               0 :       pcx->RebuildAllStyleData(NS_STYLE_HINT_REFLOW);
     854                 :     }
     855                 : 
     856               0 :     return NS_OK;
     857                 :   }
     858                 : 
     859               0 :   if (webNav) {
     860               0 :     PRUint32 reloadFlags = nsIWebNavigation::LOAD_FLAGS_NONE;
     861                 : 
     862               0 :     if (aForceget) {
     863                 :       reloadFlags = nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE | 
     864               0 :                     nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
     865                 :     }
     866               0 :     rv = webNav->Reload(reloadFlags);
     867               0 :     if (rv == NS_BINDING_ABORTED) {
     868                 :       // This happens when we attempt to reload a POST result and the user says
     869                 :       // no at the "do you want to reload?" prompt.  Don't propagate this one
     870                 :       // back to callers.
     871               0 :       rv = NS_OK;
     872                 :     }
     873                 :   } else {
     874               0 :     rv = NS_ERROR_FAILURE;
     875                 :   }
     876                 : 
     877               0 :   return rv;
     878                 : }
     879                 : 
     880                 : NS_IMETHODIMP
     881               0 : nsLocation::Replace(const nsAString& aUrl)
     882                 : {
     883               0 :   nsresult rv = NS_OK;
     884                 : 
     885                 :   // Get JSContext from stack.
     886                 :   nsCOMPtr<nsIJSContextStack>
     887               0 :   stack(do_GetService("@mozilla.org/js/xpc/ContextStack;1"));
     888                 : 
     889               0 :   if (stack) {
     890                 :     JSContext *cx;
     891                 : 
     892               0 :     rv = GetContextFromStack(stack, &cx);
     893               0 :     NS_ENSURE_SUCCESS(rv, rv);
     894               0 :     if (cx) {
     895               0 :       return SetHrefWithContext(cx, aUrl, true);
     896                 :     }
     897                 :   }
     898                 : 
     899               0 :   nsAutoString oldHref;
     900                 : 
     901               0 :   rv = GetHref(oldHref);
     902               0 :   NS_ENSURE_SUCCESS(rv, rv);
     903                 : 
     904               0 :   nsCOMPtr<nsIURI> oldUri;
     905                 : 
     906               0 :   rv = NS_NewURI(getter_AddRefs(oldUri), oldHref);
     907               0 :   NS_ENSURE_SUCCESS(rv, rv);
     908                 : 
     909               0 :   return SetHrefWithBase(aUrl, oldUri, true);
     910                 : }
     911                 : 
     912                 : NS_IMETHODIMP
     913               0 : nsLocation::Assign(const nsAString& aUrl)
     914                 : {
     915               0 :   nsAutoString oldHref;
     916               0 :   nsresult result = NS_OK;
     917                 : 
     918               0 :   result = GetHref(oldHref);
     919                 : 
     920               0 :   if (NS_SUCCEEDED(result)) {
     921               0 :     nsCOMPtr<nsIURI> oldUri;
     922                 : 
     923               0 :     result = NS_NewURI(getter_AddRefs(oldUri), oldHref);
     924                 : 
     925               0 :     if (oldUri) {
     926               0 :       result = SetHrefWithBase(aUrl, oldUri, false);
     927                 :     }
     928                 :   }
     929                 : 
     930               0 :   return result;
     931                 : }
     932                 : 
     933                 : NS_IMETHODIMP
     934               0 : nsLocation::ToString(nsAString& aReturn)
     935                 : {
     936               0 :   return GetHref(aReturn);
     937                 : }
     938                 : 
     939                 : nsresult
     940               0 : nsLocation::GetSourceDocument(JSContext* cx, nsIDocument** aDocument)
     941                 : {
     942                 :   // XXX Code duplicated from nsHTMLDocument
     943                 :   // XXX Tom said this reminded him of the "Six Degrees of
     944                 :   // Kevin Bacon" game. We try to get from here to there using
     945                 :   // whatever connections possible. The problem is that this
     946                 :   // could break if any of the connections along the way change.
     947                 :   // I wish there were a better way.
     948                 : 
     949               0 :   nsresult rv = NS_ERROR_FAILURE;
     950                 : 
     951                 :   // We need to use the dynamically scoped global and assume that the
     952                 :   // current JSContext is a DOM context with a nsIScriptGlobalObject so
     953                 :   // that we can get the url of the caller.
     954                 :   // XXX This will fail on non-DOM contexts :(
     955                 : 
     956                 :   nsCOMPtr<nsIDOMWindow> window =
     957               0 :     do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx), &rv);
     958                 : 
     959               0 :   if (window) {
     960               0 :     nsCOMPtr<nsIDOMDocument> domDoc;
     961               0 :     rv = window->GetDocument(getter_AddRefs(domDoc));
     962               0 :     if (domDoc) {
     963               0 :       return CallQueryInterface(domDoc, aDocument);
     964                 :     }
     965                 :   } else {
     966               0 :     *aDocument = nsnull;
     967                 :   }
     968                 : 
     969               0 :   return rv;
     970                 : }
     971                 : 
     972                 : nsresult
     973               0 : nsLocation::GetSourceBaseURL(JSContext* cx, nsIURI** sourceURL)
     974                 : {
     975               0 :   nsCOMPtr<nsIDocument> doc;
     976               0 :   nsresult rv = GetSourceDocument(cx, getter_AddRefs(doc));
     977               0 :   if (doc) {
     978               0 :     *sourceURL = doc->GetBaseURI().get();
     979                 :   } else {
     980               0 :     *sourceURL = nsnull;
     981                 :   }
     982                 : 
     983               0 :   return rv;
     984                 : }

Generated by: LCOV version 1.7