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