1 // Copyright (c) 2011 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/string_number_conversions.h" 6 #include "base/utf_string_conversions.h" 7 #include "chrome/browser/browser_process.h" 8 #include "chrome/browser/browser_signin.h" 9 #include "chrome/browser/extensions/extension_browsertest.h" 10 #include "chrome/browser/extensions/extension_test_message_listener.h" 11 #include "chrome/browser/extensions/extension_webstore_private_api.h" 12 #include "chrome/browser/net/gaia/token_service.h" 13 #include "chrome/browser/profiles/profile_manager.h" 14 #include "chrome/browser/sync/profile_sync_service.h" 15 #include "chrome/browser/ui/browser.h" 16 #include "chrome/common/chrome_switches.h" 17 #include "chrome/common/net/gaia/gaia_constants.h" 18 #include "chrome/common/url_constants.h" 19 #include "chrome/test/ui_test_utils.h" 20 #include "content/browser/tab_contents/tab_contents.h" 21 #include "googleurl/src/gurl.h" 22 #include "net/base/mock_host_resolver.h" 23 24 using chrome::kHttpScheme; 25 using chrome::kStandardSchemeSeparator; 26 27 namespace { 28 29 const char kTestUrlHostname[] = "www.example.com"; 30 31 } // namespace 32 33 // A fake version of ProfileSyncService used for testing. 34 class FakeProfileSyncService : public ProfileSyncService { 35 public: 36 FakeProfileSyncService() 37 : ProfileSyncService(NULL, NULL, ""), 38 setup_(false) { 39 } 40 virtual ~FakeProfileSyncService() {} 41 42 // Overrides of virtual methods in ProfileSyncService. 43 virtual bool HasSyncSetupCompleted() const { 44 return setup_; 45 } 46 virtual void ChangePreferredDataTypes(const syncable::ModelTypeSet& types) { 47 types_ = types; 48 } 49 virtual void GetPreferredDataTypes(syncable::ModelTypeSet* types) const { 50 *types = types_; 51 } 52 virtual void SetSyncSetupCompleted() { 53 setup_ = true; 54 } 55 56 private: 57 bool setup_; 58 syncable::ModelTypeSet types_; 59 }; 60 61 class FakeBrowserSignin : public BrowserSignin { 62 public: 63 // The |username_after_login| parameter determines what this fake 64 // BrowserSignin will set the username to when ShowLoginDialog is called. 65 FakeBrowserSignin(bool should_succeed, 66 const std::string& initial_username, 67 const std::string& username_after_login) 68 : BrowserSignin(NULL), 69 should_succeed_(should_succeed), 70 username_(initial_username), 71 username_after_login_(username_after_login) { 72 } 73 virtual ~FakeBrowserSignin() {} 74 75 virtual std::string GetSignedInUsername() const { 76 return username_; 77 } 78 79 virtual void RequestSignin(TabContents* tab_contents, 80 const string16& preferred_email, 81 const string16& message, 82 SigninDelegate* delegate) { 83 if (should_succeed_) { 84 // Simulate valid login. 85 username_ = username_after_login_; 86 delegate->OnLoginSuccess(); 87 88 // Fake a token available notification. 89 Profile* profile = tab_contents->profile(); 90 if (profile->IsOffTheRecord()) { 91 profile = g_browser_process->profile_manager()->GetDefaultProfile(); 92 } 93 TokenService* token_service = profile->GetTokenService(); 94 token_service->IssueAuthTokenForTest(GaiaConstants::kGaiaService, 95 "new_token"); 96 } else { 97 delegate->OnLoginFailure(GoogleServiceAuthError( 98 GoogleServiceAuthError::REQUEST_CANCELED)); 99 } 100 } 101 102 private: 103 bool should_succeed_; 104 std::string username_; 105 std::string username_after_login_; 106 }; 107 108 class ExtensionWebstorePrivateBrowserTest : public ExtensionBrowserTest { 109 public: 110 ExtensionWebstorePrivateBrowserTest() { 111 test_url_base_ = std::string() + kHttpScheme + kStandardSchemeSeparator + 112 kTestUrlHostname; 113 } 114 115 void SetUpCommandLine(CommandLine* command_line) { 116 ExtensionBrowserTest::SetUpCommandLine(command_line); 117 command_line->AppendSwitchASCII(switches::kAppsGalleryURL, test_url_base_); 118 } 119 120 // This generates a regular test server url pointing to a test file at 121 // |relative_path|, but replaces the hostname with kTestUrlHostname so that 122 // we get the webstore private APIs injected (this happens because of the 123 // command line switch we added in SetupCommandLine). 124 GURL GetUrl(const std::string& relative_path) { 125 GURL base_url = test_server()->GetURL( 126 "files/extensions/webstore_private/" + relative_path); 127 GURL::Replacements replacements; 128 std::string replacement_host = std::string(kTestUrlHostname); 129 replacements.SetHostStr(replacement_host); 130 return base_url.ReplaceComponents(replacements); 131 } 132 133 void RunLoginTestImpl(bool incognito, 134 const std::string& relative_path, 135 const std::string& initial_login, 136 bool login_succeeds, 137 const std::string& login_result) { 138 // Clear the token service so previous tests don't affect things. 139 TokenService* token_service = browser()->profile()->GetTokenService(); 140 token_service->ResetCredentialsInMemory(); 141 if (!initial_login.empty()) { 142 // Initialize the token service with an existing token. 143 token_service->IssueAuthTokenForTest(GaiaConstants::kGaiaService, 144 "existing_token"); 145 } 146 147 FakeProfileSyncService sync_service; 148 FakeBrowserSignin signin(login_succeeds, initial_login, login_result); 149 WebstorePrivateApi::SetTestingProfileSyncService(&sync_service); 150 WebstorePrivateApi::SetTestingBrowserSignin(&signin); 151 152 ExtensionTestMessageListener listener("success", false); 153 GURL url = GetUrl(relative_path); 154 if (incognito) { 155 ui_test_utils::OpenURLOffTheRecord(browser()->profile(), url); 156 } else { 157 ui_test_utils::NavigateToURL(browser(), url); 158 } 159 EXPECT_TRUE(listener.WaitUntilSatisfied()); 160 161 WebstorePrivateApi::SetTestingBrowserSignin(NULL); 162 WebstorePrivateApi::SetTestingProfileSyncService(NULL); 163 } 164 165 void RunLoginTest(const std::string& relative_path, 166 const std::string& initial_login, 167 bool login_succeeds, 168 const std::string& login_result) { 169 RunLoginTestImpl(true, 170 relative_path, 171 initial_login, 172 login_succeeds, 173 login_result); 174 RunLoginTestImpl(false, 175 relative_path, 176 initial_login, 177 login_succeeds, 178 login_result); 179 } 180 181 protected: 182 std::string test_url_base_; 183 }; 184 185 IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateBrowserTest, BrowserLogin) { 186 host_resolver()->AddRule(kTestUrlHostname, "127.0.0.1"); 187 ASSERT_TRUE(test_server()->Start()); 188 189 RunLoginTest("browser_login/expect_nonempty.html", 190 "foo (at) bar.com", false, ""); 191 192 RunLoginTest("browser_login/prompt_no_preferred.html", "", true, ""); 193 194 RunLoginTest("browser_login/prompt_preferred.html", "", true, "foo (at) bar.com"); 195 196 RunLoginTest("browser_login/prompt_login_fails.html", 197 "", false, "foo (at) bar.com"); 198 } 199