1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "third_party/blink/renderer/modules/background_sync/sync_manager.h"
6
7 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
8 #include "third_party/blink/public/platform/platform.h"
9 #include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
10 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
11 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
12 #include "third_party/blink/renderer/core/dom/dom_exception.h"
13 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
14 #include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
15 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
16 #include "third_party/blink/renderer/platform/bindings/script_state.h"
17 #include "third_party/blink/renderer/platform/heap/heap.h"
18 #include "third_party/blink/renderer/platform/heap/persistent.h"
19 #include "third_party/blink/renderer/platform/wtf/functional.h"
20
21 namespace blink {
22
SyncManager(ServiceWorkerRegistration * registration,scoped_refptr<base::SequencedTaskRunner> task_runner)23 SyncManager::SyncManager(ServiceWorkerRegistration* registration,
24 scoped_refptr<base::SequencedTaskRunner> task_runner)
25 : registration_(registration),
26 background_sync_service_(registration->GetExecutionContext()) {
27 DCHECK(registration);
28 registration->GetExecutionContext()->GetBrowserInterfaceBroker().GetInterface(
29 background_sync_service_.BindNewPipeAndPassReceiver(task_runner));
30 }
31
registerFunction(ScriptState * script_state,const String & tag,ExceptionState & exception_state)32 ScriptPromise SyncManager::registerFunction(ScriptState* script_state,
33 const String& tag,
34 ExceptionState& exception_state) {
35 if (!registration_->active()) {
36 exception_state.ThrowDOMException(
37 DOMExceptionCode::kInvalidStateError,
38 "Registration failed - no active Service Worker");
39 return ScriptPromise();
40 }
41
42 auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
43 ScriptPromise promise = resolver->Promise();
44
45 mojom::blink::SyncRegistrationOptionsPtr sync_registration =
46 mojom::blink::SyncRegistrationOptions::New();
47 sync_registration->tag = tag;
48
49 background_sync_service_->Register(
50 std::move(sync_registration), registration_->RegistrationId(),
51 WTF::Bind(&SyncManager::RegisterCallback, WrapPersistent(this),
52 WrapPersistent(resolver)));
53
54 return promise;
55 }
56
getTags(ScriptState * script_state)57 ScriptPromise SyncManager::getTags(ScriptState* script_state) {
58 auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
59 ScriptPromise promise = resolver->Promise();
60
61 background_sync_service_->GetRegistrations(
62 registration_->RegistrationId(),
63 WTF::Bind(&SyncManager::GetRegistrationsCallback,
64 WrapPersistent(resolver)));
65
66 return promise;
67 }
68
RegisterCallback(ScriptPromiseResolver * resolver,mojom::blink::BackgroundSyncError error,mojom::blink::SyncRegistrationOptionsPtr options)69 void SyncManager::RegisterCallback(
70 ScriptPromiseResolver* resolver,
71 mojom::blink::BackgroundSyncError error,
72 mojom::blink::SyncRegistrationOptionsPtr options) {
73 // TODO(iclelland): Determine the correct error message to return in each case
74 switch (error) {
75 case mojom::blink::BackgroundSyncError::NONE:
76 if (!options) {
77 resolver->Resolve(v8::Null(resolver->GetScriptState()->GetIsolate()));
78 return;
79 }
80 resolver->Resolve();
81 // Let the service know that the registration promise is resolved so that
82 // it can fire the event.
83
84 background_sync_service_->DidResolveRegistration(
85 mojom::blink::BackgroundSyncRegistrationInfo::New(
86 registration_->RegistrationId(), options->tag,
87 mojom::blink::BackgroundSyncType::ONE_SHOT));
88 break;
89 case mojom::blink::BackgroundSyncError::NOT_FOUND:
90 NOTREACHED();
91 break;
92 case mojom::blink::BackgroundSyncError::STORAGE:
93 resolver->Reject(MakeGarbageCollected<DOMException>(
94 DOMExceptionCode::kUnknownError, "Background Sync is disabled."));
95 break;
96 case mojom::blink::BackgroundSyncError::NOT_ALLOWED:
97 resolver->Reject(MakeGarbageCollected<DOMException>(
98 DOMExceptionCode::kInvalidAccessError,
99 "Attempted to register a sync event without a "
100 "window or registration tag too long."));
101 break;
102 case mojom::blink::BackgroundSyncError::PERMISSION_DENIED:
103 resolver->Reject(MakeGarbageCollected<DOMException>(
104 DOMExceptionCode::kNotAllowedError, "Permission denied."));
105 break;
106 case mojom::blink::BackgroundSyncError::NO_SERVICE_WORKER:
107 resolver->Reject(MakeGarbageCollected<DOMException>(
108 DOMExceptionCode::kInvalidStateError,
109 "Registration failed - no active Service Worker"));
110 break;
111 }
112 }
113
114 // static
GetRegistrationsCallback(ScriptPromiseResolver * resolver,mojom::blink::BackgroundSyncError error,WTF::Vector<mojom::blink::SyncRegistrationOptionsPtr> registrations)115 void SyncManager::GetRegistrationsCallback(
116 ScriptPromiseResolver* resolver,
117 mojom::blink::BackgroundSyncError error,
118 WTF::Vector<mojom::blink::SyncRegistrationOptionsPtr> registrations) {
119 // TODO(iclelland): Determine the correct error message to return in each case
120 switch (error) {
121 case mojom::blink::BackgroundSyncError::NONE: {
122 Vector<String> tags;
123 for (const auto& r : registrations) {
124 tags.push_back(r->tag);
125 }
126 resolver->Resolve(tags);
127 break;
128 }
129 case mojom::blink::BackgroundSyncError::NOT_FOUND:
130 case mojom::blink::BackgroundSyncError::NOT_ALLOWED:
131 case mojom::blink::BackgroundSyncError::PERMISSION_DENIED:
132 // These errors should never be returned from
133 // BackgroundSyncManager::GetRegistrations
134 NOTREACHED();
135 break;
136 case mojom::blink::BackgroundSyncError::STORAGE:
137 resolver->Reject(MakeGarbageCollected<DOMException>(
138 DOMExceptionCode::kUnknownError, "Background Sync is disabled."));
139 break;
140 case mojom::blink::BackgroundSyncError::NO_SERVICE_WORKER:
141 resolver->Reject(MakeGarbageCollected<DOMException>(
142 DOMExceptionCode::kUnknownError, "No service worker is active."));
143 break;
144 }
145 }
146
Trace(Visitor * visitor) const147 void SyncManager::Trace(Visitor* visitor) const {
148 visitor->Trace(registration_);
149 visitor->Trace(background_sync_service_);
150 ScriptWrappable::Trace(visitor);
151 }
152
153 } // namespace blink
154