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 3// found in the LICENSE file. 4 5#include "base/bind.h" 6#include "base/files/file_path.h" 7#include "base/memory/scoped_ptr.h" 8#include "base/message_loop/message_loop.h" 9#include "base/path_service.h" 10#include "base/strings/string_number_conversions.h" 11#include "chrome/browser/chromeos/first_run/drive_first_run_controller.h" 12#include "chrome/browser/extensions/crx_installer.h" 13#include "chrome/browser/extensions/extension_service.h" 14#include "chrome/browser/extensions/extension_test_notification_observer.h" 15#include "chrome/common/chrome_paths.h" 16#include "chrome/test/base/in_process_browser_test.h" 17#include "content/public/test/test_utils.h" 18#include "extensions/browser/extension_system.h" 19#include "net/dns/mock_host_resolver.h" 20#include "net/http/http_status_code.h" 21#include "net/test/embedded_test_server/embedded_test_server.h" 22#include "net/test/embedded_test_server/http_request.h" 23#include "net/test/embedded_test_server/http_response.h" 24 25namespace chromeos { 26 27namespace { 28 29// Directory containing data files for the tests. 30const char kTestDirectory[] = "drive_first_run"; 31 32// Directory containing correct hosted app page served by the test server. 33const char kGoodServerDirectory[] = "good"; 34 35// Directory containing incorrect hosted app page served by the test server. 36const char kBadServerDirectory[] = "bad"; 37 38// Name of the test hosted app .crx file. 39const char kTestAppCrxName[] = "app.crx"; 40 41// App id of the test hosted app. 42const char kTestAppId[] = "kipccbklifbfblhpplnmklieangbjnhb"; 43 44// The endpoint belonging to the test hosted app. 45const char kTestEndpointUrl[] = "http://example.com/endpoint.html"; 46 47} // namespace 48 49class DriveFirstRunTest : public InProcessBrowserTest, 50 public DriveFirstRunController::Observer { 51 protected: 52 DriveFirstRunTest(); 53 54 // InProcessBrowserTest overrides: 55 virtual void SetUpOnMainThread() OVERRIDE; 56 virtual void TearDownOnMainThread() OVERRIDE; 57 58 // DriveFirstRunController::Observer overrides: 59 virtual void OnCompletion(bool success) OVERRIDE; 60 virtual void OnTimedOut() OVERRIDE; 61 62 void InstallApp(); 63 64 void InitTestServer(const std::string& directory); 65 66 bool WaitForFirstRunResult(); 67 68 void EnableOfflineMode(); 69 70 void SetDelays(int initial_delay_secs, int timeout_secs); 71 72 bool timed_out() const { return timed_out_; } 73 74 private: 75 // |controller_| is responsible for its own lifetime. 76 DriveFirstRunController* controller_; 77 scoped_refptr<content::MessageLoopRunner> runner_; 78 79 bool timed_out_; 80 bool waiting_for_result_; 81 bool success_; 82 base::FilePath test_data_dir_; 83 std::string endpoint_url_; 84}; 85 86DriveFirstRunTest::DriveFirstRunTest() : 87 timed_out_(false), 88 waiting_for_result_(false), 89 success_(false) {} 90 91void DriveFirstRunTest::SetUpOnMainThread() { 92 InProcessBrowserTest::SetUpOnMainThread(); 93 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_); 94 test_data_dir_ = test_data_dir_.AppendASCII(kTestDirectory); 95 96 host_resolver()->AddRule("example.com", "127.0.0.1"); 97 98 // |controller_| will delete itself when it completes. 99 controller_ = new DriveFirstRunController(browser()->profile()); 100 controller_->AddObserver(this); 101 controller_->SetDelaysForTest(0, 10); 102 controller_->SetAppInfoForTest(kTestAppId, kTestEndpointUrl); 103} 104 105void DriveFirstRunTest::TearDownOnMainThread() { 106 content::RunAllPendingInMessageLoop(); 107} 108 109void DriveFirstRunTest::InitTestServer(const std::string& directory) { 110 embedded_test_server()->ServeFilesFromDirectory( 111 test_data_dir_.AppendASCII(directory)); 112 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 113 114 // Configure the endpoint to use the test server's port. 115 const GURL url(kTestEndpointUrl); 116 GURL::Replacements replacements; 117 std::string port(base::IntToString(embedded_test_server()->port())); 118 replacements.SetPortStr(port); 119 endpoint_url_ = url.ReplaceComponents(replacements).spec(); 120 controller_->SetAppInfoForTest(kTestAppId, endpoint_url_); 121} 122 123void DriveFirstRunTest::InstallApp() { 124 ExtensionService* extension_service = extensions::ExtensionSystem::Get( 125 browser()->profile())->extension_service(); 126 scoped_refptr<extensions::CrxInstaller> installer = 127 extensions::CrxInstaller::CreateSilent(extension_service); 128 129 installer->InstallCrx(test_data_dir_.AppendASCII(kTestAppCrxName)); 130 ExtensionTestNotificationObserver observer(browser()); 131 observer.WaitForExtensionLoad(); 132 133 ASSERT_TRUE(extension_service->GetExtensionById(kTestAppId, false)); 134} 135 136void DriveFirstRunTest::EnableOfflineMode() { 137 controller_->EnableOfflineMode(); 138} 139 140void DriveFirstRunTest::SetDelays(int initial_delay_secs, int timeout_secs) { 141 controller_->SetDelaysForTest(initial_delay_secs, timeout_secs); 142} 143 144bool DriveFirstRunTest::WaitForFirstRunResult() { 145 waiting_for_result_ = true; 146 runner_ = new content::MessageLoopRunner; 147 runner_->Run(); 148 EXPECT_FALSE(waiting_for_result_); 149 return success_; 150} 151 152void DriveFirstRunTest::OnCompletion(bool success) { 153 EXPECT_TRUE(waiting_for_result_); 154 waiting_for_result_ = false; 155 success_ = success; 156 runner_->Quit(); 157 158 // |controller_| will eventually delete itself upon completion, so invalidate 159 // the pointer. 160 controller_ = NULL; 161} 162 163void DriveFirstRunTest::OnTimedOut() { 164 timed_out_ = true; 165} 166 167IN_PROC_BROWSER_TEST_F(DriveFirstRunTest, OfflineEnabled) { 168 InstallApp(); 169 InitTestServer(kGoodServerDirectory); 170 EnableOfflineMode(); 171 EXPECT_TRUE(WaitForFirstRunResult()); 172} 173 174IN_PROC_BROWSER_TEST_F(DriveFirstRunTest, AppNotInstalled) { 175 InitTestServer(kGoodServerDirectory); 176 EnableOfflineMode(); 177 EXPECT_FALSE(WaitForFirstRunResult()); 178 EXPECT_FALSE(timed_out()); 179} 180 181IN_PROC_BROWSER_TEST_F(DriveFirstRunTest, TimedOut) { 182 // Test that the controller times out instead of hanging forever. 183 InstallApp(); 184 InitTestServer(kBadServerDirectory); 185 SetDelays(0, 0); 186 EnableOfflineMode(); 187 EXPECT_FALSE(WaitForFirstRunResult()); 188 EXPECT_TRUE(timed_out()); 189} 190 191} // namespace chromeos 192