LCOV - code coverage report
Current view: top level - dom/base - Location.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 79 456 17.3 %
Date: 2017-07-14 16:53:18 Functions: 13 39 33.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "Location.h"
       8             : #include "nsIScriptSecurityManager.h"
       9             : #include "nsIScriptObjectPrincipal.h"
      10             : #include "nsIScriptContext.h"
      11             : #include "nsIDocShell.h"
      12             : #include "nsIDocShellLoadInfo.h"
      13             : #include "nsIWebNavigation.h"
      14             : #include "nsCDefaultURIFixup.h"
      15             : #include "nsIURIFixup.h"
      16             : #include "nsIURL.h"
      17             : #include "nsIJARURI.h"
      18             : #include "nsNetUtil.h"
      19             : #include "nsCOMPtr.h"
      20             : #include "nsEscape.h"
      21             : #include "nsIDOMWindow.h"
      22             : #include "nsIDocument.h"
      23             : #include "nsIPresShell.h"
      24             : #include "nsPresContext.h"
      25             : #include "nsError.h"
      26             : #include "nsDOMClassInfoID.h"
      27             : #include "nsReadableUtils.h"
      28             : #include "nsITextToSubURI.h"
      29             : #include "nsJSUtils.h"
      30             : #include "nsContentUtils.h"
      31             : #include "nsGlobalWindow.h"
      32             : #include "mozilla/Likely.h"
      33             : #include "nsCycleCollectionParticipant.h"
      34             : #include "NullPrincipal.h"
      35             : #include "mozilla/Unused.h"
      36             : #include "mozilla/dom/LocationBinding.h"
      37             : #include "mozilla/dom/ScriptSettings.h"
      38             : 
      39             : namespace mozilla {
      40             : namespace dom {
      41             : 
      42           3 : Location::Location(nsPIDOMWindowInner* aWindow, nsIDocShell *aDocShell)
      43           3 :   : mInnerWindow(aWindow)
      44             : {
      45           3 :   MOZ_ASSERT(aDocShell);
      46           3 :   MOZ_ASSERT(mInnerWindow->IsInnerWindow());
      47             : 
      48           3 :   mDocShell = do_GetWeakReference(aDocShell);
      49           3 : }
      50             : 
      51           0 : Location::~Location()
      52             : {
      53           0 : }
      54             : 
      55             : // QueryInterface implementation for Location
      56          59 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Location)
      57           6 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      58           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      59           0 : NS_INTERFACE_MAP_END
      60             : 
      61          19 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Location, mInnerWindow)
      62             : 
      63           7 : NS_IMPL_CYCLE_COLLECTING_ADDREF(Location)
      64           1 : NS_IMPL_CYCLE_COLLECTING_RELEASE(Location)
      65             : 
      66             : nsresult
      67           0 : Location::CheckURL(nsIURI* aURI, nsIDocShellLoadInfo** aLoadInfo)
      68             : {
      69           0 :   *aLoadInfo = nullptr;
      70             : 
      71           0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
      72           0 :   NS_ENSURE_TRUE(docShell, NS_ERROR_NOT_AVAILABLE);
      73             : 
      74           0 :   nsCOMPtr<nsIPrincipal> triggeringPrincipal;
      75           0 :   nsCOMPtr<nsIURI> sourceURI;
      76           0 :   net::ReferrerPolicy referrerPolicy = net::RP_Unset;
      77             : 
      78           0 :   if (JSContext *cx = nsContentUtils::GetCurrentJSContext()) {
      79             :     // No cx means that there's no JS running, or at least no JS that
      80             :     // was run through code that properly pushed a context onto the
      81             :     // context stack (as all code that runs JS off of web pages
      82             :     // does). We won't bother with security checks in this case, but
      83             :     // we need to create the loadinfo etc.
      84             : 
      85             :     // Get security manager.
      86           0 :     nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
      87           0 :     NS_ENSURE_STATE(ssm);
      88             : 
      89             :     // Check to see if URI is allowed.
      90           0 :     nsresult rv = ssm->CheckLoadURIFromScript(cx, aURI);
      91           0 :     NS_ENSURE_SUCCESS(rv, rv);
      92             : 
      93             :     // Make the load's referrer reflect changes to the document's URI caused by
      94             :     // push/replaceState, if possible.  First, get the document corresponding to
      95             :     // fp.  If the document's original URI (i.e. its URI before
      96             :     // push/replaceState) matches the principal's URI, use the document's
      97             :     // current URI as the referrer.  If they don't match, use the principal's
      98             :     // URI.
      99             :     //
     100             :     // The triggering principal for this load should be the principal of the
     101             :     // incumbent document (which matches where the referrer information is
     102             :     // coming from) when there is an incumbent document, and the subject
     103             :     // principal otherwise.  Note that the URI in the triggering principal
     104             :     // may not match the referrer URI in various cases, notably including
     105             :     // the cases when the incumbent document's document URI was modified
     106             :     // after the document was loaded.
     107             : 
     108             :     nsCOMPtr<nsPIDOMWindowInner> incumbent =
     109           0 :       do_QueryInterface(mozilla::dom::GetIncumbentGlobal());
     110           0 :     nsCOMPtr<nsIDocument> doc = incumbent ? incumbent->GetDoc() : nullptr;
     111             : 
     112           0 :     if (doc) {
     113           0 :       nsCOMPtr<nsIURI> docOriginalURI, docCurrentURI, principalURI;
     114           0 :       docOriginalURI = doc->GetOriginalURI();
     115           0 :       docCurrentURI = doc->GetDocumentURI();
     116           0 :       rv = doc->NodePrincipal()->GetURI(getter_AddRefs(principalURI));
     117           0 :       NS_ENSURE_SUCCESS(rv, rv);
     118             : 
     119           0 :       triggeringPrincipal = doc->NodePrincipal();
     120           0 :       referrerPolicy = doc->GetReferrerPolicy();
     121             : 
     122           0 :       bool urisEqual = false;
     123           0 :       if (docOriginalURI && docCurrentURI && principalURI) {
     124           0 :         principalURI->Equals(docOriginalURI, &urisEqual);
     125             :       }
     126           0 :       if (urisEqual) {
     127           0 :         sourceURI = docCurrentURI;
     128             :       }
     129             :       else {
     130             :         // Use principalURI as long as it is not an NullPrincipalURI.  We
     131             :         // could add a method such as GetReferrerURI to principals to make this
     132             :         // cleaner, but given that we need to start using Source Browsing
     133             :         // Context for referrer (see Bug 960639) this may be wasted effort at
     134             :         // this stage.
     135           0 :         if (principalURI) {
     136             :           bool isNullPrincipalScheme;
     137           0 :           rv = principalURI->SchemeIs(NS_NULLPRINCIPAL_SCHEME,
     138           0 :                                      &isNullPrincipalScheme);
     139           0 :           if (NS_SUCCEEDED(rv) && !isNullPrincipalScheme) {
     140           0 :             sourceURI = principalURI;
     141             :           }
     142             :         }
     143             :       }
     144             :     }
     145             :     else {
     146             :       // No document; determine triggeringPrincipal by quering the
     147             :       // subjectPrincipal, wich is the principal of the current JS
     148             :       // compartment, or a null principal in case there is no
     149             :       // compartment yet.
     150           0 :       triggeringPrincipal = nsContentUtils::SubjectPrincipal();
     151             :     }
     152             :   }
     153             : 
     154             :   // Create load info
     155           0 :   nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
     156           0 :   docShell->CreateLoadInfo(getter_AddRefs(loadInfo));
     157           0 :   NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE);
     158             : 
     159           0 :   loadInfo->SetTriggeringPrincipal(triggeringPrincipal);
     160             : 
     161           0 :   if (sourceURI) {
     162           0 :     loadInfo->SetReferrer(sourceURI);
     163           0 :     loadInfo->SetReferrerPolicy(referrerPolicy);
     164             :   }
     165             : 
     166           0 :   loadInfo.swap(*aLoadInfo);
     167             : 
     168           0 :   return NS_OK;
     169             : }
     170             : 
     171             : nsresult
     172           8 : Location::GetURI(nsIURI** aURI, bool aGetInnermostURI)
     173             : {
     174           8 :   *aURI = nullptr;
     175             : 
     176          16 :   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
     177           8 :   if (!mDocShell) {
     178           0 :     return NS_OK;
     179             :   }
     180             : 
     181             :   nsresult rv;
     182          16 :   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell, &rv));
     183           8 :   if (NS_FAILED(rv)) {
     184           0 :     return rv;
     185             :   }
     186             : 
     187          16 :   nsCOMPtr<nsIURI> uri;
     188           8 :   rv = webNav->GetCurrentURI(getter_AddRefs(uri));
     189           8 :   NS_ENSURE_SUCCESS(rv, rv);
     190             : 
     191             :   // It is valid for docshell to return a null URI. Don't try to fixup
     192             :   // if this happens.
     193           8 :   if (!uri) {
     194           0 :     return NS_OK;
     195             :   }
     196             : 
     197           8 :   if (aGetInnermostURI) {
     198           2 :     nsCOMPtr<nsIJARURI> jarURI(do_QueryInterface(uri));
     199           1 :     while (jarURI) {
     200           0 :       jarURI->GetJARFile(getter_AddRefs(uri));
     201           0 :       jarURI = do_QueryInterface(uri);
     202             :     }
     203             :   }
     204             : 
     205           8 :   NS_ASSERTION(uri, "nsJARURI screwed up?");
     206             : 
     207          16 :   nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID, &rv));
     208           8 :   NS_ENSURE_SUCCESS(rv, rv);
     209             : 
     210           8 :   return urifixup->CreateExposableURI(uri, aURI);
     211             : }
     212             : 
     213             : nsresult
     214           0 : Location::GetWritableURI(nsIURI** aURI, const nsACString* aNewRef)
     215             : {
     216           0 :   *aURI = nullptr;
     217             : 
     218           0 :   nsCOMPtr<nsIURI> uri;
     219             : 
     220           0 :   nsresult rv = GetURI(getter_AddRefs(uri));
     221           0 :   if (NS_FAILED(rv) || !uri) {
     222           0 :     return rv;
     223             :   }
     224             : 
     225           0 :   if (!aNewRef) {
     226           0 :     return uri->Clone(aURI);
     227             :   }
     228             : 
     229           0 :   return uri->CloneWithNewRef(*aNewRef, aURI);
     230             : }
     231             : 
     232             : nsresult
     233           0 : Location::SetURI(nsIURI* aURI, bool aReplace)
     234             : {
     235           0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
     236           0 :   if (docShell) {
     237           0 :     nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
     238             : 
     239           0 :     if(NS_FAILED(CheckURL(aURI, getter_AddRefs(loadInfo))))
     240           0 :       return NS_ERROR_FAILURE;
     241             : 
     242           0 :     if (aReplace) {
     243           0 :       loadInfo->SetLoadType(nsIDocShellLoadInfo::loadStopContentAndReplace);
     244             :     } else {
     245           0 :       loadInfo->SetLoadType(nsIDocShellLoadInfo::loadStopContent);
     246             :     }
     247             : 
     248             :     // Get the incumbent script's browsing context to set as source.
     249             :     nsCOMPtr<nsPIDOMWindowInner> sourceWindow =
     250           0 :       do_QueryInterface(mozilla::dom::GetIncumbentGlobal());
     251           0 :     if (sourceWindow) {
     252           0 :       loadInfo->SetSourceDocShell(sourceWindow->GetDocShell());
     253             :     }
     254             : 
     255           0 :     return docShell->LoadURI(aURI, loadInfo,
     256           0 :                              nsIWebNavigation::LOAD_FLAGS_NONE, true);
     257             :   }
     258             : 
     259           0 :   return NS_OK;
     260             : }
     261             : 
     262             : void
     263           0 : Location::GetHash(nsAString& aHash,
     264             :                   nsIPrincipal& aSubjectPrincipal,
     265             :                   ErrorResult& aRv)
     266             : {
     267           0 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     268           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     269           0 :     return;
     270             :   }
     271             : 
     272           0 :   aHash.SetLength(0);
     273             : 
     274           0 :   nsCOMPtr<nsIURI> uri;
     275           0 :   aRv = GetURI(getter_AddRefs(uri));
     276           0 :   if (NS_WARN_IF(aRv.Failed()) || !uri) {
     277           0 :     return;
     278             :   }
     279             : 
     280           0 :   nsAutoCString ref;
     281           0 :   nsAutoString unicodeRef;
     282             : 
     283           0 :   aRv = uri->GetRef(ref);
     284           0 :   if (NS_WARN_IF(aRv.Failed())) {
     285           0 :     return;
     286             :   }
     287             : 
     288           0 :   if (!ref.IsEmpty()) {
     289           0 :     aHash.Assign(char16_t('#'));
     290           0 :     AppendUTF8toUTF16(ref, aHash);
     291             :   }
     292             : 
     293           0 :   if (aHash == mCachedHash) {
     294             :     // Work around ShareThis stupidly polling location.hash every
     295             :     // 5ms all the time by handing out the same exact string buffer
     296             :     // we handed out last time.
     297           0 :     aHash = mCachedHash;
     298             :   } else {
     299           0 :     mCachedHash = aHash;
     300             :   }
     301             : }
     302             : 
     303             : void
     304           0 : Location::SetHash(const nsAString& aHash,
     305             :                   nsIPrincipal& aSubjectPrincipal,
     306             :                   ErrorResult& aRv)
     307             : {
     308           0 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     309           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     310           0 :     return;
     311             :   }
     312             : 
     313           0 :   NS_ConvertUTF16toUTF8 hash(aHash);
     314           0 :   if (hash.IsEmpty() || hash.First() != char16_t('#')) {
     315           0 :     hash.Insert(char16_t('#'), 0);
     316             :   }
     317             : 
     318           0 :   nsCOMPtr<nsIURI> uri;
     319           0 :   aRv = GetWritableURI(getter_AddRefs(uri), &hash);
     320           0 :   if (NS_WARN_IF(aRv.Failed()) || !uri) {
     321           0 :     return;
     322             :   }
     323             : 
     324           0 :   aRv = SetURI(uri);
     325             : }
     326             : 
     327             : void
     328           0 : Location::GetHost(nsAString& aHost,
     329             :                   nsIPrincipal& aSubjectPrincipal,
     330             :                   ErrorResult& aRv)
     331             : {
     332           0 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     333           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     334           0 :     return;
     335             :   }
     336             : 
     337           0 :   aHost.Truncate();
     338             : 
     339           0 :   nsCOMPtr<nsIURI> uri;
     340             :   nsresult result;
     341             : 
     342           0 :   result = GetURI(getter_AddRefs(uri), true);
     343             : 
     344           0 :   if (uri) {
     345           0 :     nsAutoCString hostport;
     346             : 
     347           0 :     result = uri->GetHostPort(hostport);
     348             : 
     349           0 :     if (NS_SUCCEEDED(result)) {
     350           0 :       AppendUTF8toUTF16(hostport, aHost);
     351             :     }
     352             :   }
     353             : }
     354             : 
     355             : void
     356           0 : Location::SetHost(const nsAString& aHost,
     357             :                   nsIPrincipal& aSubjectPrincipal,
     358             :                   ErrorResult& aRv)
     359             : {
     360           0 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     361           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     362           0 :     return;
     363             :   }
     364             : 
     365           0 :   nsCOMPtr<nsIURI> uri;
     366           0 :   aRv = GetWritableURI(getter_AddRefs(uri));
     367           0 :   if (NS_WARN_IF(aRv.Failed()) || !uri) {
     368           0 :     return;
     369             :   }
     370             : 
     371           0 :   aRv = uri->SetHostPort(NS_ConvertUTF16toUTF8(aHost));
     372           0 :   if (NS_WARN_IF(aRv.Failed())) {
     373           0 :     return;
     374             :   }
     375             : 
     376           0 :   aRv = SetURI(uri);
     377             : }
     378             : 
     379             : void
     380           1 : Location::GetHostname(nsAString& aHostname,
     381             :                       nsIPrincipal& aSubjectPrincipal,
     382             :                       ErrorResult& aRv)
     383             : {
     384           1 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     385           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     386           0 :     return;
     387             :   }
     388             : 
     389           1 :   aHostname.Truncate();
     390             : 
     391           2 :   nsCOMPtr<nsIURI> uri;
     392           1 :   GetURI(getter_AddRefs(uri), true);
     393           1 :   if (uri) {
     394           1 :     nsContentUtils::GetHostOrIPv6WithBrackets(uri, aHostname);
     395             :   }
     396             : }
     397             : 
     398             : void
     399           0 : Location::SetHostname(const nsAString& aHostname,
     400             :                       nsIPrincipal& aSubjectPrincipal,
     401             :                       ErrorResult& aRv)
     402             : {
     403           0 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     404           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     405           0 :     return;
     406             :   }
     407             : 
     408           0 :   nsCOMPtr<nsIURI> uri;
     409           0 :   aRv = GetWritableURI(getter_AddRefs(uri));
     410           0 :   if (NS_WARN_IF(aRv.Failed()) || !uri) {
     411           0 :     return;
     412             :   }
     413             : 
     414           0 :   aRv = uri->SetHost(NS_ConvertUTF16toUTF8(aHostname));
     415           0 :   if (NS_WARN_IF(aRv.Failed())) {
     416           0 :     return;
     417             :   }
     418             : 
     419           0 :   aRv = SetURI(uri);
     420             : }
     421             : 
     422             : nsresult
     423           5 : Location::GetHref(nsAString& aHref)
     424             : {
     425           5 :   aHref.Truncate();
     426             : 
     427          10 :   nsCOMPtr<nsIURI> uri;
     428           5 :   nsresult rv = GetURI(getter_AddRefs(uri));
     429           5 :   if (NS_WARN_IF(NS_FAILED(rv)) || !uri) {
     430           0 :     return rv;
     431             :   }
     432             : 
     433          10 :   nsAutoCString uriString;
     434           5 :   rv = uri->GetSpec(uriString);
     435           5 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     436           0 :     return rv;
     437             :   }
     438             : 
     439           5 :   AppendUTF8toUTF16(uriString, aHref);
     440           5 :   return NS_OK;
     441             : }
     442             : 
     443             : void
     444           0 : Location::SetHref(const nsAString& aHref,
     445             :                   nsIPrincipal& aSubjectPrincipal,
     446             :                   ErrorResult& aRv)
     447             : {
     448           0 :   JSContext *cx = nsContentUtils::GetCurrentJSContext();
     449           0 :   if (cx) {
     450           0 :     aRv = SetHrefWithContext(cx, aHref, false);
     451           0 :     return;
     452             :   }
     453             : 
     454           0 :   nsAutoString oldHref;
     455           0 :   aRv = GetHref(oldHref);
     456           0 :   if (NS_WARN_IF(aRv.Failed())) {
     457           0 :     return;
     458             :   }
     459             : 
     460           0 :   nsCOMPtr<nsIURI> oldUri;
     461           0 :   aRv = NS_NewURI(getter_AddRefs(oldUri), oldHref);
     462           0 :   if (NS_WARN_IF(aRv.Failed())) {
     463           0 :     return;
     464             :   }
     465             : 
     466           0 :   aRv = SetHrefWithBase(aHref, oldUri, false);
     467           0 :   if (NS_WARN_IF(aRv.Failed())) {
     468           0 :     return;
     469             :   }
     470             : }
     471             : 
     472             : nsresult
     473           0 : Location::SetHrefWithContext(JSContext* cx, const nsAString& aHref,
     474             :                              bool aReplace)
     475             : {
     476           0 :   nsCOMPtr<nsIURI> base;
     477             : 
     478             :   // Get the source of the caller
     479           0 :   nsresult result = GetSourceBaseURL(cx, getter_AddRefs(base));
     480             : 
     481           0 :   if (NS_FAILED(result)) {
     482           0 :     return result;
     483             :   }
     484             : 
     485           0 :   return SetHrefWithBase(aHref, base, aReplace);
     486             : }
     487             : 
     488             : nsresult
     489           0 : Location::SetHrefWithBase(const nsAString& aHref, nsIURI* aBase,
     490             :                           bool aReplace)
     491             : {
     492             :   nsresult result;
     493           0 :   nsCOMPtr<nsIURI> newUri;
     494             : 
     495           0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
     496             : 
     497           0 :   if (nsIDocument* doc = GetEntryDocument()) {
     498           0 :     result = NS_NewURI(getter_AddRefs(newUri), aHref,
     499           0 :                        doc->GetDocumentCharacterSet(), aBase);
     500             :   } else {
     501           0 :     result = NS_NewURI(getter_AddRefs(newUri), aHref, nullptr, aBase);
     502             :   }
     503             : 
     504           0 :   if (newUri) {
     505             :     /* Check with the scriptContext if it is currently processing a script tag.
     506             :      * If so, this must be a <script> tag with a location.href in it.
     507             :      * we want to do a replace load, in such a situation.
     508             :      * In other cases, for example if a event handler or a JS timer
     509             :      * had a location.href in it, we want to do a normal load,
     510             :      * so that the new url will be appended to Session History.
     511             :      * This solution is tricky. Hopefully it isn't going to bite
     512             :      * anywhere else. This is part of solution for bug # 39938, 72197
     513             :      */
     514           0 :     bool inScriptTag = false;
     515           0 :     nsIScriptContext* scriptContext = nullptr;
     516           0 :     nsCOMPtr<nsPIDOMWindowInner> win = do_QueryInterface(GetEntryGlobal());
     517           0 :     if (win) {
     518           0 :       scriptContext = nsGlobalWindow::Cast(win)->GetContextInternal();
     519             :     }
     520             : 
     521           0 :     if (scriptContext) {
     522           0 :       if (scriptContext->GetProcessingScriptTag()) {
     523             :         // Now check to make sure that the script is running in our window,
     524             :         // since we only want to replace if the location is set by a
     525             :         // <script> tag in the same window.  See bug 178729.
     526             :         nsCOMPtr<nsIScriptGlobalObject> ourGlobal =
     527           0 :           docShell ? docShell->GetScriptGlobalObject() : nullptr;
     528           0 :         inScriptTag = (ourGlobal == scriptContext->GetGlobalObject());
     529             :       }
     530             :     }
     531             : 
     532           0 :     return SetURI(newUri, aReplace || inScriptTag);
     533             :   }
     534             : 
     535           0 :   return result;
     536             : }
     537             : 
     538             : void
     539           0 : Location::GetOrigin(nsAString& aOrigin,
     540             :                     nsIPrincipal& aSubjectPrincipal,
     541             :                     ErrorResult& aRv)
     542             : {
     543           0 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     544           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     545           0 :     return;
     546             :   }
     547             : 
     548           0 :   aOrigin.Truncate();
     549             : 
     550           0 :   nsCOMPtr<nsIURI> uri;
     551           0 :   aRv = GetURI(getter_AddRefs(uri), true);
     552           0 :   if (NS_WARN_IF(aRv.Failed()) || !uri) {
     553           0 :     return;
     554             :   }
     555             : 
     556           0 :   nsAutoString origin;
     557           0 :   aRv = nsContentUtils::GetUTFOrigin(uri, origin);
     558           0 :   if (NS_WARN_IF(aRv.Failed())) {
     559           0 :     return;
     560             :   }
     561             : 
     562           0 :   aOrigin = origin;
     563             : }
     564             : 
     565             : void
     566           0 : Location::GetPathname(nsAString& aPathname,
     567             :                       nsIPrincipal& aSubjectPrincipal,
     568             :                       ErrorResult& aRv)
     569             : {
     570           0 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     571           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     572           0 :     return;
     573             :   }
     574             : 
     575           0 :   aPathname.Truncate();
     576             : 
     577           0 :   nsCOMPtr<nsIURI> uri;
     578           0 :   aRv = GetURI(getter_AddRefs(uri));
     579           0 :   if (NS_WARN_IF(aRv.Failed()) || !uri) {
     580           0 :     return;
     581             :   }
     582             : 
     583           0 :   nsAutoCString file;
     584             : 
     585           0 :   aRv = uri->GetFilePath(file);
     586           0 :   if (NS_WARN_IF(aRv.Failed())) {
     587           0 :     return;
     588             :   }
     589             : 
     590           0 :   AppendUTF8toUTF16(file, aPathname);
     591             : }
     592             : 
     593             : void
     594           0 : Location::SetPathname(const nsAString& aPathname,
     595             :                       nsIPrincipal& aSubjectPrincipal,
     596             :                       ErrorResult& aRv)
     597             : {
     598           0 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     599           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     600           0 :     return;
     601             :   }
     602             : 
     603           0 :   nsCOMPtr<nsIURI> uri;
     604           0 :   aRv = GetWritableURI(getter_AddRefs(uri));
     605           0 :   if (NS_WARN_IF(aRv.Failed()) || !uri) {
     606           0 :     return;
     607             :   }
     608             : 
     609           0 :   if (NS_SUCCEEDED(uri->SetFilePath(NS_ConvertUTF16toUTF8(aPathname)))) {
     610           0 :     aRv = SetURI(uri);
     611             :   }
     612             : }
     613             : 
     614             : void
     615           0 : Location::GetPort(nsAString& aPort,
     616             :                   nsIPrincipal& aSubjectPrincipal,
     617             :                   ErrorResult& aRv)
     618             : {
     619           0 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     620           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     621           0 :     return;
     622             :   }
     623             : 
     624           0 :   aPort.SetLength(0);
     625             : 
     626           0 :   nsCOMPtr<nsIURI> uri;
     627           0 :   aRv = GetURI(getter_AddRefs(uri), true);
     628           0 :   if (NS_WARN_IF(aRv.Failed()) || !uri) {
     629           0 :     return;
     630             :   }
     631             : 
     632             :   int32_t port;
     633           0 :   nsresult result = uri->GetPort(&port);
     634             : 
     635             :   // Don't propagate this exception to caller
     636           0 :   if (NS_SUCCEEDED(result) && -1 != port) {
     637           0 :     nsAutoString portStr;
     638           0 :     portStr.AppendInt(port);
     639           0 :     aPort.Append(portStr);
     640             :   }
     641             : }
     642             : 
     643             : void
     644           0 : Location::SetPort(const nsAString& aPort,
     645             :                   nsIPrincipal& aSubjectPrincipal,
     646             :                   ErrorResult& aRv)
     647             : {
     648           0 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     649           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     650           0 :     return;
     651             :   }
     652             : 
     653           0 :   nsCOMPtr<nsIURI> uri;
     654           0 :   aRv = GetWritableURI(getter_AddRefs(uri));
     655           0 :   if (NS_WARN_IF(aRv.Failed() || !uri)) {
     656           0 :     return;
     657             :   }
     658             : 
     659             :   // perhaps use nsReadingIterators at some point?
     660           0 :   NS_ConvertUTF16toUTF8 portStr(aPort);
     661           0 :   const char *buf = portStr.get();
     662           0 :   int32_t port = -1;
     663             : 
     664           0 :   if (!portStr.IsEmpty() && buf) {
     665           0 :     if (*buf == ':') {
     666           0 :       port = atol(buf+1);
     667             :     }
     668             :     else {
     669           0 :       port = atol(buf);
     670             :     }
     671             :   }
     672             : 
     673           0 :   aRv = uri->SetPort(port);
     674           0 :   if (NS_WARN_IF(aRv.Failed())) {
     675           0 :     return;
     676             :   }
     677             : 
     678           0 :   aRv = SetURI(uri);
     679             : }
     680             : 
     681             : void
     682           1 : Location::GetProtocol(nsAString& aProtocol,
     683             :                       nsIPrincipal& aSubjectPrincipal,
     684             :                       ErrorResult& aRv)
     685             : {
     686           1 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     687           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     688           0 :     return;
     689             :   }
     690             : 
     691           1 :   aProtocol.SetLength(0);
     692             : 
     693           2 :   nsCOMPtr<nsIURI> uri;
     694           1 :   aRv = GetURI(getter_AddRefs(uri));
     695           1 :   if (NS_WARN_IF(aRv.Failed()) || !uri) {
     696           0 :     return;
     697             :   }
     698             : 
     699           2 :   nsAutoCString protocol;
     700             : 
     701           1 :   aRv = uri->GetScheme(protocol);
     702           1 :   if (NS_WARN_IF(aRv.Failed())) {
     703           0 :     return;
     704             :   }
     705             : 
     706           1 :   CopyASCIItoUTF16(protocol, aProtocol);
     707           1 :   aProtocol.Append(char16_t(':'));
     708             : }
     709             : 
     710             : void
     711           0 : Location::SetProtocol(const nsAString& aProtocol,
     712             :                       nsIPrincipal& aSubjectPrincipal,
     713             :                       ErrorResult& aRv)
     714             : {
     715           0 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     716           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     717           0 :     return;
     718             :   }
     719             : 
     720           0 :   nsCOMPtr<nsIURI> uri;
     721           0 :   aRv = GetWritableURI(getter_AddRefs(uri));
     722           0 :   if (NS_WARN_IF(aRv.Failed()) || !uri) {
     723           0 :     return;
     724             :   }
     725             : 
     726           0 :   nsAString::const_iterator start, end;
     727           0 :   aProtocol.BeginReading(start);
     728           0 :   aProtocol.EndReading(end);
     729           0 :   nsAString::const_iterator iter(start);
     730           0 :   Unused << FindCharInReadable(':', iter, end);
     731             : 
     732           0 :   nsresult rv = uri->SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter)));
     733           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     734             :     // Oh, I wish nsStandardURL returned NS_ERROR_MALFORMED_URI for _all_ the
     735             :     // malformed cases, not just some of them!
     736           0 :     aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
     737           0 :     return;
     738             :   }
     739             : 
     740           0 :   nsAutoCString newSpec;
     741           0 :   aRv = uri->GetSpec(newSpec);
     742           0 :   if (NS_WARN_IF(aRv.Failed())) {
     743           0 :     return;
     744             :   }
     745             :   // We may want a new URI class for the new URI, so recreate it:
     746           0 :   rv = NS_NewURI(getter_AddRefs(uri), newSpec);
     747           0 :   if (NS_FAILED(rv)) {
     748           0 :     if (rv == NS_ERROR_MALFORMED_URI) {
     749           0 :       rv = NS_ERROR_DOM_SYNTAX_ERR;
     750             :     }
     751             : 
     752           0 :     aRv.Throw(rv);
     753           0 :     return;
     754             :   }
     755             : 
     756             :   bool isHttp;
     757           0 :   aRv = uri->SchemeIs("http", &isHttp);
     758           0 :   if (NS_WARN_IF(aRv.Failed())) {
     759           0 :     return;
     760             :   }
     761             : 
     762             :   bool isHttps;
     763           0 :   aRv = uri->SchemeIs("https", &isHttps);
     764           0 :   if (NS_WARN_IF(aRv.Failed())) {
     765           0 :     return;
     766             :   }
     767             : 
     768           0 :   if (!isHttp && !isHttps) {
     769             :     // No-op, per spec.
     770           0 :     return;
     771             :   }
     772             : 
     773           0 :   aRv = SetURI(uri);
     774             : }
     775             : 
     776             : void
     777           1 : Location::GetSearch(nsAString& aSearch,
     778             :                     nsIPrincipal& aSubjectPrincipal,
     779             :                     ErrorResult& aRv)
     780             : {
     781           1 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     782           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     783           0 :     return;
     784             :   }
     785             : 
     786           1 :   aSearch.SetLength(0);
     787             : 
     788           2 :   nsCOMPtr<nsIURI> uri;
     789           1 :   nsresult result = NS_OK;
     790             : 
     791           1 :   result = GetURI(getter_AddRefs(uri));
     792             : 
     793           2 :   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
     794             : 
     795           1 :   if (url) {
     796           2 :     nsAutoCString search;
     797             : 
     798           1 :     result = url->GetQuery(search);
     799             : 
     800           1 :     if (NS_SUCCEEDED(result) && !search.IsEmpty()) {
     801           0 :       aSearch.Assign(char16_t('?'));
     802           0 :       AppendUTF8toUTF16(search, aSearch);
     803             :     }
     804             :   }
     805             : }
     806             : 
     807             : void
     808           0 : Location::SetSearch(const nsAString& aSearch,
     809             :                     nsIPrincipal& aSubjectPrincipal,
     810             :                     ErrorResult& aRv)
     811             : {
     812           0 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     813           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     814           0 :     return;
     815             :   }
     816             : 
     817           0 :   nsCOMPtr<nsIURI> uri;
     818           0 :   aRv = GetWritableURI(getter_AddRefs(uri));
     819           0 :   nsCOMPtr<nsIURL> url(do_QueryInterface(uri));
     820           0 :   if (NS_WARN_IF(aRv.Failed()) || !url) {
     821           0 :     return;
     822             :   }
     823             : 
     824           0 :   aRv = url->SetQuery(NS_ConvertUTF16toUTF8(aSearch));
     825           0 :   if (NS_WARN_IF(aRv.Failed())) {
     826           0 :     return;
     827             :   }
     828             : 
     829           0 :   aRv = SetURI(uri);
     830             : }
     831             : 
     832             : nsresult
     833           0 : Location::Reload(bool aForceget)
     834             : {
     835           0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
     836           0 :   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(docShell));
     837           0 :   nsCOMPtr<nsPIDOMWindowOuter> window = docShell ? docShell->GetWindow()
     838           0 :                                                  : nullptr;
     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 = window->GetExtantDoc();
     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, eRestyle_Subtree);
     854             :     }
     855             : 
     856           0 :     return NS_OK;
     857             :   }
     858             : 
     859           0 :   if (!webNav) {
     860           0 :     return NS_ERROR_FAILURE;
     861             :   }
     862             : 
     863           0 :   uint32_t reloadFlags = nsIWebNavigation::LOAD_FLAGS_NONE;
     864             : 
     865           0 :   if (aForceget) {
     866           0 :     reloadFlags = nsIWebNavigation::LOAD_FLAGS_BYPASS_CACHE |
     867             :                   nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
     868             :   }
     869             : 
     870           0 :   nsresult rv = webNav->Reload(reloadFlags);
     871           0 :   if (rv == NS_BINDING_ABORTED) {
     872             :     // This happens when we attempt to reload a POST result and the user says
     873             :     // no at the "do you want to reload?" prompt.  Don't propagate this one
     874             :     // back to callers.
     875           0 :     rv = NS_OK;
     876             :   }
     877             : 
     878           0 :   return rv;
     879             : }
     880             : 
     881             : void
     882           0 : Location::Replace(const nsAString& aUrl,
     883             :                   nsIPrincipal& aSubjectPrincipal,
     884             :                   ErrorResult& aRv)
     885             : {
     886           0 :   if (JSContext *cx = nsContentUtils::GetCurrentJSContext()) {
     887           0 :     aRv = SetHrefWithContext(cx, aUrl, true);
     888           0 :     return;
     889             :   }
     890             : 
     891           0 :   nsAutoString oldHref;
     892           0 :   aRv = GetHref(oldHref);
     893           0 :   if (NS_WARN_IF(aRv.Failed())) {
     894           0 :     return;
     895             :   }
     896             : 
     897           0 :   nsCOMPtr<nsIURI> oldUri;
     898             : 
     899           0 :   aRv = NS_NewURI(getter_AddRefs(oldUri), oldHref);
     900           0 :   if (NS_WARN_IF(aRv.Failed())) {
     901           0 :     return;
     902             :   }
     903             : 
     904           0 :   aRv = SetHrefWithBase(aUrl, oldUri, true);
     905             : }
     906             : 
     907             : void
     908           0 : Location::Assign(const nsAString& aUrl,
     909             :                  nsIPrincipal& aSubjectPrincipal,
     910             :                  ErrorResult& aRv)
     911             : {
     912           0 :   if (!CallerSubsumes(&aSubjectPrincipal)) {
     913           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     914           0 :     return;
     915             :   }
     916             : 
     917           0 :   if (JSContext *cx = nsContentUtils::GetCurrentJSContext()) {
     918           0 :     aRv = SetHrefWithContext(cx, aUrl, false);
     919           0 :     return;
     920             :   }
     921             : 
     922           0 :   nsAutoString oldHref;
     923           0 :   aRv = GetHref(oldHref);
     924           0 :   if (NS_WARN_IF(aRv.Failed())) {
     925           0 :     return;
     926             :   }
     927             : 
     928           0 :   nsCOMPtr<nsIURI> oldUri;
     929           0 :   aRv = NS_NewURI(getter_AddRefs(oldUri), oldHref);
     930           0 :   if (NS_WARN_IF(aRv.Failed())) {
     931           0 :     return;
     932             :   }
     933             : 
     934           0 :   if (oldUri) {
     935           0 :     aRv = SetHrefWithBase(aUrl, oldUri, false);
     936             :   }
     937             : }
     938             : 
     939             : nsresult
     940           0 : Location::GetSourceBaseURL(JSContext* cx, nsIURI** sourceURL)
     941             : {
     942           0 :   *sourceURL = nullptr;
     943           0 :   nsIDocument* doc = GetEntryDocument();
     944             :   // If there's no entry document, we either have no Script Entry Point or one
     945             :   // that isn't a DOM Window.  This doesn't generally happen with the DOM, but
     946             :   // can sometimes happen with extension code in certain IPC configurations.  If
     947             :   // this happens, try falling back on the current document associated with the
     948             :   // docshell. If that fails, just return null and hope that the caller passed
     949             :   // an absolute URI.
     950           0 :   nsCOMPtr<nsIDocShell> docShell(do_QueryReferent(mDocShell));
     951           0 :   if (!doc && docShell) {
     952             :     nsCOMPtr<nsPIDOMWindowOuter> docShellWin =
     953           0 :       do_QueryInterface(docShell->GetScriptGlobalObject());
     954           0 :     if (docShellWin) {
     955           0 :       doc = docShellWin->GetDoc();
     956             :     }
     957             :   }
     958           0 :   NS_ENSURE_TRUE(doc, NS_OK);
     959           0 :   *sourceURL = doc->GetBaseURI().take();
     960           0 :   return NS_OK;
     961             : }
     962             : 
     963             : bool
     964           8 : Location::CallerSubsumes(nsIPrincipal* aSubjectPrincipal)
     965             : {
     966           8 :   MOZ_ASSERT(aSubjectPrincipal);
     967             : 
     968             :   // Get the principal associated with the location object.  Note that this is
     969             :   // the principal of the page which will actually be navigated, not the
     970             :   // principal of the Location object itself.  This is why we need this check
     971             :   // even though we only allow limited cross-origin access to Location objects
     972             :   // in general.
     973          16 :   nsCOMPtr<nsPIDOMWindowOuter> outer = mInnerWindow->GetOuterWindow();
     974           8 :   if (MOZ_UNLIKELY(!outer))
     975           0 :     return false;
     976          16 :   nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(outer);
     977           8 :   bool subsumes = false;
     978             :   nsresult rv =
     979           8 :     aSubjectPrincipal->SubsumesConsideringDomain(sop->GetPrincipal(),
     980          16 :                                                  &subsumes);
     981           8 :   NS_ENSURE_SUCCESS(rv, false);
     982           8 :   return subsumes;
     983             : }
     984             : 
     985             : JSObject*
     986           3 : Location::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     987             : {
     988           3 :   return LocationBinding::Wrap(aCx, this, aGivenProto);
     989             : }
     990             : 
     991             : } // dom namespace
     992             : } // mozilla namespace

Generated by: LCOV version 1.13