OLD | NEW |
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 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/files/file_path.h" | 12 #include "base/files/file_path.h" |
13 #include "base/memory/ptr_util.h" | 13 #include "base/memory/ptr_util.h" |
14 #include "base/run_loop.h" | 14 #include "base/run_loop.h" |
15 #include "base/test/simple_test_tick_clock.h" | 15 #include "base/test/simple_test_tick_clock.h" |
16 #include "base/time/time.h" | 16 #include "base/time/time.h" |
17 #include "content/browser/browser_thread_impl.h" | 17 #include "content/browser/browser_thread_impl.h" |
18 #include "content/browser/service_worker/embedded_worker_instance.h" | 18 #include "content/browser/service_worker/embedded_worker_instance.h" |
19 #include "content/browser/service_worker/embedded_worker_registry.h" | 19 #include "content/browser/service_worker/embedded_worker_registry.h" |
20 #include "content/browser/service_worker/embedded_worker_status.h" | 20 #include "content/browser/service_worker/embedded_worker_status.h" |
21 #include "content/browser/service_worker/embedded_worker_test_helper.h" | 21 #include "content/browser/service_worker/embedded_worker_test_helper.h" |
22 #include "content/browser/service_worker/service_worker_context_core.h" | 22 #include "content/browser/service_worker/service_worker_context_core.h" |
23 #include "content/browser/service_worker/service_worker_context_wrapper.h" | 23 #include "content/browser/service_worker/service_worker_context_wrapper.h" |
24 #include "content/browser/service_worker/service_worker_handle.h" | 24 #include "content/browser/service_worker/service_worker_handle.h" |
| 25 #include "content/browser/service_worker/service_worker_navigation_handle_core.h
" |
25 #include "content/browser/service_worker/service_worker_test_utils.h" | 26 #include "content/browser/service_worker/service_worker_test_utils.h" |
26 #include "content/common/service_worker/embedded_worker_messages.h" | 27 #include "content/common/service_worker/embedded_worker_messages.h" |
27 #include "content/common/service_worker/service_worker_messages.h" | 28 #include "content/common/service_worker/service_worker_messages.h" |
28 #include "content/common/service_worker/service_worker_types.h" | 29 #include "content/common/service_worker/service_worker_types.h" |
29 #include "content/common/service_worker/service_worker_utils.h" | 30 #include "content/common/service_worker/service_worker_utils.h" |
| 31 #include "content/public/common/browser_side_navigation_policy.h" |
30 #include "content/public/common/content_switches.h" | 32 #include "content/public/common/content_switches.h" |
31 #include "content/public/test/mock_resource_context.h" | 33 #include "content/public/test/mock_resource_context.h" |
32 #include "content/public/test/test_browser_thread_bundle.h" | 34 #include "content/public/test/test_browser_thread_bundle.h" |
33 #include "content/test/test_content_browser_client.h" | 35 #include "content/test/test_content_browser_client.h" |
34 #include "testing/gtest/include/gtest/gtest.h" | 36 #include "testing/gtest/include/gtest/gtest.h" |
35 | 37 |
36 namespace content { | 38 namespace content { |
37 | 39 |
38 namespace { | 40 namespace { |
39 | 41 |
40 static void SaveStatusCallback(bool* called, | 42 static void SaveStatusCallback(bool* called, |
41 ServiceWorkerStatusCode* out, | 43 ServiceWorkerStatusCode* out, |
42 ServiceWorkerStatusCode status) { | 44 ServiceWorkerStatusCode status) { |
43 *called = true; | 45 *called = true; |
44 *out = status; | 46 *out = status; |
45 } | 47 } |
46 | 48 |
47 void SetUpDummyMessagePort(std::vector<MessagePort>* ports) { | 49 void SetUpDummyMessagePort(std::vector<MessagePort>* ports) { |
48 // Let the other end of the pipe close. | 50 // Let the other end of the pipe close. |
49 mojo::MessagePipe pipe; | 51 mojo::MessagePipe pipe; |
50 ports->push_back(MessagePort(std::move(pipe.handle0))); | 52 ports->push_back(MessagePort(std::move(pipe.handle0))); |
51 } | 53 } |
52 | 54 |
| 55 struct RemoteProviderInfo { |
| 56 mojom::ServiceWorkerProviderHostAssociatedPtr host_ptr; |
| 57 mojom::ServiceWorkerProviderAssociatedRequest client_request; |
| 58 }; |
| 59 |
| 60 RemoteProviderInfo SetupProviderHostInfoPtrs( |
| 61 ServiceWorkerProviderHostInfo* host_info) { |
| 62 RemoteProviderInfo remote_info; |
| 63 mojom::ServiceWorkerProviderAssociatedPtr browser_side_client_ptr; |
| 64 remote_info.client_request = |
| 65 mojo::MakeIsolatedRequest(&browser_side_client_ptr); |
| 66 host_info->host_request = mojo::MakeIsolatedRequest(&remote_info.host_ptr); |
| 67 host_info->client_ptr_info = browser_side_client_ptr.PassInterface(); |
| 68 EXPECT_TRUE(host_info->host_request.is_pending()); |
| 69 EXPECT_TRUE(host_info->client_ptr_info.is_valid()); |
| 70 EXPECT_TRUE(remote_info.host_ptr.is_bound()); |
| 71 EXPECT_TRUE(remote_info.client_request.is_pending()); |
| 72 return remote_info; |
| 73 } |
| 74 |
| 75 std::unique_ptr<ServiceWorkerNavigationHandleCore> CreateNavigationHandleCore( |
| 76 ServiceWorkerContextWrapper* context_wrapper) { |
| 77 std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core; |
| 78 BrowserThread::PostTaskAndReplyWithResult( |
| 79 BrowserThread::UI, FROM_HERE, |
| 80 base::Bind( |
| 81 [](ServiceWorkerContextWrapper* wrapper) { |
| 82 return base::MakeUnique<ServiceWorkerNavigationHandleCore>(nullptr, |
| 83 wrapper); |
| 84 }, |
| 85 context_wrapper), |
| 86 base::Bind( |
| 87 [](std::unique_ptr<ServiceWorkerNavigationHandleCore>* dest, |
| 88 std::unique_ptr<ServiceWorkerNavigationHandleCore> src) { |
| 89 *dest = std::move(src); |
| 90 }, |
| 91 &navigation_handle_core)); |
| 92 base::RunLoop().RunUntilIdle(); |
| 93 return navigation_handle_core; |
| 94 } |
| 95 |
53 } // namespace | 96 } // namespace |
54 | 97 |
55 static const int kRenderFrameId = 1; | 98 static const int kRenderFrameId = 1; |
56 | 99 |
57 class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost { | 100 class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost { |
58 public: | 101 public: |
59 TestingServiceWorkerDispatcherHost( | 102 TestingServiceWorkerDispatcherHost( |
60 int process_id, | 103 int process_id, |
61 ServiceWorkerContextWrapper* context_wrapper, | 104 ServiceWorkerContextWrapper* context_wrapper, |
62 ResourceContext* resource_context, | 105 ResourceContext* resource_context, |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 int embedded_worker_id) { | 204 int embedded_worker_id) { |
162 dispatcher_host_->OnSetHostedVersionId(provider_id, version_id, | 205 dispatcher_host_->OnSetHostedVersionId(provider_id, version_id, |
163 embedded_worker_id); | 206 embedded_worker_id); |
164 } | 207 } |
165 | 208 |
166 void SendProviderCreated(ServiceWorkerProviderType type, | 209 void SendProviderCreated(ServiceWorkerProviderType type, |
167 const GURL& pattern) { | 210 const GURL& pattern) { |
168 const int64_t kProviderId = 99; | 211 const int64_t kProviderId = 99; |
169 ServiceWorkerProviderHostInfo info(kProviderId, MSG_ROUTING_NONE, type, | 212 ServiceWorkerProviderHostInfo info(kProviderId, MSG_ROUTING_NONE, type, |
170 true /* is_parent_frame_secure */); | 213 true /* is_parent_frame_secure */); |
| 214 remote_endpoint_.BindWithProviderHostInfo(&info); |
| 215 |
171 dispatcher_host_->OnProviderCreated(std::move(info)); | 216 dispatcher_host_->OnProviderCreated(std::move(info)); |
172 helper_->SimulateAddProcessToPattern(pattern, | 217 helper_->SimulateAddProcessToPattern(pattern, |
173 helper_->mock_render_process_id()); | 218 helper_->mock_render_process_id()); |
174 provider_host_ = context()->GetProviderHost( | 219 provider_host_ = context()->GetProviderHost( |
175 helper_->mock_render_process_id(), kProviderId); | 220 helper_->mock_render_process_id(), kProviderId); |
176 } | 221 } |
177 | 222 |
178 void SendRegister(int64_t provider_id, GURL pattern, GURL worker_url) { | 223 void SendRegister(int64_t provider_id, GURL pattern, GURL worker_url) { |
179 dispatcher_host_->OnMessageReceived( | 224 dispatcher_host_->OnMessageReceived( |
180 ServiceWorkerHostMsg_RegisterServiceWorker( | 225 ServiceWorkerHostMsg_RegisterServiceWorker( |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 const ServiceWorkerDispatcherHost::StatusCallback& callback) { | 291 const ServiceWorkerDispatcherHost::StatusCallback& callback) { |
247 dispatcher_host_->DispatchExtendableMessageEvent( | 292 dispatcher_host_->DispatchExtendableMessageEvent( |
248 std::move(worker), message, source_origin, sent_message_ports, | 293 std::move(worker), message, source_origin, sent_message_ports, |
249 sender_provider_host, callback); | 294 sender_provider_host, callback); |
250 } | 295 } |
251 | 296 |
252 std::unique_ptr<ServiceWorkerProviderHost> CreateServiceWorkerProviderHost( | 297 std::unique_ptr<ServiceWorkerProviderHost> CreateServiceWorkerProviderHost( |
253 int provider_id) { | 298 int provider_id) { |
254 return CreateProviderHostWithDispatcherHost( | 299 return CreateProviderHostWithDispatcherHost( |
255 helper_->mock_render_process_id(), provider_id, context()->AsWeakPtr(), | 300 helper_->mock_render_process_id(), provider_id, context()->AsWeakPtr(), |
256 kRenderFrameId, dispatcher_host_.get()); | 301 kRenderFrameId, dispatcher_host_.get(), &remote_endpoint_); |
257 } | 302 } |
258 | 303 |
259 TestBrowserThreadBundle browser_thread_bundle_; | 304 TestBrowserThreadBundle browser_thread_bundle_; |
260 content::MockResourceContext resource_context_; | 305 content::MockResourceContext resource_context_; |
261 std::unique_ptr<EmbeddedWorkerTestHelper> helper_; | 306 std::unique_ptr<EmbeddedWorkerTestHelper> helper_; |
262 scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_; | 307 scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_; |
263 scoped_refptr<ServiceWorkerRegistration> registration_; | 308 scoped_refptr<ServiceWorkerRegistration> registration_; |
264 scoped_refptr<ServiceWorkerVersion> version_; | 309 scoped_refptr<ServiceWorkerVersion> version_; |
265 ServiceWorkerProviderHost* provider_host_; | 310 ServiceWorkerProviderHost* provider_host_; |
| 311 ServiceWorkerRemoteProviderEndpoint remote_endpoint_; |
266 }; | 312 }; |
267 | 313 |
268 class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient { | 314 class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient { |
269 public: | 315 public: |
270 ServiceWorkerTestContentBrowserClient() {} | 316 ServiceWorkerTestContentBrowserClient() {} |
271 bool AllowServiceWorker( | 317 bool AllowServiceWorker( |
272 const GURL& scope, | 318 const GURL& scope, |
273 const GURL& first_party, | 319 const GURL& first_party, |
274 content::ResourceContext* context, | 320 content::ResourceContext* context, |
275 const base::Callback<WebContents*(void)>& wc_getter) override { | 321 const base::Callback<WebContents*(void)>& wc_getter) override { |
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 // Let the shutdown reach the simulated IO thread. | 548 // Let the shutdown reach the simulated IO thread. |
503 base::RunLoop().RunUntilIdle(); | 549 base::RunLoop().RunUntilIdle(); |
504 | 550 |
505 Register(-1, | 551 Register(-1, |
506 GURL(), | 552 GURL(), |
507 GURL(), | 553 GURL(), |
508 ServiceWorkerMsg_ServiceWorkerRegistrationError::ID); | 554 ServiceWorkerMsg_ServiceWorkerRegistrationError::ID); |
509 } | 555 } |
510 | 556 |
511 TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) { | 557 TEST_F(ServiceWorkerDispatcherHostTest, ProviderCreatedAndDestroyed) { |
512 const int kProviderId = 1001; | 558 // |kProviderId| must be -2 when PlzNavigate is enabled to match the |
| 559 // pre-created provider host. Otherwise |kProviderId| is just a dummy value. |
| 560 const int kProviderId = (IsBrowserSideNavigationEnabled() ? -2 : 1001); |
513 int process_id = helper_->mock_render_process_id(); | 561 int process_id = helper_->mock_render_process_id(); |
514 | 562 |
515 dispatcher_host_->OnProviderCreated(ServiceWorkerProviderHostInfo( | 563 // Setup ServiceWorkerProviderHostInfo. |
516 kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW, | 564 ServiceWorkerProviderHostInfo host_info_1(kProviderId, 1 /* route_id */, |
517 true /* is_parent_frame_secure */)); | 565 SERVICE_WORKER_PROVIDER_FOR_WINDOW, |
| 566 true /* is_parent_frame_secure */); |
| 567 ServiceWorkerProviderHostInfo host_info_2(kProviderId, 1 /* route_id */, |
| 568 SERVICE_WORKER_PROVIDER_FOR_WINDOW, |
| 569 true /* is_parent_frame_secure */); |
| 570 ServiceWorkerProviderHostInfo host_info_3(kProviderId, 1 /* route_id */, |
| 571 SERVICE_WORKER_PROVIDER_FOR_WINDOW, |
| 572 true /* is_parent_frame_secure */); |
| 573 RemoteProviderInfo remote_info_1 = SetupProviderHostInfoPtrs(&host_info_1); |
| 574 RemoteProviderInfo remote_info_2 = SetupProviderHostInfoPtrs(&host_info_2); |
| 575 RemoteProviderInfo remote_info_3 = SetupProviderHostInfoPtrs(&host_info_3); |
| 576 |
| 577 // PlzNavigate |
| 578 std::unique_ptr<ServiceWorkerNavigationHandleCore> navigation_handle_core; |
| 579 if (IsBrowserSideNavigationEnabled()) { |
| 580 navigation_handle_core = |
| 581 CreateNavigationHandleCore(helper_->context_wrapper()); |
| 582 ASSERT_TRUE(navigation_handle_core); |
| 583 // ProviderHost should be created before OnProviderCreated. |
| 584 navigation_handle_core->DidPreCreateProviderHost( |
| 585 ServiceWorkerProviderHost::PreCreateNavigationHost( |
| 586 helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */, |
| 587 base::Callback<WebContents*(void)>())); |
| 588 } |
| 589 |
| 590 dispatcher_host_->OnProviderCreated(std::move(host_info_1)); |
518 EXPECT_TRUE(context()->GetProviderHost(process_id, kProviderId)); | 591 EXPECT_TRUE(context()->GetProviderHost(process_id, kProviderId)); |
519 | 592 |
520 // Two with the same ID should be seen as a bad message. | 593 // Two with the same ID should be seen as a bad message. |
521 dispatcher_host_->OnProviderCreated(ServiceWorkerProviderHostInfo( | 594 dispatcher_host_->OnProviderCreated(std::move(host_info_2)); |
522 kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW, | |
523 true /* is_parent_frame_secure */)); | |
524 EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_); | 595 EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_); |
525 | 596 |
526 dispatcher_host_->OnProviderDestroyed(kProviderId); | 597 // Releasing the interface pointer destroys the counterpart. |
| 598 remote_info_1.host_ptr.reset(); |
| 599 base::RunLoop().RunUntilIdle(); |
527 EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId)); | 600 EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId)); |
528 | 601 |
529 // Destroying an ID that does not exist warrants a bad message. | 602 // PlzNavigate |
530 dispatcher_host_->OnProviderDestroyed(kProviderId); | 603 // Prepare another navigation handle to create another provider host. |
531 EXPECT_EQ(2, dispatcher_host_->bad_messages_received_count_); | 604 if (IsBrowserSideNavigationEnabled()) { |
| 605 navigation_handle_core = |
| 606 CreateNavigationHandleCore(helper_->context_wrapper()); |
| 607 ASSERT_TRUE(navigation_handle_core); |
| 608 // ProviderHost should be created before OnProviderCreated. |
| 609 navigation_handle_core->DidPreCreateProviderHost( |
| 610 ServiceWorkerProviderHost::PreCreateNavigationHost( |
| 611 helper_->context()->AsWeakPtr(), true /* are_ancestors_secure */, |
| 612 base::Callback<WebContents*(void)>())); |
| 613 } |
532 | 614 |
533 // Deletion of the dispatcher_host should cause providers for that | 615 // Deletion of the dispatcher_host should cause providers for that |
534 // process to get deleted as well. | 616 // process to get deleted as well. |
535 dispatcher_host_->OnProviderCreated(ServiceWorkerProviderHostInfo( | 617 dispatcher_host_->OnProviderCreated(std::move(host_info_3)); |
536 kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW, | |
537 true /* is_parent_frame_secure */)); | |
538 EXPECT_TRUE(context()->GetProviderHost(process_id, kProviderId)); | 618 EXPECT_TRUE(context()->GetProviderHost(process_id, kProviderId)); |
539 EXPECT_TRUE(dispatcher_host_->HasOneRef()); | 619 EXPECT_TRUE(dispatcher_host_->HasOneRef()); |
540 dispatcher_host_ = nullptr; | 620 dispatcher_host_ = nullptr; |
541 EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId)); | 621 EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId)); |
542 } | 622 } |
543 | 623 |
544 TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_SameOrigin) { | 624 TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_SameOrigin) { |
545 const int64_t kProviderId = 99; // Dummy value | 625 const int64_t kProviderId = 99; // Dummy value |
546 std::unique_ptr<ServiceWorkerProviderHost> host( | 626 std::unique_ptr<ServiceWorkerProviderHost> host( |
547 CreateServiceWorkerProviderHost(kProviderId)); | 627 CreateServiceWorkerProviderHost(kProviderId)); |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
662 // We should be able to hook up a new dispatcher host although the old object | 742 // We should be able to hook up a new dispatcher host although the old object |
663 // is not yet destroyed. This is what the browser does when reusing a crashed | 743 // is not yet destroyed. This is what the browser does when reusing a crashed |
664 // render process. | 744 // render process. |
665 scoped_refptr<TestingServiceWorkerDispatcherHost> new_dispatcher_host( | 745 scoped_refptr<TestingServiceWorkerDispatcherHost> new_dispatcher_host( |
666 new TestingServiceWorkerDispatcherHost( | 746 new TestingServiceWorkerDispatcherHost( |
667 process_id, context_wrapper(), &resource_context_, helper_.get())); | 747 process_id, context_wrapper(), &resource_context_, helper_.get())); |
668 | 748 |
669 // To show the new dispatcher can operate, simulate provider creation. Since | 749 // To show the new dispatcher can operate, simulate provider creation. Since |
670 // the old dispatcher cleaned up the old provider host, the new one won't | 750 // the old dispatcher cleaned up the old provider host, the new one won't |
671 // complain. | 751 // complain. |
672 new_dispatcher_host->OnProviderCreated(ServiceWorkerProviderHostInfo( | 752 ServiceWorkerProviderHostInfo host_info(provider_id, MSG_ROUTING_NONE, |
673 provider_id, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW, | 753 SERVICE_WORKER_PROVIDER_FOR_WINDOW, |
674 true /* is_parent_frame_secure */)); | 754 true /* is_parent_frame_secure */); |
| 755 ServiceWorkerRemoteProviderEndpoint remote_endpoint; |
| 756 remote_endpoint.BindWithProviderHostInfo(&host_info); |
| 757 new_dispatcher_host->OnProviderCreated(std::move(host_info)); |
675 EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_); | 758 EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_); |
676 } | 759 } |
677 | 760 |
678 TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent) { | 761 TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent) { |
679 GURL pattern = GURL("http://www.example.com/"); | 762 GURL pattern = GURL("http://www.example.com/"); |
680 GURL script_url = GURL("http://www.example.com/service_worker.js"); | 763 GURL script_url = GURL("http://www.example.com/service_worker.js"); |
681 | 764 |
682 SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, pattern); | 765 SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, pattern); |
683 SetUpRegistration(pattern, script_url); | 766 SetUpRegistration(pattern, script_url); |
684 | 767 |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
833 const int kFetchEventId = 91; // Dummy value | 916 const int kFetchEventId = 91; // Dummy value |
834 dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_FetchEventResponse( | 917 dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_FetchEventResponse( |
835 version_->embedded_worker()->embedded_worker_id(), kFetchEventId, | 918 version_->embedded_worker()->embedded_worker_id(), kFetchEventId, |
836 ServiceWorkerResponse(), base::Time::Now())); | 919 ServiceWorkerResponse(), base::Time::Now())); |
837 | 920 |
838 base::RunLoop().RunUntilIdle(); | 921 base::RunLoop().RunUntilIdle(); |
839 EXPECT_EQ(0, dispatcher_host_->bad_messages_received_count_); | 922 EXPECT_EQ(0, dispatcher_host_->bad_messages_received_count_); |
840 } | 923 } |
841 | 924 |
842 } // namespace content | 925 } // namespace content |
OLD | NEW |