• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
FakeProfileSyncService()36   FakeProfileSyncService()
37       : ProfileSyncService(NULL, NULL, ""),
38         setup_(false) {
39   }
~FakeProfileSyncService()40   virtual ~FakeProfileSyncService() {}
41 
42   // Overrides of virtual methods in ProfileSyncService.
HasSyncSetupCompleted() const43   virtual bool HasSyncSetupCompleted() const {
44     return setup_;
45   }
ChangePreferredDataTypes(const syncable::ModelTypeSet & types)46   virtual void ChangePreferredDataTypes(const syncable::ModelTypeSet& types) {
47     types_ = types;
48   }
GetPreferredDataTypes(syncable::ModelTypeSet * types) const49   virtual void GetPreferredDataTypes(syncable::ModelTypeSet* types) const {
50     *types = types_;
51   }
SetSyncSetupCompleted()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.
FakeBrowserSignin(bool should_succeed,const std::string & initial_username,const std::string & username_after_login)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   }
~FakeBrowserSignin()73   virtual ~FakeBrowserSignin() {}
74 
GetSignedInUsername() const75   virtual std::string GetSignedInUsername() const {
76     return username_;
77   }
78 
RequestSignin(TabContents * tab_contents,const string16 & preferred_email,const string16 & message,SigninDelegate * delegate)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:
ExtensionWebstorePrivateBrowserTest()110   ExtensionWebstorePrivateBrowserTest() {
111     test_url_base_ = std::string() + kHttpScheme + kStandardSchemeSeparator +
112                      kTestUrlHostname;
113   }
114 
SetUpCommandLine(CommandLine * command_line)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).
GetUrl(const std::string & relative_path)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 
RunLoginTestImpl(bool incognito,const std::string & relative_path,const std::string & initial_login,bool login_succeeds,const std::string & login_result)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 
RunLoginTest(const std::string & relative_path,const std::string & initial_login,bool login_succeeds,const std::string & login_result)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 
IN_PROC_BROWSER_TEST_F(ExtensionWebstorePrivateBrowserTest,BrowserLogin)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@bar.com", false, "");
191 
192   RunLoginTest("browser_login/prompt_no_preferred.html", "", true, "");
193 
194   RunLoginTest("browser_login/prompt_preferred.html", "", true, "foo@bar.com");
195 
196   RunLoginTest("browser_login/prompt_login_fails.html",
197                "", false, "foo@bar.com");
198 }
199