| Index: content/browser/navigator_connect/navigator_connect_service_worker_service_factory.cc
|
| diff --git a/content/browser/navigator_connect/navigator_connect_context.cc b/content/browser/navigator_connect/navigator_connect_service_worker_service_factory.cc
|
| similarity index 19%
|
| rename from content/browser/navigator_connect/navigator_connect_context.cc
|
| rename to content/browser/navigator_connect/navigator_connect_service_worker_service_factory.cc
|
| index 45d6a6f6cf74f17072ed984b4038c4d921e8f806..1fc27f3321d158f073eda950a187e94cff6291e3 100644
|
| --- a/content/browser/navigator_connect/navigator_connect_context.cc
|
| +++ b/content/browser/navigator_connect/navigator_connect_service_worker_service_factory.cc
|
| @@ -1,71 +1,96 @@
|
| -// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// 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_context.h"
|
| +#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/common/navigator_connect_types.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 {
|
|
|
| -struct NavigatorConnectContext::Connection {
|
| - CrossOriginServiceWorkerClient client;
|
| - int64 service_worker_registration_id;
|
| - GURL service_worker_registration_origin;
|
| -};
|
| +namespace {
|
|
|
| -NavigatorConnectContext::NavigatorConnectContext(
|
| - const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
|
| - : service_worker_context_(service_worker_context) {
|
| -}
|
| +// 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 base::string16& message,
|
| + const std::vector<int>& sent_message_port_ids) 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<int>& sent_message_port_ids,
|
| + 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_;
|
|
|
| -NavigatorConnectContext::~NavigatorConnectContext() {
|
| + 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) {
|
| }
|
|
|
| -void NavigatorConnectContext::RegisterConnection(
|
| - const CrossOriginServiceWorkerClient& client,
|
| - const scoped_refptr<ServiceWorkerRegistration>&
|
| - service_worker_registration) {
|
| - MessagePortService::GetInstance()->UpdateMessagePort(
|
| - client.message_port_id, this, client.message_port_id);
|
| - MessagePortService::GetInstance()->ReleaseMessages(client.message_port_id);
|
| - Connection& connection = connections_[client.message_port_id];
|
| - connection.client = client;
|
| - connection.service_worker_registration_id = service_worker_registration->id();
|
| - connection.service_worker_registration_origin =
|
| - service_worker_registration->pattern().GetOrigin();
|
| +NavigatorConnectServiceWorkerService::~NavigatorConnectServiceWorkerService() {
|
| }
|
|
|
| -void NavigatorConnectContext::SendMessage(
|
| +void NavigatorConnectServiceWorkerService::SendMessage(
|
| int route_id,
|
| const base::string16& message,
|
| const std::vector<int>& sent_message_port_ids) {
|
| - DCHECK(connections_.find(route_id) != connections_.end());
|
| - const Connection& connection = connections_[route_id];
|
| + DCHECK(route_id == client_.message_port_id);
|
|
|
| - // Hold messages while service worker is found, activated, and message sent
|
| - // causing ServiceWorkerScriptContext::OnCrossOriginMessageToWorker to
|
| - // construct WebMessagePortChannelImpl instances which send
|
| - // MessagePortHostMsg_ReleaseMessages.
|
| + // 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 (int sent_message_port_id : sent_message_port_ids)
|
| MessagePortService::GetInstance()->HoldMessages(sent_message_port_id);
|
|
|
| service_worker_context_->context()->storage()->FindRegistrationForId(
|
| - connection.service_worker_registration_id,
|
| - connection.service_worker_registration_origin,
|
| - base::Bind(&NavigatorConnectContext::DoSendMessage, this,
|
| - connection.client, message, sent_message_port_ids));
|
| + service_worker_registration_id_, service_worker_registration_origin_,
|
| + base::Bind(&NavigatorConnectServiceWorkerService::DeliverMessage,
|
| + weak_factory_.GetWeakPtr(), message, sent_message_port_ids));
|
| }
|
|
|
| -void NavigatorConnectContext::SendMessagesAreQueued(int route_id) {
|
| +void NavigatorConnectServiceWorkerService::SendMessagesAreQueued(int route_id) {
|
| NOTREACHED() << "navigator.connect endpoints should never queue messages.";
|
| }
|
|
|
| -void NavigatorConnectContext::DoSendMessage(
|
| - const CrossOriginServiceWorkerClient& client,
|
| +void NavigatorConnectServiceWorkerService::DeliverMessage(
|
| const base::string16& message,
|
| const std::vector<int>& sent_message_port_ids,
|
| ServiceWorkerStatusCode service_worker_status,
|
| @@ -84,8 +109,86 @@ void NavigatorConnectContext::DoSendMessage(
|
| }
|
|
|
| active_version->DispatchCrossOriginMessageEvent(
|
| - client, message, sent_message_port_ids,
|
| + client_, message, sent_message_port_ids,
|
| 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_->context()->storage()->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);
|
| + return;
|
| + }
|
| +
|
| + ServiceWorkerVersion* active_version = registration->active_version();
|
| + if (!active_version) {
|
| + // No active version, reject connection attempt.
|
| + OnConnectResult(callback, client, registration, status, false);
|
| + return;
|
| + }
|
| +
|
| + active_version->DispatchCrossOriginConnectEvent(
|
| + base::Bind(&NavigatorConnectServiceWorkerServiceFactory::OnConnectResult,
|
| + weak_factory_.GetWeakPtr(), callback, client, registration),
|
| + client);
|
| +}
|
| +
|
| +void NavigatorConnectServiceWorkerServiceFactory::OnConnectResult(
|
| + const ConnectCallback& callback,
|
| + const NavigatorConnectClient& client,
|
| + const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
|
| + ServiceWorkerStatusCode status,
|
| + bool accept_connection) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::IO);
|
| +
|
| + if (status != SERVICE_WORKER_OK || !accept_connection) {
|
| + callback.Run(nullptr);
|
| + return;
|
| + }
|
| +
|
| + // TODO(mek): Keep track of NavigatorConnectServiceWorkerService instances and
|
| + // clean them up when a service worker registration is deleted.
|
| + callback.Run(new NavigatorConnectServiceWorkerService(
|
| + service_worker_context_, client, service_worker_registration));
|
| +}
|
| +
|
| } // namespace content
|
|
|