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 |