netwerk/ipc/NeckoParent.cpp

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim: set sw=2 ts=8 et tw=80 : */
michael@0 3
michael@0 4 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 5 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 7
michael@0 8 #include "necko-config.h"
michael@0 9 #include "nsHttp.h"
michael@0 10 #include "mozilla/net/NeckoParent.h"
michael@0 11 #include "mozilla/net/HttpChannelParent.h"
michael@0 12 #include "mozilla/net/CookieServiceParent.h"
michael@0 13 #include "mozilla/net/WyciwygChannelParent.h"
michael@0 14 #include "mozilla/net/FTPChannelParent.h"
michael@0 15 #include "mozilla/net/WebSocketChannelParent.h"
michael@0 16 #ifdef NECKO_PROTOCOL_rtsp
michael@0 17 #include "mozilla/net/RtspControllerParent.h"
michael@0 18 #include "mozilla/net/RtspChannelParent.h"
michael@0 19 #endif
michael@0 20 #include "mozilla/net/DNSRequestParent.h"
michael@0 21 #include "mozilla/net/RemoteOpenFileParent.h"
michael@0 22 #include "mozilla/net/ChannelDiverterParent.h"
michael@0 23 #include "mozilla/dom/ContentParent.h"
michael@0 24 #include "mozilla/dom/TabParent.h"
michael@0 25 #include "mozilla/dom/network/TCPSocketParent.h"
michael@0 26 #include "mozilla/dom/network/TCPServerSocketParent.h"
michael@0 27 #include "mozilla/dom/network/UDPSocketParent.h"
michael@0 28 #include "mozilla/ipc/URIUtils.h"
michael@0 29 #include "mozilla/LoadContext.h"
michael@0 30 #include "mozilla/AppProcessChecker.h"
michael@0 31 #include "nsPrintfCString.h"
michael@0 32 #include "nsHTMLDNSPrefetch.h"
michael@0 33 #include "nsIAppsService.h"
michael@0 34 #include "nsIUDPSocketFilter.h"
michael@0 35 #include "nsEscape.h"
michael@0 36 #include "RemoteOpenFileParent.h"
michael@0 37 #include "SerializedLoadContext.h"
michael@0 38
michael@0 39 using mozilla::dom::ContentParent;
michael@0 40 using mozilla::dom::TabParent;
michael@0 41 using mozilla::net::PTCPSocketParent;
michael@0 42 using mozilla::dom::TCPSocketParent;
michael@0 43 using mozilla::net::PTCPServerSocketParent;
michael@0 44 using mozilla::dom::TCPServerSocketParent;
michael@0 45 using mozilla::net::PUDPSocketParent;
michael@0 46 using mozilla::dom::UDPSocketParent;
michael@0 47 using IPC::SerializedLoadContext;
michael@0 48
michael@0 49 namespace mozilla {
michael@0 50 namespace net {
michael@0 51
michael@0 52 // C++ file contents
michael@0 53 NeckoParent::NeckoParent()
michael@0 54 {
michael@0 55 // Init HTTP protocol handler now since we need atomTable up and running very
michael@0 56 // early (IPDL argument handling for PHttpChannel constructor needs it) so
michael@0 57 // normal init (during 1st Http channel request) isn't early enough.
michael@0 58 nsCOMPtr<nsIProtocolHandler> proto =
michael@0 59 do_GetService("@mozilla.org/network/protocol;1?name=http");
michael@0 60
michael@0 61 if (UsingNeckoIPCSecurity()) {
michael@0 62 // cache values for core/packaged apps basepaths
michael@0 63 nsAutoString corePath, webPath;
michael@0 64 nsCOMPtr<nsIAppsService> appsService = do_GetService(APPS_SERVICE_CONTRACTID);
michael@0 65 if (appsService) {
michael@0 66 appsService->GetCoreAppsBasePath(corePath);
michael@0 67 appsService->GetWebAppsBasePath(webPath);
michael@0 68 }
michael@0 69 // corePath may be empty: we don't use it for all build types
michael@0 70 MOZ_ASSERT(!webPath.IsEmpty());
michael@0 71
michael@0 72 LossyCopyUTF16toASCII(corePath, mCoreAppsBasePath);
michael@0 73 LossyCopyUTF16toASCII(webPath, mWebAppsBasePath);
michael@0 74 }
michael@0 75 }
michael@0 76
michael@0 77 NeckoParent::~NeckoParent()
michael@0 78 {
michael@0 79 }
michael@0 80
michael@0 81 static PBOverrideStatus
michael@0 82 PBOverrideStatusFromLoadContext(const SerializedLoadContext& aSerialized)
michael@0 83 {
michael@0 84 if (!aSerialized.IsNotNull() && aSerialized.IsPrivateBitValid()) {
michael@0 85 return aSerialized.mUsePrivateBrowsing ?
michael@0 86 kPBOverride_Private :
michael@0 87 kPBOverride_NotPrivate;
michael@0 88 }
michael@0 89 return kPBOverride_Unset;
michael@0 90 }
michael@0 91
michael@0 92 const char*
michael@0 93 NeckoParent::GetValidatedAppInfo(const SerializedLoadContext& aSerialized,
michael@0 94 PContentParent* aContent,
michael@0 95 uint32_t* aAppId,
michael@0 96 bool* aInBrowserElement)
michael@0 97 {
michael@0 98 *aAppId = NECKO_UNKNOWN_APP_ID;
michael@0 99 *aInBrowserElement = false;
michael@0 100
michael@0 101 if (UsingNeckoIPCSecurity()) {
michael@0 102 if (!aSerialized.IsNotNull()) {
michael@0 103 return "SerializedLoadContext from child is null";
michael@0 104 }
michael@0 105 }
michael@0 106
michael@0 107 const InfallibleTArray<PBrowserParent*>& browsers = aContent->ManagedPBrowserParent();
michael@0 108 for (uint32_t i = 0; i < browsers.Length(); i++) {
michael@0 109 nsRefPtr<TabParent> tabParent = static_cast<TabParent*>(browsers[i]);
michael@0 110 uint32_t appId = tabParent->OwnOrContainingAppId();
michael@0 111 bool inBrowserElement = aSerialized.IsNotNull() ? aSerialized.mIsInBrowserElement
michael@0 112 : tabParent->IsBrowserElement();
michael@0 113
michael@0 114 if (appId == NECKO_UNKNOWN_APP_ID) {
michael@0 115 continue;
michael@0 116 }
michael@0 117 // We may get appID=NO_APP if child frame is neither a browser nor an app
michael@0 118 if (appId == NECKO_NO_APP_ID) {
michael@0 119 if (tabParent->HasOwnApp()) {
michael@0 120 continue;
michael@0 121 }
michael@0 122 if (UsingNeckoIPCSecurity() && tabParent->IsBrowserElement()) {
michael@0 123 // <iframe mozbrowser> which doesn't have an <iframe mozapp> above it.
michael@0 124 // This is not supported now, and we'll need to do a code audit to make
michael@0 125 // sure we can handle it (i.e don't short-circuit using separate
michael@0 126 // namespace if just appID==0)
michael@0 127 continue;
michael@0 128 }
michael@0 129 }
michael@0 130 *aAppId = appId;
michael@0 131 *aInBrowserElement = inBrowserElement;
michael@0 132 return nullptr;
michael@0 133 }
michael@0 134
michael@0 135 if (browsers.Length() != 0) {
michael@0 136 return "App does not have permission";
michael@0 137 }
michael@0 138
michael@0 139 if (!UsingNeckoIPCSecurity()) {
michael@0 140 // We are running xpcshell tests
michael@0 141 if (aSerialized.IsNotNull()) {
michael@0 142 *aAppId = aSerialized.mAppId;
michael@0 143 *aInBrowserElement = aSerialized.mIsInBrowserElement;
michael@0 144 } else {
michael@0 145 *aAppId = NECKO_NO_APP_ID;
michael@0 146 }
michael@0 147 return nullptr;
michael@0 148 }
michael@0 149
michael@0 150 return "ContentParent does not have any PBrowsers";
michael@0 151 }
michael@0 152
michael@0 153 const char *
michael@0 154 NeckoParent::CreateChannelLoadContext(PBrowserParent* aBrowser,
michael@0 155 PContentParent* aContent,
michael@0 156 const SerializedLoadContext& aSerialized,
michael@0 157 nsCOMPtr<nsILoadContext> &aResult)
michael@0 158 {
michael@0 159 uint32_t appId = NECKO_UNKNOWN_APP_ID;
michael@0 160 bool inBrowser = false;
michael@0 161 dom::Element* topFrameElement = nullptr;
michael@0 162 const char* error = GetValidatedAppInfo(aSerialized, aContent, &appId, &inBrowser);
michael@0 163 if (error) {
michael@0 164 return error;
michael@0 165 }
michael@0 166
michael@0 167 if (aBrowser) {
michael@0 168 nsRefPtr<TabParent> tabParent = static_cast<TabParent*>(aBrowser);
michael@0 169 topFrameElement = tabParent->GetOwnerElement();
michael@0 170 }
michael@0 171
michael@0 172 // if !UsingNeckoIPCSecurity(), we may not have a LoadContext to set. This is
michael@0 173 // the common case for most xpcshell tests.
michael@0 174 if (aSerialized.IsNotNull()) {
michael@0 175 aResult = new LoadContext(aSerialized, topFrameElement, appId, inBrowser);
michael@0 176 }
michael@0 177
michael@0 178 return nullptr;
michael@0 179 }
michael@0 180
michael@0 181 PHttpChannelParent*
michael@0 182 NeckoParent::AllocPHttpChannelParent(PBrowserParent* aBrowser,
michael@0 183 const SerializedLoadContext& aSerialized,
michael@0 184 const HttpChannelCreationArgs& aOpenArgs)
michael@0 185 {
michael@0 186 nsCOMPtr<nsILoadContext> loadContext;
michael@0 187 const char *error = CreateChannelLoadContext(aBrowser, Manager(),
michael@0 188 aSerialized, loadContext);
michael@0 189 if (error) {
michael@0 190 printf_stderr("NeckoParent::AllocPHttpChannelParent: "
michael@0 191 "FATAL error: %s: KILLING CHILD PROCESS\n",
michael@0 192 error);
michael@0 193 return nullptr;
michael@0 194 }
michael@0 195 PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(aSerialized);
michael@0 196 HttpChannelParent *p = new HttpChannelParent(aBrowser, loadContext, overrideStatus);
michael@0 197 p->AddRef();
michael@0 198 return p;
michael@0 199 }
michael@0 200
michael@0 201 bool
michael@0 202 NeckoParent::DeallocPHttpChannelParent(PHttpChannelParent* channel)
michael@0 203 {
michael@0 204 HttpChannelParent *p = static_cast<HttpChannelParent *>(channel);
michael@0 205 p->Release();
michael@0 206 return true;
michael@0 207 }
michael@0 208
michael@0 209 bool
michael@0 210 NeckoParent::RecvPHttpChannelConstructor(
michael@0 211 PHttpChannelParent* aActor,
michael@0 212 PBrowserParent* aBrowser,
michael@0 213 const SerializedLoadContext& aSerialized,
michael@0 214 const HttpChannelCreationArgs& aOpenArgs)
michael@0 215 {
michael@0 216 HttpChannelParent* p = static_cast<HttpChannelParent*>(aActor);
michael@0 217 return p->Init(aOpenArgs);
michael@0 218 }
michael@0 219
michael@0 220 PFTPChannelParent*
michael@0 221 NeckoParent::AllocPFTPChannelParent(PBrowserParent* aBrowser,
michael@0 222 const SerializedLoadContext& aSerialized,
michael@0 223 const FTPChannelCreationArgs& aOpenArgs)
michael@0 224 {
michael@0 225 nsCOMPtr<nsILoadContext> loadContext;
michael@0 226 const char *error = CreateChannelLoadContext(aBrowser, Manager(),
michael@0 227 aSerialized, loadContext);
michael@0 228 if (error) {
michael@0 229 printf_stderr("NeckoParent::AllocPFTPChannelParent: "
michael@0 230 "FATAL error: %s: KILLING CHILD PROCESS\n",
michael@0 231 error);
michael@0 232 return nullptr;
michael@0 233 }
michael@0 234 PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(aSerialized);
michael@0 235 FTPChannelParent *p = new FTPChannelParent(loadContext, overrideStatus);
michael@0 236 p->AddRef();
michael@0 237 return p;
michael@0 238 }
michael@0 239
michael@0 240 bool
michael@0 241 NeckoParent::DeallocPFTPChannelParent(PFTPChannelParent* channel)
michael@0 242 {
michael@0 243 FTPChannelParent *p = static_cast<FTPChannelParent *>(channel);
michael@0 244 p->Release();
michael@0 245 return true;
michael@0 246 }
michael@0 247
michael@0 248 bool
michael@0 249 NeckoParent::RecvPFTPChannelConstructor(
michael@0 250 PFTPChannelParent* aActor,
michael@0 251 PBrowserParent* aBrowser,
michael@0 252 const SerializedLoadContext& aSerialized,
michael@0 253 const FTPChannelCreationArgs& aOpenArgs)
michael@0 254 {
michael@0 255 FTPChannelParent* p = static_cast<FTPChannelParent*>(aActor);
michael@0 256 return p->Init(aOpenArgs);
michael@0 257 }
michael@0 258
michael@0 259 PCookieServiceParent*
michael@0 260 NeckoParent::AllocPCookieServiceParent()
michael@0 261 {
michael@0 262 return new CookieServiceParent();
michael@0 263 }
michael@0 264
michael@0 265 bool
michael@0 266 NeckoParent::DeallocPCookieServiceParent(PCookieServiceParent* cs)
michael@0 267 {
michael@0 268 delete cs;
michael@0 269 return true;
michael@0 270 }
michael@0 271
michael@0 272 PWyciwygChannelParent*
michael@0 273 NeckoParent::AllocPWyciwygChannelParent()
michael@0 274 {
michael@0 275 WyciwygChannelParent *p = new WyciwygChannelParent();
michael@0 276 p->AddRef();
michael@0 277 return p;
michael@0 278 }
michael@0 279
michael@0 280 bool
michael@0 281 NeckoParent::DeallocPWyciwygChannelParent(PWyciwygChannelParent* channel)
michael@0 282 {
michael@0 283 WyciwygChannelParent *p = static_cast<WyciwygChannelParent *>(channel);
michael@0 284 p->Release();
michael@0 285 return true;
michael@0 286 }
michael@0 287
michael@0 288 PWebSocketParent*
michael@0 289 NeckoParent::AllocPWebSocketParent(PBrowserParent* browser,
michael@0 290 const SerializedLoadContext& serialized)
michael@0 291 {
michael@0 292 nsCOMPtr<nsILoadContext> loadContext;
michael@0 293 const char *error = CreateChannelLoadContext(browser, Manager(),
michael@0 294 serialized, loadContext);
michael@0 295 if (error) {
michael@0 296 printf_stderr("NeckoParent::AllocPWebSocketParent: "
michael@0 297 "FATAL error: %s: KILLING CHILD PROCESS\n",
michael@0 298 error);
michael@0 299 return nullptr;
michael@0 300 }
michael@0 301
michael@0 302 TabParent* tabParent = static_cast<TabParent*>(browser);
michael@0 303 PBOverrideStatus overrideStatus = PBOverrideStatusFromLoadContext(serialized);
michael@0 304 WebSocketChannelParent* p = new WebSocketChannelParent(tabParent, loadContext,
michael@0 305 overrideStatus);
michael@0 306 p->AddRef();
michael@0 307 return p;
michael@0 308 }
michael@0 309
michael@0 310 bool
michael@0 311 NeckoParent::DeallocPWebSocketParent(PWebSocketParent* actor)
michael@0 312 {
michael@0 313 WebSocketChannelParent* p = static_cast<WebSocketChannelParent*>(actor);
michael@0 314 p->Release();
michael@0 315 return true;
michael@0 316 }
michael@0 317
michael@0 318 PRtspControllerParent*
michael@0 319 NeckoParent::AllocPRtspControllerParent()
michael@0 320 {
michael@0 321 #ifdef NECKO_PROTOCOL_rtsp
michael@0 322 RtspControllerParent* p = new RtspControllerParent();
michael@0 323 p->AddRef();
michael@0 324 return p;
michael@0 325 #else
michael@0 326 return nullptr;
michael@0 327 #endif
michael@0 328 }
michael@0 329
michael@0 330 bool
michael@0 331 NeckoParent::DeallocPRtspControllerParent(PRtspControllerParent* actor)
michael@0 332 {
michael@0 333 #ifdef NECKO_PROTOCOL_rtsp
michael@0 334 RtspControllerParent* p = static_cast<RtspControllerParent*>(actor);
michael@0 335 p->Release();
michael@0 336 #endif
michael@0 337 return true;
michael@0 338 }
michael@0 339
michael@0 340 PRtspChannelParent*
michael@0 341 NeckoParent::AllocPRtspChannelParent(const RtspChannelConnectArgs& aArgs)
michael@0 342 {
michael@0 343 #ifdef NECKO_PROTOCOL_rtsp
michael@0 344 nsCOMPtr<nsIURI> uri = DeserializeURI(aArgs.uri());
michael@0 345 RtspChannelParent *p = new RtspChannelParent(uri);
michael@0 346 p->AddRef();
michael@0 347 return p;
michael@0 348 #else
michael@0 349 return nullptr;
michael@0 350 #endif
michael@0 351 }
michael@0 352
michael@0 353 bool
michael@0 354 NeckoParent::RecvPRtspChannelConstructor(
michael@0 355 PRtspChannelParent* aActor,
michael@0 356 const RtspChannelConnectArgs& aConnectArgs)
michael@0 357 {
michael@0 358 #ifdef NECKO_PROTOCOL_rtsp
michael@0 359 RtspChannelParent* p = static_cast<RtspChannelParent*>(aActor);
michael@0 360 return p->Init(aConnectArgs);
michael@0 361 #else
michael@0 362 return nullptr;
michael@0 363 #endif
michael@0 364 }
michael@0 365
michael@0 366 bool
michael@0 367 NeckoParent::DeallocPRtspChannelParent(PRtspChannelParent* actor)
michael@0 368 {
michael@0 369 #ifdef NECKO_PROTOCOL_rtsp
michael@0 370 RtspChannelParent* p = static_cast<RtspChannelParent*>(actor);
michael@0 371 p->Release();
michael@0 372 #endif
michael@0 373 return true;
michael@0 374 }
michael@0 375
michael@0 376 PTCPSocketParent*
michael@0 377 NeckoParent::AllocPTCPSocketParent()
michael@0 378 {
michael@0 379 TCPSocketParent* p = new TCPSocketParent();
michael@0 380 p->AddIPDLReference();
michael@0 381 return p;
michael@0 382 }
michael@0 383
michael@0 384 bool
michael@0 385 NeckoParent::DeallocPTCPSocketParent(PTCPSocketParent* actor)
michael@0 386 {
michael@0 387 TCPSocketParent* p = static_cast<TCPSocketParent*>(actor);
michael@0 388 p->ReleaseIPDLReference();
michael@0 389 return true;
michael@0 390 }
michael@0 391
michael@0 392 PTCPServerSocketParent*
michael@0 393 NeckoParent::AllocPTCPServerSocketParent(const uint16_t& aLocalPort,
michael@0 394 const uint16_t& aBacklog,
michael@0 395 const nsString& aBinaryType)
michael@0 396 {
michael@0 397 TCPServerSocketParent* p = new TCPServerSocketParent();
michael@0 398 p->AddIPDLReference();
michael@0 399 return p;
michael@0 400 }
michael@0 401
michael@0 402 bool
michael@0 403 NeckoParent::RecvPTCPServerSocketConstructor(PTCPServerSocketParent* aActor,
michael@0 404 const uint16_t& aLocalPort,
michael@0 405 const uint16_t& aBacklog,
michael@0 406 const nsString& aBinaryType)
michael@0 407 {
michael@0 408 return static_cast<TCPServerSocketParent*>(aActor)->
michael@0 409 Init(this, aLocalPort, aBacklog, aBinaryType);
michael@0 410 }
michael@0 411
michael@0 412 bool
michael@0 413 NeckoParent::DeallocPTCPServerSocketParent(PTCPServerSocketParent* actor)
michael@0 414 {
michael@0 415 TCPServerSocketParent* p = static_cast<TCPServerSocketParent*>(actor);
michael@0 416 p->ReleaseIPDLReference();
michael@0 417 return true;
michael@0 418 }
michael@0 419
michael@0 420 PUDPSocketParent*
michael@0 421 NeckoParent::AllocPUDPSocketParent(const nsCString& aHost,
michael@0 422 const uint16_t& aPort,
michael@0 423 const nsCString& aFilter)
michael@0 424 {
michael@0 425 UDPSocketParent* p = nullptr;
michael@0 426
michael@0 427 // Only allow socket if it specifies a valid packet filter.
michael@0 428 nsAutoCString contractId(NS_NETWORK_UDP_SOCKET_FILTER_HANDLER_PREFIX);
michael@0 429 contractId.Append(aFilter);
michael@0 430
michael@0 431 if (!aFilter.IsEmpty()) {
michael@0 432 nsCOMPtr<nsIUDPSocketFilterHandler> filterHandler =
michael@0 433 do_GetService(contractId.get());
michael@0 434 if (filterHandler) {
michael@0 435 nsCOMPtr<nsIUDPSocketFilter> filter;
michael@0 436 nsresult rv = filterHandler->NewFilter(getter_AddRefs(filter));
michael@0 437 if (NS_SUCCEEDED(rv)) {
michael@0 438 p = new UDPSocketParent(filter);
michael@0 439 } else {
michael@0 440 printf_stderr("Cannot create filter that content specified. "
michael@0 441 "filter name: %s, error code: %d.", aFilter.get(), rv);
michael@0 442 }
michael@0 443 } else {
michael@0 444 printf_stderr("Content doesn't have a valid filter. "
michael@0 445 "filter name: %s.", aFilter.get());
michael@0 446 }
michael@0 447 }
michael@0 448
michael@0 449 NS_IF_ADDREF(p);
michael@0 450 return p;
michael@0 451 }
michael@0 452
michael@0 453 bool
michael@0 454 NeckoParent::RecvPUDPSocketConstructor(PUDPSocketParent* aActor,
michael@0 455 const nsCString& aHost,
michael@0 456 const uint16_t& aPort,
michael@0 457 const nsCString& aFilter)
michael@0 458 {
michael@0 459 return static_cast<UDPSocketParent*>(aActor)->Init(aHost, aPort);
michael@0 460 }
michael@0 461
michael@0 462 bool
michael@0 463 NeckoParent::DeallocPUDPSocketParent(PUDPSocketParent* actor)
michael@0 464 {
michael@0 465 UDPSocketParent* p = static_cast<UDPSocketParent*>(actor);
michael@0 466 p->Release();
michael@0 467 return true;
michael@0 468 }
michael@0 469
michael@0 470 PDNSRequestParent*
michael@0 471 NeckoParent::AllocPDNSRequestParent(const nsCString& aHost,
michael@0 472 const uint32_t& aFlags)
michael@0 473 {
michael@0 474 DNSRequestParent *p = new DNSRequestParent();
michael@0 475 p->AddRef();
michael@0 476 return p;
michael@0 477 }
michael@0 478
michael@0 479 bool
michael@0 480 NeckoParent::RecvPDNSRequestConstructor(PDNSRequestParent* aActor,
michael@0 481 const nsCString& aHost,
michael@0 482 const uint32_t& aFlags)
michael@0 483 {
michael@0 484 static_cast<DNSRequestParent*>(aActor)->DoAsyncResolve(aHost, aFlags);
michael@0 485 return true;
michael@0 486 }
michael@0 487
michael@0 488 bool
michael@0 489 NeckoParent::DeallocPDNSRequestParent(PDNSRequestParent* aParent)
michael@0 490 {
michael@0 491 DNSRequestParent *p = static_cast<DNSRequestParent*>(aParent);
michael@0 492 p->Release();
michael@0 493 return true;
michael@0 494 }
michael@0 495
michael@0 496 PRemoteOpenFileParent*
michael@0 497 NeckoParent::AllocPRemoteOpenFileParent(const URIParams& aURI,
michael@0 498 const OptionalURIParams& aAppURI)
michael@0 499 {
michael@0 500 nsCOMPtr<nsIURI> uri = DeserializeURI(aURI);
michael@0 501 nsCOMPtr<nsIFileURL> fileURL = do_QueryInterface(uri);
michael@0 502 if (!fileURL) {
michael@0 503 return nullptr;
michael@0 504 }
michael@0 505
michael@0 506 // security checks
michael@0 507 if (UsingNeckoIPCSecurity()) {
michael@0 508 nsCOMPtr<nsIAppsService> appsService =
michael@0 509 do_GetService(APPS_SERVICE_CONTRACTID);
michael@0 510 if (!appsService) {
michael@0 511 return nullptr;
michael@0 512 }
michael@0 513 bool haveValidBrowser = false;
michael@0 514 bool hasManage = false;
michael@0 515 nsCOMPtr<mozIApplication> mozApp;
michael@0 516 for (uint32_t i = 0; i < Manager()->ManagedPBrowserParent().Length(); i++) {
michael@0 517 nsRefPtr<TabParent> tabParent =
michael@0 518 static_cast<TabParent*>(Manager()->ManagedPBrowserParent()[i]);
michael@0 519 uint32_t appId = tabParent->OwnOrContainingAppId();
michael@0 520 nsresult rv = appsService->GetAppByLocalId(appId, getter_AddRefs(mozApp));
michael@0 521 if (NS_FAILED(rv) || !mozApp) {
michael@0 522 continue;
michael@0 523 }
michael@0 524 hasManage = false;
michael@0 525 rv = mozApp->HasPermission("webapps-manage", &hasManage);
michael@0 526 if (NS_FAILED(rv)) {
michael@0 527 continue;
michael@0 528 }
michael@0 529 haveValidBrowser = true;
michael@0 530 break;
michael@0 531 }
michael@0 532
michael@0 533 if (!haveValidBrowser) {
michael@0 534 return nullptr;
michael@0 535 }
michael@0 536
michael@0 537 nsAutoCString requestedPath;
michael@0 538 fileURL->GetPath(requestedPath);
michael@0 539 NS_UnescapeURL(requestedPath);
michael@0 540
michael@0 541 // Check if we load the whitelisted app uri for the neterror page.
michael@0 542 bool netErrorWhiteList = false;
michael@0 543
michael@0 544 nsCOMPtr<nsIURI> appUri = DeserializeURI(aAppURI);
michael@0 545 if (appUri) {
michael@0 546 nsAdoptingString netErrorURI;
michael@0 547 netErrorURI = Preferences::GetString("b2g.neterror.url");
michael@0 548 if (netErrorURI) {
michael@0 549 nsAutoCString spec;
michael@0 550 appUri->GetSpec(spec);
michael@0 551 netErrorWhiteList = spec.Equals(NS_ConvertUTF16toUTF8(netErrorURI).get());
michael@0 552 }
michael@0 553 }
michael@0 554
michael@0 555 if (hasManage || netErrorWhiteList) {
michael@0 556 // webapps-manage permission means allow reading any application.zip file
michael@0 557 // in either the regular webapps directory, or the core apps directory (if
michael@0 558 // we're using one).
michael@0 559 NS_NAMED_LITERAL_CSTRING(appzip, "/application.zip");
michael@0 560 nsAutoCString pathEnd;
michael@0 561 requestedPath.Right(pathEnd, appzip.Length());
michael@0 562 if (!pathEnd.Equals(appzip)) {
michael@0 563 return nullptr;
michael@0 564 }
michael@0 565 nsAutoCString pathStart;
michael@0 566 requestedPath.Left(pathStart, mWebAppsBasePath.Length());
michael@0 567 if (!pathStart.Equals(mWebAppsBasePath)) {
michael@0 568 if (mCoreAppsBasePath.IsEmpty()) {
michael@0 569 return nullptr;
michael@0 570 }
michael@0 571 requestedPath.Left(pathStart, mCoreAppsBasePath.Length());
michael@0 572 if (!pathStart.Equals(mCoreAppsBasePath)) {
michael@0 573 return nullptr;
michael@0 574 }
michael@0 575 }
michael@0 576 // Finally: make sure there are no "../" in URI.
michael@0 577 // Note: not checking for symlinks (would cause I/O for each path
michael@0 578 // component). So it's up to us to avoid creating symlinks that could
michael@0 579 // provide attack vectors.
michael@0 580 if (PL_strnstr(requestedPath.BeginReading(), "/../",
michael@0 581 requestedPath.Length())) {
michael@0 582 printf_stderr("NeckoParent::AllocPRemoteOpenFile: "
michael@0 583 "FATAL error: requested file URI '%s' contains '/../' "
michael@0 584 "KILLING CHILD PROCESS\n", requestedPath.get());
michael@0 585 return nullptr;
michael@0 586 }
michael@0 587 } else {
michael@0 588 // regular packaged apps can only access their own application.zip file
michael@0 589 nsAutoString basePath;
michael@0 590 nsresult rv = mozApp->GetBasePath(basePath);
michael@0 591 if (NS_FAILED(rv)) {
michael@0 592 return nullptr;
michael@0 593 }
michael@0 594 nsAutoString uuid;
michael@0 595 rv = mozApp->GetId(uuid);
michael@0 596 if (NS_FAILED(rv)) {
michael@0 597 return nullptr;
michael@0 598 }
michael@0 599 nsPrintfCString mustMatch("%s/%s/application.zip",
michael@0 600 NS_LossyConvertUTF16toASCII(basePath).get(),
michael@0 601 NS_LossyConvertUTF16toASCII(uuid).get());
michael@0 602 if (!requestedPath.Equals(mustMatch)) {
michael@0 603 printf_stderr("NeckoParent::AllocPRemoteOpenFile: "
michael@0 604 "FATAL error: app without webapps-manage permission is "
michael@0 605 "requesting file '%s' but is only allowed to open its "
michael@0 606 "own application.zip at %s: KILLING CHILD PROCESS\n",
michael@0 607 requestedPath.get(), mustMatch.get());
michael@0 608 return nullptr;
michael@0 609 }
michael@0 610 }
michael@0 611 }
michael@0 612
michael@0 613 RemoteOpenFileParent* parent = new RemoteOpenFileParent(fileURL);
michael@0 614 return parent;
michael@0 615 }
michael@0 616
michael@0 617 bool
michael@0 618 NeckoParent::RecvPRemoteOpenFileConstructor(PRemoteOpenFileParent* aActor,
michael@0 619 const URIParams& aFileURI,
michael@0 620 const OptionalURIParams& aAppURI)
michael@0 621 {
michael@0 622 return static_cast<RemoteOpenFileParent*>(aActor)->OpenSendCloseDelete();
michael@0 623 }
michael@0 624
michael@0 625 bool
michael@0 626 NeckoParent::DeallocPRemoteOpenFileParent(PRemoteOpenFileParent* actor)
michael@0 627 {
michael@0 628 delete actor;
michael@0 629 return true;
michael@0 630 }
michael@0 631
michael@0 632 bool
michael@0 633 NeckoParent::RecvHTMLDNSPrefetch(const nsString& hostname,
michael@0 634 const uint16_t& flags)
michael@0 635 {
michael@0 636 nsHTMLDNSPrefetch::Prefetch(hostname, flags);
michael@0 637 return true;
michael@0 638 }
michael@0 639
michael@0 640 bool
michael@0 641 NeckoParent::RecvCancelHTMLDNSPrefetch(const nsString& hostname,
michael@0 642 const uint16_t& flags,
michael@0 643 const nsresult& reason)
michael@0 644 {
michael@0 645 nsHTMLDNSPrefetch::CancelPrefetch(hostname, flags, reason);
michael@0 646 return true;
michael@0 647 }
michael@0 648
michael@0 649 PChannelDiverterParent*
michael@0 650 NeckoParent::AllocPChannelDiverterParent(const ChannelDiverterArgs& channel)
michael@0 651 {
michael@0 652 return new ChannelDiverterParent();
michael@0 653 }
michael@0 654
michael@0 655 bool
michael@0 656 NeckoParent::RecvPChannelDiverterConstructor(PChannelDiverterParent* actor,
michael@0 657 const ChannelDiverterArgs& channel)
michael@0 658 {
michael@0 659 auto parent = static_cast<ChannelDiverterParent*>(actor);
michael@0 660 parent->Init(channel);
michael@0 661 return true;
michael@0 662 }
michael@0 663
michael@0 664 bool
michael@0 665 NeckoParent::DeallocPChannelDiverterParent(PChannelDiverterParent* parent)
michael@0 666 {
michael@0 667 delete static_cast<ChannelDiverterParent*>(parent);
michael@0 668 return true;
michael@0 669 }
michael@0 670
michael@0 671 void
michael@0 672 NeckoParent::CloneManagees(ProtocolBase* aSource,
michael@0 673 mozilla::ipc::ProtocolCloneContext* aCtx)
michael@0 674 {
michael@0 675 aCtx->SetNeckoParent(this); // For cloning protocols managed by this.
michael@0 676 PNeckoParent::CloneManagees(aSource, aCtx);
michael@0 677 }
michael@0 678
michael@0 679 mozilla::ipc::IProtocol*
michael@0 680 NeckoParent::CloneProtocol(Channel* aChannel,
michael@0 681 mozilla::ipc::ProtocolCloneContext* aCtx)
michael@0 682 {
michael@0 683 ContentParent* contentParent = aCtx->GetContentParent();
michael@0 684 nsAutoPtr<PNeckoParent> actor(contentParent->AllocPNeckoParent());
michael@0 685 if (!actor || !contentParent->RecvPNeckoConstructor(actor)) {
michael@0 686 return nullptr;
michael@0 687 }
michael@0 688 return actor.forget();
michael@0 689 }
michael@0 690
michael@0 691 }} // mozilla::net

mercurial