netwerk/ipc/NeckoParent.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/netwerk/ipc/NeckoParent.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,691 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* vim: set sw=2 ts=8 et tw=80 : */
     1.6 +
     1.7 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.8 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.9 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    1.10 +
    1.11 +#include "necko-config.h"
    1.12 +#include "nsHttp.h"
    1.13 +#include "mozilla/net/NeckoParent.h"
    1.14 +#include "mozilla/net/HttpChannelParent.h"
    1.15 +#include "mozilla/net/CookieServiceParent.h"
    1.16 +#include "mozilla/net/WyciwygChannelParent.h"
    1.17 +#include "mozilla/net/FTPChannelParent.h"
    1.18 +#include "mozilla/net/WebSocketChannelParent.h"
    1.19 +#ifdef NECKO_PROTOCOL_rtsp
    1.20 +#include "mozilla/net/RtspControllerParent.h"
    1.21 +#include "mozilla/net/RtspChannelParent.h"
    1.22 +#endif
    1.23 +#include "mozilla/net/DNSRequestParent.h"
    1.24 +#include "mozilla/net/RemoteOpenFileParent.h"
    1.25 +#include "mozilla/net/ChannelDiverterParent.h"
    1.26 +#include "mozilla/dom/ContentParent.h"
    1.27 +#include "mozilla/dom/TabParent.h"
    1.28 +#include "mozilla/dom/network/TCPSocketParent.h"
    1.29 +#include "mozilla/dom/network/TCPServerSocketParent.h"
    1.30 +#include "mozilla/dom/network/UDPSocketParent.h"
    1.31 +#include "mozilla/ipc/URIUtils.h"
    1.32 +#include "mozilla/LoadContext.h"
    1.33 +#include "mozilla/AppProcessChecker.h"
    1.34 +#include "nsPrintfCString.h"
    1.35 +#include "nsHTMLDNSPrefetch.h"
    1.36 +#include "nsIAppsService.h"
    1.37 +#include "nsIUDPSocketFilter.h"
    1.38 +#include "nsEscape.h"
    1.39 +#include "RemoteOpenFileParent.h"
    1.40 +#include "SerializedLoadContext.h"
    1.41 +
    1.42 +using mozilla::dom::ContentParent;
    1.43 +using mozilla::dom::TabParent;
    1.44 +using mozilla::net::PTCPSocketParent;
    1.45 +using mozilla::dom::TCPSocketParent;
    1.46 +using mozilla::net::PTCPServerSocketParent;
    1.47 +using mozilla::dom::TCPServerSocketParent;
    1.48 +using mozilla::net::PUDPSocketParent;
    1.49 +using mozilla::dom::UDPSocketParent;
    1.50 +using IPC::SerializedLoadContext;
    1.51 +
    1.52 +namespace mozilla {
    1.53 +namespace net {
    1.54 +
    1.55 +// C++ file contents
    1.56 +NeckoParent::NeckoParent()
    1.57 +{
    1.58 +  // Init HTTP protocol handler now since we need atomTable up and running very
    1.59 +  // early (IPDL argument handling for PHttpChannel constructor needs it) so
    1.60 +  // normal init (during 1st Http channel request) isn't early enough.
    1.61 +  nsCOMPtr<nsIProtocolHandler> proto =
    1.62 +    do_GetService("@mozilla.org/network/protocol;1?name=http");
    1.63 +
    1.64 +  if (UsingNeckoIPCSecurity()) {
    1.65 +    // cache values for core/packaged apps basepaths
    1.66 +    nsAutoString corePath, webPath;
    1.67 +    nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
    1.68 +    if (appsService) {
    1.69 +      appsService->GetCoreAppsBasePath(corePath);
    1.70 +      appsService->GetWebAppsBasePath(webPath);
    1.71 +    }
    1.72 +    // corePath may be empty: we don't use it for all build types
    1.73 +    MOZ_ASSERT(!webPath.IsEmpty());
    1.74 +
    1.75 +    LossyCopyUTF16toASCII(corePath, mCoreAppsBasePath);
    1.76 +    LossyCopyUTF16toASCII(webPath, mWebAppsBasePath);
    1.77 +  }
    1.78 +}
    1.79 +
    1.80 +NeckoParent::~NeckoParent()
    1.81 +{
    1.82 +}
    1.83 +
    1.84 +static PBOverrideStatus
    1.85 +PBOverrideStatusFromLoadContext(const SerializedLoadContext& aSerialized)
    1.86 +{
    1.87 +  if (!aSerialized.IsNotNull() && aSerialized.IsPrivateBitValid()) {
    1.88 +    return aSerialized.mUsePrivateBrowsing ?
    1.89 +      kPBOverride_Private :
    1.90 +      kPBOverride_NotPrivate;
    1.91 +  }
    1.92 +  return kPBOverride_Unset;
    1.93 +}
    1.94 +
    1.95 +const char*
    1.96 +NeckoParent::GetValidatedAppInfo(const SerializedLoadContext& aSerialized,
    1.97 +                                 PContentParent* aContent,
    1.98 +                                 uint32_t* aAppId,
    1.99 +                                 bool* aInBrowserElement)
   1.100 +{
   1.101 +  *aAppId = NECKO_UNKNOWN_APP_ID;
   1.102 +  *aInBrowserElement = false;
   1.103 +
   1.104 +  if (UsingNeckoIPCSecurity()) {
   1.105 +    if (!aSerialized.IsNotNull()) {
   1.106 +      return "SerializedLoadContext from child is null";
   1.107 +    }
   1.108 +  }
   1.109 +
   1.110 +  const InfallibleTArray<PBrowserParent*>& browsers = aContent->ManagedPBrowserParent();
   1.111 +  for (uint32_t i = 0; i < browsers.Length(); i++) {
   1.112 +    nsRefPtr<TabParent> tabParent = static_cast<TabParent*>(browsers[i]);
   1.113 +    uint32_t appId = tabParent->OwnOrContainingAppId();
   1.114 +    bool inBrowserElement = aSerialized.IsNotNull() ? aSerialized.mIsInBrowserElement
   1.115 +                                                    : tabParent->IsBrowserElement();
   1.116 +
   1.117 +    if (appId == NECKO_UNKNOWN_APP_ID) {
   1.118 +      continue;
   1.119 +    }
   1.120 +    // We may get appID=NO_APP if child frame is neither a browser nor an app
   1.121 +    if (appId == NECKO_NO_APP_ID) {
   1.122 +      if (tabParent->HasOwnApp()) {
   1.123 +        continue;
   1.124 +      }
   1.125 +      if (UsingNeckoIPCSecurity() && tabParent->IsBrowserElement()) {
   1.126 +        // <iframe mozbrowser> which doesn't have an <iframe mozapp> above it.
   1.127 +        // This is not supported now, and we'll need to do a code audit to make
   1.128 +        // sure we can handle it (i.e don't short-circuit using separate
   1.129 +        // namespace if just appID==0)
   1.130 +        continue;
   1.131 +      }
   1.132 +    }
   1.133 +    *aAppId = appId;
   1.134 +    *aInBrowserElement = inBrowserElement;
   1.135 +    return nullptr;
   1.136 +  }
   1.137 +
   1.138 +  if (browsers.Length() != 0) {
   1.139 +    return "App does not have permission";
   1.140 +  }
   1.141 +
   1.142 +  if (!UsingNeckoIPCSecurity()) {
   1.143 +    // We are running xpcshell tests
   1.144 +    if (aSerialized.IsNotNull()) {
   1.145 +      *aAppId = aSerialized.mAppId;
   1.146 +      *aInBrowserElement = aSerialized.mIsInBrowserElement;
   1.147 +    } else {
   1.148 +      *aAppId = NECKO_NO_APP_ID;
   1.149 +    }
   1.150 +    return nullptr;
   1.151 +  }
   1.152 +
   1.153 +  return "ContentParent does not have any PBrowsers";
   1.154 +}
   1.155 +
   1.156 +const char *
   1.157 +NeckoParent::CreateChannelLoadContext(PBrowserParent* aBrowser,
   1.158 +                                      PContentParent* aContent,
   1.159 +                                      const SerializedLoadContext& aSerialized,
   1.160 +                                      nsCOMPtr<nsILoadContext> &aResult)
   1.161 +{
   1.162 +  uint32_t appId = NECKO_UNKNOWN_APP_ID;
   1.163 +  bool inBrowser = false;
   1.164 +  dom::Element* topFrameElement = nullptr;
   1.165 +  const char* error = GetValidatedAppInfo(aSerialized, aContent, &appId, &inBrowser);
   1.166 +  if (error) {
   1.167 +    return error;
   1.168 +  }
   1.169 +
   1.170 +  if (aBrowser) {
   1.171 +    nsRefPtr<TabParent> tabParent = static_cast<TabParent*>(aBrowser);
   1.172 +    topFrameElement = tabParent->GetOwnerElement();
   1.173 +  }
   1.174 +
   1.175 +  // if !UsingNeckoIPCSecurity(), we may not have a LoadContext to set. This is
   1.176 +  // the common case for most xpcshell tests.
   1.177 +  if (aSerialized.IsNotNull()) {
   1.178 +    aResult = new LoadContext(aSerialized, topFrameElement, appId, inBrowser);
   1.179 +  }
   1.180 +
   1.181 +  return nullptr;
   1.182 +}
   1.183 +
   1.184 +PHttpChannelParent*
   1.185 +NeckoParent::AllocPHttpChannelParent(PBrowserParent* aBrowser,
   1.186 +                                     const SerializedLoadContext& aSerialized,
   1.187 +                                     const HttpChannelCreationArgs& aOpenArgs)
   1.188 +{
   1.189 +  nsCOMPtr<nsILoadContext> loadContext;
   1.190 +  const char *error = CreateChannelLoadContext(aBrowser, Manager(),
   1.191 +                                               aSerialized, loadContext);
   1.192 +  if (error) {
   1.193 +    printf_stderr("NeckoParent::AllocPHttpChannelParent: "
   1.194 +                  "FATAL error: %s: KILLING CHILD PROCESS\n",
   1.195 +                  error);
   1.196 +    return nullptr;
   1.197 +  }
   1.198 +  PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(aSerialized);
   1.199 +  HttpChannelParent *p = new HttpChannelParent(aBrowser, loadContext, overrideStatus);
   1.200 +  p->AddRef();
   1.201 +  return p;
   1.202 +}
   1.203 +
   1.204 +bool
   1.205 +NeckoParent::DeallocPHttpChannelParent(PHttpChannelParent* channel)
   1.206 +{
   1.207 +  HttpChannelParent *p = static_cast<HttpChannelParent *>(channel);
   1.208 +  p->Release();
   1.209 +  return true;
   1.210 +}
   1.211 +
   1.212 +bool
   1.213 +NeckoParent::RecvPHttpChannelConstructor(
   1.214 +                      PHttpChannelParent* aActor,
   1.215 +                      PBrowserParent* aBrowser,
   1.216 +                      const SerializedLoadContext& aSerialized,
   1.217 +                      const HttpChannelCreationArgs& aOpenArgs)
   1.218 +{
   1.219 +  HttpChannelParent* p = static_cast<HttpChannelParent*>(aActor);
   1.220 +  return p->Init(aOpenArgs);
   1.221 +}
   1.222 +
   1.223 +PFTPChannelParent*
   1.224 +NeckoParent::AllocPFTPChannelParent(PBrowserParent* aBrowser,
   1.225 +                                    const SerializedLoadContext& aSerialized,
   1.226 +                                    const FTPChannelCreationArgs& aOpenArgs)
   1.227 +{
   1.228 +  nsCOMPtr<nsILoadContext> loadContext;
   1.229 +  const char *error = CreateChannelLoadContext(aBrowser, Manager(),
   1.230 +                                               aSerialized, loadContext);
   1.231 +  if (error) {
   1.232 +    printf_stderr("NeckoParent::AllocPFTPChannelParent: "
   1.233 +                  "FATAL error: %s: KILLING CHILD PROCESS\n",
   1.234 +                  error);
   1.235 +    return nullptr;
   1.236 +  }
   1.237 +  PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(aSerialized);
   1.238 +  FTPChannelParent *p = new FTPChannelParent(loadContext, overrideStatus);
   1.239 +  p->AddRef();
   1.240 +  return p;
   1.241 +}
   1.242 +
   1.243 +bool
   1.244 +NeckoParent::DeallocPFTPChannelParent(PFTPChannelParent* channel)
   1.245 +{
   1.246 +  FTPChannelParent *p = static_cast<FTPChannelParent *>(channel);
   1.247 +  p->Release();
   1.248 +  return true;
   1.249 +}
   1.250 +
   1.251 +bool
   1.252 +NeckoParent::RecvPFTPChannelConstructor(
   1.253 +                      PFTPChannelParent* aActor,
   1.254 +                      PBrowserParent* aBrowser,
   1.255 +                      const SerializedLoadContext& aSerialized,
   1.256 +                      const FTPChannelCreationArgs& aOpenArgs)
   1.257 +{
   1.258 +  FTPChannelParent* p = static_cast<FTPChannelParent*>(aActor);
   1.259 +  return p->Init(aOpenArgs);
   1.260 +}
   1.261 +
   1.262 +PCookieServiceParent*
   1.263 +NeckoParent::AllocPCookieServiceParent()
   1.264 +{
   1.265 +  return new CookieServiceParent();
   1.266 +}
   1.267 +
   1.268 +bool 
   1.269 +NeckoParent::DeallocPCookieServiceParent(PCookieServiceParent* cs)
   1.270 +{
   1.271 +  delete cs;
   1.272 +  return true;
   1.273 +}
   1.274 +
   1.275 +PWyciwygChannelParent*
   1.276 +NeckoParent::AllocPWyciwygChannelParent()
   1.277 +{
   1.278 +  WyciwygChannelParent *p = new WyciwygChannelParent();
   1.279 +  p->AddRef();
   1.280 +  return p;
   1.281 +}
   1.282 +
   1.283 +bool
   1.284 +NeckoParent::DeallocPWyciwygChannelParent(PWyciwygChannelParent* channel)
   1.285 +{
   1.286 +  WyciwygChannelParent *p = static_cast<WyciwygChannelParent *>(channel);
   1.287 +  p->Release();
   1.288 +  return true;
   1.289 +}
   1.290 +
   1.291 +PWebSocketParent*
   1.292 +NeckoParent::AllocPWebSocketParent(PBrowserParent* browser,
   1.293 +                                   const SerializedLoadContext& serialized)
   1.294 +{
   1.295 +  nsCOMPtr<nsILoadContext> loadContext;
   1.296 +  const char *error = CreateChannelLoadContext(browser, Manager(),
   1.297 +                                               serialized, loadContext);
   1.298 +  if (error) {
   1.299 +    printf_stderr("NeckoParent::AllocPWebSocketParent: "
   1.300 +                  "FATAL error: %s: KILLING CHILD PROCESS\n",
   1.301 +                  error);
   1.302 +    return nullptr;
   1.303 +  }
   1.304 +
   1.305 +  TabParent* tabParent = static_cast<TabParent*>(browser);
   1.306 +  PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(serialized);
   1.307 +  WebSocketChannelParent* p = new WebSocketChannelParent(tabParent, loadContext,
   1.308 +                                                         overrideStatus);
   1.309 +  p->AddRef();
   1.310 +  return p;
   1.311 +}
   1.312 +
   1.313 +bool
   1.314 +NeckoParent::DeallocPWebSocketParent(PWebSocketParent* actor)
   1.315 +{
   1.316 +  WebSocketChannelParent* p = static_cast<WebSocketChannelParent*>(actor);
   1.317 +  p->Release();
   1.318 +  return true;
   1.319 +}
   1.320 +
   1.321 +PRtspControllerParent*
   1.322 +NeckoParent::AllocPRtspControllerParent()
   1.323 +{
   1.324 +#ifdef NECKO_PROTOCOL_rtsp
   1.325 +  RtspControllerParent* p = new RtspControllerParent();
   1.326 +  p->AddRef();
   1.327 +  return p;
   1.328 +#else
   1.329 +  return nullptr;
   1.330 +#endif
   1.331 +}
   1.332 +
   1.333 +bool
   1.334 +NeckoParent::DeallocPRtspControllerParent(PRtspControllerParent* actor)
   1.335 +{
   1.336 +#ifdef NECKO_PROTOCOL_rtsp
   1.337 +  RtspControllerParent* p = static_cast<RtspControllerParent*>(actor);
   1.338 +  p->Release();
   1.339 +#endif
   1.340 +  return true;
   1.341 +}
   1.342 +
   1.343 +PRtspChannelParent*
   1.344 +NeckoParent::AllocPRtspChannelParent(const RtspChannelConnectArgs& aArgs)
   1.345 +{
   1.346 +#ifdef NECKO_PROTOCOL_rtsp
   1.347 +  nsCOMPtr<nsIURI> uri = DeserializeURI(aArgs.uri());
   1.348 +  RtspChannelParent *p = new RtspChannelParent(uri);
   1.349 +  p->AddRef();
   1.350 +  return p;
   1.351 +#else
   1.352 +  return nullptr;
   1.353 +#endif
   1.354 +}
   1.355 +
   1.356 +bool
   1.357 +NeckoParent::RecvPRtspChannelConstructor(
   1.358 +                      PRtspChannelParent* aActor,
   1.359 +                      const RtspChannelConnectArgs& aConnectArgs)
   1.360 +{
   1.361 +#ifdef NECKO_PROTOCOL_rtsp
   1.362 +  RtspChannelParent* p = static_cast<RtspChannelParent*>(aActor);
   1.363 +  return p->Init(aConnectArgs);
   1.364 +#else
   1.365 +  return nullptr;
   1.366 +#endif
   1.367 +}
   1.368 +
   1.369 +bool
   1.370 +NeckoParent::DeallocPRtspChannelParent(PRtspChannelParent* actor)
   1.371 +{
   1.372 +#ifdef NECKO_PROTOCOL_rtsp
   1.373 +  RtspChannelParent* p = static_cast<RtspChannelParent*>(actor);
   1.374 +  p->Release();
   1.375 +#endif
   1.376 +  return true;
   1.377 +}
   1.378 +
   1.379 +PTCPSocketParent*
   1.380 +NeckoParent::AllocPTCPSocketParent()
   1.381 +{
   1.382 +  TCPSocketParent* p = new TCPSocketParent();
   1.383 +  p->AddIPDLReference();
   1.384 +  return p;
   1.385 +}
   1.386 +
   1.387 +bool
   1.388 +NeckoParent::DeallocPTCPSocketParent(PTCPSocketParent* actor)
   1.389 +{
   1.390 +  TCPSocketParent* p = static_cast<TCPSocketParent*>(actor);
   1.391 +  p->ReleaseIPDLReference();
   1.392 +  return true;
   1.393 +}
   1.394 +
   1.395 +PTCPServerSocketParent*
   1.396 +NeckoParent::AllocPTCPServerSocketParent(const uint16_t& aLocalPort,
   1.397 +                                   const uint16_t& aBacklog,
   1.398 +                                   const nsString& aBinaryType)
   1.399 +{
   1.400 +  TCPServerSocketParent* p = new TCPServerSocketParent();
   1.401 +  p->AddIPDLReference();
   1.402 +  return p;
   1.403 +}
   1.404 +
   1.405 +bool
   1.406 +NeckoParent::RecvPTCPServerSocketConstructor(PTCPServerSocketParent* aActor,
   1.407 +                                             const uint16_t& aLocalPort,
   1.408 +                                             const uint16_t& aBacklog,
   1.409 +                                             const nsString& aBinaryType)
   1.410 +{
   1.411 +  return static_cast<TCPServerSocketParent*>(aActor)->
   1.412 +      Init(this, aLocalPort, aBacklog, aBinaryType);
   1.413 +}
   1.414 +
   1.415 +bool
   1.416 +NeckoParent::DeallocPTCPServerSocketParent(PTCPServerSocketParent* actor)
   1.417 +{
   1.418 +  TCPServerSocketParent* p = static_cast<TCPServerSocketParent*>(actor);
   1.419 +   p->ReleaseIPDLReference();
   1.420 +  return true;
   1.421 +}
   1.422 +
   1.423 +PUDPSocketParent*
   1.424 +NeckoParent::AllocPUDPSocketParent(const nsCString& aHost,
   1.425 +                                   const uint16_t& aPort,
   1.426 +                                   const nsCString& aFilter)
   1.427 +{
   1.428 +  UDPSocketParent* p = nullptr;
   1.429 +
   1.430 +  // Only allow socket if it specifies a valid packet filter.
   1.431 +  nsAutoCString contractId(NS_NETWORK_UDP_SOCKET_FILTER_HANDLER_PREFIX);
   1.432 +  contractId.Append(aFilter);
   1.433 +
   1.434 +  if (!aFilter.IsEmpty()) {
   1.435 +    nsCOMPtr<nsIUDPSocketFilterHandler> filterHandler =
   1.436 +      do_GetService(contractId.get());
   1.437 +    if (filterHandler) {
   1.438 +      nsCOMPtr<nsIUDPSocketFilter> filter;
   1.439 +      nsresult rv = filterHandler->NewFilter(getter_AddRefs(filter));
   1.440 +      if (NS_SUCCEEDED(rv)) {
   1.441 +        p = new UDPSocketParent(filter);
   1.442 +      } else {
   1.443 +        printf_stderr("Cannot create filter that content specified. "
   1.444 +                      "filter name: %s, error code: %d.", aFilter.get(), rv);
   1.445 +      }
   1.446 +    } else {
   1.447 +      printf_stderr("Content doesn't have a valid filter. "
   1.448 +                    "filter name: %s.", aFilter.get());
   1.449 +    }
   1.450 +  }
   1.451 +
   1.452 +  NS_IF_ADDREF(p);
   1.453 +  return p;
   1.454 +}
   1.455 +
   1.456 +bool
   1.457 +NeckoParent::RecvPUDPSocketConstructor(PUDPSocketParent* aActor,
   1.458 +                                       const nsCString& aHost,
   1.459 +                                       const uint16_t& aPort,
   1.460 +                                       const nsCString& aFilter)
   1.461 +{
   1.462 +  return static_cast<UDPSocketParent*>(aActor)->Init(aHost, aPort);
   1.463 +}
   1.464 +
   1.465 +bool
   1.466 +NeckoParent::DeallocPUDPSocketParent(PUDPSocketParent* actor)
   1.467 +{
   1.468 +  UDPSocketParent* p = static_cast<UDPSocketParent*>(actor);
   1.469 +  p->Release();
   1.470 +  return true;
   1.471 +}
   1.472 +
   1.473 +PDNSRequestParent*
   1.474 +NeckoParent::AllocPDNSRequestParent(const nsCString& aHost,
   1.475 +                                    const uint32_t& aFlags)
   1.476 +{
   1.477 +  DNSRequestParent *p = new DNSRequestParent();
   1.478 +  p->AddRef();
   1.479 +  return p;
   1.480 +}
   1.481 +
   1.482 +bool
   1.483 +NeckoParent::RecvPDNSRequestConstructor(PDNSRequestParent* aActor,
   1.484 +                                        const nsCString& aHost,
   1.485 +                                        const uint32_t& aFlags)
   1.486 +{
   1.487 +  static_cast<DNSRequestParent*>(aActor)->DoAsyncResolve(aHost, aFlags);
   1.488 +  return true;
   1.489 +}
   1.490 +
   1.491 +bool
   1.492 +NeckoParent::DeallocPDNSRequestParent(PDNSRequestParent* aParent)
   1.493 +{
   1.494 +  DNSRequestParent *p = static_cast<DNSRequestParent*>(aParent);
   1.495 +  p->Release();
   1.496 +  return true;
   1.497 +}
   1.498 +
   1.499 +PRemoteOpenFileParent*
   1.500 +NeckoParent::AllocPRemoteOpenFileParent(const URIParams& aURI,
   1.501 +                                        const OptionalURIParams& aAppURI)
   1.502 +{
   1.503 +  nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
   1.504 +  nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(uri);
   1.505 +  if (!fileURL) {
   1.506 +    return nullptr;
   1.507 +  }
   1.508 +
   1.509 +  // security checks
   1.510 +  if (UsingNeckoIPCSecurity()) {
   1.511 +    nsCOMPtr<nsIAppsService> appsService =
   1.512 +      do_GetService(APPS_SERVICE_CONTRACTID);
   1.513 +    if (!appsService) {
   1.514 +      return nullptr;
   1.515 +    }
   1.516 +    bool haveValidBrowser = false;
   1.517 +    bool hasManage = false;
   1.518 +    nsCOMPtr<mozIApplication> mozApp;
   1.519 +    for (uint32_t i = 0; i < Manager()->ManagedPBrowserParent().Length(); i++) {
   1.520 +      nsRefPtr<TabParent> tabParent =
   1.521 +        static_cast<TabParent*>(Manager()->ManagedPBrowserParent()[i]);
   1.522 +      uint32_t appId = tabParent->OwnOrContainingAppId();
   1.523 +      nsresult rv = appsService->GetAppByLocalId(appId, getter_AddRefs(mozApp));
   1.524 +      if (NS_FAILED(rv) || !mozApp) {
   1.525 +        continue;
   1.526 +      }
   1.527 +      hasManage = false;
   1.528 +      rv = mozApp->HasPermission("webapps-manage", &hasManage);
   1.529 +      if (NS_FAILED(rv)) {
   1.530 +        continue;
   1.531 +      }
   1.532 +      haveValidBrowser = true;
   1.533 +      break;
   1.534 +    }
   1.535 +
   1.536 +    if (!haveValidBrowser) {
   1.537 +      return nullptr;
   1.538 +    }
   1.539 +
   1.540 +    nsAutoCString requestedPath;
   1.541 +    fileURL->GetPath(requestedPath);
   1.542 +    NS_UnescapeURL(requestedPath);
   1.543 +
   1.544 +    // Check if we load the whitelisted app uri for the neterror page.
   1.545 +    bool netErrorWhiteList = false;
   1.546 +
   1.547 +    nsCOMPtr<nsIURI> appUri = DeserializeURI(aAppURI);
   1.548 +    if (appUri) {
   1.549 +      nsAdoptingString netErrorURI;
   1.550 +      netErrorURI = Preferences::GetString("b2g.neterror.url");
   1.551 +      if (netErrorURI) {
   1.552 +        nsAutoCString spec;
   1.553 +        appUri->GetSpec(spec);
   1.554 +        netErrorWhiteList = spec.Equals(NS_ConvertUTF16toUTF8(netErrorURI).get());
   1.555 +      }
   1.556 +    }
   1.557 +
   1.558 +    if (hasManage || netErrorWhiteList) {
   1.559 +      // webapps-manage permission means allow reading any application.zip file
   1.560 +      // in either the regular webapps directory, or the core apps directory (if
   1.561 +      // we're using one).
   1.562 +      NS_NAMED_LITERAL_CSTRING(appzip, "/application.zip");
   1.563 +      nsAutoCString pathEnd;
   1.564 +      requestedPath.Right(pathEnd, appzip.Length());
   1.565 +      if (!pathEnd.Equals(appzip)) {
   1.566 +        return nullptr;
   1.567 +      }
   1.568 +      nsAutoCString pathStart;
   1.569 +      requestedPath.Left(pathStart, mWebAppsBasePath.Length());
   1.570 +      if (!pathStart.Equals(mWebAppsBasePath)) {
   1.571 +        if (mCoreAppsBasePath.IsEmpty()) {
   1.572 +          return nullptr;
   1.573 +        }
   1.574 +        requestedPath.Left(pathStart, mCoreAppsBasePath.Length());
   1.575 +        if (!pathStart.Equals(mCoreAppsBasePath)) {
   1.576 +          return nullptr;
   1.577 +        }
   1.578 +      }
   1.579 +      // Finally: make sure there are no "../" in URI.
   1.580 +      // Note: not checking for symlinks (would cause I/O for each path
   1.581 +      // component).  So it's up to us to avoid creating symlinks that could
   1.582 +      // provide attack vectors.
   1.583 +      if (PL_strnstr(requestedPath.BeginReading(), "/../",
   1.584 +                     requestedPath.Length())) {
   1.585 +        printf_stderr("NeckoParent::AllocPRemoteOpenFile: "
   1.586 +                      "FATAL error: requested file URI '%s' contains '/../' "
   1.587 +                      "KILLING CHILD PROCESS\n", requestedPath.get());
   1.588 +        return nullptr;
   1.589 +      }
   1.590 +    } else {
   1.591 +      // regular packaged apps can only access their own application.zip file
   1.592 +      nsAutoString basePath;
   1.593 +      nsresult rv = mozApp->GetBasePath(basePath);
   1.594 +      if (NS_FAILED(rv)) {
   1.595 +        return nullptr;
   1.596 +      }
   1.597 +      nsAutoString uuid;
   1.598 +      rv = mozApp->GetId(uuid);
   1.599 +      if (NS_FAILED(rv)) {
   1.600 +        return nullptr;
   1.601 +      }
   1.602 +      nsPrintfCString mustMatch("%s/%s/application.zip",
   1.603 +                                NS_LossyConvertUTF16toASCII(basePath).get(),
   1.604 +                                NS_LossyConvertUTF16toASCII(uuid).get());
   1.605 +      if (!requestedPath.Equals(mustMatch)) {
   1.606 +        printf_stderr("NeckoParent::AllocPRemoteOpenFile: "
   1.607 +                      "FATAL error: app without webapps-manage permission is "
   1.608 +                      "requesting file '%s' but is only allowed to open its "
   1.609 +                      "own application.zip at %s: KILLING CHILD PROCESS\n",
   1.610 +                      requestedPath.get(), mustMatch.get());
   1.611 +        return nullptr;
   1.612 +      }
   1.613 +    }
   1.614 +  }
   1.615 +
   1.616 +  RemoteOpenFileParent* parent = new RemoteOpenFileParent(fileURL);
   1.617 +  return parent;
   1.618 +}
   1.619 +
   1.620 +bool
   1.621 +NeckoParent::RecvPRemoteOpenFileConstructor(PRemoteOpenFileParent* aActor,
   1.622 +                                            const URIParams& aFileURI,
   1.623 +                                            const OptionalURIParams& aAppURI)
   1.624 +{
   1.625 +  return static_cast<RemoteOpenFileParent*>(aActor)->OpenSendCloseDelete();
   1.626 +}
   1.627 +
   1.628 +bool
   1.629 +NeckoParent::DeallocPRemoteOpenFileParent(PRemoteOpenFileParent* actor)
   1.630 +{
   1.631 +  delete actor;
   1.632 +  return true;
   1.633 +}
   1.634 +
   1.635 +bool
   1.636 +NeckoParent::RecvHTMLDNSPrefetch(const nsString& hostname,
   1.637 +                                 const uint16_t& flags)
   1.638 +{
   1.639 +  nsHTMLDNSPrefetch::Prefetch(hostname, flags);
   1.640 +  return true;
   1.641 +}
   1.642 +
   1.643 +bool
   1.644 +NeckoParent::RecvCancelHTMLDNSPrefetch(const nsString& hostname,
   1.645 +                                 const uint16_t& flags,
   1.646 +                                 const nsresult& reason)
   1.647 +{
   1.648 +  nsHTMLDNSPrefetch::CancelPrefetch(hostname, flags, reason);
   1.649 +  return true;
   1.650 +}
   1.651 +
   1.652 +PChannelDiverterParent*
   1.653 +NeckoParent::AllocPChannelDiverterParent(const ChannelDiverterArgs& channel)
   1.654 +{
   1.655 +  return new ChannelDiverterParent();
   1.656 +}
   1.657 +
   1.658 +bool
   1.659 +NeckoParent::RecvPChannelDiverterConstructor(PChannelDiverterParent* actor,
   1.660 +                                             const ChannelDiverterArgs& channel)
   1.661 +{
   1.662 +  auto parent = static_cast<ChannelDiverterParent*>(actor);
   1.663 +  parent->Init(channel);
   1.664 +  return true;
   1.665 +}
   1.666 +
   1.667 +bool
   1.668 +NeckoParent::DeallocPChannelDiverterParent(PChannelDiverterParent* parent)
   1.669 +{
   1.670 +  delete static_cast<ChannelDiverterParent*>(parent);
   1.671 +  return true;
   1.672 +}
   1.673 +
   1.674 +void
   1.675 +NeckoParent::CloneManagees(ProtocolBase* aSource,
   1.676 +                         mozilla::ipc::ProtocolCloneContext* aCtx)
   1.677 +{
   1.678 +  aCtx->SetNeckoParent(this); // For cloning protocols managed by this.
   1.679 +  PNeckoParent::CloneManagees(aSource, aCtx);
   1.680 +}
   1.681 +
   1.682 +mozilla::ipc::IProtocol*
   1.683 +NeckoParent::CloneProtocol(Channel* aChannel,
   1.684 +                           mozilla::ipc::ProtocolCloneContext* aCtx)
   1.685 +{
   1.686 +  ContentParent* contentParent = aCtx->GetContentParent();
   1.687 +  nsAutoPtr<PNeckoParent> actor(contentParent->AllocPNeckoParent());
   1.688 +  if (!actor || !contentParent->RecvPNeckoConstructor(actor)) {
   1.689 +    return nullptr;
   1.690 +  }
   1.691 +  return actor.forget();
   1.692 +}
   1.693 +
   1.694 +}} // mozilla::net

mercurial