blob: cdbb0b0462df3a1c52dc3975f70b70b265d5c0e1 [file] [log] [blame]
// Copyright 2013 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/child/service_worker/web_service_worker_impl.h"
#include <utility>
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "content/child/service_worker/service_worker_dispatcher.h"
#include "content/child/service_worker/service_worker_handle_reference.h"
#include "content/child/service_worker/web_service_worker_provider_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/child/webmessageportchannel_impl.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProxy.h"
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
using blink::WebMessagePortChannel;
using blink::WebMessagePortChannelArray;
using blink::WebMessagePortChannelClient;
using blink::WebSecurityOrigin;
using blink::WebString;
namespace content {
namespace {
class HandleImpl : public blink::WebServiceWorker::Handle {
public:
explicit HandleImpl(const scoped_refptr<WebServiceWorkerImpl>& worker)
: worker_(worker) {}
~HandleImpl() override {}
blink::WebServiceWorker* serviceWorker() override { return worker_.get(); }
private:
scoped_refptr<WebServiceWorkerImpl> worker_;
DISALLOW_COPY_AND_ASSIGN(HandleImpl);
};
void SendPostMessageToWorkerOnMainThread(
ThreadSafeSender* thread_safe_sender,
int handle_id,
int provider_id,
const base::string16& message,
const url::Origin& source_origin,
std::unique_ptr<WebMessagePortChannelArray> channels) {
thread_safe_sender->Send(new ServiceWorkerHostMsg_PostMessageToWorker(
handle_id, provider_id, message, source_origin,
WebMessagePortChannelImpl::ExtractMessagePortIDs(std::move(channels))));
}
} // namespace
WebServiceWorkerImpl::WebServiceWorkerImpl(
std::unique_ptr<ServiceWorkerHandleReference> handle_ref,
ThreadSafeSender* thread_safe_sender)
: handle_ref_(std::move(handle_ref)),
state_(handle_ref_->state()),
thread_safe_sender_(thread_safe_sender),
proxy_(nullptr) {
DCHECK_NE(kInvalidServiceWorkerHandleId, handle_ref_->handle_id());
ServiceWorkerDispatcher* dispatcher =
ServiceWorkerDispatcher::GetThreadSpecificInstance();
DCHECK(dispatcher);
dispatcher->AddServiceWorker(handle_ref_->handle_id(), this);
}
void WebServiceWorkerImpl::OnStateChanged(
blink::WebServiceWorkerState new_state) {
state_ = new_state;
// TODO(nhiroki): This is a quick fix for http://crbug.com/507110
DCHECK(proxy_);
if (proxy_)
proxy_->dispatchStateChangeEvent();
}
void WebServiceWorkerImpl::setProxy(blink::WebServiceWorkerProxy* proxy) {
proxy_ = proxy;
}
blink::WebServiceWorkerProxy* WebServiceWorkerImpl::proxy() {
return proxy_;
}
blink::WebURL WebServiceWorkerImpl::url() const {
return handle_ref_->url();
}
blink::WebServiceWorkerState WebServiceWorkerImpl::state() const {
return state_;
}
void WebServiceWorkerImpl::postMessage(
blink::WebServiceWorkerProvider* provider,
const WebString& message,
const WebSecurityOrigin& source_origin,
WebMessagePortChannelArray* channels) {
WebServiceWorkerProviderImpl* provider_impl =
static_cast<WebServiceWorkerProviderImpl*>(provider);
ServiceWorkerDispatcher* dispatcher =
ServiceWorkerDispatcher::GetThreadSpecificInstance();
DCHECK(dispatcher);
// This may send channels for MessagePorts, and all internal book-keeping
// messages for MessagePort (e.g. QueueMessages) are sent from main thread
// (with thread hopping), so we need to do the same thread hopping here not
// to overtake those messages.
dispatcher->main_thread_task_runner()->PostTask(
FROM_HERE,
base::Bind(&SendPostMessageToWorkerOnMainThread,
base::RetainedRef(thread_safe_sender_),
handle_ref_->handle_id(), provider_impl->provider_id(),
// We cast WebString to string16 before crossing
// threads for thread-safety.
static_cast<base::string16>(message),
url::Origin(source_origin),
base::Passed(base::WrapUnique(channels))));
}
void WebServiceWorkerImpl::terminate() {
thread_safe_sender_->Send(
new ServiceWorkerHostMsg_TerminateWorker(handle_ref_->handle_id()));
}
// static
std::unique_ptr<blink::WebServiceWorker::Handle>
WebServiceWorkerImpl::CreateHandle(
const scoped_refptr<WebServiceWorkerImpl>& worker) {
if (!worker)
return nullptr;
return base::MakeUnique<HandleImpl>(worker);
}
WebServiceWorkerImpl::~WebServiceWorkerImpl() {
ServiceWorkerDispatcher* dispatcher =
ServiceWorkerDispatcher::GetThreadSpecificInstance();
if (dispatcher)
dispatcher->RemoveServiceWorker(handle_ref_->handle_id());
}
} // namespace content