1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include "ServiceWorkerCloneData.h"
8 
9 #include <utility>
10 #include "mozilla/RefPtr.h"
11 #include "mozilla/dom/DOMTypes.h"
12 #include "mozilla/dom/StructuredCloneHolder.h"
13 #include "nsISerialEventTarget.h"
14 #include "nsProxyRelease.h"
15 #include "nsThreadUtils.h"
16 
17 namespace mozilla {
18 namespace dom {
19 
~ServiceWorkerCloneData()20 ServiceWorkerCloneData::~ServiceWorkerCloneData() {
21   RefPtr<ipc::SharedJSAllocatedData> sharedData = TakeSharedData();
22   if (sharedData) {
23     NS_ProxyRelease(__func__, mEventTarget, sharedData.forget());
24   }
25 }
26 
ServiceWorkerCloneData()27 ServiceWorkerCloneData::ServiceWorkerCloneData()
28     : ipc::StructuredCloneData(
29           StructuredCloneHolder::StructuredCloneScope::UnknownDestination,
30           StructuredCloneHolder::TransferringSupported),
31       mEventTarget(GetCurrentSerialEventTarget()),
32       mIsErrorMessageData(false) {
33   MOZ_DIAGNOSTIC_ASSERT(mEventTarget);
34 }
35 
36 bool ServiceWorkerCloneData::
StealFromAndBuildClonedMessageDataForBackgroundParent(ClonedOrErrorMessageData & aFromClonedData,mozilla::ipc::PBackgroundParent * aParent,ClonedOrErrorMessageData & aToClonedData)37     StealFromAndBuildClonedMessageDataForBackgroundParent(
38         ClonedOrErrorMessageData& aFromClonedData,
39         mozilla::ipc::PBackgroundParent* aParent,
40         ClonedOrErrorMessageData& aToClonedData) {
41   if (aFromClonedData.type() == ClonedOrErrorMessageData::TErrorMessageData) {
42     mIsErrorMessageData = true;
43     aToClonedData = ErrorMessageData();
44     return true;
45   }
46 
47   MOZ_DIAGNOSTIC_ASSERT(aFromClonedData.type() ==
48                         ClonedOrErrorMessageData::TClonedMessageData);
49 
50   StructuredCloneData::StealFromClonedMessageDataForBackgroundParent(
51       aFromClonedData);
52 
53   ClonedMessageData messageData;
54   if (!StructuredCloneData::BuildClonedMessageDataForBackgroundParent(
55           aParent, messageData)) {
56     return false;
57   }
58 
59   aToClonedData = std::move(messageData);
60 
61   return true;
62 }
63 
BuildClonedMessageDataForBackgroundChild(mozilla::ipc::PBackgroundChild * aChild,ClonedOrErrorMessageData & aClonedData)64 bool ServiceWorkerCloneData::BuildClonedMessageDataForBackgroundChild(
65     mozilla::ipc::PBackgroundChild* aChild,
66     ClonedOrErrorMessageData& aClonedData) {
67   if (IsErrorMessageData()) {
68     aClonedData = ErrorMessageData();
69     return true;
70   }
71 
72   MOZ_DIAGNOSTIC_ASSERT(
73       CloneScope() ==
74       StructuredCloneHolder::StructuredCloneScope::DifferentProcess);
75 
76   ClonedMessageData messageData;
77   if (!StructuredCloneData::BuildClonedMessageDataForBackgroundChild(
78           aChild, messageData)) {
79     return false;
80   }
81 
82   aClonedData = std::move(messageData);
83 
84   return true;
85 }
86 
CopyFromClonedMessageDataForBackgroundParent(const ClonedOrErrorMessageData & aClonedData)87 void ServiceWorkerCloneData::CopyFromClonedMessageDataForBackgroundParent(
88     const ClonedOrErrorMessageData& aClonedData) {
89   if (aClonedData.type() == ClonedOrErrorMessageData::TErrorMessageData) {
90     mIsErrorMessageData = true;
91     return;
92   }
93 
94   MOZ_DIAGNOSTIC_ASSERT(aClonedData.type() ==
95                         ClonedOrErrorMessageData::TClonedMessageData);
96 
97   StructuredCloneData::CopyFromClonedMessageDataForBackgroundParent(
98       aClonedData);
99 }
100 
CopyFromClonedMessageDataForBackgroundChild(const ClonedOrErrorMessageData & aClonedData)101 void ServiceWorkerCloneData::CopyFromClonedMessageDataForBackgroundChild(
102     const ClonedOrErrorMessageData& aClonedData) {
103   if (aClonedData.type() == ClonedOrErrorMessageData::TErrorMessageData) {
104     mIsErrorMessageData = true;
105     return;
106   }
107 
108   MOZ_DIAGNOSTIC_ASSERT(aClonedData.type() ==
109                         ClonedOrErrorMessageData::TClonedMessageData);
110 
111   StructuredCloneData::CopyFromClonedMessageDataForBackgroundChild(aClonedData);
112 }
113 
SetAsErrorMessageData()114 void ServiceWorkerCloneData::SetAsErrorMessageData() {
115   MOZ_ASSERT(CloneScope() ==
116              StructuredCloneHolder::StructuredCloneScope::SameProcess);
117 
118   mIsErrorMessageData = true;
119 }
120 
IsErrorMessageData() const121 bool ServiceWorkerCloneData::IsErrorMessageData() const {
122   return mIsErrorMessageData;
123 }
124 
125 }  // namespace dom
126 }  // namespace mozilla
127