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