Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(178)

Side by Side Diff: content/browser/service_worker/service_worker_dispatcher_host_unittest.cc

Issue 1799413002: ServiceWorker: Release a reference when it fails to dispatch ExtendableMessageEvent (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@move_dispatch_extendable_message_event
Patch Set: reduce duplicate code Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/service_worker/service_worker_dispatcher_host.h" 5 #include "content/browser/service_worker/service_worker_dispatcher_host.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/files/file_path.h" 11 #include "base/files/file_path.h"
12 #include "base/run_loop.h" 12 #include "base/run_loop.h"
13 #include "content/browser/browser_thread_impl.h" 13 #include "content/browser/browser_thread_impl.h"
14 #include "content/browser/message_port_service.h"
14 #include "content/browser/service_worker/embedded_worker_instance.h" 15 #include "content/browser/service_worker/embedded_worker_instance.h"
15 #include "content/browser/service_worker/embedded_worker_registry.h" 16 #include "content/browser/service_worker/embedded_worker_registry.h"
16 #include "content/browser/service_worker/embedded_worker_test_helper.h" 17 #include "content/browser/service_worker/embedded_worker_test_helper.h"
17 #include "content/browser/service_worker/service_worker_context_core.h" 18 #include "content/browser/service_worker/service_worker_context_core.h"
18 #include "content/browser/service_worker/service_worker_context_wrapper.h" 19 #include "content/browser/service_worker/service_worker_context_wrapper.h"
20 #include "content/browser/service_worker/service_worker_handle.h"
19 #include "content/common/service_worker/embedded_worker_messages.h" 21 #include "content/common/service_worker/embedded_worker_messages.h"
20 #include "content/common/service_worker/service_worker_messages.h" 22 #include "content/common/service_worker/service_worker_messages.h"
21 #include "content/public/common/content_switches.h" 23 #include "content/public/common/content_switches.h"
22 #include "content/public/test/mock_resource_context.h" 24 #include "content/public/test/mock_resource_context.h"
23 #include "content/public/test/test_browser_thread_bundle.h" 25 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "content/test/test_content_browser_client.h" 26 #include "content/test/test_content_browser_client.h"
25 #include "testing/gtest/include/gtest/gtest.h" 27 #include "testing/gtest/include/gtest/gtest.h"
26 28
27 namespace content { 29 namespace content {
28 30
29 namespace { 31 namespace {
30 32
31 static void SaveStatusCallback(bool* called, 33 static void SaveStatusCallback(bool* called,
32 ServiceWorkerStatusCode* out, 34 ServiceWorkerStatusCode* out,
33 ServiceWorkerStatusCode status) { 35 ServiceWorkerStatusCode status) {
34 *called = true; 36 *called = true;
35 *out = status; 37 *out = status;
36 } 38 }
37 39
40 void SetUpDummyMessagePort(std::vector<TransferredMessagePort>* ports) {
41 int port_id = -1;
42 MessagePortService::GetInstance()->Create(MSG_ROUTING_NONE, nullptr,
43 &port_id);
44 TransferredMessagePort dummy_port;
45 dummy_port.id = port_id;
46 ports->push_back(dummy_port);
38 } 47 }
39 48
49 } // namespace
50
40 static const int kRenderFrameId = 1; 51 static const int kRenderFrameId = 1;
41 52
42 class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost { 53 class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
43 public: 54 public:
44 TestingServiceWorkerDispatcherHost( 55 TestingServiceWorkerDispatcherHost(
45 int process_id, 56 int process_id,
46 ServiceWorkerContextWrapper* context_wrapper, 57 ServiceWorkerContextWrapper* context_wrapper,
47 ResourceContext* resource_context, 58 ResourceContext* resource_context,
48 EmbeddedWorkerTestHelper* helper) 59 EmbeddedWorkerTestHelper* helper)
49 : ServiceWorkerDispatcherHost(process_id, NULL, resource_context), 60 : ServiceWorkerDispatcherHost(process_id, NULL, resource_context),
50 bad_messages_received_count_(0), 61 bad_messages_received_count_(0),
51 helper_(helper) { 62 helper_(helper) {
52 Init(context_wrapper); 63 Init(context_wrapper);
53 } 64 }
54 65
55 bool Send(IPC::Message* message) override { return helper_->Send(message); } 66 bool Send(IPC::Message* message) override { return helper_->Send(message); }
56 67
57 IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); } 68 IPC::TestSink* ipc_sink() { return helper_->ipc_sink(); }
58 69
59 void ShutdownForBadMessage() override { ++bad_messages_received_count_; } 70 void ShutdownForBadMessage() override { ++bad_messages_received_count_; }
60 71
61 int bad_messages_received_count_; 72 int bad_messages_received_count_;
62 73
63 protected: 74 protected:
64 EmbeddedWorkerTestHelper* helper_; 75 EmbeddedWorkerTestHelper* helper_;
65 ~TestingServiceWorkerDispatcherHost() override {} 76 ~TestingServiceWorkerDispatcherHost() override {}
66 }; 77 };
67 78
79 class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper {
80 public:
81 FailToStartWorkerTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
82
83 void OnStartWorker(int embedded_worker_id,
84 int64_t service_worker_version_id,
85 const GURL& scope,
86 const GURL& script_url,
87 bool pause_after_download) override {
88 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
89 registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
90 }
91 };
92
68 class ServiceWorkerDispatcherHostTest : public testing::Test { 93 class ServiceWorkerDispatcherHostTest : public testing::Test {
69 protected: 94 protected:
70 ServiceWorkerDispatcherHostTest() 95 ServiceWorkerDispatcherHostTest()
71 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {} 96 : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
72 97
73 void SetUp() override { 98 void SetUp() override {
74 helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath())); 99 Initialize(make_scoped_ptr(new EmbeddedWorkerTestHelper(base::FilePath())));
75 dispatcher_host_ = new TestingServiceWorkerDispatcherHost(
76 helper_->mock_render_process_id(), context_wrapper(),
77 &resource_context_, helper_.get());
78 } 100 }
79 101
80 void TearDown() override { helper_.reset(); } 102 void TearDown() override { helper_.reset(); }
81 103
82 ServiceWorkerContextCore* context() { return helper_->context(); } 104 ServiceWorkerContextCore* context() { return helper_->context(); }
83 ServiceWorkerContextWrapper* context_wrapper() { 105 ServiceWorkerContextWrapper* context_wrapper() {
84 return helper_->context_wrapper(); 106 return helper_->context_wrapper();
85 } 107 }
86 108
109 void Initialize(scoped_ptr<EmbeddedWorkerTestHelper> helper) {
110 helper_.reset(helper.release());
111 dispatcher_host_ = new TestingServiceWorkerDispatcherHost(
112 helper_->mock_render_process_id(), context_wrapper(),
113 &resource_context_, helper_.get());
114 }
115
87 void SendRegister(int64_t provider_id, GURL pattern, GURL worker_url) { 116 void SendRegister(int64_t provider_id, GURL pattern, GURL worker_url) {
88 dispatcher_host_->OnMessageReceived( 117 dispatcher_host_->OnMessageReceived(
89 ServiceWorkerHostMsg_RegisterServiceWorker( 118 ServiceWorkerHostMsg_RegisterServiceWorker(
90 -1, -1, provider_id, pattern, worker_url)); 119 -1, -1, provider_id, pattern, worker_url));
91 base::RunLoop().RunUntilIdle(); 120 base::RunLoop().RunUntilIdle();
92 } 121 }
93 122
94 void Register(int64_t provider_id, 123 void Register(int64_t provider_id,
95 GURL pattern, 124 GURL pattern,
96 GURL worker_url, 125 GURL worker_url,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 base::RunLoop().RunUntilIdle(); 168 base::RunLoop().RunUntilIdle();
140 } 169 }
141 170
142 void GetRegistrations(int64_t provider_id, uint32_t expected_message) { 171 void GetRegistrations(int64_t provider_id, uint32_t expected_message) {
143 SendGetRegistrations(provider_id); 172 SendGetRegistrations(provider_id);
144 EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching( 173 EXPECT_TRUE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
145 expected_message)); 174 expected_message));
146 dispatcher_host_->ipc_sink()->ClearMessages(); 175 dispatcher_host_->ipc_sink()->ClearMessages();
147 } 176 }
148 177
178 void DispatchExtendableMessageEvent(
179 scoped_refptr<ServiceWorkerVersion> worker,
180 const base::string16& message,
181 const url::Origin& source_origin,
182 const std::vector<TransferredMessagePort>& sent_message_ports,
183 ServiceWorkerProviderHost* sender_provider_host,
184 const ServiceWorkerDispatcherHost::StatusCallback& callback) {
185 dispatcher_host_->DispatchExtendableMessageEvent(
186 std::move(worker), message, source_origin, sent_message_ports,
187 sender_provider_host, callback);
188 }
189
149 ServiceWorkerProviderHost* CreateServiceWorkerProviderHost(int provider_id) { 190 ServiceWorkerProviderHost* CreateServiceWorkerProviderHost(int provider_id) {
150 return new ServiceWorkerProviderHost( 191 return new ServiceWorkerProviderHost(
151 helper_->mock_render_process_id(), kRenderFrameId, provider_id, 192 helper_->mock_render_process_id(), kRenderFrameId, provider_id,
152 SERVICE_WORKER_PROVIDER_FOR_WINDOW, context()->AsWeakPtr(), 193 SERVICE_WORKER_PROVIDER_FOR_WINDOW, context()->AsWeakPtr(),
153 dispatcher_host_.get()); 194 dispatcher_host_.get());
154 } 195 }
155 196
156
157 TestBrowserThreadBundle browser_thread_bundle_; 197 TestBrowserThreadBundle browser_thread_bundle_;
158 content::MockResourceContext resource_context_; 198 content::MockResourceContext resource_context_;
159 scoped_ptr<EmbeddedWorkerTestHelper> helper_; 199 scoped_ptr<EmbeddedWorkerTestHelper> helper_;
160 scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_; 200 scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_;
161 }; 201 };
162 202
163 class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient { 203 class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
164 public: 204 public:
165 ServiceWorkerTestContentBrowserClient() {} 205 ServiceWorkerTestContentBrowserClient() {}
166 bool AllowServiceWorker(const GURL& scope, 206 bool AllowServiceWorker(const GURL& scope,
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 process_id, context_wrapper(), &resource_context_, helper_.get())); 629 process_id, context_wrapper(), &resource_context_, helper_.get()));
590 630
591 // To show the new dispatcher can operate, simulate provider creation. Since 631 // To show the new dispatcher can operate, simulate provider creation. Since
592 // the old dispatcher cleaned up the old provider host, the new one won't 632 // the old dispatcher cleaned up the old provider host, the new one won't
593 // complain. 633 // complain.
594 new_dispatcher_host->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated( 634 new_dispatcher_host->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated(
595 kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW)); 635 kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW));
596 EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_); 636 EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_);
597 } 637 }
598 638
639 TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent) {
640 GURL pattern = GURL("http://www.example.com/");
641 GURL scope = GURL("http://www.example.com/service_worker.js");
falken 2016/03/17 06:44:36 script_url
nhiroki 2016/03/17 07:58:17 Good eye. I wrote this line while I was thinking a
642 int process_id = helper_->mock_render_process_id();
643
644 // Add a provider for a service worker to send a message.
645 const int64_t kProviderId = 99;
646 dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated(
647 kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER));
648 helper_->SimulateAddProcessToPattern(pattern, process_id);
649 ServiceWorkerProviderHost* sender_provider_host =
650 context()->GetProviderHost(process_id, kProviderId);
651
652 // Set up a registration and service worker to receive a message.
653 scoped_refptr<ServiceWorkerRegistration> registration(
654 new ServiceWorkerRegistration(pattern, 1L,
655 helper_->context()->AsWeakPtr()));
656 scoped_refptr<ServiceWorkerVersion> version(new ServiceWorkerVersion(
657 registration.get(), scope, 1L, helper_->context()->AsWeakPtr()));
658 std::vector<ServiceWorkerDatabase::ResourceRecord> records;
659 records.push_back(
660 ServiceWorkerDatabase::ResourceRecord(10, version->script_url(), 100));
661 version->script_cache_map()->SetResources(records);
662
663 // Make the registration findable via storage functions.
664 helper_->context()->storage()->LazyInitialize(base::Bind(&base::DoNothing));
665 base::RunLoop().RunUntilIdle();
666 bool called = false;
667 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
668 helper_->context()->storage()->StoreRegistration(
669 registration.get(), version.get(),
670 base::Bind(&SaveStatusCallback, &called, &status));
671 base::RunLoop().RunUntilIdle();
672 EXPECT_TRUE(called);
673 ASSERT_EQ(SERVICE_WORKER_OK, status);
falken 2016/03/17 06:44:36 Maybe it's time to refactor lines 640-673 and the
nhiroki 2016/03/17 07:58:17 Done.
674
675 // Set the running hosted version so that we can retrieve a valid service
676 // worker object information for the source attribute of the message event.
677 sender_provider_host->running_hosted_version_ = version;
678
679 // Set aside the initial refcount of the worker handle.
680 sender_provider_host->GetOrCreateServiceWorkerHandle(version.get());
681 ServiceWorkerHandle* sender_worker_handle =
682 dispatcher_host_->FindServiceWorkerHandle(
683 sender_provider_host->provider_id(), version->version_id());
684 const int ref_count = sender_worker_handle->ref_count();
685
686 // Dispatch ExtendableMessageEvent.
687 std::vector<TransferredMessagePort> ports;
688 SetUpDummyMessagePort(&ports);
689 called = false;
690 status = SERVICE_WORKER_ERROR_MAX_VALUE;
691 DispatchExtendableMessageEvent(
692 version, base::string16(), url::Origin(version->scope().GetOrigin()),
693 ports, sender_provider_host,
694 base::Bind(&SaveStatusCallback, &called, &status));
695 for (TransferredMessagePort port : ports)
696 EXPECT_TRUE(MessagePortService::GetInstance()->AreMessagesHeld(port.id));
697 EXPECT_EQ(ref_count + 1, sender_worker_handle->ref_count());
698 base::RunLoop().RunUntilIdle();
699 EXPECT_TRUE(called);
700 EXPECT_EQ(SERVICE_WORKER_OK, status);
701
702 // Messages should be held until ports are created at the destination.
703 for (TransferredMessagePort port : ports)
704 EXPECT_TRUE(MessagePortService::GetInstance()->AreMessagesHeld(port.id));
705
706 EXPECT_EQ(ref_count + 1, sender_worker_handle->ref_count());
707 }
708
709 TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent_Fail) {
710 Initialize(make_scoped_ptr(new FailToStartWorkerTestHelper));
711
712 GURL pattern = GURL("http://www.example.com/");
713 GURL scope = GURL("http://www.example.com/service_worker.js");
falken 2016/03/17 06:44:36 script_url
nhiroki 2016/03/17 07:58:17 Done.
714 int process_id = helper_->mock_render_process_id();
715
716 // Add a provider for a service worker to send a message.
717 const int64_t kProviderId = 99;
718 dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated(
719 kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_CONTROLLER));
720 helper_->SimulateAddProcessToPattern(pattern, process_id);
721 ServiceWorkerProviderHost* sender_provider_host =
722 context()->GetProviderHost(process_id, kProviderId);
723
724 // Set up a registration and service worker to receive a message.
725 scoped_refptr<ServiceWorkerRegistration> registration(
726 new ServiceWorkerRegistration(pattern, 1L,
727 helper_->context()->AsWeakPtr()));
728 scoped_refptr<ServiceWorkerVersion> version(new ServiceWorkerVersion(
729 registration.get(), scope, 1L, helper_->context()->AsWeakPtr()));
730 std::vector<ServiceWorkerDatabase::ResourceRecord> records;
731 records.push_back(
732 ServiceWorkerDatabase::ResourceRecord(10, version->script_url(), 100));
733 version->script_cache_map()->SetResources(records);
734
735 // Make the registration findable via storage functions.
736 helper_->context()->storage()->LazyInitialize(base::Bind(&base::DoNothing));
737 base::RunLoop().RunUntilIdle();
738 bool called = false;
739 ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
740 helper_->context()->storage()->StoreRegistration(
741 registration.get(), version.get(),
742 base::Bind(&SaveStatusCallback, &called, &status));
743 base::RunLoop().RunUntilIdle();
744 EXPECT_TRUE(called);
745 ASSERT_EQ(SERVICE_WORKER_OK, status);
746
747 // Set the running hosted version so that we can retrieve a valid service
748 // worker object information for the source attribute of the message event.
749 sender_provider_host->running_hosted_version_ = version;
750
751 // Set aside the initial refcount of the worker handle.
752 sender_provider_host->GetOrCreateServiceWorkerHandle(version.get());
753 ServiceWorkerHandle* sender_worker_handle =
754 dispatcher_host_->FindServiceWorkerHandle(
755 sender_provider_host->provider_id(), version->version_id());
756 const int ref_count = sender_worker_handle->ref_count();
757
758 // Try to dispatch ExtendableMessageEvent. This should fail to start the
759 // worker and to dispatch the event.
760 std::vector<TransferredMessagePort> ports;
761 SetUpDummyMessagePort(&ports);
762 called = false;
763 status = SERVICE_WORKER_ERROR_MAX_VALUE;
764 DispatchExtendableMessageEvent(
765 version, base::string16(), url::Origin(version->scope().GetOrigin()),
766 ports, sender_provider_host,
767 base::Bind(&SaveStatusCallback, &called, &status));
768 for (TransferredMessagePort port : ports)
769 EXPECT_TRUE(MessagePortService::GetInstance()->AreMessagesHeld(port.id));
770 EXPECT_EQ(ref_count + 1, sender_worker_handle->ref_count());
771 base::RunLoop().RunUntilIdle();
772 EXPECT_TRUE(called);
773 EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
774
775 // The error callback should clean up the ports and handle.
776 for (TransferredMessagePort port : ports)
777 EXPECT_FALSE(MessagePortService::GetInstance()->AreMessagesHeld(port.id));
778 EXPECT_EQ(ref_count, sender_worker_handle->ref_count());
779 }
780
599 } // namespace content 781 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698