blob: a65b82d9e442c078ce0c25068b5a803a3113bc8e [file] [log] [blame]
// Copyright 2017 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 "content/browser/background_fetch/background_fetch_service_impl.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/optional.h"
#include "content/browser/background_fetch/background_fetch_context.h"
#include "content/browser/background_fetch/background_fetch_job_controller.h"
#include "content/browser/background_fetch/background_fetch_registration_id.h"
#include "content/browser/bad_message.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/background_fetch/background_fetch_types.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_thread.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "url/origin.h"
namespace content {
namespace {
// Maximum length of a developer-provided id for a Background Fetch.
constexpr size_t kMaxIdLength = 1024 * 1024;
// Maximum length of a developer-provided title for a Background Fetch.
constexpr size_t kMaxTitleLength = 1024 * 1024;
} // namespace
// static
void BackgroundFetchServiceImpl::Create(
int render_process_id,
scoped_refptr<BackgroundFetchContext> background_fetch_context,
blink::mojom::BackgroundFetchServiceRequest request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
mojo::MakeStrongBinding(
base::MakeUnique<BackgroundFetchServiceImpl>(
render_process_id, std::move(background_fetch_context)),
std::move(request));
}
BackgroundFetchServiceImpl::BackgroundFetchServiceImpl(
int render_process_id,
scoped_refptr<BackgroundFetchContext> background_fetch_context)
: render_process_id_(render_process_id),
background_fetch_context_(std::move(background_fetch_context)) {
DCHECK(background_fetch_context_);
}
BackgroundFetchServiceImpl::~BackgroundFetchServiceImpl() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
}
void BackgroundFetchServiceImpl::Fetch(
int64_t service_worker_registration_id,
const url::Origin& origin,
const std::string& id,
const std::vector<ServiceWorkerFetchRequest>& requests,
const BackgroundFetchOptions& options,
FetchCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!ValidateId(id)) {
std::move(callback).Run(
blink::mojom::BackgroundFetchError::INVALID_ARGUMENT,
base::nullopt /* registration */);
return;
}
if (!ValidateRequests(requests)) {
std::move(callback).Run(
blink::mojom::BackgroundFetchError::INVALID_ARGUMENT,
base::nullopt /* registration */);
return;
}
BackgroundFetchRegistrationId registration_id(service_worker_registration_id,
origin, id);
background_fetch_context_->StartFetch(registration_id, requests, options,
std::move(callback));
}
void BackgroundFetchServiceImpl::UpdateUI(
int64_t service_worker_registration_id,
const url::Origin& origin,
const std::string& id,
const std::string& title,
UpdateUICallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!ValidateId(id) || !ValidateTitle(title)) {
std::move(callback).Run(
blink::mojom::BackgroundFetchError::INVALID_ARGUMENT);
return;
}
BackgroundFetchJobController* controller =
background_fetch_context_->GetActiveFetch(BackgroundFetchRegistrationId(
service_worker_registration_id, origin, id));
if (controller)
controller->UpdateUI(title);
std::move(callback).Run(controller
? blink::mojom::BackgroundFetchError::NONE
: blink::mojom::BackgroundFetchError::INVALID_ID);
}
void BackgroundFetchServiceImpl::Abort(int64_t service_worker_registration_id,
const url::Origin& origin,
const std::string& id,
AbortCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!ValidateId(id)) {
std::move(callback).Run(
blink::mojom::BackgroundFetchError::INVALID_ARGUMENT);
return;
}
BackgroundFetchJobController* controller =
background_fetch_context_->GetActiveFetch(BackgroundFetchRegistrationId(
service_worker_registration_id, origin, id));
if (controller)
controller->Abort();
std::move(callback).Run(controller
? blink::mojom::BackgroundFetchError::NONE
: blink::mojom::BackgroundFetchError::INVALID_ID);
}
void BackgroundFetchServiceImpl::GetRegistration(
int64_t service_worker_registration_id,
const url::Origin& origin,
const std::string& id,
GetRegistrationCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!ValidateId(id)) {
std::move(callback).Run(
blink::mojom::BackgroundFetchError::INVALID_ARGUMENT,
base::nullopt /* registration */);
return;
}
BackgroundFetchJobController* controller =
background_fetch_context_->GetActiveFetch(BackgroundFetchRegistrationId(
service_worker_registration_id, origin, id));
if (!controller) {
std::move(callback).Run(blink::mojom::BackgroundFetchError::INVALID_ID,
base::nullopt /* registration */);
return;
}
// Compile the BackgroundFetchRegistration object that will be given to the
// developer, representing the data associated with the |controller|.
BackgroundFetchRegistration registration;
registration.id = controller->registration_id().id();
registration.icons = controller->options().icons;
registration.title = controller->options().title;
registration.total_download_size = controller->options().total_download_size;
std::move(callback).Run(blink::mojom::BackgroundFetchError::NONE,
registration);
}
void BackgroundFetchServiceImpl::GetIds(int64_t service_worker_registration_id,
const url::Origin& origin,
GetIdsCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::move(callback).Run(
blink::mojom::BackgroundFetchError::NONE,
background_fetch_context_->GetActiveIdsForServiceWorkerRegistration(
service_worker_registration_id, origin));
}
bool BackgroundFetchServiceImpl::ValidateId(const std::string& id) {
if (id.empty() || id.size() > kMaxIdLength) {
bad_message::ReceivedBadMessage(render_process_id_,
bad_message::BFSI_INVALID_ID);
return false;
}
return true;
}
bool BackgroundFetchServiceImpl::ValidateRequests(
const std::vector<ServiceWorkerFetchRequest>& requests) {
if (requests.empty()) {
bad_message::ReceivedBadMessage(render_process_id_,
bad_message::BFSI_INVALID_REQUESTS);
return false;
}
return true;
}
bool BackgroundFetchServiceImpl::ValidateTitle(const std::string& title) {
if (title.empty() || title.size() > kMaxTitleLength) {
bad_message::ReceivedBadMessage(render_process_id_,
bad_message::BFSI_INVALID_TITLE);
return false;
}
return true;
}
} // namespace content