Commit 5dcaa25d authored by xzhan96's avatar xzhan96 Committed by Commit Bot

[ServiceWorker] Implement ServiceWorkerContainer.PostMessageToClient

Corresponds to Client.postMessage() method, sends a message from
service worker to a client.

The CL mojofies the legacy IPC: ServiceWorkerMsg_MessageToDocument.

BUG=755861

Change-Id: I5795f8af5eb775699b9b22c1dde128c4bba48ec7
Reviewed-on: https://chromium-review.googlesource.com/742237
Commit-Queue: Xiaofeng Zhang <xiaofeng.zhang@intel.com>
Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Reviewed-by: default avatarTom Sepez <tsepez@chromium.org>
Reviewed-by: default avatarMakoto Shimazu <shimazu@chromium.org>
Cr-Commit-Position: refs/heads/master@{#512732}
parent 388128a9
......@@ -40,6 +40,7 @@
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "net/base/url_util.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "third_party/WebKit/common/message_port/message_port_channel.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_object.mojom.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom.h"
......@@ -552,16 +553,14 @@ void ServiceWorkerProviderHost::PostMessageToClient(
ServiceWorkerVersion* version,
const base::string16& message,
const std::vector<blink::MessagePortChannel>& sent_message_ports) {
DCHECK(IsProviderForClient());
if (!dispatcher_host_)
return;
ServiceWorkerMsg_MessageToDocument_Params params;
params.thread_id = kDocumentMainThreadId;
params.provider_id = provider_id();
params.service_worker_info = *GetOrCreateServiceWorkerHandle(version);
params.message = message;
params.message_ports = sent_message_ports;
Send(new ServiceWorkerMsg_MessageToDocument(params));
auto message_pipes =
blink::MessagePortChannel::ReleaseHandles(sent_message_ports);
container_->PostMessageToClient(GetOrCreateServiceWorkerHandle(version),
message, std::move(message_pipes));
}
void ServiceWorkerProviderHost::CountFeature(uint32_t feature) {
......
......@@ -474,6 +474,10 @@ class MockServiceWorkerContainer : public mojom::ServiceWorkerContainer {
bool should_notify_controllerchange) override {
was_set_controller_called_ = true;
}
void PostMessageToClient(
blink::mojom::ServiceWorkerObjectInfoPtr controller,
const base::string16& message,
std::vector<mojo::ScopedMessagePipeHandle> message_pipes) override {}
bool was_set_controller_called() const { return was_set_controller_called_; }
......
......@@ -6,6 +6,7 @@ module content.mojom;
import "content/common/service_worker/controller_service_worker.mojom";
import "content/common/service_worker/service_worker_types.mojom";
import "mojo/common/string16.mojom";
import "third_party/WebKit/public/platform/modules/serviceworker/service_worker_error_type.mojom";
import "third_party/WebKit/public/platform/modules/serviceworker/service_worker_object.mojom";
import "third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom";
......@@ -94,8 +95,15 @@ interface ServiceWorkerContainer {
SetController(blink.mojom.ServiceWorkerObjectInfo controller,
array<blink.mojom.WebFeature> used_features,
bool should_notify_controllerchange);
// TODO(xiaofeng.zhang): implement them.
// Corresponds to Client#postMessage().
// Sends |message| from the service worker |source| to this service worker
// client.
// TODO(xiaofeng.zhang): Use blink.mojom.TransferableMessage as the parameter.
PostMessageToClient(blink.mojom.ServiceWorkerObjectInfo source,
mojo.common.mojom.String16 message,
array<handle<message_pipe>> message_ports);
// TODO(xiaofeng.zhang): implement it.
// ServiceWorkerStateChanged();
// ServiceWorkerRegistrationUpdateFound();
// PostMessage();
};
......@@ -127,14 +127,6 @@ IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerClientQueryOptions)
IPC_STRUCT_TRAITS_MEMBER(include_uncontrolled)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_BEGIN(ServiceWorkerMsg_MessageToDocument_Params)
IPC_STRUCT_MEMBER(int, thread_id)
IPC_STRUCT_MEMBER(int, provider_id)
IPC_STRUCT_MEMBER(blink::mojom::ServiceWorkerObjectInfo, service_worker_info)
IPC_STRUCT_MEMBER(base::string16, message)
IPC_STRUCT_MEMBER(std::vector<blink::MessagePortChannel>, message_ports)
IPC_STRUCT_END()
IPC_STRUCT_TRAITS_BEGIN(content::PushEventPayload)
IPC_STRUCT_TRAITS_MEMBER(data)
IPC_STRUCT_TRAITS_MEMBER(is_null)
......@@ -282,10 +274,6 @@ IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_SetNavigationPreloadHeaderError,
blink::mojom::ServiceWorkerErrorType,
std::string /* message */)
// Sends MessageEvent to a client document (browser->renderer).
IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_MessageToDocument,
ServiceWorkerMsg_MessageToDocument_Params)
// Notifies a client that its controller used a feature, for UseCounter
// purposes (browser->renderer). |feature| must be one of the values from
// blink::UseCounter::Feature enum.
......
......@@ -82,8 +82,6 @@ void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) {
OnSetVersionAttributes)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_UpdateFound,
OnUpdateFound)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument,
OnPostMessage)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CountFeature, OnCountFeature)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
......@@ -386,33 +384,6 @@ void ServiceWorkerDispatcher::OnUpdateFound(
found->second->OnUpdateFound();
}
void ServiceWorkerDispatcher::OnPostMessage(
const ServiceWorkerMsg_MessageToDocument_Params& params) {
// Make sure we're on the main document thread. (That must be the only
// thread we get this message)
DCHECK_EQ(kDocumentMainThreadId, params.thread_id);
TRACE_EVENT1("ServiceWorker", "ServiceWorkerDispatcher::OnPostMessage",
"Thread ID", params.thread_id);
// Adopt the reference sent from the browser process and get the corresponding
// worker object.
scoped_refptr<WebServiceWorkerImpl> worker =
GetOrCreateServiceWorker(Adopt(params.service_worker_info.Clone()));
ProviderClientMap::iterator found =
provider_clients_.find(params.provider_id);
if (found == provider_clients_.end()) {
// For now we do no queueing for messages sent to nonexistent / unattached
// client.
return;
}
found->second->DispatchMessageEvent(
WebServiceWorkerImpl::CreateHandle(worker),
blink::WebString::FromUTF16(params.message),
std::move(params.message_ports));
}
void ServiceWorkerDispatcher::OnCountFeature(int thread_id,
int provider_id,
uint32_t feature) {
......
......@@ -34,8 +34,6 @@ namespace IPC {
class Message;
}
struct ServiceWorkerMsg_MessageToDocument_Params;
namespace content {
class ServiceWorkerHandleReference;
......@@ -171,7 +169,6 @@ class CONTENT_EXPORT ServiceWorkerDispatcher : public WorkerThread::Observer {
const ServiceWorkerVersionAttributes& attributes);
void OnUpdateFound(int thread_id,
int registration_handle_id);
void OnPostMessage(const ServiceWorkerMsg_MessageToDocument_Params& params);
void OnCountFeature(int thread_id, int provider_id, uint32_t feature);
// Keeps map from handle_id to ServiceWorker object.
......
......@@ -142,10 +142,6 @@ class ServiceWorkerDispatcherTest : public testing::Test {
return ContainsKey(dispatcher_->registrations_, registration_handle_id);
}
void OnPostMessage(const ServiceWorkerMsg_MessageToDocument_Params& params) {
dispatcher_->OnPostMessage(params);
}
std::unique_ptr<ServiceWorkerHandleReference> Adopt(
blink::mojom::ServiceWorkerObjectInfoPtr info) {
return dispatcher_->Adopt(std::move(info));
......@@ -188,62 +184,18 @@ class MockWebServiceWorkerProviderClientImpl
void DispatchMessageEvent(
std::unique_ptr<blink::WebServiceWorker::Handle> handle,
const blink::WebString& message,
blink::WebVector<blink::MessagePortChannel> ports) override {
// WebPassOwnPtr cannot be owned in Chromium, so drop the handle here.
// The destruction releases ServiceWorkerHandleReference.
is_dispatch_message_event_called_ = true;
}
blink::WebVector<blink::MessagePortChannel> ports) override {}
void CountFeature(uint32_t feature) override {
used_features_.insert(feature);
}
bool is_dispatch_message_event_called() const {
return is_dispatch_message_event_called_;
}
private:
const int provider_id_;
bool is_dispatch_message_event_called_ = false;
ServiceWorkerDispatcher* dispatcher_;
std::set<uint32_t> used_features_;
};
TEST_F(ServiceWorkerDispatcherTest, OnPostMessage) {
const int kProviderId = 10;
// Assume that these objects are passed from the browser process and own
// references to browser-side registration/worker representations.
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
CreateServiceWorkerRegistrationObjectInfo();
ServiceWorkerMsg_MessageToDocument_Params params;
params.thread_id = kDocumentMainThreadId;
params.provider_id = kProviderId;
params.service_worker_info = *(info->active);
// The passed reference should be adopted but immediately released because
// there is no provider client.
OnPostMessage(params);
ASSERT_EQ(1UL, ipc_sink()->message_count());
EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
ipc_sink()->GetMessageAt(0)->type());
ipc_sink()->ClearMessages();
std::unique_ptr<MockWebServiceWorkerProviderClientImpl> provider_client(
new MockWebServiceWorkerProviderClientImpl(kProviderId, dispatcher()));
ASSERT_FALSE(provider_client->is_dispatch_message_event_called());
// The passed reference should be owned by the provider client (but the
// reference is immediately released due to limitation of the mock provider
// client. See the comment on dispatchMessageEvent() of the mock).
OnPostMessage(params);
EXPECT_TRUE(provider_client->is_dispatch_message_event_called());
ASSERT_EQ(1UL, ipc_sink()->message_count());
EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
ipc_sink()->GetMessageAt(0)->type());
}
TEST_F(ServiceWorkerDispatcherTest, GetServiceWorker) {
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr info =
CreateServiceWorkerRegistrationObjectInfo();
......
......@@ -61,8 +61,6 @@ void ServiceWorkerMessageFilter::OnStaleMessageReceived(
IPC_BEGIN_MESSAGE_MAP(ServiceWorkerMessageFilter, msg)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_SetVersionAttributes,
OnStaleSetVersionAttributes)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToDocument,
OnStaleMessageToDocument)
IPC_END_MESSAGE_MAP()
}
......@@ -81,10 +79,4 @@ void ServiceWorkerMessageFilter::OnStaleSetVersionAttributes(
// SetVersionAttributes message doesn't increment it.
}
void ServiceWorkerMessageFilter::OnStaleMessageToDocument(
const ServiceWorkerMsg_MessageToDocument_Params& params) {
SendServiceWorkerObjectDestroyed(thread_safe_sender(),
params.service_worker_info.handle_id);
}
} // namespace content
......@@ -12,8 +12,6 @@
#include "content/common/content_export.h"
#include "content/renderer/worker_thread_message_filter.h"
struct ServiceWorkerMsg_MessageToDocument_Params;
namespace content {
struct ServiceWorkerVersionAttributes;
......@@ -42,8 +40,6 @@ class CONTENT_EXPORT ServiceWorkerMessageFilter
int registration_handle_id,
int changed_mask,
const ServiceWorkerVersionAttributes& attrs);
void OnStaleMessageToDocument(
const ServiceWorkerMsg_MessageToDocument_Params& params);
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerMessageFilter);
};
......
......@@ -301,6 +301,20 @@ void ServiceWorkerProviderContext::SetController(
}
}
void ServiceWorkerProviderContext::PostMessageToClient(
blink::mojom::ServiceWorkerObjectInfoPtr source,
const base::string16& message,
std::vector<mojo::ScopedMessagePipeHandle> message_pipes) {
DCHECK(main_thread_task_runner_->RunsTasksInCurrentSequence());
ControlleeState* state = controllee_state_.get();
DCHECK(state);
if (state->web_service_worker_provider) {
state->web_service_worker_provider->PostMessageToClient(
std::move(source), message, std::move(message_pipes));
}
}
void ServiceWorkerProviderContext::OnNetworkProviderDestroyed() {
container_host_.reset();
if (controllee_state_ && controllee_state_->controller_connector)
......
......@@ -179,6 +179,10 @@ class CONTENT_EXPORT ServiceWorkerProviderContext
void SetController(blink::mojom::ServiceWorkerObjectInfoPtr controller,
const std::vector<blink::mojom::WebFeature>& used_features,
bool should_notify_controllerchange) override;
void PostMessageToClient(
blink::mojom::ServiceWorkerObjectInfoPtr source,
const base::string16& message,
std::vector<mojo::ScopedMessagePipeHandle> message_pipes) override;
const ServiceWorkerProviderType provider_type_;
const int provider_id_;
......
......@@ -303,4 +303,46 @@ TEST_F(ServiceWorkerProviderContextTest, SetController_Null) {
EXPECT_TRUE(client->was_set_controller_called());
}
TEST_F(ServiceWorkerProviderContextTest, PostMessageToClient) {
const int kProviderId = 10;
// Assume that these objects are passed from the browser process and own
// references to browser-side registration/worker representations.
blink::mojom::ServiceWorkerRegistrationObjectInfoPtr registration_info =
CreateServiceWorkerRegistrationObjectInfo();
mojom::ServiceWorkerContainerHostAssociatedPtrInfo host_ptr_info;
mojom::ServiceWorkerContainerHostAssociatedRequest host_request =
mojo::MakeRequest(&host_ptr_info);
mojom::ServiceWorkerContainerAssociatedPtr container_ptr;
mojom::ServiceWorkerContainerAssociatedRequest container_request =
mojo::MakeIsolatedRequest(&container_ptr);
auto provider_context = base::MakeRefCounted<ServiceWorkerProviderContext>(
kProviderId, SERVICE_WORKER_PROVIDER_FOR_WINDOW,
std::move(container_request), std::move(host_ptr_info), dispatcher(),
nullptr /* loader_factory_getter */);
auto provider_impl = base::MakeUnique<WebServiceWorkerProviderImpl>(
thread_safe_sender(), provider_context.get());
auto client = base::MakeUnique<MockWebServiceWorkerProviderClientImpl>();
provider_impl->SetClient(client.get());
ASSERT_FALSE(client->was_dispatch_message_event_called());
ipc_sink()->ClearMessages();
container_ptr->PostMessageToClient(
std::move(registration_info->active), base::string16(),
std::vector<mojo::ScopedMessagePipeHandle>());
base::RunLoop().RunUntilIdle();
// The passed reference should be owned by the provider client (but the
// reference is immediately released due to limitation of the mock provider
// client. See the comment on dispatchMessageEvent() of the mock).
EXPECT_TRUE(client->was_dispatch_message_event_called());
ASSERT_EQ(2UL, ipc_sink()->message_count());
EXPECT_EQ(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount::ID,
ipc_sink()->GetMessageAt(0)->type());
EXPECT_EQ(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount::ID,
ipc_sink()->GetMessageAt(1)->type());
}
} // namespace content
......@@ -17,6 +17,7 @@
#include "content/renderer/service_worker/service_worker_provider_context.h"
#include "content/renderer/service_worker/web_service_worker_impl.h"
#include "content/renderer/service_worker/web_service_worker_registration_impl.h"
#include "third_party/WebKit/common/message_port/message_port_channel.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProviderClient.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/service_worker_registration.mojom.h"
......@@ -209,7 +210,6 @@ void WebServiceWorkerProviderImpl::SetController(
GetDispatcher()->GetOrCreateServiceWorker(
ServiceWorkerHandleReference::Create(std::move(info),
thread_safe_sender_.get()));
for (uint32_t feature : features)
provider_client->CountFeature(feature);
provider_client->SetController(WebServiceWorkerImpl::CreateHandle(controller),
......@@ -220,6 +220,27 @@ int WebServiceWorkerProviderImpl::provider_id() const {
return context_->provider_id();
}
void WebServiceWorkerProviderImpl::PostMessageToClient(
blink::mojom::ServiceWorkerObjectInfoPtr source,
const base::string16& message,
std::vector<mojo::ScopedMessagePipeHandle> message_pipes) {
blink::WebServiceWorkerProviderClient* provider_client =
GetDispatcher()->GetProviderClient(context_->provider_id());
// The document may have been destroyed so that |provider_client| is null.
if (!provider_client)
return;
scoped_refptr<WebServiceWorkerImpl> worker =
GetDispatcher()->GetOrCreateServiceWorker(
ServiceWorkerHandleReference::Create(std::move(source),
thread_safe_sender_.get()));
auto message_ports =
blink::MessagePortChannel::CreateFromHandles(std::move(message_pipes));
provider_client->DispatchMessageEvent(
WebServiceWorkerImpl::CreateHandle(std::move(worker)),
blink::WebString::FromUTF16(message), std::move(message_ports));
}
void WebServiceWorkerProviderImpl::RemoveProviderClient() {
// Remove the provider client, but only if the dispatcher is still there.
// (For cleanup path we don't need to bother creating a new dispatcher)
......
......@@ -59,6 +59,12 @@ class CONTENT_EXPORT WebServiceWorkerProviderImpl
void SetController(blink::mojom::ServiceWorkerObjectInfoPtr info,
const std::set<uint32_t>& features,
bool should_notify_controller_change);
// Posts a message to the ServiceWorkerContainer for this provider.
// Corresponds to Client#postMessage().
void PostMessageToClient(
blink::mojom::ServiceWorkerObjectInfoPtr source,
const base::string16& message,
std::vector<mojo::ScopedMessagePipeHandle> message_pipes);
int provider_id() const;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment