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

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

Issue 2779763004: Create ServiceWorkerProviderHost before starting worker (Closed)
Patch Set: Fix ForeignFetchRequestHandlerTest.InitializeHandler_TimeoutBehaviorForServiceWorker Created 3 years, 6 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/embedded_worker_test_helper.h" 5 #include "content/browser/service_worker/embedded_worker_test_helper.h"
6 6
7 #include <map> 7 #include <map>
8 #include <memory> 8 #include <memory>
9 #include <string> 9 #include <string>
10 #include <utility> 10 #include <utility>
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 MockEmbeddedWorkerInstanceClient( 66 MockEmbeddedWorkerInstanceClient(
67 base::WeakPtr<EmbeddedWorkerTestHelper> helper) 67 base::WeakPtr<EmbeddedWorkerTestHelper> helper)
68 : helper_(helper), binding_(this) {} 68 : helper_(helper), binding_(this) {}
69 69
70 EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient:: 70 EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::
71 ~MockEmbeddedWorkerInstanceClient() {} 71 ~MockEmbeddedWorkerInstanceClient() {}
72 72
73 void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StartWorker( 73 void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StartWorker(
74 const EmbeddedWorkerStartParams& params, 74 const EmbeddedWorkerStartParams& params,
75 mojom::ServiceWorkerEventDispatcherRequest dispatcher_request, 75 mojom::ServiceWorkerEventDispatcherRequest dispatcher_request,
76 mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host) { 76 mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
77 mojom::ServiceWorkerProviderClientInfoPtr provider_client_info) {
77 if (!helper_) 78 if (!helper_)
78 return; 79 return;
79 80
80 embedded_worker_id_ = params.embedded_worker_id; 81 embedded_worker_id_ = params.embedded_worker_id;
81 82
82 EmbeddedWorkerInstance* worker = 83 EmbeddedWorkerInstance* worker =
83 helper_->registry()->GetWorker(params.embedded_worker_id); 84 helper_->registry()->GetWorker(params.embedded_worker_id);
84 ASSERT_TRUE(worker); 85 ASSERT_TRUE(worker);
85 EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status()); 86 EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
86 87
87 helper_->OnStartWorkerStub(params, std::move(dispatcher_request), 88 helper_->OnStartWorkerStub(params, std::move(dispatcher_request),
88 std::move(instance_host)); 89 std::move(instance_host),
90 std::move(provider_client_info));
89 } 91 }
90 92
91 void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StopWorker() { 93 void EmbeddedWorkerTestHelper::MockEmbeddedWorkerInstanceClient::StopWorker() {
92 if (!helper_) 94 if (!helper_)
93 return; 95 return;
94 96
95 ASSERT_TRUE(embedded_worker_id_); 97 ASSERT_TRUE(embedded_worker_id_);
96 EmbeddedWorkerInstance* worker = 98 EmbeddedWorkerInstance* worker =
97 helper_->registry()->GetWorker(embedded_worker_id_.value()); 99 helper_->registry()->GetWorker(embedded_worker_id_.value());
98 // |worker| is possible to be null when corresponding EmbeddedWorkerInstance 100 // |worker| is possible to be null when corresponding EmbeddedWorkerInstance
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 285
284 EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper( 286 EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
285 const base::FilePath& user_data_directory) 287 const base::FilePath& user_data_directory)
286 : browser_context_(new TestBrowserContext), 288 : browser_context_(new TestBrowserContext),
287 render_process_host_(new MockRenderProcessHost(browser_context_.get())), 289 render_process_host_(new MockRenderProcessHost(browser_context_.get())),
288 new_render_process_host_( 290 new_render_process_host_(
289 new MockRenderProcessHost(browser_context_.get())), 291 new MockRenderProcessHost(browser_context_.get())),
290 wrapper_(new ServiceWorkerContextWrapper(browser_context_.get())), 292 wrapper_(new ServiceWorkerContextWrapper(browser_context_.get())),
291 mock_instance_clients_next_index_(0), 293 mock_instance_clients_next_index_(0),
292 next_thread_id_(0), 294 next_thread_id_(0),
293 next_provider_id_(1000),
294 mock_render_process_id_(render_process_host_->GetID()), 295 mock_render_process_id_(render_process_host_->GetID()),
295 new_mock_render_process_id_(new_render_process_host_->GetID()), 296 new_mock_render_process_id_(new_render_process_host_->GetID()),
296 weak_factory_(this) { 297 weak_factory_(this) {
297 std::unique_ptr<MockServiceWorkerDatabaseTaskManager> database_task_manager( 298 std::unique_ptr<MockServiceWorkerDatabaseTaskManager> database_task_manager(
298 new MockServiceWorkerDatabaseTaskManager( 299 new MockServiceWorkerDatabaseTaskManager(
299 base::ThreadTaskRunnerHandle::Get())); 300 base::ThreadTaskRunnerHandle::Get()));
300 wrapper_->InitInternal(user_data_directory, std::move(database_task_manager), 301 wrapper_->InitInternal(user_data_directory, std::move(database_task_manager),
301 base::ThreadTaskRunnerHandle::Get(), nullptr, nullptr); 302 base::ThreadTaskRunnerHandle::Get(), nullptr, nullptr);
302 wrapper_->process_manager()->SetProcessIdForTest(mock_render_process_id()); 303 wrapper_->process_manager()->SetProcessIdForTest(mock_render_process_id());
303 wrapper_->process_manager()->SetNewProcessIdForTest(new_render_process_id()); 304 wrapper_->process_manager()->SetNewProcessIdForTest(new_render_process_id());
304 305
305 scoped_refptr<ServiceWorkerDispatcherHost> dispatcher_host( 306 scoped_refptr<ServiceWorkerDispatcherHost> dispatcher_host(
306 new MockServiceWorkerDispatcherHost( 307 new MockServiceWorkerDispatcherHost(
307 mock_render_process_id_, browser_context_->GetResourceContext(), 308 mock_render_process_id_, browser_context_->GetResourceContext(),
308 this)); 309 this));
309 wrapper_->context()->AddDispatcherHost(mock_render_process_id_, 310 dispatcher_host->Init(wrapper_.get());
310 dispatcher_host.get());
311 dispatcher_hosts_[mock_render_process_id_] = std::move(dispatcher_host); 311 dispatcher_hosts_[mock_render_process_id_] = std::move(dispatcher_host);
312 312
313 render_process_host_->OverrideBinderForTesting( 313 render_process_host_->OverrideBinderForTesting(
314 mojom::EmbeddedWorkerInstanceClient::Name_, 314 mojom::EmbeddedWorkerInstanceClient::Name_,
315 base::Bind(&MockEmbeddedWorkerInstanceClient::Bind, AsWeakPtr())); 315 base::Bind(&MockEmbeddedWorkerInstanceClient::Bind, AsWeakPtr()));
316 new_render_process_host_->OverrideBinderForTesting( 316 new_render_process_host_->OverrideBinderForTesting(
317 mojom::EmbeddedWorkerInstanceClient::Name_, 317 mojom::EmbeddedWorkerInstanceClient::Name_,
318 base::Bind(&MockEmbeddedWorkerInstanceClient::Bind, AsWeakPtr())); 318 base::Bind(&MockEmbeddedWorkerInstanceClient::Bind, AsWeakPtr()));
319 } 319 }
320 320
321 EmbeddedWorkerTestHelper::~EmbeddedWorkerTestHelper() { 321 EmbeddedWorkerTestHelper::~EmbeddedWorkerTestHelper() {
322 if (wrapper_.get()) 322 if (wrapper_.get())
323 wrapper_->Shutdown(); 323 wrapper_->Shutdown();
324 } 324 }
325 325
326 void EmbeddedWorkerTestHelper::SimulateAddProcessToPattern(const GURL& pattern, 326 void EmbeddedWorkerTestHelper::SimulateAddProcessToPattern(const GURL& pattern,
327 int process_id) { 327 int process_id) {
328 if (!context()->GetDispatcherHost(process_id)) { 328 if (!context()->GetDispatcherHost(process_id)) {
329 scoped_refptr<ServiceWorkerDispatcherHost> dispatcher_host( 329 scoped_refptr<ServiceWorkerDispatcherHost> dispatcher_host(
330 new MockServiceWorkerDispatcherHost( 330 new MockServiceWorkerDispatcherHost(
331 process_id, browser_context_->GetResourceContext(), this)); 331 process_id, browser_context_->GetResourceContext(), this));
332 wrapper_->context()->AddDispatcherHost(process_id, dispatcher_host.get()); 332 dispatcher_host->Init(wrapper_.get());
333 dispatcher_hosts_[process_id] = std::move(dispatcher_host); 333 dispatcher_hosts_[process_id] = std::move(dispatcher_host);
334 } 334 }
335 wrapper_->process_manager()->AddProcessReferenceToPattern(pattern, 335 wrapper_->process_manager()->AddProcessReferenceToPattern(pattern,
336 process_id); 336 process_id);
337 } 337 }
338 338
339 bool EmbeddedWorkerTestHelper::Send(IPC::Message* message) { 339 bool EmbeddedWorkerTestHelper::Send(IPC::Message* message) {
340 OnMessageReceived(*message); 340 OnMessageReceived(*message);
341 delete message; 341 delete message;
342 return true; 342 return true;
(...skipping 12 matching lines...) Expand all
355 sink_.OnMessageReceived(message); 355 sink_.OnMessageReceived(message);
356 356
357 return handled; 357 return handled;
358 } 358 }
359 359
360 void EmbeddedWorkerTestHelper::RegisterMockInstanceClient( 360 void EmbeddedWorkerTestHelper::RegisterMockInstanceClient(
361 std::unique_ptr<MockEmbeddedWorkerInstanceClient> client) { 361 std::unique_ptr<MockEmbeddedWorkerInstanceClient> client) {
362 mock_instance_clients_.push_back(std::move(client)); 362 mock_instance_clients_.push_back(std::move(client));
363 } 363 }
364 364
365 void EmbeddedWorkerTestHelper::RegisterMockDispatcherHost(
366 int process_id,
367 scoped_refptr<ServiceWorkerDispatcherHost> dispatcher_host) {
368 dispatcher_hosts_[process_id] = std::move(dispatcher_host);
369 }
370
365 ServiceWorkerContextCore* EmbeddedWorkerTestHelper::context() { 371 ServiceWorkerContextCore* EmbeddedWorkerTestHelper::context() {
366 return wrapper_->context(); 372 return wrapper_->context();
367 } 373 }
368 374
369 void EmbeddedWorkerTestHelper::ShutdownContext() { 375 void EmbeddedWorkerTestHelper::ShutdownContext() {
370 wrapper_->Shutdown(); 376 wrapper_->Shutdown();
371 wrapper_ = NULL; 377 wrapper_ = NULL;
372 } 378 }
373 379
374 // static 380 // static
375 net::HttpResponseInfo EmbeddedWorkerTestHelper::CreateHttpResponseInfo() { 381 net::HttpResponseInfo EmbeddedWorkerTestHelper::CreateHttpResponseInfo() {
376 net::HttpResponseInfo info; 382 net::HttpResponseInfo info;
377 const char data[] = 383 const char data[] =
378 "HTTP/1.1 200 OK\0" 384 "HTTP/1.1 200 OK\0"
379 "Content-Type: application/javascript\0" 385 "Content-Type: application/javascript\0"
380 "\0"; 386 "\0";
381 info.headers = 387 info.headers =
382 new net::HttpResponseHeaders(std::string(data, arraysize(data))); 388 new net::HttpResponseHeaders(std::string(data, arraysize(data)));
383 return info; 389 return info;
384 } 390 }
385 391
386 void EmbeddedWorkerTestHelper::OnStartWorker( 392 void EmbeddedWorkerTestHelper::OnStartWorker(
387 int embedded_worker_id, 393 int embedded_worker_id,
388 int64_t service_worker_version_id, 394 int64_t service_worker_version_id,
389 const GURL& scope, 395 const GURL& scope,
390 const GURL& script_url, 396 const GURL& script_url,
391 bool pause_after_download, 397 bool pause_after_download,
392 mojom::ServiceWorkerEventDispatcherRequest request, 398 mojom::ServiceWorkerEventDispatcherRequest request,
393 mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host) { 399 mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
400 mojom::ServiceWorkerProviderClientInfoPtr provider_client_info) {
394 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id); 401 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
395 ASSERT_TRUE(worker); 402 ASSERT_TRUE(worker);
396 MockServiceWorkerEventDispatcher::Create(AsWeakPtr(), worker->thread_id(), 403 MockServiceWorkerEventDispatcher::Create(AsWeakPtr(), worker->thread_id(),
397 std::move(request)); 404 std::move(request));
398 405
399 embedded_worker_id_service_worker_version_id_map_[embedded_worker_id] = 406 embedded_worker_id_service_worker_version_id_map_[embedded_worker_id] =
400 service_worker_version_id; 407 service_worker_version_id;
401 embedded_worker_id_instance_host_ptr_map_[embedded_worker_id].Bind( 408 embedded_worker_id_instance_host_ptr_map_[embedded_worker_id].Bind(
402 std::move(instance_host)); 409 std::move(instance_host));
410 ServiceWorkerRemoteProviderEndpoint* provider_endpoint =
411 &embedded_worker_id_remote_provider_map_[embedded_worker_id];
412 provider_endpoint->BindWithProviderClientInfo(provider_client_info.get());
403 413
404 SimulateWorkerReadyForInspection(embedded_worker_id); 414 SimulateWorkerReadyForInspection(embedded_worker_id);
405 SimulateWorkerScriptCached(embedded_worker_id); 415 SimulateWorkerScriptCached(embedded_worker_id);
406 SimulateWorkerScriptLoaded(embedded_worker_id); 416 SimulateWorkerScriptLoaded(embedded_worker_id);
407 if (!pause_after_download) 417 if (!pause_after_download)
408 OnResumeAfterDownload(embedded_worker_id); 418 OnResumeAfterDownload(embedded_worker_id);
409 } 419 }
410 420
411 void EmbeddedWorkerTestHelper::OnResumeAfterDownload(int embedded_worker_id) { 421 void EmbeddedWorkerTestHelper::OnResumeAfterDownload(int embedded_worker_id) {
412 SimulateWorkerThreadStarted(GetNextThreadId(), embedded_worker_id, 422 SimulateWorkerThreadStarted(GetNextThreadId(), embedded_worker_id);
413 GetNextProviderId());
414 SimulateWorkerScriptEvaluated(embedded_worker_id, true /* success */); 423 SimulateWorkerScriptEvaluated(embedded_worker_id, true /* success */);
415 SimulateWorkerStarted(embedded_worker_id); 424 SimulateWorkerStarted(embedded_worker_id);
416 } 425 }
417 426
418 void EmbeddedWorkerTestHelper::OnStopWorker(int embedded_worker_id) { 427 void EmbeddedWorkerTestHelper::OnStopWorker(int embedded_worker_id) {
419 // By default just notify the sender that the worker is stopped. 428 // By default just notify the sender that the worker is stopped.
420 SimulateWorkerStopped(embedded_worker_id); 429 SimulateWorkerStopped(embedded_worker_id);
421 } 430 }
422 431
423 void EmbeddedWorkerTestHelper::OnActivateEvent( 432 void EmbeddedWorkerTestHelper::OnActivateEvent(
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id); 573 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
565 ASSERT_TRUE(worker); 574 ASSERT_TRUE(worker);
566 ASSERT_TRUE(embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]); 575 ASSERT_TRUE(embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]);
567 embedded_worker_id_instance_host_ptr_map_[embedded_worker_id] 576 embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]
568 ->OnScriptLoaded(); 577 ->OnScriptLoaded();
569 base::RunLoop().RunUntilIdle(); 578 base::RunLoop().RunUntilIdle();
570 } 579 }
571 580
572 void EmbeddedWorkerTestHelper::SimulateWorkerThreadStarted( 581 void EmbeddedWorkerTestHelper::SimulateWorkerThreadStarted(
573 int thread_id, 582 int thread_id,
574 int embedded_worker_id, 583 int embedded_worker_id) {
575 int provider_id) {
576 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id); 584 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
577 ASSERT_TRUE(worker); 585 ASSERT_TRUE(worker);
578 ASSERT_TRUE(embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]); 586 ASSERT_TRUE(embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]);
579
580 // Prepare a provider host to be used by following OnThreadStarted().
581 std::unique_ptr<ServiceWorkerProviderHost> host =
582 CreateProviderHostForServiceWorkerContext(
583 worker->process_id(), provider_id, true /* is_parent_frame_secure */,
584 context()->AsWeakPtr(),
585 &embedded_worker_id_remote_provider_map_[embedded_worker_id]);
586 context()->AddProviderHost(std::move(host));
587
588 embedded_worker_id_instance_host_ptr_map_[embedded_worker_id] 587 embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]
589 ->OnThreadStarted(thread_id, provider_id); 588 ->OnThreadStarted(thread_id);
590 base::RunLoop().RunUntilIdle(); 589 base::RunLoop().RunUntilIdle();
591 } 590 }
592 591
593 void EmbeddedWorkerTestHelper::SimulateWorkerScriptEvaluated( 592 void EmbeddedWorkerTestHelper::SimulateWorkerScriptEvaluated(
594 int embedded_worker_id, 593 int embedded_worker_id,
595 bool success) { 594 bool success) {
596 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id); 595 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
597 ASSERT_TRUE(worker); 596 ASSERT_TRUE(worker);
598 ASSERT_TRUE(embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]); 597 ASSERT_TRUE(embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]);
599 embedded_worker_id_instance_host_ptr_map_[embedded_worker_id] 598 embedded_worker_id_instance_host_ptr_map_[embedded_worker_id]
(...skipping 19 matching lines...) Expand all
619 } 618 }
620 619
621 void EmbeddedWorkerTestHelper::SimulateSend(IPC::Message* message) { 620 void EmbeddedWorkerTestHelper::SimulateSend(IPC::Message* message) {
622 registry()->OnMessageReceived(*message, mock_render_process_id_); 621 registry()->OnMessageReceived(*message, mock_render_process_id_);
623 delete message; 622 delete message;
624 } 623 }
625 624
626 void EmbeddedWorkerTestHelper::OnStartWorkerStub( 625 void EmbeddedWorkerTestHelper::OnStartWorkerStub(
627 const EmbeddedWorkerStartParams& params, 626 const EmbeddedWorkerStartParams& params,
628 mojom::ServiceWorkerEventDispatcherRequest request, 627 mojom::ServiceWorkerEventDispatcherRequest request,
629 mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host) { 628 mojom::EmbeddedWorkerInstanceHostAssociatedPtrInfo instance_host,
629 mojom::ServiceWorkerProviderClientInfoPtr provider_client_info) {
630 EmbeddedWorkerInstance* worker = 630 EmbeddedWorkerInstance* worker =
631 registry()->GetWorker(params.embedded_worker_id); 631 registry()->GetWorker(params.embedded_worker_id);
632 ASSERT_TRUE(worker); 632 ASSERT_TRUE(worker);
633 EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status()); 633 EXPECT_EQ(EmbeddedWorkerStatus::STARTING, worker->status());
634 base::ThreadTaskRunnerHandle::Get()->PostTask( 634 base::ThreadTaskRunnerHandle::Get()->PostTask(
635 FROM_HERE, 635 FROM_HERE,
636 base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker, AsWeakPtr(), 636 base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker, AsWeakPtr(),
637 params.embedded_worker_id, params.service_worker_version_id, 637 params.embedded_worker_id, params.service_worker_version_id,
638 params.scope, params.script_url, params.pause_after_download, 638 params.scope, params.script_url, params.pause_after_download,
639 base::Passed(&request), base::Passed(&instance_host))); 639 base::Passed(&request), base::Passed(&instance_host),
640 base::Passed(&provider_client_info)));
640 } 641 }
641 642
642 void EmbeddedWorkerTestHelper::OnResumeAfterDownloadStub( 643 void EmbeddedWorkerTestHelper::OnResumeAfterDownloadStub(
643 int embedded_worker_id) { 644 int embedded_worker_id) {
644 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id); 645 EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
645 ASSERT_TRUE(worker); 646 ASSERT_TRUE(worker);
646 base::ThreadTaskRunnerHandle::Get()->PostTask( 647 base::ThreadTaskRunnerHandle::Get()->PostTask(
647 FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnResumeAfterDownload, 648 FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnResumeAfterDownload,
648 AsWeakPtr(), embedded_worker_id)); 649 AsWeakPtr(), embedded_worker_id));
649 } 650 }
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
793 base::Passed(&app_request), base::Passed(&response_callback), 794 base::Passed(&app_request), base::Passed(&response_callback),
794 base::Passed(&callback))); 795 base::Passed(&callback)));
795 } 796 }
796 797
797 EmbeddedWorkerRegistry* EmbeddedWorkerTestHelper::registry() { 798 EmbeddedWorkerRegistry* EmbeddedWorkerTestHelper::registry() {
798 DCHECK(context()); 799 DCHECK(context());
799 return context()->embedded_worker_registry(); 800 return context()->embedded_worker_registry();
800 } 801 }
801 802
802 } // namespace content 803 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698