netwerk/protocol/app/AppProtocolHandler.cpp

Thu, 15 Jan 2015 21:03:48 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 15 Jan 2015 21:03:48 +0100
branch
TOR_BUG_9701
changeset 11
deefc01c0e14
permissions
-rw-r--r--

Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim:set expandtab ts=2 sw=2 sts=2 cin: */
     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/. */
     7 #include "AppProtocolHandler.h"
     8 #include "nsBaseChannel.h"
     9 #include "nsJARChannel.h"
    10 #include "nsNetCID.h"
    11 #include "nsIAppsService.h"
    12 #include "nsCxPusher.h"
    13 #include "nsXULAppAPI.h"
    15 /**
    16   * This dummy channel implementation only provides enough functionality
    17   * to return a fake 404 error when the caller asks for an app:// URL
    18   * containing an unknown appId.
    19   */
    20 class DummyChannel : public nsIJARChannel
    21                           , nsRunnable
    22 {
    23 public:
    24   NS_DECL_ISUPPORTS
    25   NS_DECL_NSIREQUEST
    26   NS_DECL_NSICHANNEL
    27   NS_DECL_NSIJARCHANNEL
    29   DummyChannel();
    31   NS_IMETHODIMP Run();
    33 private:
    34   bool                        mPending;
    35   uint32_t                    mSuspendCount;
    36   nsCOMPtr<nsISupports>       mListenerContext;
    37   nsCOMPtr<nsIStreamListener> mListener;
    38   nsCOMPtr<nsILoadGroup>      mLoadGroup;
    39   nsLoadFlags                 mLoadFlags;
    40 };
    42 NS_IMPL_ISUPPORTS(DummyChannel, nsIRequest, nsIChannel, nsIJARChannel)
    44 DummyChannel::DummyChannel() : mPending(false)
    45                              , mSuspendCount(0)
    46                              , mLoadFlags(LOAD_NORMAL)
    47 {
    48 }
    50 NS_IMETHODIMP DummyChannel::GetName(nsACString &result)
    51 {
    52   result = "dummy_app_channel";
    53   return NS_OK;
    54 }
    56 NS_IMETHODIMP DummyChannel::GetStatus(nsresult *aStatus)
    57 {
    58   *aStatus = NS_ERROR_FILE_NOT_FOUND;
    59   return NS_OK;
    60 }
    62 NS_IMETHODIMP DummyChannel::IsPending(bool *aResult)
    63 {
    64   *aResult = mPending;
    65   return NS_OK;
    66 }
    68 NS_IMETHODIMP DummyChannel::Suspend()
    69 {
    70   mSuspendCount++;
    71   return NS_OK;
    72 }
    74 NS_IMETHODIMP DummyChannel::Resume()
    75 {
    76   if (mSuspendCount <= 0) {
    77     return NS_ERROR_UNEXPECTED;
    78   }
    80   if (--mSuspendCount == 0) {
    81     NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
    82   }
    83   return NS_OK;
    84 }
    86 NS_IMETHODIMP DummyChannel::Open(nsIInputStream**)
    87 {
    88   return NS_ERROR_NOT_IMPLEMENTED;
    89 }
    91 NS_IMETHODIMP DummyChannel::AsyncOpen(nsIStreamListener* aListener, nsISupports* aContext)
    92 {
    93   mListener = aListener;
    94   mListenerContext = aContext;
    95   mPending = true;
    97   if (mLoadGroup) {
    98     mLoadGroup->AddRequest(this, aContext);
    99   }
   101   if (mSuspendCount == 0) {
   102     NS_DispatchToMainThread(this, NS_DISPATCH_NORMAL);
   103   }
   105   return NS_OK;
   106 }
   108 // nsIJarChannel, needed for XHR to turn NS_ERROR_FILE_NOT_FOUND into
   109 // a 404 error.
   110 NS_IMETHODIMP DummyChannel::GetIsUnsafe(bool *aResult)
   111 {
   112   *aResult = false;
   113   return NS_OK;
   114 }
   116 NS_IMETHODIMP DummyChannel::SetAppURI(nsIURI *aURI)
   117 {
   118   return NS_ERROR_NOT_IMPLEMENTED;
   119 }
   121 NS_IMETHODIMP DummyChannel::Run()
   122 {
   123   nsresult rv = mListener->OnStartRequest(this, mListenerContext);
   124   NS_ENSURE_SUCCESS(rv, rv);
   125   mPending = false;
   126   rv = mListener->OnStopRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND);
   127   NS_ENSURE_SUCCESS(rv, rv);
   128   if (mLoadGroup) {
   129     mLoadGroup->RemoveRequest(this, mListenerContext, NS_ERROR_FILE_NOT_FOUND);
   130   }
   132   mListener = nullptr;
   133   mListenerContext = nullptr;
   134   rv = SetNotificationCallbacks(nullptr);
   135   NS_ENSURE_SUCCESS(rv, rv);
   137   return NS_OK;
   138 }
   140 NS_IMETHODIMP DummyChannel::Cancel(nsresult)
   141 {
   142   return NS_ERROR_NOT_IMPLEMENTED;
   143 }
   145 NS_IMETHODIMP DummyChannel::GetLoadGroup(nsILoadGroup* *aLoadGroup)
   146 {
   147   *aLoadGroup = mLoadGroup;
   148   NS_IF_ADDREF(*aLoadGroup);
   149   return NS_OK;
   150 }
   152 NS_IMETHODIMP DummyChannel::SetLoadGroup(nsILoadGroup* aLoadGroup)
   153 {
   154   mLoadGroup = aLoadGroup;
   155   return NS_OK;
   156 }
   158 NS_IMETHODIMP DummyChannel::GetLoadFlags(nsLoadFlags *aLoadFlags)
   159 {
   160   *aLoadFlags = mLoadFlags;
   161   return NS_OK;
   162 }
   164 NS_IMETHODIMP DummyChannel::SetLoadFlags(nsLoadFlags aLoadFlags)
   165 {
   166   mLoadFlags = aLoadFlags;
   167   return NS_OK;
   168 }
   170 NS_IMETHODIMP DummyChannel::GetOriginalURI(nsIURI**)
   171 {
   172   return NS_ERROR_NOT_IMPLEMENTED;
   173 }
   175 NS_IMETHODIMP DummyChannel::SetOriginalURI(nsIURI*)
   176 {
   177   return NS_ERROR_NOT_IMPLEMENTED;
   178 }
   180 NS_IMETHODIMP DummyChannel::GetOwner(nsISupports**)
   181 {
   182   return NS_ERROR_NOT_IMPLEMENTED;
   183 }
   185 NS_IMETHODIMP DummyChannel::SetOwner(nsISupports*)
   186 {
   187   return NS_ERROR_NOT_IMPLEMENTED;
   188 }
   190 NS_IMETHODIMP DummyChannel::GetNotificationCallbacks(nsIInterfaceRequestor**)
   191 {
   192   return NS_ERROR_NOT_IMPLEMENTED;
   193 }
   195 NS_IMETHODIMP DummyChannel::SetNotificationCallbacks(nsIInterfaceRequestor*)
   196 {
   197   return NS_ERROR_NOT_IMPLEMENTED;
   198 }
   200 NS_IMETHODIMP DummyChannel::GetSecurityInfo(nsISupports**)
   201 {
   202   return NS_ERROR_NOT_IMPLEMENTED;
   203 }
   205 NS_IMETHODIMP DummyChannel::GetContentType(nsACString&)
   206 {
   207   return NS_ERROR_NOT_IMPLEMENTED;
   208 }
   210 NS_IMETHODIMP DummyChannel::SetContentType(const nsACString&)
   211 {
   212   return NS_ERROR_NOT_IMPLEMENTED;
   213 }
   215 NS_IMETHODIMP DummyChannel::GetContentCharset(nsACString&)
   216 {
   217   return NS_ERROR_NOT_IMPLEMENTED;
   218 }
   220 NS_IMETHODIMP DummyChannel::SetContentCharset(const nsACString&)
   221 {
   222   return NS_ERROR_NOT_IMPLEMENTED;
   223 }
   225 NS_IMETHODIMP DummyChannel::GetContentLength(int64_t*)
   226 {
   227   return NS_ERROR_NOT_IMPLEMENTED;
   228 }
   230 NS_IMETHODIMP DummyChannel::SetContentLength(int64_t)
   231 {
   232   return NS_ERROR_NOT_IMPLEMENTED;
   233 }
   235 NS_IMETHODIMP DummyChannel::GetContentDisposition(uint32_t*)
   236 {
   237   return NS_ERROR_NOT_IMPLEMENTED;
   238 }
   240 NS_IMETHODIMP DummyChannel::SetContentDisposition(uint32_t)
   241 {
   242   return NS_ERROR_NOT_IMPLEMENTED;
   243 }
   245 NS_IMETHODIMP DummyChannel::GetURI(nsIURI**)
   246 {
   247   return NS_ERROR_NOT_IMPLEMENTED;
   248 }
   250 NS_IMETHODIMP DummyChannel::GetContentDispositionFilename(nsAString&)
   251 {
   252   return NS_ERROR_NOT_IMPLEMENTED;
   253 }
   255 NS_IMETHODIMP DummyChannel::SetContentDispositionFilename(nsAString const &)
   256 {
   257   return NS_ERROR_NOT_IMPLEMENTED;
   258 }
   260 NS_IMETHODIMP DummyChannel::GetContentDispositionHeader(nsACString&)
   261 {
   262   return NS_ERROR_NOT_IMPLEMENTED;
   263 }
   265 /**
   266   * app:// protocol implementation.
   267   */
   269 AppProtocolHandler::AppProtocolHandler() {
   270 }
   272 AppProtocolHandler::~AppProtocolHandler() {
   273   mAppInfoCache.Clear();
   274 }
   276 NS_IMPL_ISUPPORTS(AppProtocolHandler, nsIProtocolHandler)
   278 /* static */
   279 nsresult
   280 AppProtocolHandler::Create(nsISupports* aOuter,
   281                            const nsIID& aIID,
   282                            void* *aResult)
   283 {
   284   // Instantiate the service here since that intializes gJarHandler, which we
   285   // use indirectly (via our new JarChannel) in NewChannel.
   286   nsCOMPtr<nsIProtocolHandler> jarInitializer(
   287     do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "jar"));
   288   AppProtocolHandler* ph = new AppProtocolHandler();
   289   if (ph == nullptr) {
   290     return NS_ERROR_OUT_OF_MEMORY;
   291   }
   292   NS_ADDREF(ph);
   293   nsresult rv = ph->QueryInterface(aIID, aResult);
   294   NS_RELEASE(ph);
   295   return rv;
   296 }
   298 NS_IMETHODIMP
   299 AppProtocolHandler::GetScheme(nsACString &aResult)
   300 {
   301   aResult.AssignLiteral("app");
   302   return NS_OK;
   303 }
   305 NS_IMETHODIMP
   306 AppProtocolHandler::GetDefaultPort(int32_t *aResult)
   307 {
   308   // No ports for the app protocol.
   309   *aResult = -1;
   310   return NS_OK;
   311 }
   313 NS_IMETHODIMP
   314 AppProtocolHandler::GetProtocolFlags(uint32_t *aResult)
   315 {
   316   *aResult = URI_NOAUTH |
   317              URI_DANGEROUS_TO_LOAD |
   318              URI_CROSS_ORIGIN_NEEDS_WEBAPPS_PERM;
   319   return NS_OK;
   320 }
   322 NS_IMETHODIMP
   323 AppProtocolHandler::NewURI(const nsACString &aSpec,
   324                            const char *aCharset, // ignore charset info
   325                            nsIURI *aBaseURI,
   326                            nsIURI **result)
   327 {
   328   nsresult rv;
   329   nsCOMPtr<nsIStandardURL> surl(do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv));
   330   NS_ENSURE_SUCCESS(rv, rv);
   332   rv = surl->Init(nsIStandardURL::URLTYPE_STANDARD, -1, aSpec, aCharset, aBaseURI);
   333   NS_ENSURE_SUCCESS(rv, rv);
   335   nsCOMPtr<nsIURL> url(do_QueryInterface(surl, &rv));
   336   NS_ENSURE_SUCCESS(rv, rv);
   338   url.forget(result);
   339   return NS_OK;
   340 }
   342 // We map app://ABCDEF/path/to/file.ext to
   343 // jar:file:///path/to/profile/webapps/ABCDEF/application.zip!/path/to/file.ext
   344 NS_IMETHODIMP
   345 AppProtocolHandler::NewChannel(nsIURI* aUri, nsIChannel* *aResult)
   346 {
   347   NS_ENSURE_ARG_POINTER(aUri);
   348   nsRefPtr<nsJARChannel> channel = new nsJARChannel();
   350   nsAutoCString host;
   351   nsresult rv = aUri->GetHost(host);
   352   NS_ENSURE_SUCCESS(rv, rv);
   354   nsAutoCString fileSpec;
   355   nsCOMPtr<nsIURL> url = do_QueryInterface(aUri);
   356   rv = url->GetFilePath(fileSpec);
   357   NS_ENSURE_SUCCESS(rv, rv);
   359   mozilla::dom::AppInfo *appInfo;
   361   if (!mAppInfoCache.Get(host, &appInfo)) {
   362     nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
   363     if (!appsService) {
   364       return NS_ERROR_FAILURE;
   365     }
   367     mozilla::AutoSafeJSContext cx;
   368     JS::RootedValue jsInfo(cx);
   369     rv = appsService->GetAppInfo(NS_ConvertUTF8toUTF16(host), &jsInfo);
   370     if (NS_FAILED(rv) || !jsInfo.isObject()) {
   371       // Return a DummyChannel.
   372       printf_stderr("!! Creating a dummy channel for %s (no appInfo)\n", host.get());
   373       NS_IF_ADDREF(*aResult = new DummyChannel());
   374       return NS_OK;
   375     }
   377     appInfo = new mozilla::dom::AppInfo();
   378     JSAutoCompartment ac(cx, &jsInfo.toObject());
   379     if (!appInfo->Init(cx, jsInfo) || appInfo->mPath.IsEmpty()) {
   380       // Return a DummyChannel.
   381       printf_stderr("!! Creating a dummy channel for %s (invalid appInfo)\n", host.get());
   382       NS_IF_ADDREF(*aResult = new DummyChannel());
   383       return NS_OK;
   384     }
   385     mAppInfoCache.Put(host, appInfo);
   386   }
   388   bool noRemote = (appInfo->mIsCoreApp ||
   389                    XRE_GetProcessType() == GeckoProcessType_Default);
   391   // In-parent and CoreApps can directly access files, so use jar:file://
   392   nsAutoCString jarSpec(noRemote ? "jar:file://"
   393                                  : "jar:remoteopenfile://");
   394   jarSpec += NS_ConvertUTF16toUTF8(appInfo->mPath) +
   395              NS_LITERAL_CSTRING("/application.zip!") +
   396              fileSpec;
   398   nsCOMPtr<nsIURI> jarURI;
   399   rv = NS_NewURI(getter_AddRefs(jarURI),
   400                  jarSpec, nullptr, nullptr);
   401   NS_ENSURE_SUCCESS(rv, rv);
   403   rv = channel->Init(jarURI);
   404   NS_ENSURE_SUCCESS(rv, rv);
   406   rv = channel->SetAppURI(aUri);
   407   NS_ENSURE_SUCCESS(rv, rv);
   409   rv = channel->SetOriginalURI(aUri);
   410   NS_ENSURE_SUCCESS(rv, rv);
   412   channel.forget(aResult);
   413   return NS_OK;
   414 }
   416 NS_IMETHODIMP
   417 AppProtocolHandler::AllowPort(int32_t aPort, const char *aScheme, bool *aRetval)
   418 {
   419   // No port allowed for this scheme.
   420   *aRetval = false;
   421   return NS_OK;
   422 }

mercurial