LCOV - code coverage report
Current view: top level - dom/jsurl - nsJSProtocolHandler.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 563 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 109 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim: set ts=4 sw=4 et tw=78: */
       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 "nsCOMPtr.h"
       8             : #include "jsapi.h"
       9             : #include "jswrapper.h"
      10             : #include "nsCRT.h"
      11             : #include "nsError.h"
      12             : #include "nsXPIDLString.h"
      13             : #include "nsReadableUtils.h"
      14             : #include "nsJSProtocolHandler.h"
      15             : #include "nsStringStream.h"
      16             : #include "nsNetUtil.h"
      17             : 
      18             : #include "nsIStreamListener.h"
      19             : #include "nsIComponentManager.h"
      20             : #include "nsIServiceManager.h"
      21             : #include "nsIURI.h"
      22             : #include "nsIScriptContext.h"
      23             : #include "nsIScriptGlobalObject.h"
      24             : #include "nsIPrincipal.h"
      25             : #include "nsIScriptSecurityManager.h"
      26             : #include "nsIInterfaceRequestor.h"
      27             : #include "nsIInterfaceRequestorUtils.h"
      28             : #include "nsIWindowMediator.h"
      29             : #include "nsPIDOMWindow.h"
      30             : #include "nsIConsoleService.h"
      31             : #include "nsXPIDLString.h"
      32             : #include "nsEscape.h"
      33             : #include "nsIWebNavigation.h"
      34             : #include "nsIDocShell.h"
      35             : #include "nsIContentViewer.h"
      36             : #include "nsIXPConnect.h"
      37             : #include "nsContentUtils.h"
      38             : #include "nsJSUtils.h"
      39             : #include "nsThreadUtils.h"
      40             : #include "nsIScriptChannel.h"
      41             : #include "nsIDocument.h"
      42             : #include "nsILoadInfo.h"
      43             : #include "nsIObjectInputStream.h"
      44             : #include "nsIObjectOutputStream.h"
      45             : #include "nsIWritablePropertyBag2.h"
      46             : #include "nsIContentSecurityPolicy.h"
      47             : #include "nsSandboxFlags.h"
      48             : #include "mozilla/dom/ScriptSettings.h"
      49             : #include "nsILoadInfo.h"
      50             : #include "nsContentSecurityManager.h"
      51             : 
      52             : #include "mozilla/ipc/URIUtils.h"
      53             : 
      54             : using mozilla::dom::AutoEntryScript;
      55             : 
      56             : static NS_DEFINE_CID(kJSURICID, NS_JSURI_CID);
      57             : 
      58             : class nsJSThunk : public nsIInputStream
      59             : {
      60             : public:
      61             :     nsJSThunk();
      62             : 
      63             :     NS_DECL_THREADSAFE_ISUPPORTS
      64           0 :     NS_FORWARD_SAFE_NSIINPUTSTREAM(mInnerStream)
      65             : 
      66             :     nsresult Init(nsIURI* uri);
      67             :     nsresult EvaluateScript(nsIChannel *aChannel,
      68             :                             PopupControlState aPopupState,
      69             :                             uint32_t aExecutionPolicy,
      70             :                             nsPIDOMWindowInner *aOriginalInnerWindow);
      71             : 
      72             : protected:
      73             :     virtual ~nsJSThunk();
      74             : 
      75             :     nsCOMPtr<nsIInputStream>    mInnerStream;
      76             :     nsCString                   mScript;
      77             :     nsCString                   mURL;
      78             : };
      79             : 
      80             : //
      81             : // nsISupports implementation...
      82             : //
      83           0 : NS_IMPL_ISUPPORTS(nsJSThunk, nsIInputStream)
      84             : 
      85             : 
      86           0 : nsJSThunk::nsJSThunk()
      87             : {
      88           0 : }
      89             : 
      90           0 : nsJSThunk::~nsJSThunk()
      91             : {
      92           0 : }
      93             : 
      94           0 : nsresult nsJSThunk::Init(nsIURI* uri)
      95             : {
      96           0 :     NS_ENSURE_ARG_POINTER(uri);
      97             : 
      98             :     // Get the script string to evaluate...
      99           0 :     nsresult rv = uri->GetPath(mScript);
     100           0 :     if (NS_FAILED(rv)) return rv;
     101             : 
     102             :     // Get the url.
     103           0 :     rv = uri->GetSpec(mURL);
     104           0 :     if (NS_FAILED(rv)) return rv;
     105             : 
     106           0 :     return NS_OK;
     107             : }
     108             : 
     109             : static bool
     110           0 : IsISO88591(const nsString& aString)
     111             : {
     112           0 :     for (nsString::const_char_iterator c = aString.BeginReading(),
     113           0 :                                    c_end = aString.EndReading();
     114           0 :          c < c_end; ++c) {
     115           0 :         if (*c > 255)
     116           0 :             return false;
     117             :     }
     118           0 :     return true;
     119             : }
     120             : 
     121             : static
     122           0 : nsIScriptGlobalObject* GetGlobalObject(nsIChannel* aChannel)
     123             : {
     124             :     // Get the global object owner from the channel
     125           0 :     nsCOMPtr<nsIDocShell> docShell;
     126           0 :     NS_QueryNotificationCallbacks(aChannel, docShell);
     127           0 :     if (!docShell) {
     128           0 :         NS_WARNING("Unable to get a docShell from the channel!");
     129           0 :         return nullptr;
     130             :     }
     131             : 
     132             :     // So far so good: get the script global from its docshell
     133           0 :     nsIScriptGlobalObject* global = docShell->GetScriptGlobalObject();
     134             : 
     135           0 :     NS_ASSERTION(global,
     136             :                  "Unable to get an nsIScriptGlobalObject from the "
     137             :                  "docShell!");
     138           0 :     return global;
     139             : }
     140             : 
     141           0 : nsresult nsJSThunk::EvaluateScript(nsIChannel *aChannel,
     142             :                                    PopupControlState aPopupState,
     143             :                                    uint32_t aExecutionPolicy,
     144             :                                    nsPIDOMWindowInner *aOriginalInnerWindow)
     145             : {
     146           0 :     if (aExecutionPolicy == nsIScriptChannel::NO_EXECUTION) {
     147             :         // Nothing to do here.
     148           0 :         return NS_ERROR_DOM_RETVAL_UNDEFINED;
     149             :     }
     150             : 
     151           0 :     NS_ENSURE_ARG_POINTER(aChannel);
     152             : 
     153             :     // Get principal of code for execution
     154           0 :     nsCOMPtr<nsISupports> owner;
     155           0 :     aChannel->GetOwner(getter_AddRefs(owner));
     156           0 :     nsCOMPtr<nsIPrincipal> principal = do_QueryInterface(owner);
     157           0 :     if (!principal) {
     158           0 :         nsCOMPtr<nsILoadInfo> loadInfo;
     159           0 :         aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
     160           0 :         if (loadInfo && loadInfo->GetForceInheritPrincipal()) {
     161           0 :             principal = loadInfo->PrincipalToInherit();
     162           0 :             if (!principal) {
     163           0 :                 principal = loadInfo->TriggeringPrincipal();
     164             :             }
     165             :         } else {
     166             :             // No execution without a principal!
     167           0 :             NS_ASSERTION(!owner, "Non-principal owner?");
     168           0 :             NS_WARNING("No principal to execute JS with");
     169           0 :             return NS_ERROR_DOM_RETVAL_UNDEFINED;
     170             :         }
     171             :     }
     172             : 
     173             :     nsresult rv;
     174             : 
     175             :     // CSP check: javascript: URIs disabled unless "inline" scripts are
     176             :     // allowed.
     177           0 :     nsCOMPtr<nsIContentSecurityPolicy> csp;
     178           0 :     rv = principal->GetCsp(getter_AddRefs(csp));
     179           0 :     NS_ENSURE_SUCCESS(rv, rv);
     180           0 :     if (csp) {
     181           0 :         bool allowsInlineScript = true;
     182           0 :         rv = csp->GetAllowsInline(nsIContentPolicy::TYPE_SCRIPT,
     183           0 :                                   EmptyString(), // aNonce
     184             :                                   true,         // aParserCreated
     185           0 :                                   EmptyString(), // aContent
     186             :                                   0,             // aLineNumber
     187           0 :                                   &allowsInlineScript);
     188             : 
     189             :         //return early if inline scripts are not allowed
     190           0 :         if (!allowsInlineScript) {
     191           0 :           return NS_ERROR_DOM_RETVAL_UNDEFINED;
     192             :         }
     193             :     }
     194             : 
     195             :     // Get the global object we should be running on.
     196           0 :     nsIScriptGlobalObject* global = GetGlobalObject(aChannel);
     197           0 :     if (!global) {
     198           0 :         return NS_ERROR_FAILURE;
     199             :     }
     200             : 
     201             :     // Sandboxed document check: javascript: URI's are disabled
     202             :     // in a sandboxed document unless 'allow-scripts' was specified.
     203           0 :     nsIDocument* doc = aOriginalInnerWindow->GetExtantDoc();
     204           0 :     if (doc && doc->HasScriptsBlockedBySandbox()) {
     205           0 :         return NS_ERROR_DOM_RETVAL_UNDEFINED;
     206             :     }
     207             : 
     208             :     // Push our popup control state
     209           0 :     nsAutoPopupStatePusher popupStatePusher(aPopupState);
     210             : 
     211             :     // Make sure we still have the same inner window as we used to.
     212           0 :     nsCOMPtr<nsPIDOMWindowOuter> win = do_QueryInterface(global);
     213           0 :     nsPIDOMWindowInner *innerWin = win->GetCurrentInnerWindow();
     214             : 
     215           0 :     if (innerWin != aOriginalInnerWindow) {
     216           0 :         return NS_ERROR_UNEXPECTED;
     217             :     }
     218             : 
     219           0 :     nsCOMPtr<nsIScriptGlobalObject> innerGlobal = do_QueryInterface(innerWin);
     220             : 
     221           0 :     mozilla::DebugOnly<nsCOMPtr<nsIDOMWindow>> domWindow(do_QueryInterface(global, &rv));
     222           0 :     if (NS_FAILED(rv)) {
     223           0 :         return NS_ERROR_FAILURE;
     224             :     }
     225             : 
     226             :     // So far so good: get the script context from its owner.
     227           0 :     nsCOMPtr<nsIScriptContext> scriptContext = global->GetContext();
     228           0 :     if (!scriptContext)
     229           0 :         return NS_ERROR_FAILURE;
     230             : 
     231           0 :     nsAutoCString script(mScript);
     232             :     // Unescape the script
     233           0 :     NS_UnescapeURL(script);
     234             : 
     235             : 
     236           0 :     nsCOMPtr<nsIScriptSecurityManager> securityManager;
     237           0 :     securityManager = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv);
     238           0 :     if (NS_FAILED(rv))
     239           0 :         return rv;
     240             : 
     241             :     // New script entry point required, due to the "Create a script" step of
     242             :     // http://www.whatwg.org/specs/web-apps/current-work/#javascript-protocol
     243           0 :     nsAutoMicroTask mt;
     244           0 :     AutoEntryScript aes(innerGlobal, "javascript: URI", true);
     245           0 :     JSContext* cx = aes.cx();
     246           0 :     JS::Rooted<JSObject*> globalJSObject(cx, innerGlobal->GetGlobalJSObject());
     247           0 :     NS_ENSURE_TRUE(globalJSObject, NS_ERROR_UNEXPECTED);
     248             : 
     249             :     //-- Don't execute unless the script principal subsumes the
     250             :     //   principal of the context.
     251           0 :     nsIPrincipal* objectPrincipal = nsContentUtils::ObjectPrincipal(globalJSObject);
     252             : 
     253             :     bool subsumes;
     254           0 :     rv = principal->Subsumes(objectPrincipal, &subsumes);
     255           0 :     if (NS_FAILED(rv))
     256           0 :         return rv;
     257             : 
     258           0 :     if (!subsumes) {
     259           0 :         return NS_ERROR_DOM_RETVAL_UNDEFINED;
     260             :     }
     261             : 
     262             :     // Fail if someone tries to execute in a global with system principal.
     263           0 :     if (nsContentUtils::IsSystemPrincipal(objectPrincipal)) {
     264           0 :         return NS_ERROR_DOM_SECURITY_ERR;
     265             :     }
     266             : 
     267           0 :     JS::Rooted<JS::Value> v (cx, JS::UndefinedValue());
     268             :     // Finally, we have everything needed to evaluate the expression.
     269           0 :     JS::CompileOptions options(cx);
     270           0 :     options.setFileAndLine(mURL.get(), 1)
     271           0 :            .setVersion(JSVERSION_DEFAULT);
     272             :     {
     273           0 :         nsJSUtils::ExecutionContext exec(cx, globalJSObject);
     274           0 :         exec.SetCoerceToString(true);
     275           0 :         exec.CompileAndExec(options, NS_ConvertUTF8toUTF16(script));
     276           0 :         rv = exec.ExtractReturnValue(&v);
     277             :     }
     278             : 
     279           0 :     js::AssertSameCompartment(cx, v);
     280             : 
     281           0 :     if (NS_FAILED(rv) || !(v.isString() || v.isUndefined())) {
     282           0 :         return NS_ERROR_MALFORMED_URI;
     283           0 :     } else if (v.isUndefined()) {
     284           0 :         return NS_ERROR_DOM_RETVAL_UNDEFINED;
     285             :     } else {
     286           0 :         MOZ_ASSERT(rv != NS_SUCCESS_DOM_SCRIPT_EVALUATION_THREW,
     287             :                    "How did we get a non-undefined return value?");
     288           0 :         nsAutoJSString result;
     289           0 :         if (!result.init(cx, v)) {
     290           0 :             return NS_ERROR_OUT_OF_MEMORY;
     291             :         }
     292             : 
     293             :         char *bytes;
     294             :         uint32_t bytesLen;
     295           0 :         NS_NAMED_LITERAL_CSTRING(isoCharset, "windows-1252");
     296           0 :         NS_NAMED_LITERAL_CSTRING(utf8Charset, "UTF-8");
     297             :         const nsLiteralCString *charset;
     298           0 :         if (IsISO88591(result)) {
     299             :             // For compatibility, if the result is ISO-8859-1, we use
     300             :             // windows-1252, so that people can compatibly create images
     301             :             // using javascript: URLs.
     302           0 :             bytes = ToNewCString(result);
     303           0 :             bytesLen = result.Length();
     304           0 :             charset = &isoCharset;
     305             :         }
     306             :         else {
     307           0 :             bytes = ToNewUTF8String(result, &bytesLen);
     308           0 :             charset = &utf8Charset;
     309             :         }
     310           0 :         aChannel->SetContentCharset(*charset);
     311           0 :         if (bytes)
     312           0 :             rv = NS_NewByteInputStream(getter_AddRefs(mInnerStream),
     313             :                                        bytes, bytesLen,
     314             :                                        NS_ASSIGNMENT_ADOPT);
     315             :         else
     316           0 :             rv = NS_ERROR_OUT_OF_MEMORY;
     317             :     }
     318             : 
     319           0 :     return rv;
     320             : }
     321             : 
     322             : ////////////////////////////////////////////////////////////////////////////////
     323             : 
     324             : class nsJSChannel : public nsIChannel,
     325             :                     public nsIStreamListener,
     326             :                     public nsIScriptChannel,
     327             :                     public nsIPropertyBag2
     328             : {
     329             : public:
     330             :     nsJSChannel();
     331             : 
     332             :     NS_DECL_ISUPPORTS
     333             :     NS_DECL_NSIREQUEST
     334             :     NS_DECL_NSICHANNEL
     335             :     NS_DECL_NSIREQUESTOBSERVER
     336             :     NS_DECL_NSISTREAMLISTENER
     337             :     NS_DECL_NSISCRIPTCHANNEL
     338           0 :     NS_FORWARD_SAFE_NSIPROPERTYBAG(mPropertyBag)
     339           0 :     NS_FORWARD_SAFE_NSIPROPERTYBAG2(mPropertyBag)
     340             : 
     341             :     nsresult Init(nsIURI *aURI, nsILoadInfo* aLoadInfo);
     342             : 
     343             :     // Actually evaluate the script.
     344             :     void EvaluateScript();
     345             : 
     346             : protected:
     347             :     virtual ~nsJSChannel();
     348             : 
     349             :     nsresult StopAll();
     350             : 
     351             :     void NotifyListener();
     352             : 
     353             :     void CleanupStrongRefs();
     354             : 
     355             : protected:
     356             :     nsCOMPtr<nsIChannel>    mStreamChannel;
     357             :     nsCOMPtr<nsIPropertyBag2> mPropertyBag;
     358             :     nsCOMPtr<nsIStreamListener> mListener;  // Our final listener
     359             :     nsCOMPtr<nsPIDOMWindowInner> mOriginalInnerWindow;  // The inner window our load
     360             :                                                         // started against.
     361             :     // If we blocked onload on a document in AsyncOpen2, this is the document we
     362             :     // did it on.
     363             :     nsCOMPtr<nsIDocument>   mDocumentOnloadBlockedOn;
     364             : 
     365             :     nsresult mStatus; // Our status
     366             : 
     367             :     nsLoadFlags             mLoadFlags;
     368             :     nsLoadFlags             mActualLoadFlags; // See AsyncOpen2
     369             : 
     370             :     RefPtr<nsJSThunk>     mIOThunk;
     371             :     PopupControlState       mPopupState;
     372             :     uint32_t                mExecutionPolicy;
     373             :     bool                    mIsAsync;
     374             :     bool                    mIsActive;
     375             :     bool                    mOpenedStreamChannel;
     376             : };
     377             : 
     378           0 : nsJSChannel::nsJSChannel() :
     379             :     mStatus(NS_OK),
     380             :     mLoadFlags(LOAD_NORMAL),
     381             :     mActualLoadFlags(LOAD_NORMAL),
     382             :     mPopupState(openOverridden),
     383             :     mExecutionPolicy(NO_EXECUTION),
     384             :     mIsAsync(true),
     385             :     mIsActive(false),
     386           0 :     mOpenedStreamChannel(false)
     387             : {
     388           0 : }
     389             : 
     390           0 : nsJSChannel::~nsJSChannel()
     391             : {
     392           0 : }
     393             : 
     394           0 : nsresult nsJSChannel::StopAll()
     395             : {
     396           0 :     nsresult rv = NS_ERROR_UNEXPECTED;
     397           0 :     nsCOMPtr<nsIWebNavigation> webNav;
     398           0 :     NS_QueryNotificationCallbacks(mStreamChannel, webNav);
     399             : 
     400           0 :     NS_ASSERTION(webNav, "Can't get nsIWebNavigation from channel!");
     401           0 :     if (webNav) {
     402           0 :         rv = webNav->Stop(nsIWebNavigation::STOP_ALL);
     403             :     }
     404             : 
     405           0 :     return rv;
     406             : }
     407             : 
     408           0 : nsresult nsJSChannel::Init(nsIURI* aURI, nsILoadInfo* aLoadInfo)
     409             : {
     410           0 :     RefPtr<nsJSURI> jsURI;
     411           0 :     nsresult rv = aURI->QueryInterface(kJSURICID,
     412           0 :                                        getter_AddRefs(jsURI));
     413           0 :     NS_ENSURE_SUCCESS(rv, rv);
     414             : 
     415             :     // Create the nsIStreamIO layer used by the nsIStreamIOChannel.
     416           0 :     mIOThunk = new nsJSThunk();
     417             : 
     418             :     // Create a stock input stream channel...
     419             :     // Remember, until AsyncOpen is called, the script will not be evaluated
     420             :     // and the underlying Input Stream will not be created...
     421           0 :     nsCOMPtr<nsIChannel> channel;
     422           0 :     rv = NS_NewInputStreamChannelInternal(getter_AddRefs(channel),
     423             :                                           aURI,
     424             :                                           mIOThunk,
     425           0 :                                           NS_LITERAL_CSTRING("text/html"),
     426           0 :                                           EmptyCString(),
     427           0 :                                           aLoadInfo);
     428           0 :     NS_ENSURE_SUCCESS(rv, rv);
     429             : 
     430           0 :     rv = mIOThunk->Init(aURI);
     431           0 :     if (NS_SUCCEEDED(rv)) {
     432           0 :         mStreamChannel = channel;
     433           0 :         mPropertyBag = do_QueryInterface(channel);
     434             :         nsCOMPtr<nsIWritablePropertyBag2> writableBag =
     435           0 :             do_QueryInterface(channel);
     436           0 :         if (writableBag && jsURI->GetBaseURI()) {
     437           0 :             writableBag->SetPropertyAsInterface(NS_LITERAL_STRING("baseURI"),
     438           0 :                                                 jsURI->GetBaseURI());
     439             :         }
     440             :     }
     441             : 
     442           0 :     return rv;
     443             : }
     444             : 
     445             : NS_IMETHODIMP
     446           0 : nsJSChannel::GetIsDocument(bool *aIsDocument)
     447             : {
     448           0 :   return NS_GetIsDocumentChannel(this, aIsDocument);
     449             : }
     450             : 
     451             : //
     452             : // nsISupports implementation...
     453             : //
     454             : 
     455           0 : NS_IMPL_ISUPPORTS(nsJSChannel, nsIChannel, nsIRequest, nsIRequestObserver,
     456             :                   nsIStreamListener, nsIScriptChannel, nsIPropertyBag,
     457             :                   nsIPropertyBag2)
     458             : 
     459             : //
     460             : // nsIRequest implementation...
     461             : //
     462             : 
     463             : NS_IMETHODIMP
     464           0 : nsJSChannel::GetName(nsACString &aResult)
     465             : {
     466           0 :     return mStreamChannel->GetName(aResult);
     467             : }
     468             : 
     469             : NS_IMETHODIMP
     470           0 : nsJSChannel::IsPending(bool *aResult)
     471             : {
     472           0 :     *aResult = mIsActive;
     473           0 :     return NS_OK;
     474             : }
     475             : 
     476             : NS_IMETHODIMP
     477           0 : nsJSChannel::GetStatus(nsresult *aResult)
     478             : {
     479           0 :     if (NS_SUCCEEDED(mStatus) && mOpenedStreamChannel) {
     480           0 :         return mStreamChannel->GetStatus(aResult);
     481             :     }
     482             : 
     483           0 :     *aResult = mStatus;
     484             : 
     485           0 :     return NS_OK;
     486             : }
     487             : 
     488             : NS_IMETHODIMP
     489           0 : nsJSChannel::Cancel(nsresult aStatus)
     490             : {
     491           0 :     mStatus = aStatus;
     492             : 
     493           0 :     if (mOpenedStreamChannel) {
     494           0 :         mStreamChannel->Cancel(aStatus);
     495             :     }
     496             : 
     497           0 :     return NS_OK;
     498             : }
     499             : 
     500             : NS_IMETHODIMP
     501           0 : nsJSChannel::Suspend()
     502             : {
     503           0 :     return mStreamChannel->Suspend();
     504             : }
     505             : 
     506             : NS_IMETHODIMP
     507           0 : nsJSChannel::Resume()
     508             : {
     509           0 :     return mStreamChannel->Resume();
     510             : }
     511             : 
     512             : //
     513             : // nsIChannel implementation
     514             : //
     515             : 
     516             : NS_IMETHODIMP
     517           0 : nsJSChannel::GetOriginalURI(nsIURI * *aURI)
     518             : {
     519           0 :     return mStreamChannel->GetOriginalURI(aURI);
     520             : }
     521             : 
     522             : NS_IMETHODIMP
     523           0 : nsJSChannel::SetOriginalURI(nsIURI *aURI)
     524             : {
     525           0 :     return mStreamChannel->SetOriginalURI(aURI);
     526             : }
     527             : 
     528             : NS_IMETHODIMP
     529           0 : nsJSChannel::GetURI(nsIURI * *aURI)
     530             : {
     531           0 :     return mStreamChannel->GetURI(aURI);
     532             : }
     533             : 
     534             : NS_IMETHODIMP
     535           0 : nsJSChannel::Open(nsIInputStream **aResult)
     536             : {
     537           0 :     nsresult rv = mIOThunk->EvaluateScript(mStreamChannel, mPopupState,
     538             :                                            mExecutionPolicy,
     539           0 :                                            mOriginalInnerWindow);
     540           0 :     NS_ENSURE_SUCCESS(rv, rv);
     541             : 
     542           0 :     return mStreamChannel->Open(aResult);
     543             : }
     544             : 
     545             : NS_IMETHODIMP
     546           0 : nsJSChannel::Open2(nsIInputStream** aStream)
     547             : {
     548           0 :     nsCOMPtr<nsIStreamListener> listener;
     549           0 :     nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
     550           0 :     NS_ENSURE_SUCCESS(rv, rv);
     551           0 :     return Open(aStream);
     552             : }
     553             : 
     554             : NS_IMETHODIMP
     555           0 : nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
     556             : {
     557             : #ifdef DEBUG
     558             :     {
     559           0 :     nsCOMPtr<nsILoadInfo> loadInfo = nsIChannel::GetLoadInfo();
     560           0 :     MOZ_ASSERT(!loadInfo || loadInfo->GetSecurityMode() == 0 ||
     561             :                loadInfo->GetInitialSecurityCheckDone(),
     562             :                "security flags in loadInfo but asyncOpen2() not called");
     563             :     }
     564             : #endif
     565           0 :     MOZ_RELEASE_ASSERT(!aContext, "please call AsyncOpen2()");
     566             : 
     567           0 :     NS_ENSURE_ARG(aListener);
     568             : 
     569             :     // First make sure that we have a usable inner window; we'll want to make
     570             :     // sure that we execute against that inner and no other.
     571           0 :     nsIScriptGlobalObject* global = GetGlobalObject(this);
     572           0 :     if (!global) {
     573           0 :         return NS_ERROR_NOT_AVAILABLE;
     574             :     }
     575             : 
     576           0 :     nsCOMPtr<nsPIDOMWindowOuter> win(do_QueryInterface(global));
     577           0 :     NS_ASSERTION(win, "Our global is not a window??");
     578             : 
     579             :     // Make sure we create a new inner window if one doesn't already exist (see
     580             :     // bug 306630).
     581           0 :     mOriginalInnerWindow = win->EnsureInnerWindow();
     582           0 :     if (!mOriginalInnerWindow) {
     583           0 :         return NS_ERROR_NOT_AVAILABLE;
     584             :     }
     585             : 
     586           0 :     mListener = aListener;
     587             : 
     588           0 :     mIsActive = true;
     589             : 
     590             :     // Temporarily set the LOAD_BACKGROUND flag to suppress load group observer
     591             :     // notifications (and hence nsIWebProgressListener notifications) from
     592             :     // being dispatched.  This is required since we suppress LOAD_DOCUMENT_URI,
     593             :     // which means that the DocLoader would not generate document start and
     594             :     // stop notifications (see bug 257875).
     595           0 :     mActualLoadFlags = mLoadFlags;
     596           0 :     mLoadFlags |= LOAD_BACKGROUND;
     597             : 
     598             :     // Add the javascript channel to its loadgroup so that we know if
     599             :     // network loads were canceled or not...
     600           0 :     nsCOMPtr<nsILoadGroup> loadGroup;
     601           0 :     mStreamChannel->GetLoadGroup(getter_AddRefs(loadGroup));
     602           0 :     if (loadGroup) {
     603           0 :         nsresult rv = loadGroup->AddRequest(this, nullptr);
     604           0 :         if (NS_FAILED(rv)) {
     605           0 :             mIsActive = false;
     606           0 :             CleanupStrongRefs();
     607           0 :             return rv;
     608             :         }
     609             :     }
     610             : 
     611           0 :     mDocumentOnloadBlockedOn = mOriginalInnerWindow->GetExtantDoc();
     612           0 :     if (mDocumentOnloadBlockedOn) {
     613             :         // If we're a document channel, we need to actually block onload on our
     614             :         // _parent_ document.  This is because we don't actually set our
     615             :         // LOAD_DOCUMENT_URI flag, so a docloader we're loading in as the
     616             :         // document channel will claim to not be busy, and our parent's onload
     617             :         // could fire too early.
     618             :         nsLoadFlags loadFlags;
     619           0 :         mStreamChannel->GetLoadFlags(&loadFlags);
     620           0 :         if (loadFlags & LOAD_DOCUMENT_URI) {
     621             :             mDocumentOnloadBlockedOn =
     622           0 :                 mDocumentOnloadBlockedOn->GetParentDocument();
     623             :         }
     624             :     }
     625           0 :     if (mDocumentOnloadBlockedOn) {
     626           0 :         mDocumentOnloadBlockedOn->BlockOnload();
     627             :     }
     628             : 
     629             : 
     630           0 :     mPopupState = win->GetPopupControlState();
     631             : 
     632             :     void (nsJSChannel::*method)();
     633             :     const char* name;
     634           0 :     if (mIsAsync) {
     635             :         // post an event to do the rest
     636           0 :         method = &nsJSChannel::EvaluateScript;
     637           0 :         name = "nsJSChannel::EvaluateScript";
     638             :     } else {
     639           0 :         EvaluateScript();
     640           0 :         if (mOpenedStreamChannel) {
     641             :             // That will handle notifying things
     642           0 :             return NS_OK;
     643             :         }
     644             : 
     645           0 :         NS_ASSERTION(NS_FAILED(mStatus), "We should have failed _somehow_");
     646             : 
     647             :         // mStatus is going to be NS_ERROR_DOM_RETVAL_UNDEFINED if we didn't
     648             :         // have any content resulting from the execution and NS_BINDING_ABORTED
     649             :         // if something we did causes our own load to be stopped.  Return
     650             :         // success in those cases, and error out in all others.
     651           0 :         if (mStatus != NS_ERROR_DOM_RETVAL_UNDEFINED &&
     652           0 :             mStatus != NS_BINDING_ABORTED) {
     653             :             // Note that calling EvaluateScript() handled removing us from the
     654             :             // loadgroup and marking us as not active anymore.
     655           0 :             CleanupStrongRefs();
     656           0 :             return mStatus;
     657             :         }
     658             : 
     659             :         // We're returning success from asyncOpen2(), but we didn't open a
     660             :         // stream channel.  We'll have to notify ourselves, but make sure to do
     661             :         // it asynchronously.
     662           0 :         method = &nsJSChannel::NotifyListener;
     663           0 :         name = "nsJSChannel::NotifyListener";
     664             :     }
     665             : 
     666           0 :     nsresult rv = NS_DispatchToCurrentThread(
     667           0 :       mozilla::NewRunnableMethod(name, this, method));
     668             : 
     669           0 :     if (NS_FAILED(rv)) {
     670           0 :         loadGroup->RemoveRequest(this, nullptr, rv);
     671           0 :         mIsActive = false;
     672           0 :         CleanupStrongRefs();
     673             :     }
     674           0 :     return rv;
     675             : }
     676             : 
     677             : NS_IMETHODIMP
     678           0 : nsJSChannel::AsyncOpen2(nsIStreamListener *aListener)
     679             : {
     680           0 :   nsCOMPtr<nsIStreamListener> listener = aListener;
     681           0 :   nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
     682           0 :   NS_ENSURE_SUCCESS(rv, rv);
     683           0 :   return AsyncOpen(listener, nullptr);
     684             : }
     685             : 
     686             : void
     687           0 : nsJSChannel::EvaluateScript()
     688             : {
     689             :     // Synchronously execute the script...
     690             :     // mIsActive is used to indicate the the request is 'busy' during the
     691             :     // the script evaluation phase.  This means that IsPending() will
     692             :     // indicate the the request is busy while the script is executing...
     693             : 
     694             :     // Note that we want to be in the loadgroup and pending while we evaluate
     695             :     // the script, so that we find out if the loadgroup gets canceled by the
     696             :     // script execution (in which case we shouldn't pump out data even if the
     697             :     // script returns it).
     698             : 
     699           0 :     if (NS_SUCCEEDED(mStatus)) {
     700           0 :         nsresult rv = mIOThunk->EvaluateScript(mStreamChannel, mPopupState,
     701             :                                                mExecutionPolicy,
     702           0 :                                                mOriginalInnerWindow);
     703             : 
     704             :         // Note that evaluation may have canceled us, so recheck mStatus again
     705           0 :         if (NS_FAILED(rv) && NS_SUCCEEDED(mStatus)) {
     706           0 :             mStatus = rv;
     707             :         }
     708             :     }
     709             : 
     710             :     // Remove the javascript channel from its loadgroup...
     711           0 :     nsCOMPtr<nsILoadGroup> loadGroup;
     712           0 :     mStreamChannel->GetLoadGroup(getter_AddRefs(loadGroup));
     713           0 :     if (loadGroup) {
     714           0 :         loadGroup->RemoveRequest(this, nullptr, mStatus);
     715             :     }
     716             : 
     717             :     // Reset load flags to their original value...
     718           0 :     mLoadFlags = mActualLoadFlags;
     719             : 
     720             :     // We're no longer active, it's now up to the stream channel to do
     721             :     // the loading, if needed.
     722           0 :     mIsActive = false;
     723             : 
     724           0 :     if (NS_FAILED(mStatus)) {
     725           0 :         if (mIsAsync) {
     726           0 :             NotifyListener();
     727             :         }
     728           0 :         return;
     729             :     }
     730             : 
     731             :     // EvaluateScript() succeeded, and we were not canceled, that
     732             :     // means there's data to parse as a result of evaluating the
     733             :     // script.
     734             : 
     735             :     // Get the stream channels load flags (!= mLoadFlags).
     736             :     nsLoadFlags loadFlags;
     737           0 :     mStreamChannel->GetLoadFlags(&loadFlags);
     738             : 
     739             :     uint32_t disposition;
     740           0 :     if (NS_FAILED(mStreamChannel->GetContentDisposition(&disposition)))
     741           0 :         disposition = nsIChannel::DISPOSITION_INLINE;
     742           0 :     if (loadFlags & LOAD_DOCUMENT_URI && disposition != nsIChannel::DISPOSITION_ATTACHMENT) {
     743             :         // We're loaded as the document channel and not expecting to download
     744             :         // the result. If we go on, we'll blow away the current document. Make
     745             :         // sure that's ok. If so, stop all pending network loads.
     746             : 
     747           0 :         nsCOMPtr<nsIDocShell> docShell;
     748           0 :         NS_QueryNotificationCallbacks(mStreamChannel, docShell);
     749           0 :         if (docShell) {
     750           0 :             nsCOMPtr<nsIContentViewer> cv;
     751           0 :             docShell->GetContentViewer(getter_AddRefs(cv));
     752             : 
     753           0 :             if (cv) {
     754             :                 bool okToUnload;
     755             : 
     756           0 :                 if (NS_SUCCEEDED(cv->PermitUnload(&okToUnload)) &&
     757           0 :                     !okToUnload) {
     758             :                     // The user didn't want to unload the current
     759             :                     // page, translate this into an undefined
     760             :                     // return from the javascript: URL...
     761           0 :                     mStatus = NS_ERROR_DOM_RETVAL_UNDEFINED;
     762             :                 }
     763             :             }
     764             :         }
     765             : 
     766           0 :         if (NS_SUCCEEDED(mStatus)) {
     767           0 :             mStatus = StopAll();
     768             :         }
     769             :     }
     770             : 
     771           0 :     if (NS_FAILED(mStatus)) {
     772           0 :         if (mIsAsync) {
     773           0 :             NotifyListener();
     774             :         }
     775           0 :         return;
     776             :     }
     777             : 
     778           0 :     mStatus = mStreamChannel->AsyncOpen2(this);
     779           0 :     if (NS_SUCCEEDED(mStatus)) {
     780             :         // mStreamChannel will call OnStartRequest and OnStopRequest on
     781             :         // us, so we'll be sure to call them on our listener.
     782           0 :         mOpenedStreamChannel = true;
     783             : 
     784             :         // Now readd ourselves to the loadgroup so we can receive
     785             :         // cancellation notifications.
     786           0 :         mIsActive = true;
     787           0 :         if (loadGroup) {
     788           0 :             mStatus = loadGroup->AddRequest(this, nullptr);
     789             : 
     790             :             // If AddRequest failed, that's OK.  The key is to make sure we get
     791             :             // cancelled if needed, and that call just canceled us if it
     792             :             // failed.  We'll still get notified by the stream channel when it
     793             :             // finishes.
     794             :         }
     795             : 
     796           0 :     } else if (mIsAsync) {
     797           0 :         NotifyListener();
     798             :     }
     799             : 
     800           0 :     return;
     801             : }
     802             : 
     803             : void
     804           0 : nsJSChannel::NotifyListener()
     805             : {
     806           0 :     mListener->OnStartRequest(this, nullptr);
     807           0 :     mListener->OnStopRequest(this, nullptr, mStatus);
     808             : 
     809           0 :     CleanupStrongRefs();
     810           0 : }
     811             : 
     812             : void
     813           0 : nsJSChannel::CleanupStrongRefs()
     814             : {
     815           0 :     mListener = nullptr;
     816           0 :     mOriginalInnerWindow = nullptr;
     817           0 :     if (mDocumentOnloadBlockedOn) {
     818           0 :         mDocumentOnloadBlockedOn->UnblockOnload(false);
     819           0 :         mDocumentOnloadBlockedOn = nullptr;
     820             :     }
     821           0 : }
     822             : 
     823             : NS_IMETHODIMP
     824           0 : nsJSChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
     825             : {
     826           0 :     *aLoadFlags = mLoadFlags;
     827             : 
     828           0 :     return NS_OK;
     829             : }
     830             : 
     831             : NS_IMETHODIMP
     832           0 : nsJSChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
     833             : {
     834             :     // Figure out whether the LOAD_BACKGROUND bit in aLoadFlags is
     835             :     // actually right.
     836           0 :     bool bogusLoadBackground = false;
     837           0 :     if (mIsActive && !(mActualLoadFlags & LOAD_BACKGROUND) &&
     838           0 :         (aLoadFlags & LOAD_BACKGROUND)) {
     839             :         // We're getting a LOAD_BACKGROUND, but it's probably just our own fake
     840             :         // flag being mirrored to us.  The one exception is if our loadgroup is
     841             :         // LOAD_BACKGROUND.
     842           0 :         bool loadGroupIsBackground = false;
     843           0 :         nsCOMPtr<nsILoadGroup> loadGroup;
     844           0 :         mStreamChannel->GetLoadGroup(getter_AddRefs(loadGroup));
     845           0 :         if (loadGroup) {
     846             :             nsLoadFlags loadGroupFlags;
     847           0 :             loadGroup->GetLoadFlags(&loadGroupFlags);
     848           0 :             loadGroupIsBackground = ((loadGroupFlags & LOAD_BACKGROUND) != 0);
     849             :         }
     850           0 :         bogusLoadBackground = !loadGroupIsBackground;
     851             :     }
     852             : 
     853             :     // Classifying a javascript: URI doesn't help us, and requires
     854             :     // NSS to boot, which we don't have in content processes.  See
     855             :     // https://bugzilla.mozilla.org/show_bug.cgi?id=617838.
     856           0 :     aLoadFlags &= ~LOAD_CLASSIFY_URI;
     857             : 
     858             :     // Since the javascript channel is never the actual channel that
     859             :     // any data is loaded through, don't ever set the
     860             :     // LOAD_DOCUMENT_URI flag on it, since that could lead to two
     861             :     // 'document channels' in the loadgroup if a javascript: URL is
     862             :     // loaded while a document is being loaded in the same window.
     863             : 
     864             :     // XXXbz this, and a whole lot of other hackery, could go away if we'd just
     865             :     // cancel the current document load on javascript: load start like IE does.
     866             : 
     867           0 :     mLoadFlags = aLoadFlags & ~LOAD_DOCUMENT_URI;
     868             : 
     869           0 :     if (bogusLoadBackground) {
     870           0 :         aLoadFlags = aLoadFlags & ~LOAD_BACKGROUND;
     871             :     }
     872             : 
     873           0 :     mActualLoadFlags = aLoadFlags;
     874             : 
     875             :     // ... but the underlying stream channel should get this bit, if
     876             :     // set, since that'll be the real document channel if the
     877             :     // javascript: URL generated data.
     878             : 
     879           0 :     return mStreamChannel->SetLoadFlags(aLoadFlags);
     880             : }
     881             : 
     882             : NS_IMETHODIMP
     883           0 : nsJSChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
     884             : {
     885           0 :     return mStreamChannel->GetLoadGroup(aLoadGroup);
     886             : }
     887             : 
     888             : NS_IMETHODIMP
     889           0 : nsJSChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
     890             : {
     891           0 :     if (aLoadGroup) {
     892             :         bool streamPending;
     893           0 :         nsresult rv = mStreamChannel->IsPending(&streamPending);
     894           0 :         NS_ENSURE_SUCCESS(rv, rv);
     895             : 
     896           0 :         if (streamPending) {
     897           0 :             nsCOMPtr<nsILoadGroup> curLoadGroup;
     898           0 :             mStreamChannel->GetLoadGroup(getter_AddRefs(curLoadGroup));
     899             : 
     900           0 :             if (aLoadGroup != curLoadGroup) {
     901             :                 // Move the stream channel to our new loadgroup.  Make sure to
     902             :                 // add it before removing it, so that we don't trigger onload
     903             :                 // by accident.
     904           0 :                 aLoadGroup->AddRequest(mStreamChannel, nullptr);
     905           0 :                 if (curLoadGroup) {
     906           0 :                     curLoadGroup->RemoveRequest(mStreamChannel, nullptr,
     907           0 :                                                 NS_BINDING_RETARGETED);
     908             :                 }
     909             :             }
     910             :         }
     911             :     }
     912             : 
     913           0 :     return mStreamChannel->SetLoadGroup(aLoadGroup);
     914             : }
     915             : 
     916             : NS_IMETHODIMP
     917           0 : nsJSChannel::GetOwner(nsISupports* *aOwner)
     918             : {
     919           0 :     return mStreamChannel->GetOwner(aOwner);
     920             : }
     921             : 
     922             : NS_IMETHODIMP
     923           0 : nsJSChannel::SetOwner(nsISupports* aOwner)
     924             : {
     925           0 :     return mStreamChannel->SetOwner(aOwner);
     926             : }
     927             : 
     928             : NS_IMETHODIMP
     929           0 : nsJSChannel::GetLoadInfo(nsILoadInfo* *aLoadInfo)
     930             : {
     931           0 :     return mStreamChannel->GetLoadInfo(aLoadInfo);
     932             : }
     933             : 
     934             : NS_IMETHODIMP
     935           0 : nsJSChannel::SetLoadInfo(nsILoadInfo* aLoadInfo)
     936             : {
     937           0 :     return mStreamChannel->SetLoadInfo(aLoadInfo);
     938             : }
     939             : 
     940             : NS_IMETHODIMP
     941           0 : nsJSChannel::GetNotificationCallbacks(nsIInterfaceRequestor* *aCallbacks)
     942             : {
     943           0 :     return mStreamChannel->GetNotificationCallbacks(aCallbacks);
     944             : }
     945             : 
     946             : NS_IMETHODIMP
     947           0 : nsJSChannel::SetNotificationCallbacks(nsIInterfaceRequestor* aCallbacks)
     948             : {
     949           0 :     return mStreamChannel->SetNotificationCallbacks(aCallbacks);
     950             : }
     951             : 
     952             : NS_IMETHODIMP
     953           0 : nsJSChannel::GetSecurityInfo(nsISupports * *aSecurityInfo)
     954             : {
     955           0 :     return mStreamChannel->GetSecurityInfo(aSecurityInfo);
     956             : }
     957             : 
     958             : NS_IMETHODIMP
     959           0 : nsJSChannel::GetContentType(nsACString &aContentType)
     960             : {
     961           0 :     return mStreamChannel->GetContentType(aContentType);
     962             : }
     963             : 
     964             : NS_IMETHODIMP
     965           0 : nsJSChannel::SetContentType(const nsACString &aContentType)
     966             : {
     967           0 :     return mStreamChannel->SetContentType(aContentType);
     968             : }
     969             : 
     970             : NS_IMETHODIMP
     971           0 : nsJSChannel::GetContentCharset(nsACString &aContentCharset)
     972             : {
     973           0 :     return mStreamChannel->GetContentCharset(aContentCharset);
     974             : }
     975             : 
     976             : NS_IMETHODIMP
     977           0 : nsJSChannel::SetContentCharset(const nsACString &aContentCharset)
     978             : {
     979           0 :     return mStreamChannel->SetContentCharset(aContentCharset);
     980             : }
     981             : 
     982             : NS_IMETHODIMP
     983           0 : nsJSChannel::GetContentDisposition(uint32_t *aContentDisposition)
     984             : {
     985           0 :     return mStreamChannel->GetContentDisposition(aContentDisposition);
     986             : }
     987             : 
     988             : NS_IMETHODIMP
     989           0 : nsJSChannel::SetContentDisposition(uint32_t aContentDisposition)
     990             : {
     991           0 :     return mStreamChannel->SetContentDisposition(aContentDisposition);
     992             : }
     993             : 
     994             : NS_IMETHODIMP
     995           0 : nsJSChannel::GetContentDispositionFilename(nsAString &aContentDispositionFilename)
     996             : {
     997           0 :     return mStreamChannel->GetContentDispositionFilename(aContentDispositionFilename);
     998             : }
     999             : 
    1000             : NS_IMETHODIMP
    1001           0 : nsJSChannel::SetContentDispositionFilename(const nsAString &aContentDispositionFilename)
    1002             : {
    1003           0 :     return mStreamChannel->SetContentDispositionFilename(aContentDispositionFilename);
    1004             : }
    1005             : 
    1006             : NS_IMETHODIMP
    1007           0 : nsJSChannel::GetContentDispositionHeader(nsACString &aContentDispositionHeader)
    1008             : {
    1009           0 :     return mStreamChannel->GetContentDispositionHeader(aContentDispositionHeader);
    1010             : }
    1011             : 
    1012             : NS_IMETHODIMP
    1013           0 : nsJSChannel::GetContentLength(int64_t *aContentLength)
    1014             : {
    1015           0 :     return mStreamChannel->GetContentLength(aContentLength);
    1016             : }
    1017             : 
    1018             : NS_IMETHODIMP
    1019           0 : nsJSChannel::SetContentLength(int64_t aContentLength)
    1020             : {
    1021           0 :     return mStreamChannel->SetContentLength(aContentLength);
    1022             : }
    1023             : 
    1024             : NS_IMETHODIMP
    1025           0 : nsJSChannel::OnStartRequest(nsIRequest* aRequest,
    1026             :                             nsISupports* aContext)
    1027             : {
    1028           0 :     NS_ENSURE_TRUE(aRequest == mStreamChannel, NS_ERROR_UNEXPECTED);
    1029             : 
    1030           0 :     return mListener->OnStartRequest(this, aContext);
    1031             : }
    1032             : 
    1033             : NS_IMETHODIMP
    1034           0 : nsJSChannel::OnDataAvailable(nsIRequest* aRequest,
    1035             :                              nsISupports* aContext,
    1036             :                              nsIInputStream* aInputStream,
    1037             :                              uint64_t aOffset,
    1038             :                              uint32_t aCount)
    1039             : {
    1040           0 :     NS_ENSURE_TRUE(aRequest == mStreamChannel, NS_ERROR_UNEXPECTED);
    1041             : 
    1042           0 :     return mListener->OnDataAvailable(this, aContext, aInputStream, aOffset,
    1043           0 :                                       aCount);
    1044             : }
    1045             : 
    1046             : NS_IMETHODIMP
    1047           0 : nsJSChannel::OnStopRequest(nsIRequest* aRequest,
    1048             :                            nsISupports* aContext,
    1049             :                            nsresult aStatus)
    1050             : {
    1051           0 :     NS_ENSURE_TRUE(aRequest == mStreamChannel, NS_ERROR_UNEXPECTED);
    1052             : 
    1053           0 :     nsCOMPtr<nsIStreamListener> listener = mListener;
    1054             : 
    1055           0 :     CleanupStrongRefs();
    1056             : 
    1057             :     // Make sure aStatus matches what GetStatus() returns
    1058           0 :     if (NS_FAILED(mStatus)) {
    1059           0 :         aStatus = mStatus;
    1060             :     }
    1061             : 
    1062           0 :     nsresult rv = listener->OnStopRequest(this, aContext, aStatus);
    1063             : 
    1064           0 :     nsCOMPtr<nsILoadGroup> loadGroup;
    1065           0 :     mStreamChannel->GetLoadGroup(getter_AddRefs(loadGroup));
    1066           0 :     if (loadGroup) {
    1067           0 :         loadGroup->RemoveRequest(this, nullptr, mStatus);
    1068             :     }
    1069             : 
    1070           0 :     mIsActive = false;
    1071             : 
    1072           0 :     return rv;
    1073             : }
    1074             : 
    1075             : NS_IMETHODIMP
    1076           0 : nsJSChannel::SetExecutionPolicy(uint32_t aPolicy)
    1077             : {
    1078           0 :     NS_ENSURE_ARG(aPolicy <= EXECUTE_NORMAL);
    1079             : 
    1080           0 :     mExecutionPolicy = aPolicy;
    1081           0 :     return NS_OK;
    1082             : }
    1083             : 
    1084             : NS_IMETHODIMP
    1085           0 : nsJSChannel::GetExecutionPolicy(uint32_t* aPolicy)
    1086             : {
    1087           0 :     *aPolicy = mExecutionPolicy;
    1088           0 :     return NS_OK;
    1089             : }
    1090             : 
    1091             : NS_IMETHODIMP
    1092           0 : nsJSChannel::SetExecuteAsync(bool aIsAsync)
    1093             : {
    1094           0 :     if (!mIsActive) {
    1095           0 :         mIsAsync = aIsAsync;
    1096             :     }
    1097             :     // else ignore this call
    1098           0 :     NS_WARNING_ASSERTION(!mIsActive,
    1099             :                          "Calling SetExecuteAsync on active channel?");
    1100             : 
    1101           0 :     return NS_OK;
    1102             : }
    1103             : 
    1104             : NS_IMETHODIMP
    1105           0 : nsJSChannel::GetExecuteAsync(bool* aIsAsync)
    1106             : {
    1107           0 :     *aIsAsync = mIsAsync;
    1108           0 :     return NS_OK;
    1109             : }
    1110             : 
    1111             : ////////////////////////////////////////////////////////////////////////////////
    1112             : 
    1113           0 : nsJSProtocolHandler::nsJSProtocolHandler()
    1114             : {
    1115           0 : }
    1116             : 
    1117             : nsresult
    1118           0 : nsJSProtocolHandler::Init()
    1119             : {
    1120           0 :     return NS_OK;
    1121             : }
    1122             : 
    1123           0 : nsJSProtocolHandler::~nsJSProtocolHandler()
    1124             : {
    1125           0 : }
    1126             : 
    1127           0 : NS_IMPL_ISUPPORTS(nsJSProtocolHandler, nsIProtocolHandler)
    1128             : 
    1129             : nsresult
    1130           0 : nsJSProtocolHandler::Create(nsISupports *aOuter, REFNSIID aIID, void **aResult)
    1131             : {
    1132           0 :     if (aOuter)
    1133           0 :         return NS_ERROR_NO_AGGREGATION;
    1134             : 
    1135           0 :     nsJSProtocolHandler* ph = new nsJSProtocolHandler();
    1136           0 :     NS_ADDREF(ph);
    1137           0 :     nsresult rv = ph->Init();
    1138           0 :     if (NS_SUCCEEDED(rv)) {
    1139           0 :         rv = ph->QueryInterface(aIID, aResult);
    1140             :     }
    1141           0 :     NS_RELEASE(ph);
    1142           0 :     return rv;
    1143             : }
    1144             : 
    1145             : nsresult
    1146           0 : nsJSProtocolHandler::EnsureUTF8Spec(const nsCString& aSpec, const char *aCharset,
    1147             :                                     nsACString &aUTF8Spec)
    1148             : {
    1149           0 :   aUTF8Spec.Truncate();
    1150             : 
    1151             :   nsresult rv;
    1152             : 
    1153           0 :   if (!mTextToSubURI) {
    1154           0 :     mTextToSubURI = do_GetService(NS_ITEXTTOSUBURI_CONTRACTID, &rv);
    1155           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1156             :   }
    1157           0 :   nsAutoString uStr;
    1158           0 :   rv = mTextToSubURI->UnEscapeNonAsciiURI(nsDependentCString(aCharset), aSpec, uStr);
    1159           0 :   NS_ENSURE_SUCCESS(rv, rv);
    1160             : 
    1161           0 :   if (!IsASCII(uStr)) {
    1162           0 :     rv = NS_EscapeURL(NS_ConvertUTF16toUTF8(uStr),
    1163             :                       esc_AlwaysCopy | esc_OnlyNonASCII, aUTF8Spec,
    1164             :                       mozilla::fallible);
    1165           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1166             :   }
    1167             : 
    1168           0 :   return NS_OK;
    1169             : }
    1170             : 
    1171             : ////////////////////////////////////////////////////////////////////////////////
    1172             : // nsIProtocolHandler methods:
    1173             : 
    1174             : NS_IMETHODIMP
    1175           0 : nsJSProtocolHandler::GetScheme(nsACString &result)
    1176             : {
    1177           0 :     result = "javascript";
    1178           0 :     return NS_OK;
    1179             : }
    1180             : 
    1181             : NS_IMETHODIMP
    1182           0 : nsJSProtocolHandler::GetDefaultPort(int32_t *result)
    1183             : {
    1184           0 :     *result = -1;        // no port for javascript: URLs
    1185           0 :     return NS_OK;
    1186             : }
    1187             : 
    1188             : NS_IMETHODIMP
    1189           0 : nsJSProtocolHandler::GetProtocolFlags(uint32_t *result)
    1190             : {
    1191           0 :     *result = URI_NORELATIVE | URI_NOAUTH | URI_INHERITS_SECURITY_CONTEXT |
    1192             :         URI_LOADABLE_BY_ANYONE | URI_NON_PERSISTABLE | URI_OPENING_EXECUTES_SCRIPT;
    1193           0 :     return NS_OK;
    1194             : }
    1195             : 
    1196             : NS_IMETHODIMP
    1197           0 : nsJSProtocolHandler::NewURI(const nsACString &aSpec,
    1198             :                             const char *aCharset,
    1199             :                             nsIURI *aBaseURI,
    1200             :                             nsIURI **result)
    1201             : {
    1202             :     nsresult rv;
    1203             : 
    1204             :     // javascript: URLs (currently) have no additional structure beyond that
    1205             :     // provided by standard URLs, so there is no "outer" object given to
    1206             :     // CreateInstance.
    1207             : 
    1208           0 :     nsCOMPtr<nsIURI> url = new nsJSURI(aBaseURI);
    1209             : 
    1210           0 :     if (!aCharset || !nsCRT::strcasecmp("UTF-8", aCharset))
    1211           0 :       rv = url->SetSpec(aSpec);
    1212             :     else {
    1213           0 :       nsAutoCString utf8Spec;
    1214           0 :       rv = EnsureUTF8Spec(PromiseFlatCString(aSpec), aCharset, utf8Spec);
    1215           0 :       if (NS_SUCCEEDED(rv)) {
    1216           0 :         if (utf8Spec.IsEmpty())
    1217           0 :           rv = url->SetSpec(aSpec);
    1218             :         else
    1219           0 :           rv = url->SetSpec(utf8Spec);
    1220             :       }
    1221             :     }
    1222             : 
    1223           0 :     if (NS_FAILED(rv)) {
    1224           0 :         return rv;
    1225             :     }
    1226             : 
    1227           0 :     url.forget(result);
    1228           0 :     return rv;
    1229             : }
    1230             : 
    1231             : NS_IMETHODIMP
    1232           0 : nsJSProtocolHandler::NewChannel2(nsIURI* uri,
    1233             :                                  nsILoadInfo* aLoadInfo,
    1234             :                                  nsIChannel** result)
    1235             : {
    1236             :     nsresult rv;
    1237             : 
    1238           0 :     NS_ENSURE_ARG_POINTER(uri);
    1239           0 :     RefPtr<nsJSChannel> channel = new nsJSChannel();
    1240           0 :     if (!channel) {
    1241           0 :         return NS_ERROR_OUT_OF_MEMORY;
    1242             :     }
    1243             : 
    1244           0 :     rv = channel->Init(uri, aLoadInfo);
    1245           0 :     NS_ENSURE_SUCCESS(rv, rv);
    1246             : 
    1247           0 :     if (NS_SUCCEEDED(rv)) {
    1248           0 :         channel.forget(result);
    1249             :     }
    1250           0 :     return rv;
    1251             : }
    1252             : 
    1253             : NS_IMETHODIMP
    1254           0 : nsJSProtocolHandler::NewChannel(nsIURI* uri, nsIChannel* *result)
    1255             : {
    1256           0 :     return NewChannel2(uri, nullptr, result);
    1257             : }
    1258             : 
    1259             : NS_IMETHODIMP
    1260           0 : nsJSProtocolHandler::AllowPort(int32_t port, const char *scheme, bool *_retval)
    1261             : {
    1262             :     // don't override anything.
    1263           0 :     *_retval = false;
    1264           0 :     return NS_OK;
    1265             : }
    1266             : 
    1267             : ////////////////////////////////////////////////////////////
    1268             : // nsJSURI implementation
    1269             : static NS_DEFINE_CID(kThisSimpleURIImplementationCID,
    1270             :                      NS_THIS_SIMPLEURI_IMPLEMENTATION_CID);
    1271             : 
    1272             : 
    1273           0 : NS_IMPL_ADDREF_INHERITED(nsJSURI, mozilla::net::nsSimpleURI)
    1274           0 : NS_IMPL_RELEASE_INHERITED(nsJSURI, mozilla::net::nsSimpleURI)
    1275             : 
    1276           0 : NS_INTERFACE_MAP_BEGIN(nsJSURI)
    1277           0 :   if (aIID.Equals(kJSURICID))
    1278           0 :       foundInterface = static_cast<nsIURI*>(this);
    1279           0 :   else if (aIID.Equals(kThisSimpleURIImplementationCID)) {
    1280             :       // Need to return explicitly here, because if we just set foundInterface
    1281             :       // to null the NS_INTERFACE_MAP_END_INHERITING will end up calling into
    1282             :       // nsSimplURI::QueryInterface and finding something for this CID.
    1283           0 :       *aInstancePtr = nullptr;
    1284           0 :       return NS_NOINTERFACE;
    1285             :   }
    1286             :   else
    1287           0 : NS_INTERFACE_MAP_END_INHERITING(mozilla::net::nsSimpleURI)
    1288             : 
    1289             : // nsISerializable methods:
    1290             : 
    1291             : NS_IMETHODIMP
    1292           0 : nsJSURI::Read(nsIObjectInputStream* aStream)
    1293             : {
    1294           0 :     nsresult rv = mozilla::net::nsSimpleURI::Read(aStream);
    1295           0 :     if (NS_FAILED(rv)) return rv;
    1296             : 
    1297             :     bool haveBase;
    1298           0 :     rv = aStream->ReadBoolean(&haveBase);
    1299           0 :     if (NS_FAILED(rv)) return rv;
    1300             : 
    1301           0 :     if (haveBase) {
    1302           0 :         nsCOMPtr<nsISupports> supports;
    1303           0 :         rv = aStream->ReadObject(true, getter_AddRefs(supports));
    1304           0 :         if (NS_FAILED(rv)) return rv;
    1305           0 :         mBaseURI = do_QueryInterface(supports);
    1306             :     }
    1307             : 
    1308           0 :     return NS_OK;
    1309             : }
    1310             : 
    1311             : NS_IMETHODIMP
    1312           0 : nsJSURI::Write(nsIObjectOutputStream* aStream)
    1313             : {
    1314           0 :     nsresult rv = mozilla::net::nsSimpleURI::Write(aStream);
    1315           0 :     if (NS_FAILED(rv)) return rv;
    1316             : 
    1317           0 :     rv = aStream->WriteBoolean(mBaseURI != nullptr);
    1318           0 :     if (NS_FAILED(rv)) return rv;
    1319             : 
    1320           0 :     if (mBaseURI) {
    1321           0 :         rv = aStream->WriteObject(mBaseURI, true);
    1322           0 :         if (NS_FAILED(rv)) return rv;
    1323             :     }
    1324             : 
    1325           0 :     return NS_OK;
    1326             : }
    1327             : 
    1328             : // nsIIPCSerializableURI
    1329             : void
    1330           0 : nsJSURI::Serialize(mozilla::ipc::URIParams& aParams)
    1331             : {
    1332             :     using namespace mozilla::ipc;
    1333             : 
    1334           0 :     JSURIParams jsParams;
    1335           0 :     URIParams simpleParams;
    1336             : 
    1337           0 :     mozilla::net::nsSimpleURI::Serialize(simpleParams);
    1338             : 
    1339           0 :     jsParams.simpleParams() = simpleParams;
    1340           0 :     if (mBaseURI) {
    1341           0 :         SerializeURI(mBaseURI, jsParams.baseURI());
    1342             :     } else {
    1343           0 :         jsParams.baseURI() = mozilla::void_t();
    1344             :     }
    1345             : 
    1346           0 :     aParams = jsParams;
    1347           0 : }
    1348             : 
    1349             : bool
    1350           0 : nsJSURI::Deserialize(const mozilla::ipc::URIParams& aParams)
    1351             : {
    1352             :     using namespace mozilla::ipc;
    1353             : 
    1354           0 :     if (aParams.type() != URIParams::TJSURIParams) {
    1355           0 :         NS_ERROR("Received unknown parameters from the other process!");
    1356           0 :         return false;
    1357             :     }
    1358             : 
    1359           0 :     const JSURIParams& jsParams = aParams.get_JSURIParams();
    1360           0 :     mozilla::net::nsSimpleURI::Deserialize(jsParams.simpleParams());
    1361             : 
    1362           0 :     if (jsParams.baseURI().type() != OptionalURIParams::Tvoid_t) {
    1363           0 :         mBaseURI = DeserializeURI(jsParams.baseURI().get_URIParams());
    1364             :     } else {
    1365           0 :         mBaseURI = nullptr;
    1366             :     }
    1367           0 :     return true;
    1368             : }
    1369             : 
    1370             : // nsSimpleURI methods:
    1371             : /* virtual */ mozilla::net::nsSimpleURI*
    1372           0 : nsJSURI::StartClone(mozilla::net::nsSimpleURI::RefHandlingEnum refHandlingMode,
    1373             :                     const nsACString& newRef)
    1374             : {
    1375           0 :     nsCOMPtr<nsIURI> baseClone;
    1376           0 :     if (mBaseURI) {
    1377             :       // Note: We preserve ref on *base* URI, regardless of ref handling mode.
    1378           0 :       nsresult rv = mBaseURI->Clone(getter_AddRefs(baseClone));
    1379           0 :       if (NS_FAILED(rv)) {
    1380           0 :         return nullptr;
    1381             :       }
    1382             :     }
    1383             : 
    1384           0 :     nsJSURI* url = new nsJSURI(baseClone);
    1385           0 :     SetRefOnClone(url, refHandlingMode, newRef);
    1386           0 :     return url;
    1387             : }
    1388             : 
    1389             : /* virtual */ nsresult
    1390           0 : nsJSURI::EqualsInternal(nsIURI* aOther,
    1391             :                         mozilla::net::nsSimpleURI::RefHandlingEnum aRefHandlingMode,
    1392             :                         bool* aResult)
    1393             : {
    1394           0 :     NS_ENSURE_ARG_POINTER(aOther);
    1395           0 :     NS_PRECONDITION(aResult, "null pointer for outparam");
    1396             : 
    1397           0 :     RefPtr<nsJSURI> otherJSURI;
    1398           0 :     nsresult rv = aOther->QueryInterface(kJSURICID,
    1399           0 :                                          getter_AddRefs(otherJSURI));
    1400           0 :     if (NS_FAILED(rv)) {
    1401           0 :         *aResult = false; // aOther is not a nsJSURI --> not equal.
    1402           0 :         return NS_OK;
    1403             :     }
    1404             : 
    1405             :     // Compare the member data that our base class knows about.
    1406           0 :     if (!mozilla::net::nsSimpleURI::EqualsInternal(otherJSURI, aRefHandlingMode)) {
    1407           0 :         *aResult = false;
    1408           0 :         return NS_OK;
    1409             :     }
    1410             : 
    1411             :     // Compare the piece of additional member data that we add to base class.
    1412           0 :     nsIURI* otherBaseURI = otherJSURI->GetBaseURI();
    1413             : 
    1414           0 :     if (mBaseURI) {
    1415             :         // (As noted in StartClone, we always honor refs on mBaseURI)
    1416           0 :         return mBaseURI->Equals(otherBaseURI, aResult);
    1417             :     }
    1418             : 
    1419           0 :     *aResult = !otherBaseURI;
    1420           0 :     return NS_OK;
    1421             : }
    1422             : 
    1423             : NS_IMETHODIMP
    1424           0 : nsJSURI::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc)
    1425             : {
    1426           0 :     *aClassIDNoAlloc = kJSURICID;
    1427           0 :     return NS_OK;
    1428             : }
    1429             : 

Generated by: LCOV version 1.13