#include "content/browser/service_worker/service_worker_provider_host.h"
#include "base/stl_util.h"
+#include "content/browser/message_port_message_filter.h"
+#include "content/browser/service_worker/service_worker_context_core.h"
+#include "content/browser/service_worker/service_worker_context_request_handler.h"
+#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
+#include "content/browser/service_worker/service_worker_dispatcher_host.h"
+#include "content/browser/service_worker/service_worker_handle.h"
#include "content/browser/service_worker/service_worker_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
+#include "content/common/service_worker/service_worker_messages.h"
namespace content {
+static const int kDocumentMainThreadId = 0;
+
ServiceWorkerProviderHost::ServiceWorkerProviderHost(
- int process_id, int provider_id)
+ int process_id, int provider_id,
+ base::WeakPtr<ServiceWorkerContextCore> context,
+ ServiceWorkerDispatcherHost* dispatcher_host)
: process_id_(process_id),
- provider_id_(provider_id) {
+ provider_id_(provider_id),
+ context_(context),
+ dispatcher_host_(dispatcher_host) {
}
ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
- AssociateVersion(NULL);
+ if (active_version_)
+ active_version_->RemoveControllee(this);
+ if (pending_version_)
+ pending_version_->RemovePendingControllee(this);
}
-void ServiceWorkerProviderHost::AssociateVersion(
+void ServiceWorkerProviderHost::SetActiveVersion(
ServiceWorkerVersion* version) {
- if (associated_version())
- associated_version_->RemoveProcessToWorker(process_id_);
- associated_version_ = version;
+ if (version == active_version_)
+ return;
+ scoped_refptr<ServiceWorkerVersion> previous_version = active_version_;
+ active_version_ = version;
if (version)
- version->AddProcessToWorker(process_id_);
+ version->AddControllee(this);
+ if (previous_version)
+ previous_version->RemoveControllee(this);
+
+ if (!dispatcher_host_)
+ return; // Could be NULL in some tests.
+
+ ServiceWorkerObjectInfo info;
+ if (context_ && version) {
+ scoped_ptr<ServiceWorkerHandle> handle =
+ ServiceWorkerHandle::Create(context_, dispatcher_host_,
+ kDocumentMainThreadId, version);
+ info = handle->GetObjectInfo();
+ dispatcher_host_->RegisterServiceWorkerHandle(handle.Pass());
+ }
+ dispatcher_host_->Send(
+ new ServiceWorkerMsg_SetCurrentServiceWorker(
+ kDocumentMainThreadId, provider_id(), info));
}
-void ServiceWorkerProviderHost::AddScriptClient(int thread_id) {
- DCHECK(!ContainsKey(script_client_thread_ids_, thread_id));
- script_client_thread_ids_.insert(thread_id);
+void ServiceWorkerProviderHost::SetPendingVersion(
+ ServiceWorkerVersion* version) {
+ if (version == pending_version_)
+ return;
+ scoped_refptr<ServiceWorkerVersion> previous_version = pending_version_;
+ pending_version_ = version;
+ if (version)
+ version->AddPendingControllee(this);
+ if (previous_version)
+ previous_version->RemovePendingControllee(this);
+
+ if (!dispatcher_host_)
+ return; // Could be NULL in some tests.
+
+ // TODO(kinuko): dispatch pendingchange event to the document.
}
-void ServiceWorkerProviderHost::RemoveScriptClient(int thread_id) {
- DCHECK(ContainsKey(script_client_thread_ids_, thread_id));
- script_client_thread_ids_.erase(thread_id);
+bool ServiceWorkerProviderHost::SetHostedVersionId(int64 version_id) {
+ if (!context_)
+ return true; // System is shutting down.
+ if (active_version_)
+ return false; // Unexpected bad message.
+
+ ServiceWorkerVersion* live_version = context_->GetLiveVersion(version_id);
+ if (!live_version)
+ return true; // Was deleted before it got started.
+
+ ServiceWorkerVersionInfo info = live_version->GetInfo();
+ if (info.running_status != ServiceWorkerVersion::STARTING ||
+ info.process_id != process_id_) {
+ // If we aren't trying to start this version in our process
+ // something is amiss.
+ return false;
+ }
+
+ running_hosted_version_ = live_version;
+ return true;
}
-bool ServiceWorkerProviderHost::ShouldHandleRequest(
- ResourceType::Type resource_type) const {
- if (ServiceWorkerUtils::IsMainResourceType(resource_type))
- return true;
+scoped_ptr<ServiceWorkerRequestHandler>
+ServiceWorkerProviderHost::CreateRequestHandler(
+ ResourceType::Type resource_type) {
+ if (IsHostToRunningServiceWorker()) {
+ return scoped_ptr<ServiceWorkerRequestHandler>(
+ new ServiceWorkerContextRequestHandler(
+ context_, AsWeakPtr(), resource_type));
+ }
+ if (ServiceWorkerUtils::IsMainResourceType(resource_type) ||
+ active_version()) {
+ return scoped_ptr<ServiceWorkerRequestHandler>(
+ new ServiceWorkerControlleeRequestHandler(
+ context_, AsWeakPtr(), resource_type));
+ }
+ return scoped_ptr<ServiceWorkerRequestHandler>();
+}
- if (associated_version())
- return true;
+void ServiceWorkerProviderHost::PostMessage(
+ const base::string16& message,
+ const std::vector<int>& sent_message_port_ids) {
+ if (!dispatcher_host_)
+ return; // Could be NULL in some tests.
- // TODO(kinuko): Handle ServiceWorker cases.
- // For now we always return false here, so that we don't handle
- // requests for ServiceWorker (either for the main or sub resources).
+ std::vector<int> new_routing_ids;
+ dispatcher_host_->message_port_message_filter()->
+ UpdateMessagePortsWithNewRoutes(sent_message_port_ids,
+ &new_routing_ids);
- return false;
+ dispatcher_host_->Send(
+ new ServiceWorkerMsg_MessageToDocument(
+ kDocumentMainThreadId, provider_id(),
+ message,
+ sent_message_port_ids,
+ new_routing_ids));
}
} // namespace content