Home | History | Annotate | Download | only in extensions
      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