ServiceWorkerRegistrationDescriptor.cpp (8870B)
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 "mozilla/dom/ServiceWorkerRegistrationDescriptor.h" 8 9 #include "ServiceWorkerInfo.h" 10 #include "mozilla/dom/IPCServiceWorkerRegistrationDescriptor.h" 11 #include "mozilla/ipc/PBackgroundSharedTypes.h" 12 13 namespace mozilla::dom { 14 15 using mozilla::ipc::PrincipalInfo; 16 using mozilla::ipc::PrincipalInfoToPrincipal; 17 18 Maybe<IPCServiceWorkerDescriptor> 19 ServiceWorkerRegistrationDescriptor::NewestInternal() const { 20 Maybe<IPCServiceWorkerDescriptor> result; 21 if (mData->installing().isSome()) { 22 result.emplace(mData->installing().ref()); 23 } else if (mData->waiting().isSome()) { 24 result.emplace(mData->waiting().ref()); 25 } else if (mData->active().isSome()) { 26 result.emplace(mData->active().ref()); 27 } 28 return result; 29 } 30 31 ServiceWorkerRegistrationDescriptor::ServiceWorkerRegistrationDescriptor( 32 uint64_t aId, uint64_t aVersion, nsIPrincipal* aPrincipal, 33 const nsACString& aScope, WorkerType aType, 34 ServiceWorkerUpdateViaCache aUpdateViaCache) 35 : mData(MakeUnique<IPCServiceWorkerRegistrationDescriptor>()) { 36 MOZ_ALWAYS_SUCCEEDS( 37 PrincipalToPrincipalInfo(aPrincipal, &mData->principalInfo())); 38 39 mData->id() = aId; 40 mData->version() = aVersion; 41 mData->scope() = aScope; 42 mData->type() = aType; 43 mData->updateViaCache() = aUpdateViaCache; 44 mData->installing() = Nothing(); 45 mData->waiting() = Nothing(); 46 mData->active() = Nothing(); 47 } 48 49 ServiceWorkerRegistrationDescriptor::ServiceWorkerRegistrationDescriptor( 50 uint64_t aId, uint64_t aVersion, 51 const mozilla::ipc::PrincipalInfo& aPrincipalInfo, const nsACString& aScope, 52 WorkerType aType, ServiceWorkerUpdateViaCache aUpdateViaCache) 53 : mData(MakeUnique<IPCServiceWorkerRegistrationDescriptor>( 54 aId, aVersion, aPrincipalInfo, nsCString(aScope), aType, 55 aUpdateViaCache, Nothing(), Nothing(), Nothing())) {} 56 57 ServiceWorkerRegistrationDescriptor::ServiceWorkerRegistrationDescriptor( 58 const IPCServiceWorkerRegistrationDescriptor& aDescriptor) 59 : mData(MakeUnique<IPCServiceWorkerRegistrationDescriptor>(aDescriptor)) { 60 #ifndef FUZZING_SNAPSHOT 61 MOZ_DIAGNOSTIC_ASSERT(IsValid()); 62 #endif 63 } 64 65 ServiceWorkerRegistrationDescriptor::ServiceWorkerRegistrationDescriptor( 66 const ServiceWorkerRegistrationDescriptor& aRight) { 67 // UniquePtr doesn't have a default copy constructor, so we can't rely 68 // on default copy construction. Use the assignment operator to 69 // minimize duplication. 70 operator=(aRight); 71 } 72 73 ServiceWorkerRegistrationDescriptor& 74 ServiceWorkerRegistrationDescriptor::operator=( 75 const ServiceWorkerRegistrationDescriptor& aRight) { 76 if (this == &aRight) { 77 return *this; 78 } 79 mData.reset(); 80 mData = MakeUnique<IPCServiceWorkerRegistrationDescriptor>(*aRight.mData); 81 MOZ_DIAGNOSTIC_ASSERT(IsValid()); 82 return *this; 83 } 84 85 ServiceWorkerRegistrationDescriptor::ServiceWorkerRegistrationDescriptor( 86 ServiceWorkerRegistrationDescriptor&& aRight) 87 : mData(std::move(aRight.mData)) { 88 MOZ_DIAGNOSTIC_ASSERT(IsValid()); 89 } 90 91 ServiceWorkerRegistrationDescriptor& 92 ServiceWorkerRegistrationDescriptor::operator=( 93 ServiceWorkerRegistrationDescriptor&& aRight) { 94 mData.reset(); 95 mData = std::move(aRight.mData); 96 MOZ_DIAGNOSTIC_ASSERT(IsValid()); 97 return *this; 98 } 99 100 ServiceWorkerRegistrationDescriptor::~ServiceWorkerRegistrationDescriptor() { 101 // Non-default destructor to avoid exposing the IPC type in the header. 102 } 103 104 bool ServiceWorkerRegistrationDescriptor::operator==( 105 const ServiceWorkerRegistrationDescriptor& aRight) const { 106 return *mData == *aRight.mData; 107 } 108 109 uint64_t ServiceWorkerRegistrationDescriptor::Id() const { return mData->id(); } 110 111 uint64_t ServiceWorkerRegistrationDescriptor::Version() const { 112 return mData->version(); 113 } 114 115 ServiceWorkerUpdateViaCache 116 ServiceWorkerRegistrationDescriptor::UpdateViaCache() const { 117 return mData->updateViaCache(); 118 } 119 120 const mozilla::ipc::PrincipalInfo& 121 ServiceWorkerRegistrationDescriptor::PrincipalInfo() const { 122 return mData->principalInfo(); 123 } 124 125 Result<nsCOMPtr<nsIPrincipal>, nsresult> 126 ServiceWorkerRegistrationDescriptor::GetPrincipal() const { 127 AssertIsOnMainThread(); 128 return PrincipalInfoToPrincipal(mData->principalInfo()); 129 } 130 131 const nsCString& ServiceWorkerRegistrationDescriptor::Scope() const { 132 return mData->scope(); 133 } 134 135 WorkerType ServiceWorkerRegistrationDescriptor::Type() const { 136 return mData->type(); 137 } 138 139 Maybe<ServiceWorkerDescriptor> 140 ServiceWorkerRegistrationDescriptor::GetInstalling() const { 141 Maybe<ServiceWorkerDescriptor> result; 142 143 if (mData->installing().isSome()) { 144 result.emplace(ServiceWorkerDescriptor(mData->installing().ref())); 145 } 146 147 return result; 148 } 149 150 Maybe<ServiceWorkerDescriptor> ServiceWorkerRegistrationDescriptor::GetWaiting() 151 const { 152 Maybe<ServiceWorkerDescriptor> result; 153 154 if (mData->waiting().isSome()) { 155 result.emplace(ServiceWorkerDescriptor(mData->waiting().ref())); 156 } 157 158 return result; 159 } 160 161 Maybe<ServiceWorkerDescriptor> ServiceWorkerRegistrationDescriptor::GetActive() 162 const { 163 Maybe<ServiceWorkerDescriptor> result; 164 165 if (mData->active().isSome()) { 166 result.emplace(ServiceWorkerDescriptor(mData->active().ref())); 167 } 168 169 return result; 170 } 171 172 Maybe<ServiceWorkerDescriptor> ServiceWorkerRegistrationDescriptor::Newest() 173 const { 174 Maybe<ServiceWorkerDescriptor> result; 175 Maybe<IPCServiceWorkerDescriptor> newest(NewestInternal()); 176 if (newest.isSome()) { 177 result.emplace(ServiceWorkerDescriptor(newest.ref())); 178 } 179 return result; 180 } 181 182 bool ServiceWorkerRegistrationDescriptor::HasWorker( 183 const ServiceWorkerDescriptor& aDescriptor) const { 184 Maybe<ServiceWorkerDescriptor> installing = GetInstalling(); 185 Maybe<ServiceWorkerDescriptor> waiting = GetWaiting(); 186 Maybe<ServiceWorkerDescriptor> active = GetActive(); 187 return (installing.isSome() && installing.ref().Matches(aDescriptor)) || 188 (waiting.isSome() && waiting.ref().Matches(aDescriptor)) || 189 (active.isSome() && active.ref().Matches(aDescriptor)); 190 } 191 192 namespace { 193 194 bool IsValidWorker( 195 const Maybe<IPCServiceWorkerDescriptor>& aWorker, const nsACString& aScope, 196 const mozilla::ipc::ContentPrincipalInfo& aContentPrincipal) { 197 if (aWorker.isNothing()) { 198 return true; 199 } 200 201 auto& worker = aWorker.ref(); 202 if (worker.scope() != aScope) { 203 return false; 204 } 205 206 auto& principalInfo = worker.principalInfo(); 207 if (principalInfo.type() != 208 mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) { 209 return false; 210 } 211 212 auto& contentPrincipal = principalInfo.get_ContentPrincipalInfo(); 213 if (contentPrincipal.originNoSuffix() != aContentPrincipal.originNoSuffix() || 214 contentPrincipal.attrs() != aContentPrincipal.attrs()) { 215 return false; 216 } 217 218 return true; 219 } 220 221 } // anonymous namespace 222 223 bool ServiceWorkerRegistrationDescriptor::IsValid() const { 224 auto& principalInfo = PrincipalInfo(); 225 if (principalInfo.type() != 226 mozilla::ipc::PrincipalInfo::TContentPrincipalInfo) { 227 return false; 228 } 229 230 auto& contentPrincipal = principalInfo.get_ContentPrincipalInfo(); 231 if (!IsValidWorker(mData->installing(), Scope(), contentPrincipal) || 232 !IsValidWorker(mData->waiting(), Scope(), contentPrincipal) || 233 !IsValidWorker(mData->active(), Scope(), contentPrincipal)) { 234 return false; 235 } 236 237 return true; 238 } 239 240 void ServiceWorkerRegistrationDescriptor::SetUpdateViaCache( 241 ServiceWorkerUpdateViaCache aUpdateViaCache) { 242 mData->updateViaCache() = aUpdateViaCache; 243 } 244 245 void ServiceWorkerRegistrationDescriptor::SetWorkerType(WorkerType aType) { 246 mData->type() = aType; 247 } 248 249 void ServiceWorkerRegistrationDescriptor::SetWorkers( 250 ServiceWorkerInfo* aInstalling, ServiceWorkerInfo* aWaiting, 251 ServiceWorkerInfo* aActive) { 252 if (aInstalling) { 253 aInstalling->SetRegistrationVersion(Version()); 254 mData->installing() = Some(aInstalling->Descriptor().ToIPC()); 255 } else { 256 mData->installing() = Nothing(); 257 } 258 259 if (aWaiting) { 260 aWaiting->SetRegistrationVersion(Version()); 261 mData->waiting() = Some(aWaiting->Descriptor().ToIPC()); 262 } else { 263 mData->waiting() = Nothing(); 264 } 265 266 if (aActive) { 267 aActive->SetRegistrationVersion(Version()); 268 mData->active() = Some(aActive->Descriptor().ToIPC()); 269 } else { 270 mData->active() = Nothing(); 271 } 272 273 MOZ_DIAGNOSTIC_ASSERT(IsValid()); 274 } 275 276 void ServiceWorkerRegistrationDescriptor::SetVersion(uint64_t aVersion) { 277 MOZ_DIAGNOSTIC_ASSERT(aVersion > mData->version()); 278 mData->version() = aVersion; 279 } 280 281 const IPCServiceWorkerRegistrationDescriptor& 282 ServiceWorkerRegistrationDescriptor::ToIPC() const { 283 return *mData; 284 } 285 286 } // namespace mozilla::dom