blob: 8e13b62d69b8912cc8395bfe7b6231cee485bddd [file] [log] [blame]
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/background_sync/sync_manager.h"
#include "third_party/blink/public/platform/interface_provider.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/callback_promise_adapter.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/service_worker/service_worker_registration.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/heap/persistent.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
namespace blink {
SyncManager::SyncManager(ServiceWorkerRegistration* registration,
scoped_refptr<base::SequencedTaskRunner> task_runner)
: registration_(registration), task_runner_(std::move(task_runner)) {
DCHECK(registration);
}
ScriptPromise SyncManager::registerFunction(ScriptState* script_state,
const String& tag) {
if (!registration_->active()) {
return ScriptPromise::RejectWithDOMException(
script_state, MakeGarbageCollected<DOMException>(
DOMExceptionCode::kInvalidStateError,
"Registration failed - no active Service Worker"));
}
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
mojom::blink::SyncRegistrationOptionsPtr sync_registration =
mojom::blink::SyncRegistrationOptions::New();
sync_registration->tag = tag;
GetBackgroundSyncServicePtr()->Register(
std::move(sync_registration), registration_->RegistrationId(),
WTF::Bind(&SyncManager::RegisterCallback, WrapPersistent(this),
WrapPersistent(resolver)));
return promise;
}
ScriptPromise SyncManager::getTags(ScriptState* script_state) {
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
ScriptPromise promise = resolver->Promise();
GetBackgroundSyncServicePtr()->GetOneShotSyncRegistrations(
registration_->RegistrationId(),
WTF::Bind(&SyncManager::GetRegistrationsCallback,
WrapPersistent(resolver)));
return promise;
}
const mojom::blink::BackgroundSyncServicePtr&
SyncManager::GetBackgroundSyncServicePtr() {
if (!background_sync_service_.get()) {
Platform::Current()->GetInterfaceProvider()->GetInterface(
mojo::MakeRequest(&background_sync_service_, task_runner_));
}
return background_sync_service_;
}
void SyncManager::RegisterCallback(
ScriptPromiseResolver* resolver,
mojom::blink::BackgroundSyncError error,
mojom::blink::SyncRegistrationOptionsPtr options) {
// TODO(iclelland): Determine the correct error message to return in each case
switch (error) {
case mojom::blink::BackgroundSyncError::NONE:
if (!options) {
resolver->Resolve(v8::Null(resolver->GetScriptState()->GetIsolate()));
return;
}
resolver->Resolve();
// Let the service know that the registration promise is resolved so that
// it can fire the event.
GetBackgroundSyncServicePtr()->DidResolveRegistration(
mojom::blink::BackgroundSyncRegistrationInfo::New(
registration_->RegistrationId(), options->tag,
mojom::blink::BackgroundSyncType::ONE_SHOT));
break;
case mojom::blink::BackgroundSyncError::NOT_FOUND:
NOTREACHED();
break;
case mojom::blink::BackgroundSyncError::STORAGE:
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kUnknownError, "Background Sync is disabled."));
break;
case mojom::blink::BackgroundSyncError::NOT_ALLOWED:
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kInvalidAccessError,
"Attempted to register a sync event without a "
"window or registration tag too long."));
break;
case mojom::blink::BackgroundSyncError::PERMISSION_DENIED:
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kNotAllowedError, "Permission denied."));
break;
case mojom::blink::BackgroundSyncError::NO_SERVICE_WORKER:
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kUnknownError, "No service worker is active."));
break;
}
}
// static
void SyncManager::GetRegistrationsCallback(
ScriptPromiseResolver* resolver,
mojom::blink::BackgroundSyncError error,
WTF::Vector<mojom::blink::SyncRegistrationOptionsPtr> registrations) {
// TODO(iclelland): Determine the correct error message to return in each case
switch (error) {
case mojom::blink::BackgroundSyncError::NONE: {
Vector<String> tags;
for (const auto& r : registrations) {
tags.push_back(r->tag);
}
resolver->Resolve(tags);
break;
}
case mojom::blink::BackgroundSyncError::NOT_FOUND:
case mojom::blink::BackgroundSyncError::NOT_ALLOWED:
case mojom::blink::BackgroundSyncError::PERMISSION_DENIED:
// These errors should never be returned from
// BackgroundSyncManager::GetOneShotSyncRegistrations
NOTREACHED();
break;
case mojom::blink::BackgroundSyncError::STORAGE:
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kUnknownError, "Background Sync is disabled."));
break;
case mojom::blink::BackgroundSyncError::NO_SERVICE_WORKER:
resolver->Reject(MakeGarbageCollected<DOMException>(
DOMExceptionCode::kUnknownError, "No service worker is active."));
break;
}
}
void SyncManager::Trace(blink::Visitor* visitor) {
visitor->Trace(registration_);
ScriptWrappable::Trace(visitor);
}
} // namespace blink