| Index: content/browser/navigator_connect/navigator_connect_service_worker_service_factory.cc
|
| diff --git a/content/browser/navigator_connect/navigator_connect_service_worker_service_factory.cc b/content/browser/navigator_connect/navigator_connect_service_worker_service_factory.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..36f4ed4fbb9afb6e3ba9266ef5e2c77ee290b04e
|
| --- /dev/null
|
| +++ b/content/browser/navigator_connect/navigator_connect_service_worker_service_factory.cc
|
| @@ -0,0 +1,205 @@
|
| +// 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 "content/browser/navigator_connect/navigator_connect_service_worker_service_factory.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "content/browser/message_port_service.h"
|
| +#include "content/browser/service_worker/service_worker_context_wrapper.h"
|
| +#include "content/browser/service_worker/service_worker_utils.h"
|
| +#include "content/public/browser/browser_thread.h"
|
| +#include "content/public/browser/message_port_delegate.h"
|
| +#include "content/public/common/navigator_connect_client.h"
|
| +
|
| +namespace content {
|
| +
|
| +namespace {
|
| +
|
| +// MessagePortDelegate implementation that directs all messages to the
|
| +// oncrossoriginmessage event of a service worker.
|
| +// TODO(mek): Somehow clean up message ports when a service worker is
|
| +// unregistered.
|
| +class NavigatorConnectServiceWorkerService : public MessagePortDelegate {
|
| + public:
|
| + NavigatorConnectServiceWorkerService(
|
| + const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
|
| + const NavigatorConnectClient& client,
|
| + const scoped_refptr<ServiceWorkerRegistration>&
|
| + service_worker_registration);
|
| + ~NavigatorConnectServiceWorkerService() override;
|
| +
|
| + // MessagePortDelegate implementation.
|
| + void SendMessage(
|
| + int route_id,
|
| + const MessagePortMessage& message,
|
| + const std::vector<TransferredMessagePort>& sent_message_ports) override;
|
| + void SendMessagesAreQueued(int route_id) override;
|
| +
|
| + private:
|
| + // Callback called by SendMessage when the ServiceWorkerRegistration for this
|
| + // service has been located.
|
| + void DeliverMessage(
|
| + const base::string16& message,
|
| + const std::vector<TransferredMessagePort>& sent_message_ports,
|
| + ServiceWorkerStatusCode service_worker_status,
|
| + const scoped_refptr<ServiceWorkerRegistration>&
|
| + service_worker_registration);
|
| +
|
| + scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
|
| + NavigatorConnectClient client_;
|
| + int64 service_worker_registration_id_;
|
| + GURL service_worker_registration_origin_;
|
| +
|
| + base::WeakPtrFactory<NavigatorConnectServiceWorkerService> weak_factory_;
|
| +};
|
| +
|
| +NavigatorConnectServiceWorkerService::NavigatorConnectServiceWorkerService(
|
| + const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
|
| + const NavigatorConnectClient& client,
|
| + const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration)
|
| + : service_worker_context_(service_worker_context),
|
| + client_(client),
|
| + service_worker_registration_id_(service_worker_registration->id()),
|
| + service_worker_registration_origin_(
|
| + service_worker_registration->pattern().GetOrigin()),
|
| + weak_factory_(this) {
|
| +}
|
| +
|
| +NavigatorConnectServiceWorkerService::~NavigatorConnectServiceWorkerService() {
|
| +}
|
| +
|
| +void NavigatorConnectServiceWorkerService::SendMessage(
|
| + int route_id,
|
| + const MessagePortMessage& message,
|
| + const std::vector<TransferredMessagePort>& sent_message_ports) {
|
| + DCHECK(route_id == client_.message_port_id);
|
| + DCHECK(message.message_as_value.empty());
|
| +
|
| + // Hold messages on transferred message ports. Actual delivery of the message
|
| + // by the service can be asynchronous. When a message is delivered,
|
| + // WebMessagePortChannelImpl instances will be constructed which send
|
| + // MessagePortHostMsg_ReleaseMessages to release messages.
|
| + for (const auto& port : sent_message_ports)
|
| + MessagePortService::GetInstance()->HoldMessages(port.id);
|
| +
|
| + service_worker_context_->FindRegistrationForId(
|
| + service_worker_registration_id_, service_worker_registration_origin_,
|
| + base::Bind(&NavigatorConnectServiceWorkerService::DeliverMessage,
|
| + weak_factory_.GetWeakPtr(), message.message_as_string,
|
| + sent_message_ports));
|
| +}
|
| +
|
| +void NavigatorConnectServiceWorkerService::SendMessagesAreQueued(int route_id) {
|
| + NOTREACHED() << "navigator.connect endpoints should never queue messages.";
|
| +}
|
| +
|
| +void NavigatorConnectServiceWorkerService::DeliverMessage(
|
| + const base::string16& message,
|
| + const std::vector<TransferredMessagePort>& sent_message_ports,
|
| + ServiceWorkerStatusCode service_worker_status,
|
| + const scoped_refptr<ServiceWorkerRegistration>&
|
| + service_worker_registration) {
|
| + if (service_worker_status != SERVICE_WORKER_OK) {
|
| + // TODO(mek): Do something when no service worker was found.
|
| + return;
|
| + }
|
| +
|
| + ServiceWorkerVersion* active_version =
|
| + service_worker_registration->active_version();
|
| + if (!active_version) {
|
| + // TODO(mek): Do something when no active version exists.
|
| + return;
|
| + }
|
| +
|
| + active_version->DispatchCrossOriginMessageEvent(
|
| + client_, message, sent_message_ports,
|
| + base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +NavigatorConnectServiceWorkerServiceFactory::
|
| + NavigatorConnectServiceWorkerServiceFactory(const scoped_refptr<
|
| + ServiceWorkerContextWrapper>& service_worker_context)
|
| + : service_worker_context_(service_worker_context), weak_factory_(this) {
|
| +}
|
| +
|
| +NavigatorConnectServiceWorkerServiceFactory::
|
| + ~NavigatorConnectServiceWorkerServiceFactory() {
|
| +}
|
| +
|
| +bool NavigatorConnectServiceWorkerServiceFactory::HandlesUrl(
|
| + const GURL& target_url) {
|
| + // Always return true, all URLs could potentially have a service worker, and
|
| + // this factory will be installed as first factory, so it will only be used
|
| + // if no other factory claims to handle the url.
|
| + return true;
|
| +}
|
| +
|
| +void NavigatorConnectServiceWorkerServiceFactory::Connect(
|
| + const NavigatorConnectClient& client,
|
| + const ConnectCallback& callback) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + // Find the right service worker to service this connection.
|
| + service_worker_context_->FindRegistrationForDocument(
|
| + client.target_url,
|
| + base::Bind(&NavigatorConnectServiceWorkerServiceFactory::
|
| + GotServiceWorkerRegistration,
|
| + weak_factory_.GetWeakPtr(), callback, client));
|
| +}
|
| +
|
| +void NavigatorConnectServiceWorkerServiceFactory::GotServiceWorkerRegistration(
|
| + const ConnectCallback& callback,
|
| + const NavigatorConnectClient& client,
|
| + ServiceWorkerStatusCode status,
|
| + const scoped_refptr<ServiceWorkerRegistration>& registration) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| + if (status != SERVICE_WORKER_OK) {
|
| + // No service worker found, reject connection attempt.
|
| + OnConnectResult(callback, client, registration, status, false,
|
| + base::string16(), base::string16());
|
| + return;
|
| + }
|
| +
|
| + ServiceWorkerVersion* active_version = registration->active_version();
|
| + if (!active_version) {
|
| + // No active version, reject connection attempt.
|
| + OnConnectResult(callback, client, registration, status, false,
|
| + base::string16(), base::string16());
|
| + return;
|
| + }
|
| +
|
| + active_version->DispatchServicePortConnectEvent(
|
| + base::Bind(&NavigatorConnectServiceWorkerServiceFactory::OnConnectResult,
|
| + weak_factory_.GetWeakPtr(), callback, client, registration),
|
| + client.target_url, client.origin, client.message_port_id);
|
| +}
|
| +
|
| +void NavigatorConnectServiceWorkerServiceFactory::OnConnectResult(
|
| + const ConnectCallback& callback,
|
| + const NavigatorConnectClient& client,
|
| + const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
|
| + ServiceWorkerStatusCode status,
|
| + bool accept_connection,
|
| + const base::string16& name,
|
| + const base::string16& data) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + if (status != SERVICE_WORKER_OK || !accept_connection) {
|
| + callback.Run(nullptr, false);
|
| + return;
|
| + }
|
| +
|
| + // TODO(mek): Keep track of name and data for this port.
|
| + // TODO(mek): http://crbug.com/462744 Keep track of these
|
| + // NavigatorConnectServiceWorkerService instances and clean them up when a
|
| + // service worker registration is deleted.
|
| + callback.Run(
|
| + new NavigatorConnectServiceWorkerService(service_worker_context_, client,
|
| + service_worker_registration),
|
| + false);
|
| +}
|
| +
|
| +} // namespace content
|
|
|