15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file.
45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/logging.h"
75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/run_loop.h"
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/browser_thread_impl.h"
95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/fileapi/mock_url_request_delegate.h"
105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/service_worker/embedded_worker_test_helper.h"
115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/service_worker/service_worker_context_core.h"
125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/service_worker/service_worker_provider_host.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/service_worker/service_worker_registration.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/service_worker/service_worker_registration.h"
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/service_worker/service_worker_url_request_job.h"
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/browser/service_worker/service_worker_utils.h"
1803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "content/common/resource_request_body.h"
195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "content/public/test/test_browser_thread_bundle.h"
205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "net/url_request/url_request_context.h"
215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace content {
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace {
265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int kMockRenderProcessId = 1224;
281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint kMockProviderId = 1;
295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void EmptyCallback() {}
315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class ServiceWorkerControlleeRequestHandlerTest : public testing::Test {
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) public:
365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ServiceWorkerControlleeRequestHandlerTest()
375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    helper_.reset(new EmbeddedWorkerTestHelper(kMockRenderProcessId));
415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // A new unstored registration/version.
435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scope_ = GURL("http://host/scope/");
445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    script_url_ = GURL("http://host/script.js");
455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    registration_ = new ServiceWorkerRegistration(
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        scope_, 1L, context()->AsWeakPtr());
475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    version_ = new ServiceWorkerVersion(
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        registration_.get(), script_url_, 1L, context()->AsWeakPtr());
495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    // An empty host.
515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        kMockRenderProcessId, kMockProviderId,
535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        context()->AsWeakPtr(), NULL));
545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    provider_host_ = host->AsWeakPtr();
556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    context()->AddProviderHost(host.Pass());
565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    context()->storage()->LazyInitialize(base::Bind(&EmptyCallback));
585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    base::RunLoop().RunUntilIdle();
595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  virtual void TearDown() OVERRIDE {
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    version_ = NULL;
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    registration_ = NULL;
645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    helper_.reset();
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ServiceWorkerContextCore* context() const { return helper_->context(); }
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) protected:
705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TestBrowserThreadBundle browser_thread_bundle_;
715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<EmbeddedWorkerTestHelper> helper_;
725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<ServiceWorkerRegistration> registration_;
735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<ServiceWorkerVersion> version_;
745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  net::URLRequestContext url_request_context_;
765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  MockURLRequestDelegate url_request_delegate_;
775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GURL scope_;
785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  GURL script_url_;
795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)};
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TEST_F(ServiceWorkerControlleeRequestHandlerTest, ActivateWaitingVersion) {
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Store a registration that is installed but not activated yet.
835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  version_->SetStatus(ServiceWorkerVersion::INSTALLED);
841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  registration_->SetWaitingVersion(version_.get());
855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  context()->storage()->StoreRegistration(
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      registration_.get(),
871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      version_.get(),
885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Conduct a main resource load.
925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  const GURL kDocUrl("http://host/scope/doc");
935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<net::URLRequest> request = url_request_context_.CreateRequest(
945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      kDocUrl,
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      net::DEFAULT_PRIORITY,
965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      &url_request_delegate_,
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      NULL);
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_ptr<ServiceWorkerControlleeRequestHandler> handler(
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new ServiceWorkerControlleeRequestHandler(
1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          context()->AsWeakPtr(),
1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          provider_host_,
10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          base::WeakPtr<storage::BlobStorageContext>(),
10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          RESOURCE_TYPE_MAIN_FRAME,
10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)          scoped_refptr<ResourceRequestBody>()));
1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  scoped_refptr<net::URLRequestJob> job =
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      handler->MaybeCreateJob(request.get(), NULL);
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ServiceWorkerURLRequestJob* sw_job =
1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      static_cast<ServiceWorkerURLRequestJob*>(job.get());
1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_FALSE(sw_job->ShouldFallbackToNetwork());
1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_FALSE(version_->HasControllee());
1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::RunLoop().RunUntilIdle();
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_EQ(ServiceWorkerVersion::ACTIVATED,
1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)            version_->status());
1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_FALSE(sw_job->ShouldFallbackToNetwork());
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(sw_job->ShouldForwardToServiceWorker());
1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(version_->HasControllee());
1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Navigations should trigger an update too.
1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  handler.reset(NULL);
1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  EXPECT_TRUE(version_->update_timer_.IsRunning());
1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// Test to not regress crbug/414118.
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciTEST_F(ServiceWorkerControlleeRequestHandlerTest, DeletedProviderHost) {
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Store a registration so the call to FindRegistrationForDocument will read
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // from the database.
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  registration_->SetActiveVersion(version_.get());
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  context()->storage()->StoreRegistration(
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      registration_.get(),
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      version_.get(),
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::RunLoop().RunUntilIdle();
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  version_ = NULL;
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  registration_ = NULL;
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Conduct a main resource load.
1421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  const GURL kDocUrl("http://host/scope/doc");
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<net::URLRequest> request = url_request_context_.CreateRequest(
1441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      kDocUrl,
1451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      net::DEFAULT_PRIORITY,
1461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      &url_request_delegate_,
1471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      NULL);
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_ptr<ServiceWorkerControlleeRequestHandler> handler(
1491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new ServiceWorkerControlleeRequestHandler(
1501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          context()->AsWeakPtr(),
1511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          provider_host_,
1521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          base::WeakPtr<storage::BlobStorageContext>(),
1531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          RESOURCE_TYPE_MAIN_FRAME,
1541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          scoped_refptr<ResourceRequestBody>()));
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<net::URLRequestJob> job =
1561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      handler->MaybeCreateJob(request.get(), NULL);
1571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  ServiceWorkerURLRequestJob* sw_job =
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      static_cast<ServiceWorkerURLRequestJob*>(job.get());
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(sw_job->ShouldFallbackToNetwork());
1611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
1621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Shouldn't crash if the ProviderHost is deleted prior to completion of
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // the database lookup.
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  context()->RemoveProviderHost(kMockRenderProcessId, kMockProviderId);
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(provider_host_.get());
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  base::RunLoop().RunUntilIdle();
1681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_TRUE(sw_job->ShouldFallbackToNetwork());
1691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EXPECT_FALSE(sw_job->ShouldForwardToServiceWorker());
1701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}  // namespace content
173