• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 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 <set>
6 #include <string>
7 #include <vector>
8 
9 #include "base/command_line.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/values.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/extensions/api/identity/identity_api.h"
16 #include "chrome/browser/extensions/component_loader.h"
17 #include "chrome/browser/extensions/extension_apitest.h"
18 #include "chrome/browser/extensions/extension_browsertest.h"
19 #include "chrome/browser/extensions/extension_function_test_utils.h"
20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/signin/account_reconcilor_factory.h"
23 #include "chrome/browser/signin/fake_account_reconcilor.h"
24 #include "chrome/browser/signin/fake_profile_oauth2_token_service.h"
25 #include "chrome/browser/signin/fake_profile_oauth2_token_service_builder.h"
26 #include "chrome/browser/signin/fake_signin_manager.h"
27 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
28 #include "chrome/browser/signin/signin_manager_factory.h"
29 #include "chrome/browser/ui/browser.h"
30 #include "chrome/browser/ui/browser_window.h"
31 #include "chrome/common/chrome_switches.h"
32 #include "chrome/common/extensions/api/identity.h"
33 #include "chrome/common/extensions/api/identity/oauth2_manifest_handler.h"
34 #include "chrome/test/base/in_process_browser_test.h"
35 #include "chrome/test/base/test_switches.h"
36 #include "components/crx_file/id_util.h"
37 #include "components/signin/core/browser/signin_manager.h"
38 #include "components/signin/core/common/profile_management_switches.h"
39 #include "components/signin/core/common/signin_pref_names.h"
40 #include "content/public/browser/notification_service.h"
41 #include "content/public/browser/notification_source.h"
42 #include "content/public/test/test_utils.h"
43 #include "extensions/browser/guest_view/guest_view_base.h"
44 #include "extensions/common/test_util.h"
45 #include "google_apis/gaia/google_service_auth_error.h"
46 #include "google_apis/gaia/oauth2_mint_token_flow.h"
47 #include "net/test/spawned_test_server/spawned_test_server.h"
48 #include "testing/gmock/include/gmock/gmock.h"
49 #include "testing/gtest/include/gtest/gtest.h"
50 #include "url/gurl.h"
51 
52 using testing::_;
53 using testing::Return;
54 using testing::ReturnRef;
55 
56 namespace extensions {
57 
58 namespace {
59 
60 namespace errors = identity_constants;
61 namespace utils = extension_function_test_utils;
62 
63 static const char kAccessToken[] = "auth_token";
64 static const char kExtensionId[] = "ext_id";
65 
66 // This helps us be able to wait until an UIThreadExtensionFunction calls
67 // SendResponse.
68 class SendResponseDelegate
69     : public UIThreadExtensionFunction::DelegateForTests {
70  public:
SendResponseDelegate()71   SendResponseDelegate() : should_post_quit_(false) {}
72 
~SendResponseDelegate()73   virtual ~SendResponseDelegate() {}
74 
set_should_post_quit(bool should_quit)75   void set_should_post_quit(bool should_quit) {
76     should_post_quit_ = should_quit;
77   }
78 
HasResponse()79   bool HasResponse() {
80     return response_.get() != NULL;
81   }
82 
GetResponse()83   bool GetResponse() {
84     EXPECT_TRUE(HasResponse());
85     return *response_.get();
86   }
87 
OnSendResponse(UIThreadExtensionFunction * function,bool success,bool bad_message)88   virtual void OnSendResponse(UIThreadExtensionFunction* function,
89                               bool success,
90                               bool bad_message) OVERRIDE {
91     ASSERT_FALSE(bad_message);
92     ASSERT_FALSE(HasResponse());
93     response_.reset(new bool);
94     *response_ = success;
95     if (should_post_quit_) {
96       base::MessageLoopForUI::current()->Quit();
97     }
98   }
99 
100  private:
101   scoped_ptr<bool> response_;
102   bool should_post_quit_;
103 };
104 
105 class AsyncExtensionBrowserTest : public ExtensionBrowserTest {
106  protected:
107   // Asynchronous function runner allows tests to manipulate the browser window
108   // after the call happens.
RunFunctionAsync(UIThreadExtensionFunction * function,const std::string & args)109   void RunFunctionAsync(
110       UIThreadExtensionFunction* function,
111       const std::string& args) {
112     response_delegate_.reset(new SendResponseDelegate);
113     function->set_test_delegate(response_delegate_.get());
114     scoped_ptr<base::ListValue> parsed_args(utils::ParseList(args));
115     EXPECT_TRUE(parsed_args.get()) <<
116         "Could not parse extension function arguments: " << args;
117     function->SetArgs(parsed_args.get());
118 
119     if (!function->extension()) {
120       scoped_refptr<Extension> empty_extension(
121           test_util::CreateEmptyExtension());
122       function->set_extension(empty_extension.get());
123     }
124 
125     function->set_browser_context(browser()->profile());
126     function->set_has_callback(true);
127     function->Run()->Execute();
128   }
129 
WaitForError(UIThreadExtensionFunction * function)130   std::string WaitForError(UIThreadExtensionFunction* function) {
131     RunMessageLoopUntilResponse();
132     EXPECT_FALSE(function->GetResultList()) << "Did not expect a result";
133     return function->GetError();
134   }
135 
WaitForSingleResult(UIThreadExtensionFunction * function)136   base::Value* WaitForSingleResult(UIThreadExtensionFunction* function) {
137     RunMessageLoopUntilResponse();
138     EXPECT_TRUE(function->GetError().empty()) << "Unexpected error: "
139                                               << function->GetError();
140     const base::Value* single_result = NULL;
141     if (function->GetResultList() != NULL &&
142         function->GetResultList()->Get(0, &single_result)) {
143       return single_result->DeepCopy();
144     }
145     return NULL;
146   }
147 
148  private:
RunMessageLoopUntilResponse()149   void RunMessageLoopUntilResponse() {
150     // If the RunAsync of |function| didn't already call SendResponse, run the
151     // message loop until they do.
152     if (!response_delegate_->HasResponse()) {
153       response_delegate_->set_should_post_quit(true);
154       content::RunMessageLoop();
155     }
156     EXPECT_TRUE(response_delegate_->HasResponse());
157   }
158 
159   scoped_ptr<SendResponseDelegate> response_delegate_;
160 };
161 
162 class TestHangOAuth2MintTokenFlow : public OAuth2MintTokenFlow {
163  public:
TestHangOAuth2MintTokenFlow()164   TestHangOAuth2MintTokenFlow()
165       : OAuth2MintTokenFlow(NULL, NULL, OAuth2MintTokenFlow::Parameters()) {}
166 
Start()167   virtual void Start() OVERRIDE {
168     // Do nothing, simulating a hanging network call.
169   }
170 };
171 
172 class TestOAuth2MintTokenFlow : public OAuth2MintTokenFlow {
173  public:
174   enum ResultType {
175     ISSUE_ADVICE_SUCCESS,
176     MINT_TOKEN_SUCCESS,
177     MINT_TOKEN_FAILURE,
178     MINT_TOKEN_BAD_CREDENTIALS,
179     MINT_TOKEN_SERVICE_ERROR
180   };
181 
TestOAuth2MintTokenFlow(ResultType result,OAuth2MintTokenFlow::Delegate * delegate)182   TestOAuth2MintTokenFlow(ResultType result,
183                           OAuth2MintTokenFlow::Delegate* delegate)
184     : OAuth2MintTokenFlow(NULL, delegate, OAuth2MintTokenFlow::Parameters()),
185       result_(result),
186       delegate_(delegate) {
187   }
188 
Start()189   virtual void Start() OVERRIDE {
190     switch (result_) {
191       case ISSUE_ADVICE_SUCCESS: {
192         IssueAdviceInfo info;
193         delegate_->OnIssueAdviceSuccess(info);
194         break;
195       }
196       case MINT_TOKEN_SUCCESS: {
197         delegate_->OnMintTokenSuccess(kAccessToken, 3600);
198         break;
199       }
200       case MINT_TOKEN_FAILURE: {
201         GoogleServiceAuthError error(GoogleServiceAuthError::CONNECTION_FAILED);
202         delegate_->OnMintTokenFailure(error);
203         break;
204       }
205       case MINT_TOKEN_BAD_CREDENTIALS: {
206         GoogleServiceAuthError error(
207             GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
208         delegate_->OnMintTokenFailure(error);
209         break;
210       }
211       case MINT_TOKEN_SERVICE_ERROR: {
212         GoogleServiceAuthError error =
213             GoogleServiceAuthError::FromServiceError("invalid_scope");
214         delegate_->OnMintTokenFailure(error);
215         break;
216       }
217     }
218   }
219 
220  private:
221   ResultType result_;
222   OAuth2MintTokenFlow::Delegate* delegate_;
223 };
224 
225 // Waits for a specific GURL to generate a NOTIFICATION_LOAD_STOP event and
226 // saves a pointer to the window embedding the WebContents, which can be later
227 // closed.
228 class WaitForGURLAndCloseWindow : public content::WindowedNotificationObserver {
229  public:
WaitForGURLAndCloseWindow(GURL url)230   explicit WaitForGURLAndCloseWindow(GURL url)
231       : WindowedNotificationObserver(
232             content::NOTIFICATION_LOAD_STOP,
233             content::NotificationService::AllSources()),
234         url_(url) {}
235 
236   // NotificationObserver:
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)237   virtual void Observe(int type,
238                        const content::NotificationSource& source,
239                        const content::NotificationDetails& details) OVERRIDE {
240     content::NavigationController* web_auth_flow_controller =
241         content::Source<content::NavigationController>(source).ptr();
242     content::WebContents* web_contents =
243         web_auth_flow_controller->GetWebContents();
244 
245     if (web_contents->GetURL() == url_) {
246       // It is safe to keep the pointer here, because we know in a test, that
247       // the WebContents won't go away before CloseEmbedderWebContents is
248       // called. Don't copy this code to production.
249       GuestViewBase* guest = GuestViewBase::FromWebContents(web_contents);
250       embedder_web_contents_ = guest->embedder_web_contents();
251       // Condtionally invoke parent class so that Wait will not exit
252       // until the target URL arrives.
253       content::WindowedNotificationObserver::Observe(type, source, details);
254     }
255   }
256 
257   // Closes the window embedding the WebContents. The action is separated from
258   // the Observe method to make sure the list of observers is not deleted,
259   // while some event is already being processed. (That causes ASAN failures.)
CloseEmbedderWebContents()260   void CloseEmbedderWebContents() {
261     if (embedder_web_contents_)
262       embedder_web_contents_->Close();
263   }
264 
265  private:
266   GURL url_;
267   content::WebContents* embedder_web_contents_;
268 };
269 
270 }  // namespace
271 
272 class FakeGetAuthTokenFunction : public IdentityGetAuthTokenFunction {
273  public:
FakeGetAuthTokenFunction()274   FakeGetAuthTokenFunction()
275       : login_access_token_result_(true),
276         auto_login_access_token_(true),
277         login_ui_result_(true),
278         scope_ui_result_(true),
279         login_ui_shown_(false),
280         scope_ui_shown_(false) {}
281 
set_login_access_token_result(bool result)282   void set_login_access_token_result(bool result) {
283     login_access_token_result_ = result;
284   }
285 
set_auto_login_access_token(bool automatic)286   void set_auto_login_access_token(bool automatic) {
287     auto_login_access_token_ = automatic;
288   }
289 
set_login_ui_result(bool result)290   void set_login_ui_result(bool result) { login_ui_result_ = result; }
291 
set_mint_token_flow(scoped_ptr<OAuth2MintTokenFlow> flow)292   void set_mint_token_flow(scoped_ptr<OAuth2MintTokenFlow> flow) {
293     flow_ = flow.Pass();
294   }
295 
set_mint_token_result(TestOAuth2MintTokenFlow::ResultType result_type)296   void set_mint_token_result(TestOAuth2MintTokenFlow::ResultType result_type) {
297     set_mint_token_flow(scoped_ptr<TestOAuth2MintTokenFlow>(
298                             new TestOAuth2MintTokenFlow(result_type, this))
299                             .PassAs<OAuth2MintTokenFlow>());
300   }
301 
set_scope_ui_failure(GaiaWebAuthFlow::Failure failure)302   void set_scope_ui_failure(GaiaWebAuthFlow::Failure failure) {
303     scope_ui_result_ = false;
304     scope_ui_failure_ = failure;
305   }
306 
set_scope_ui_oauth_error(const std::string & oauth_error)307   void set_scope_ui_oauth_error(const std::string& oauth_error) {
308     scope_ui_result_ = false;
309     scope_ui_failure_ = GaiaWebAuthFlow::OAUTH_ERROR;
310     scope_ui_oauth_error_ = oauth_error;
311   }
312 
login_ui_shown() const313   bool login_ui_shown() const { return login_ui_shown_; }
314 
scope_ui_shown() const315   bool scope_ui_shown() const { return scope_ui_shown_; }
316 
login_access_token() const317   std::string login_access_token() const { return login_access_token_; }
318 
StartLoginAccessTokenRequest()319   virtual void StartLoginAccessTokenRequest() OVERRIDE {
320     if (auto_login_access_token_) {
321       if (login_access_token_result_) {
322         OnGetTokenSuccess(login_token_request_.get(),
323                           "access_token",
324                           base::Time::Now() + base::TimeDelta::FromHours(1LL));
325       } else {
326         GoogleServiceAuthError error(
327             GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
328         OnGetTokenFailure(login_token_request_.get(), error);
329       }
330     } else {
331       // Make a request to the token service. The test now must tell
332       // the token service to issue an access token (or an error).
333       IdentityGetAuthTokenFunction::StartLoginAccessTokenRequest();
334     }
335   }
336 
ShowLoginPopup()337   virtual void ShowLoginPopup() OVERRIDE {
338     EXPECT_FALSE(login_ui_shown_);
339     login_ui_shown_ = true;
340     if (login_ui_result_)
341       SigninSuccess();
342     else
343       SigninFailed();
344   }
345 
ShowOAuthApprovalDialog(const IssueAdviceInfo & issue_advice)346   virtual void ShowOAuthApprovalDialog(
347       const IssueAdviceInfo& issue_advice) OVERRIDE {
348     scope_ui_shown_ = true;
349 
350     if (scope_ui_result_) {
351       OnGaiaFlowCompleted(kAccessToken, "3600");
352     } else if (scope_ui_failure_ == GaiaWebAuthFlow::SERVICE_AUTH_ERROR) {
353       GoogleServiceAuthError error(GoogleServiceAuthError::CONNECTION_FAILED);
354       OnGaiaFlowFailure(scope_ui_failure_, error, "");
355     } else {
356       GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
357       OnGaiaFlowFailure(scope_ui_failure_, error, scope_ui_oauth_error_);
358     }
359   }
360 
CreateMintTokenFlow(const std::string & login_access_token)361   virtual OAuth2MintTokenFlow* CreateMintTokenFlow(
362       const std::string& login_access_token) OVERRIDE {
363     EXPECT_TRUE(login_access_token_.empty());
364     // Save the login token used to create the flow so tests can see
365     // what account was used.
366     login_access_token_ = login_access_token;
367     return flow_.release();
368   }
369 
370  private:
~FakeGetAuthTokenFunction()371   virtual ~FakeGetAuthTokenFunction() {}
372   bool login_access_token_result_;
373   bool auto_login_access_token_;
374   bool login_ui_result_;
375   bool scope_ui_result_;
376   GaiaWebAuthFlow::Failure scope_ui_failure_;
377   std::string scope_ui_oauth_error_;
378   bool login_ui_shown_;
379   bool scope_ui_shown_;
380 
381   scoped_ptr<OAuth2MintTokenFlow> flow_;
382 
383   std::string login_access_token_;
384 };
385 
386 class MockQueuedMintRequest : public IdentityMintRequestQueue::Request {
387  public:
388   MOCK_METHOD1(StartMintToken, void(IdentityMintRequestQueue::MintType));
389 };
390 
CreateIds(std::string email,std::string obfid)391 gaia::AccountIds CreateIds(std::string email, std::string obfid) {
392   gaia::AccountIds ids;
393   ids.account_key = email;
394   ids.email = email;
395   ids.gaia = obfid;
396   return ids;
397 }
398 
399 class IdentityGetAccountsFunctionTest : public ExtensionBrowserTest {
SetUpCommandLine(CommandLine * command_line)400   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
401     ExtensionBrowserTest::SetUpCommandLine(command_line);
402     command_line->AppendSwitch(switches::kExtensionsMultiAccount);
403   }
404 
405  protected:
SetAccountState(gaia::AccountIds ids,bool is_signed_in)406   void SetAccountState(gaia::AccountIds ids, bool is_signed_in) {
407     IdentityAPI::GetFactoryInstance()->Get(profile())->SetAccountStateForTest(
408         ids, is_signed_in);
409   }
410 
ExpectGetAccounts(const std::vector<std::string> & accounts)411   testing::AssertionResult ExpectGetAccounts(
412       const std::vector<std::string>& accounts) {
413     scoped_refptr<IdentityGetAccountsFunction> func(
414         new IdentityGetAccountsFunction);
415     func->set_extension(test_util::CreateEmptyExtension(kExtensionId).get());
416     if (!utils::RunFunction(
417             func.get(), std::string("[]"), browser(), utils::NONE)) {
418       return GenerateFailureResult(accounts, NULL)
419              << "getAccounts did not return a result.";
420     }
421     const base::ListValue* callback_arguments = func->GetResultList();
422     if (!callback_arguments)
423       return GenerateFailureResult(accounts, NULL) << "NULL result";
424 
425     if (callback_arguments->GetSize() != 1) {
426       return GenerateFailureResult(accounts, NULL)
427              << "Expected 1 argument but got " << callback_arguments->GetSize();
428     }
429 
430     const base::ListValue* results;
431     if (!callback_arguments->GetList(0, &results))
432       GenerateFailureResult(accounts, NULL) << "Result was not an array";
433 
434     std::set<std::string> result_ids;
435     for (base::ListValue::const_iterator it = results->begin();
436          it != results->end();
437          ++it) {
438       scoped_ptr<api::identity::AccountInfo> info =
439           api::identity::AccountInfo::FromValue(**it);
440       if (info.get())
441         result_ids.insert(info->id);
442       else
443         return GenerateFailureResult(accounts, results);
444     }
445 
446     for (std::vector<std::string>::const_iterator it = accounts.begin();
447          it != accounts.end();
448          ++it) {
449       if (result_ids.find(*it) == result_ids.end())
450         return GenerateFailureResult(accounts, results);
451     }
452 
453     return testing::AssertionResult(true);
454   }
455 
GenerateFailureResult(const::std::vector<std::string> & accounts,const base::ListValue * results)456   testing::AssertionResult GenerateFailureResult(
457       const ::std::vector<std::string>& accounts,
458       const base::ListValue* results) {
459     testing::Message msg("Expected: ");
460     for (std::vector<std::string>::const_iterator it = accounts.begin();
461          it != accounts.end();
462          ++it) {
463       msg << *it << " ";
464     }
465     msg << "Actual: ";
466     if (!results) {
467       msg << "NULL";
468     } else {
469       for (base::ListValue::const_iterator it = results->begin();
470            it != results->end();
471            ++it) {
472         scoped_ptr<api::identity::AccountInfo> info =
473             api::identity::AccountInfo::FromValue(**it);
474         if (info.get())
475           msg << info->id << " ";
476         else
477           msg << *it << "<-" << (*it)->GetType() << " ";
478       }
479     }
480 
481     return testing::AssertionFailure(msg);
482   }
483 };
484 
IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest,MultiAccountOn)485 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, MultiAccountOn) {
486   EXPECT_TRUE(switches::IsExtensionsMultiAccount());
487 }
488 
IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest,NoneSignedIn)489 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, NoneSignedIn) {
490   EXPECT_TRUE(ExpectGetAccounts(std::vector<std::string>()));
491 }
492 
IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest,PrimaryAccountSignedIn)493 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest,
494                        PrimaryAccountSignedIn) {
495   SetAccountState(CreateIds("primary@example.com", "1"), true);
496   std::vector<std::string> primary;
497   primary.push_back("1");
498   EXPECT_TRUE(ExpectGetAccounts(primary));
499 }
500 
IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest,TwoAccountsSignedIn)501 IN_PROC_BROWSER_TEST_F(IdentityGetAccountsFunctionTest, TwoAccountsSignedIn) {
502   SetAccountState(CreateIds("primary@example.com", "1"), true);
503   SetAccountState(CreateIds("secondary@example.com", "2"), true);
504   std::vector<std::string> two_accounts;
505   two_accounts.push_back("1");
506   two_accounts.push_back("2");
507   EXPECT_TRUE(ExpectGetAccounts(two_accounts));
508 }
509 
510 class IdentityOldProfilesGetAccountsFunctionTest
511     : public IdentityGetAccountsFunctionTest {
SetUpCommandLine(CommandLine * command_line)512   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
513     // Don't add the multi-account switch that parent class would have.
514   }
515 };
516 
IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest,MultiAccountOff)517 IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest,
518                        MultiAccountOff) {
519   EXPECT_FALSE(switches::IsExtensionsMultiAccount());
520 }
521 
IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest,TwoAccountsSignedIn)522 IN_PROC_BROWSER_TEST_F(IdentityOldProfilesGetAccountsFunctionTest,
523                        TwoAccountsSignedIn) {
524   SetAccountState(CreateIds("primary@example.com", "1"), true);
525   SetAccountState(CreateIds("secondary@example.com", "2"), true);
526   std::vector<std::string> only_primary;
527   only_primary.push_back("1");
528   EXPECT_TRUE(ExpectGetAccounts(only_primary));
529 }
530 
531 class IdentityGetProfileUserInfoFunctionTest : public ExtensionBrowserTest {
532  protected:
RunGetProfileUserInfo()533   scoped_ptr<api::identity::ProfileUserInfo> RunGetProfileUserInfo() {
534     scoped_refptr<IdentityGetProfileUserInfoFunction> func(
535         new IdentityGetProfileUserInfoFunction);
536     func->set_extension(test_util::CreateEmptyExtension(kExtensionId).get());
537     scoped_ptr<base::Value> value(
538         utils::RunFunctionAndReturnSingleResult(func.get(), "[]", browser()));
539     return api::identity::ProfileUserInfo::FromValue(*value.get());
540   }
541 
RunGetProfileUserInfoWithEmail()542   scoped_ptr<api::identity::ProfileUserInfo> RunGetProfileUserInfoWithEmail() {
543     scoped_refptr<IdentityGetProfileUserInfoFunction> func(
544         new IdentityGetProfileUserInfoFunction);
545     func->set_extension(CreateExtensionWithEmailPermission());
546     scoped_ptr<base::Value> value(
547         utils::RunFunctionAndReturnSingleResult(func.get(), "[]", browser()));
548     return api::identity::ProfileUserInfo::FromValue(*value.get());
549   }
550 
551  private:
CreateExtensionWithEmailPermission()552   scoped_refptr<Extension> CreateExtensionWithEmailPermission() {
553     scoped_ptr<base::DictionaryValue> test_extension_value(
554         utils::ParseDictionary(
555             "{\"name\": \"Test\", \"version\": \"1.0\", "
556             "\"permissions\": [\"identity.email\"]}"));
557     return utils::CreateExtension(test_extension_value.get());
558   }
559 };
560 
IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,NotSignedIn)561 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest, NotSignedIn) {
562   scoped_ptr<api::identity::ProfileUserInfo> info =
563       RunGetProfileUserInfoWithEmail();
564   EXPECT_TRUE(info->email.empty());
565   EXPECT_TRUE(info->id.empty());
566 }
567 
IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,SignedIn)568 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest, SignedIn) {
569   profile()->GetPrefs()
570       ->SetString(prefs::kGoogleServicesUsername, "president@example.com");
571   profile()->GetPrefs()
572       ->SetString(prefs::kGoogleServicesUserAccountId, "12345");
573 
574   scoped_ptr<api::identity::ProfileUserInfo> info =
575       RunGetProfileUserInfoWithEmail();
576   EXPECT_EQ("president@example.com", info->email);
577   EXPECT_EQ("12345", info->id);
578 }
579 
IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,NotSignedInNoEmail)580 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,
581                        NotSignedInNoEmail) {
582   scoped_ptr<api::identity::ProfileUserInfo> info = RunGetProfileUserInfo();
583   EXPECT_TRUE(info->email.empty());
584   EXPECT_TRUE(info->id.empty());
585 }
586 
IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,SignedInNoEmail)587 IN_PROC_BROWSER_TEST_F(IdentityGetProfileUserInfoFunctionTest,
588                        SignedInNoEmail) {
589   profile()->GetPrefs()->SetString(prefs::kGoogleServicesUsername,
590                                    "president@example.com");
591   profile()->GetPrefs()->SetString(prefs::kGoogleServicesUserAccountId,
592                                    "12345");
593 
594   scoped_ptr<api::identity::ProfileUserInfo> info = RunGetProfileUserInfo();
595   EXPECT_TRUE(info->email.empty());
596   EXPECT_EQ("12345", info->id);
597 }
598 
599 class GetAuthTokenFunctionTest : public AsyncExtensionBrowserTest {
600  public:
SetUpCommandLine(CommandLine * command_line)601   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
602     AsyncExtensionBrowserTest::SetUpCommandLine(command_line);
603     command_line->AppendSwitch(switches::kExtensionsMultiAccount);
604   }
605 
SetUpInProcessBrowserTestFixture()606   virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
607     AsyncExtensionBrowserTest::SetUpInProcessBrowserTestFixture();
608 
609     will_create_browser_context_services_subscription_ =
610         BrowserContextDependencyManager::GetInstance()
611             ->RegisterWillCreateBrowserContextServicesCallbackForTesting(
612                   base::Bind(&GetAuthTokenFunctionTest::
613                                  OnWillCreateBrowserContextServices,
614                              base::Unretained(this)))
615             .Pass();
616   }
617 
OnWillCreateBrowserContextServices(content::BrowserContext * context)618   void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
619     // Replace the signin manager and token service with fakes. Do this ahead of
620     // creating the browser so that a bunch of classes don't register as
621     // observers and end up needing to unregister when the fake is substituted.
622     SigninManagerFactory::GetInstance()->SetTestingFactory(
623         context, &FakeSigninManagerBase::Build);
624     ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory(
625         context, &BuildFakeProfileOAuth2TokenService);
626     AccountReconcilorFactory::GetInstance()->SetTestingFactory(
627         context, &FakeAccountReconcilor::Build);
628   }
629 
SetUpOnMainThread()630   virtual void SetUpOnMainThread() OVERRIDE {
631     AsyncExtensionBrowserTest::SetUpOnMainThread();
632 
633     // Grab references to the fake signin manager and token service.
634     signin_manager_ = static_cast<FakeSigninManagerForTesting*>(
635         SigninManagerFactory::GetInstance()->GetForProfile(profile()));
636     ASSERT_TRUE(signin_manager_);
637     token_service_ = static_cast<FakeProfileOAuth2TokenService*>(
638         ProfileOAuth2TokenServiceFactory::GetInstance()->GetForProfile(
639             profile()));
640     ASSERT_TRUE(token_service_);
641   }
642 
SignIn(const std::string account_key)643   void SignIn(const std::string account_key) {
644 #if defined(OS_CHROMEOS)
645     signin_manager_->SetAuthenticatedUsername(account_key);
646 #else
647     signin_manager_->SignIn(account_key, "password");
648 #endif
649     token_service_->IssueRefreshTokenForUser(account_key, "refresh_token");
650   }
651 
IssueLoginRefreshTokenForAccount(const std::string account_key)652   void IssueLoginRefreshTokenForAccount(const std::string account_key) {
653     token_service_->IssueRefreshTokenForUser(account_key, "refresh_token");
654   }
655 
IssueLoginAccessTokenForAccount(const std::string account_key)656   void IssueLoginAccessTokenForAccount(const std::string account_key) {
657     token_service_->IssueAllTokensForAccount(
658         account_key,
659         "access_token-" + account_key,
660         base::Time::Now() + base::TimeDelta::FromSeconds(3600));
661   }
662 
SetAccountState(gaia::AccountIds ids,bool is_signed_in)663   void SetAccountState(gaia::AccountIds ids, bool is_signed_in) {
664     IdentityAPI::GetFactoryInstance()->Get(profile())->SetAccountStateForTest(
665         ids, is_signed_in);
666   }
667 
668  protected:
669   enum OAuth2Fields {
670     NONE = 0,
671     CLIENT_ID = 1,
672     SCOPES = 2,
673     AS_COMPONENT = 4
674   };
675 
676   FakeSigninManagerForTesting* signin_manager_;
677   FakeProfileOAuth2TokenService* token_service_;
678 
~GetAuthTokenFunctionTest()679   virtual ~GetAuthTokenFunctionTest() {}
680 
681   // Helper to create an extension with specific OAuth2Info fields set.
682   // |fields_to_set| should be computed by using fields of Oauth2Fields enum.
CreateExtension(int fields_to_set)683   const Extension* CreateExtension(int fields_to_set) {
684     const Extension* ext;
685     base::FilePath manifest_path =
686         test_data_dir_.AppendASCII("platform_apps/oauth2");
687     base::FilePath component_manifest_path =
688         test_data_dir_.AppendASCII("packaged_app/component_oauth2");
689     if ((fields_to_set & AS_COMPONENT) == 0)
690       ext = LoadExtension(manifest_path);
691     else
692       ext = LoadExtensionAsComponent(component_manifest_path);
693     OAuth2Info& oauth2_info =
694         const_cast<OAuth2Info&>(OAuth2Info::GetOAuth2Info(ext));
695     if ((fields_to_set & CLIENT_ID) != 0)
696       oauth2_info.client_id = "client1";
697     if ((fields_to_set & SCOPES) != 0) {
698       oauth2_info.scopes.push_back("scope1");
699       oauth2_info.scopes.push_back("scope2");
700     }
701 
702     extension_id_ = ext->id();
703     oauth_scopes_ = std::set<std::string>(oauth2_info.scopes.begin(),
704                                           oauth2_info.scopes.end());
705     return ext;
706   }
707 
id_api()708   IdentityAPI* id_api() {
709     return IdentityAPI::GetFactoryInstance()->Get(browser()->profile());
710   }
711 
GetPrimaryAccountId()712   const std::string GetPrimaryAccountId() {
713     SigninManagerBase* signin_manager =
714         SigninManagerFactory::GetForProfile(browser()->profile());
715     return signin_manager->GetAuthenticatedAccountId();
716   }
717 
SetCachedToken(const IdentityTokenCacheValue & token_data)718   void SetCachedToken(const IdentityTokenCacheValue& token_data) {
719     ExtensionTokenKey key(extension_id_, GetPrimaryAccountId(), oauth_scopes_);
720     id_api()->SetCachedToken(key, token_data);
721   }
722 
GetCachedToken(std::string account_id)723   const IdentityTokenCacheValue& GetCachedToken(std::string account_id) {
724     if (account_id.empty())
725       account_id = GetPrimaryAccountId();
726     ExtensionTokenKey key(extension_id_, account_id, oauth_scopes_);
727     return id_api()->GetCachedToken(key);
728   }
729 
QueueRequestStart(IdentityMintRequestQueue::MintType type,IdentityMintRequestQueue::Request * request)730   void QueueRequestStart(IdentityMintRequestQueue::MintType type,
731                          IdentityMintRequestQueue::Request* request) {
732     ExtensionTokenKey key(extension_id_, GetPrimaryAccountId(), oauth_scopes_);
733     id_api()->mint_queue()->RequestStart(type, key, request);
734   }
735 
QueueRequestComplete(IdentityMintRequestQueue::MintType type,IdentityMintRequestQueue::Request * request)736   void QueueRequestComplete(IdentityMintRequestQueue::MintType type,
737                             IdentityMintRequestQueue::Request* request) {
738     ExtensionTokenKey key(extension_id_, GetPrimaryAccountId(), oauth_scopes_);
739     id_api()->mint_queue()->RequestComplete(type, key, request);
740   }
741 
742  private:
743   std::string extension_id_;
744   std::set<std::string> oauth_scopes_;
745 
746   scoped_ptr<base::CallbackList<void(content::BrowserContext*)>::Subscription>
747       will_create_browser_context_services_subscription_;
748 };
749 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NoClientId)750 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
751                        NoClientId) {
752   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
753   func->set_extension(CreateExtension(SCOPES));
754   std::string error = utils::RunFunctionAndReturnError(
755       func.get(), "[{}]", browser());
756   EXPECT_EQ(std::string(errors::kInvalidClientId), error);
757   EXPECT_FALSE(func->login_ui_shown());
758   EXPECT_FALSE(func->scope_ui_shown());
759 }
760 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NoScopes)761 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
762                        NoScopes) {
763   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
764   func->set_extension(CreateExtension(CLIENT_ID));
765   std::string error = utils::RunFunctionAndReturnError(
766       func.get(), "[{}]", browser());
767   EXPECT_EQ(std::string(errors::kInvalidScopes), error);
768   EXPECT_FALSE(func->login_ui_shown());
769   EXPECT_FALSE(func->scope_ui_shown());
770 }
771 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveNotSignedIn)772 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
773                        NonInteractiveNotSignedIn) {
774   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
775   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
776   std::string error = utils::RunFunctionAndReturnError(
777       func.get(), "[{}]", browser());
778   EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
779   EXPECT_FALSE(func->login_ui_shown());
780   EXPECT_FALSE(func->scope_ui_shown());
781 }
782 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveMintFailure)783 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
784                        NonInteractiveMintFailure) {
785   SignIn("primary@example.com");
786   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
787   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
788   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE);
789   std::string error =
790       utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
791   EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
792   EXPECT_FALSE(func->login_ui_shown());
793   EXPECT_FALSE(func->scope_ui_shown());
794 }
795 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveLoginAccessTokenFailure)796 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
797                        NonInteractiveLoginAccessTokenFailure) {
798   SignIn("primary@example.com");
799   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
800   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
801   func->set_login_access_token_result(false);
802   std::string error = utils::RunFunctionAndReturnError(
803       func.get(), "[{}]", browser());
804   EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
805 }
806 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveMintAdviceSuccess)807 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
808                        NonInteractiveMintAdviceSuccess) {
809   SignIn("primary@example.com");
810   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
811   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
812   func->set_extension(extension.get());
813   func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
814   std::string error =
815       utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
816   EXPECT_EQ(std::string(errors::kNoGrant), error);
817   EXPECT_FALSE(func->login_ui_shown());
818   EXPECT_FALSE(func->scope_ui_shown());
819 
820   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE,
821             GetCachedToken(std::string()).status());
822 }
823 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveMintBadCredentials)824 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
825                        NonInteractiveMintBadCredentials) {
826   SignIn("primary@example.com");
827   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
828   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
829   func->set_mint_token_result(
830       TestOAuth2MintTokenFlow::MINT_TOKEN_BAD_CREDENTIALS);
831   std::string error =
832       utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
833   EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
834   EXPECT_FALSE(func->login_ui_shown());
835   EXPECT_FALSE(func->scope_ui_shown());
836 }
837 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveMintServiceError)838 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
839                        NonInteractiveMintServiceError) {
840   SignIn("primary@example.com");
841   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
842   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
843   func->set_mint_token_result(
844       TestOAuth2MintTokenFlow::MINT_TOKEN_SERVICE_ERROR);
845   std::string error =
846       utils::RunFunctionAndReturnError(func.get(), "[{}]", browser());
847   EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
848   EXPECT_FALSE(func->login_ui_shown());
849   EXPECT_FALSE(func->scope_ui_shown());
850 }
851 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NoOptionsSuccess)852 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
853                        NoOptionsSuccess) {
854   SignIn("primary@example.com");
855 #if defined(OS_WIN) && defined(USE_ASH)
856   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
857   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
858     return;
859 #endif
860 
861   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
862   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
863   func->set_extension(extension.get());
864   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
865   scoped_ptr<base::Value> value(
866       utils::RunFunctionAndReturnSingleResult(func.get(), "[]", browser()));
867   std::string access_token;
868   EXPECT_TRUE(value->GetAsString(&access_token));
869   EXPECT_EQ(std::string(kAccessToken), access_token);
870   EXPECT_FALSE(func->login_ui_shown());
871   EXPECT_FALSE(func->scope_ui_shown());
872   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
873             GetCachedToken(std::string()).status());
874 }
875 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveSuccess)876 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
877                        NonInteractiveSuccess) {
878   SignIn("primary@example.com");
879 #if defined(OS_WIN) && defined(USE_ASH)
880   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
881   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
882     return;
883 #endif
884 
885   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
886   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
887   func->set_extension(extension.get());
888   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
889   scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
890       func.get(), "[{}]", browser()));
891   std::string access_token;
892   EXPECT_TRUE(value->GetAsString(&access_token));
893   EXPECT_EQ(std::string(kAccessToken), access_token);
894   EXPECT_FALSE(func->login_ui_shown());
895   EXPECT_FALSE(func->scope_ui_shown());
896   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
897             GetCachedToken(std::string()).status());
898 }
899 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginCanceled)900 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
901                        InteractiveLoginCanceled) {
902   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
903   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
904   func->set_login_ui_result(false);
905   std::string error = utils::RunFunctionAndReturnError(
906       func.get(), "[{\"interactive\": true}]", browser());
907   EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
908   EXPECT_TRUE(func->login_ui_shown());
909   EXPECT_FALSE(func->scope_ui_shown());
910 }
911 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveMintBadCredentialsLoginCanceled)912 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
913                        InteractiveMintBadCredentialsLoginCanceled) {
914   SignIn("primary@example.com");
915   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
916   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
917   func->set_mint_token_result(
918       TestOAuth2MintTokenFlow::MINT_TOKEN_BAD_CREDENTIALS);
919   func->set_login_ui_result(false);
920   std::string error = utils::RunFunctionAndReturnError(
921       func.get(), "[{\"interactive\": true}]", browser());
922   EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
923   EXPECT_TRUE(func->login_ui_shown());
924   EXPECT_FALSE(func->scope_ui_shown());
925 }
926 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginSuccessNoToken)927 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
928                        InteractiveLoginSuccessNoToken) {
929   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
930   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
931   func->set_login_ui_result(false);
932   std::string error = utils::RunFunctionAndReturnError(
933       func.get(), "[{\"interactive\": true}]", browser());
934   EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
935   EXPECT_TRUE(func->login_ui_shown());
936   EXPECT_FALSE(func->scope_ui_shown());
937 }
938 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginSuccessMintFailure)939 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
940                        InteractiveLoginSuccessMintFailure) {
941   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
942   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
943   func->set_login_ui_result(true);
944   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE);
945   std::string error = utils::RunFunctionAndReturnError(
946       func.get(), "[{\"interactive\": true}]", browser());
947   EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
948   EXPECT_TRUE(func->login_ui_shown());
949   EXPECT_FALSE(func->scope_ui_shown());
950 }
951 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginSuccessLoginAccessTokenFailure)952 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
953                        InteractiveLoginSuccessLoginAccessTokenFailure) {
954   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
955   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
956   func->set_login_ui_result(true);
957   func->set_login_access_token_result(false);
958   std::string error = utils::RunFunctionAndReturnError(
959       func.get(), "[{\"interactive\": true}]", browser());
960   EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
961   EXPECT_TRUE(func->login_ui_shown());
962   EXPECT_FALSE(func->scope_ui_shown());
963 }
964 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginSuccessMintSuccess)965 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
966                        InteractiveLoginSuccessMintSuccess) {
967   // TODO(courage): verify that account_id in token service requests
968   // is correct once manual token minting for tests is implemented.
969   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
970   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
971   func->set_login_ui_result(true);
972   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
973   scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
974       func.get(), "[{\"interactive\": true}]", browser()));
975   std::string access_token;
976   EXPECT_TRUE(value->GetAsString(&access_token));
977   EXPECT_EQ(std::string(kAccessToken), access_token);
978   EXPECT_TRUE(func->login_ui_shown());
979   EXPECT_FALSE(func->scope_ui_shown());
980 }
981 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginSuccessApprovalAborted)982 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
983                        InteractiveLoginSuccessApprovalAborted) {
984   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
985   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
986   func->set_login_ui_result(true);
987   func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
988   func->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED);
989   std::string error = utils::RunFunctionAndReturnError(
990       func.get(), "[{\"interactive\": true}]", browser());
991   EXPECT_EQ(std::string(errors::kUserRejected), error);
992   EXPECT_TRUE(func->login_ui_shown());
993   EXPECT_TRUE(func->scope_ui_shown());
994 }
995 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveLoginSuccessApprovalSuccess)996 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
997                        InteractiveLoginSuccessApprovalSuccess) {
998   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
999   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1000   func->set_extension(extension.get());
1001   func->set_login_ui_result(true);
1002   func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1003 
1004   scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1005       func.get(), "[{\"interactive\": true}]", browser()));
1006   std::string access_token;
1007   EXPECT_TRUE(value->GetAsString(&access_token));
1008   EXPECT_EQ(std::string(kAccessToken), access_token);
1009   EXPECT_TRUE(func->login_ui_shown());
1010   EXPECT_TRUE(func->scope_ui_shown());
1011 }
1012 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveApprovalAborted)1013 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1014                        InteractiveApprovalAborted) {
1015   SignIn("primary@example.com");
1016   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1017   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1018   func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1019   func->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED);
1020   std::string error = utils::RunFunctionAndReturnError(
1021       func.get(), "[{\"interactive\": true}]", browser());
1022   EXPECT_EQ(std::string(errors::kUserRejected), error);
1023   EXPECT_FALSE(func->login_ui_shown());
1024   EXPECT_TRUE(func->scope_ui_shown());
1025 }
1026 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveApprovalLoadFailed)1027 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1028                        InteractiveApprovalLoadFailed) {
1029   SignIn("primary@example.com");
1030   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1031   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1032   func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1033   func->set_scope_ui_failure(GaiaWebAuthFlow::LOAD_FAILED);
1034   std::string error = utils::RunFunctionAndReturnError(
1035       func.get(), "[{\"interactive\": true}]", browser());
1036   EXPECT_EQ(std::string(errors::kPageLoadFailure), error);
1037   EXPECT_FALSE(func->login_ui_shown());
1038   EXPECT_TRUE(func->scope_ui_shown());
1039 }
1040 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveApprovalInvalidRedirect)1041 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1042                        InteractiveApprovalInvalidRedirect) {
1043   SignIn("primary@example.com");
1044   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1045   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1046   func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1047   func->set_scope_ui_failure(GaiaWebAuthFlow::INVALID_REDIRECT);
1048   std::string error = utils::RunFunctionAndReturnError(
1049       func.get(), "[{\"interactive\": true}]", browser());
1050   EXPECT_EQ(std::string(errors::kInvalidRedirect), error);
1051   EXPECT_FALSE(func->login_ui_shown());
1052   EXPECT_TRUE(func->scope_ui_shown());
1053 }
1054 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveApprovalConnectionFailure)1055 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1056                        InteractiveApprovalConnectionFailure) {
1057   SignIn("primary@example.com");
1058   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1059   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1060   func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1061   func->set_scope_ui_failure(GaiaWebAuthFlow::SERVICE_AUTH_ERROR);
1062   std::string error = utils::RunFunctionAndReturnError(
1063       func.get(), "[{\"interactive\": true}]", browser());
1064   EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
1065   EXPECT_FALSE(func->login_ui_shown());
1066   EXPECT_TRUE(func->scope_ui_shown());
1067 }
1068 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveApprovalOAuthErrors)1069 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1070                        InteractiveApprovalOAuthErrors) {
1071   SignIn("primary@example.com");
1072   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1073 
1074   std::map<std::string, std::string> error_map;
1075   error_map.insert(std::make_pair("access_denied", errors::kUserRejected));
1076   error_map.insert(std::make_pair("invalid_scope", errors::kInvalidScopes));
1077   error_map.insert(std::make_pair(
1078       "unmapped_error", std::string(errors::kAuthFailure) + "unmapped_error"));
1079 
1080   for (std::map<std::string, std::string>::const_iterator
1081            it = error_map.begin();
1082        it != error_map.end();
1083        ++it) {
1084     scoped_refptr<FakeGetAuthTokenFunction> func(
1085         new FakeGetAuthTokenFunction());
1086     func->set_extension(extension.get());
1087     // Make sure we don't get a cached issue_advice result, which would cause
1088     // flow to be leaked.
1089     id_api()->EraseAllCachedTokens();
1090     func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1091     func->set_scope_ui_oauth_error(it->first);
1092     std::string error = utils::RunFunctionAndReturnError(
1093         func.get(), "[{\"interactive\": true}]", browser());
1094     EXPECT_EQ(it->second, error);
1095     EXPECT_FALSE(func->login_ui_shown());
1096     EXPECT_TRUE(func->scope_ui_shown());
1097   }
1098 }
1099 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveApprovalSuccess)1100 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1101                        InteractiveApprovalSuccess) {
1102   SignIn("primary@example.com");
1103   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1104   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1105   func->set_extension(extension.get());
1106   func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1107 
1108   scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1109       func.get(), "[{\"interactive\": true}]", browser()));
1110   std::string access_token;
1111   EXPECT_TRUE(value->GetAsString(&access_token));
1112   EXPECT_EQ(std::string(kAccessToken), access_token);
1113   EXPECT_FALSE(func->login_ui_shown());
1114   EXPECT_TRUE(func->scope_ui_shown());
1115 
1116   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1117             GetCachedToken(std::string()).status());
1118 }
1119 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NoninteractiveQueue)1120 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoninteractiveQueue) {
1121   SignIn("primary@example.com");
1122   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1123   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1124   func->set_extension(extension.get());
1125 
1126   // Create a fake request to block the queue.
1127   MockQueuedMintRequest queued_request;
1128   IdentityMintRequestQueue::MintType type =
1129       IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE;
1130 
1131   EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
1132   QueueRequestStart(type, &queued_request);
1133 
1134   // The real request will start processing, but wait in the queue behind
1135   // the blocker.
1136   RunFunctionAsync(func.get(), "[{}]");
1137   // Verify that we have fetched the login token at this point.
1138   testing::Mock::VerifyAndClearExpectations(func.get());
1139 
1140   // The flow will be created after the first queued request clears.
1141   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1142 
1143   QueueRequestComplete(type, &queued_request);
1144 
1145   scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
1146   std::string access_token;
1147   EXPECT_TRUE(value->GetAsString(&access_token));
1148   EXPECT_EQ(std::string(kAccessToken), access_token);
1149   EXPECT_FALSE(func->login_ui_shown());
1150   EXPECT_FALSE(func->scope_ui_shown());
1151 }
1152 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveQueue)1153 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueue) {
1154   SignIn("primary@example.com");
1155   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1156   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1157   func->set_extension(extension.get());
1158 
1159   // Create a fake request to block the queue.
1160   MockQueuedMintRequest queued_request;
1161   IdentityMintRequestQueue::MintType type =
1162       IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE;
1163 
1164   EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
1165   QueueRequestStart(type, &queued_request);
1166 
1167   // The real request will start processing, but wait in the queue behind
1168   // the blocker.
1169   func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1170   RunFunctionAsync(func.get(), "[{\"interactive\": true}]");
1171   // Verify that we have fetched the login token and run the first flow.
1172   testing::Mock::VerifyAndClearExpectations(func.get());
1173   EXPECT_FALSE(func->scope_ui_shown());
1174 
1175   // The UI will be displayed and a token retrieved after the first
1176   // queued request clears.
1177   QueueRequestComplete(type, &queued_request);
1178 
1179   scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
1180   std::string access_token;
1181   EXPECT_TRUE(value->GetAsString(&access_token));
1182   EXPECT_EQ(std::string(kAccessToken), access_token);
1183   EXPECT_FALSE(func->login_ui_shown());
1184   EXPECT_TRUE(func->scope_ui_shown());
1185 }
1186 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveQueueShutdown)1187 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueueShutdown) {
1188   SignIn("primary@example.com");
1189   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1190   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1191   func->set_extension(extension.get());
1192 
1193   // Create a fake request to block the queue.
1194   MockQueuedMintRequest queued_request;
1195   IdentityMintRequestQueue::MintType type =
1196       IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE;
1197 
1198   EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
1199   QueueRequestStart(type, &queued_request);
1200 
1201   // The real request will start processing, but wait in the queue behind
1202   // the blocker.
1203   func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1204   RunFunctionAsync(func.get(), "[{\"interactive\": true}]");
1205   // Verify that we have fetched the login token and run the first flow.
1206   testing::Mock::VerifyAndClearExpectations(func.get());
1207   EXPECT_FALSE(func->scope_ui_shown());
1208 
1209   // After the request is canceled, the function will complete.
1210   func->OnShutdown();
1211   EXPECT_EQ(std::string(errors::kCanceled), WaitForError(func.get()));
1212   EXPECT_FALSE(func->login_ui_shown());
1213   EXPECT_FALSE(func->scope_ui_shown());
1214 
1215   QueueRequestComplete(type, &queued_request);
1216 }
1217 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NoninteractiveShutdown)1218 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoninteractiveShutdown) {
1219   SignIn("primary@example.com");
1220   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1221   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1222   func->set_extension(extension.get());
1223 
1224   scoped_ptr<TestHangOAuth2MintTokenFlow> flow(
1225       new TestHangOAuth2MintTokenFlow());
1226   func->set_mint_token_flow(flow.PassAs<OAuth2MintTokenFlow>());
1227   RunFunctionAsync(func.get(), "[{\"interactive\": false}]");
1228 
1229   // After the request is canceled, the function will complete.
1230   func->OnShutdown();
1231   EXPECT_EQ(std::string(errors::kCanceled), WaitForError(func.get()));
1232 }
1233 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveQueuedNoninteractiveFails)1234 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1235                        InteractiveQueuedNoninteractiveFails) {
1236   SignIn("primary@example.com");
1237   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1238   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1239   func->set_extension(extension.get());
1240 
1241   // Create a fake request to block the interactive queue.
1242   MockQueuedMintRequest queued_request;
1243   IdentityMintRequestQueue::MintType type =
1244       IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE;
1245 
1246   EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
1247   QueueRequestStart(type, &queued_request);
1248 
1249   // Non-interactive requests fail without hitting GAIA, because a
1250   // consent UI is known to be up.
1251   std::string error = utils::RunFunctionAndReturnError(
1252       func.get(), "[{}]", browser());
1253   EXPECT_EQ(std::string(errors::kNoGrant), error);
1254   EXPECT_FALSE(func->login_ui_shown());
1255   EXPECT_FALSE(func->scope_ui_shown());
1256 
1257   QueueRequestComplete(type, &queued_request);
1258 }
1259 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveCacheHit)1260 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1261                        NonInteractiveCacheHit) {
1262   SignIn("primary@example.com");
1263   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1264   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1265   func->set_extension(extension.get());
1266 
1267   // pre-populate the cache with a token
1268   IdentityTokenCacheValue token(kAccessToken,
1269                                 base::TimeDelta::FromSeconds(3600));
1270   SetCachedToken(token);
1271 
1272   // Get a token. Should not require a GAIA request.
1273   scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1274       func.get(), "[{}]", browser()));
1275   std::string access_token;
1276   EXPECT_TRUE(value->GetAsString(&access_token));
1277   EXPECT_EQ(std::string(kAccessToken), access_token);
1278   EXPECT_FALSE(func->login_ui_shown());
1279   EXPECT_FALSE(func->scope_ui_shown());
1280 }
1281 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,NonInteractiveIssueAdviceCacheHit)1282 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1283                        NonInteractiveIssueAdviceCacheHit) {
1284   SignIn("primary@example.com");
1285   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1286   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1287   func->set_extension(extension.get());
1288 
1289   // pre-populate the cache with advice
1290   IssueAdviceInfo info;
1291   IdentityTokenCacheValue token(info);
1292   SetCachedToken(token);
1293 
1294   // Should return an error without a GAIA request.
1295   std::string error = utils::RunFunctionAndReturnError(
1296       func.get(), "[{}]", browser());
1297   EXPECT_EQ(std::string(errors::kNoGrant), error);
1298   EXPECT_FALSE(func->login_ui_shown());
1299   EXPECT_FALSE(func->scope_ui_shown());
1300 }
1301 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,InteractiveCacheHit)1302 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1303                        InteractiveCacheHit) {
1304   SignIn("primary@example.com");
1305   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1306   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1307   func->set_extension(extension.get());
1308 
1309   // Create a fake request to block the queue.
1310   MockQueuedMintRequest queued_request;
1311   IdentityMintRequestQueue::MintType type =
1312       IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE;
1313 
1314   EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
1315   QueueRequestStart(type, &queued_request);
1316 
1317   // The real request will start processing, but wait in the queue behind
1318   // the blocker.
1319   func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1320   RunFunctionAsync(func.get(), "[{\"interactive\": true}]");
1321 
1322   // Populate the cache with a token while the request is blocked.
1323   IdentityTokenCacheValue token(kAccessToken,
1324                                 base::TimeDelta::FromSeconds(3600));
1325   SetCachedToken(token);
1326 
1327   // When we wake up the request, it returns the cached token without
1328   // displaying a UI, or hitting GAIA.
1329 
1330   QueueRequestComplete(type, &queued_request);
1331 
1332   scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
1333   std::string access_token;
1334   EXPECT_TRUE(value->GetAsString(&access_token));
1335   EXPECT_EQ(std::string(kAccessToken), access_token);
1336   EXPECT_FALSE(func->login_ui_shown());
1337   EXPECT_FALSE(func->scope_ui_shown());
1338 }
1339 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,LoginInvalidatesTokenCache)1340 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1341                        LoginInvalidatesTokenCache) {
1342   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1343   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1344   func->set_extension(extension.get());
1345 
1346   // pre-populate the cache with a token
1347   IdentityTokenCacheValue token(kAccessToken,
1348                                 base::TimeDelta::FromSeconds(3600));
1349   SetCachedToken(token);
1350 
1351   // Because the user is not signed in, the token will be removed,
1352   // and we'll hit GAIA for new tokens.
1353   func->set_login_ui_result(true);
1354   func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1355 
1356   scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1357       func.get(), "[{\"interactive\": true}]", browser()));
1358   std::string access_token;
1359   EXPECT_TRUE(value->GetAsString(&access_token));
1360   EXPECT_EQ(std::string(kAccessToken), access_token);
1361   EXPECT_TRUE(func->login_ui_shown());
1362   EXPECT_TRUE(func->scope_ui_shown());
1363   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1364             GetCachedToken(std::string()).status());
1365 }
1366 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,ComponentWithChromeClientId)1367 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ComponentWithChromeClientId) {
1368   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1369   scoped_refptr<const Extension> extension(
1370       CreateExtension(SCOPES | AS_COMPONENT));
1371   func->set_extension(extension.get());
1372   const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
1373   EXPECT_TRUE(oauth2_info.client_id.empty());
1374   EXPECT_FALSE(func->GetOAuth2ClientId().empty());
1375   EXPECT_NE("client1", func->GetOAuth2ClientId());
1376 }
1377 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,ComponentWithNormalClientId)1378 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ComponentWithNormalClientId) {
1379   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1380   scoped_refptr<const Extension> extension(
1381       CreateExtension(CLIENT_ID | SCOPES | AS_COMPONENT));
1382   func->set_extension(extension.get());
1383   EXPECT_EQ("client1", func->GetOAuth2ClientId());
1384 }
1385 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiDefaultUser)1386 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiDefaultUser) {
1387   SignIn("primary@example.com");
1388   SetAccountState(CreateIds("primary@example.com", "1"), true);
1389   SetAccountState(CreateIds("secondary@example.com", "2"), true);
1390 
1391   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1392   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1393   func->set_extension(extension.get());
1394   func->set_auto_login_access_token(false);
1395   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1396 
1397   RunFunctionAsync(func.get(), "[{}]");
1398 
1399   IssueLoginAccessTokenForAccount("primary@example.com");
1400 
1401   scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
1402   std::string access_token;
1403   EXPECT_TRUE(value->GetAsString(&access_token));
1404   EXPECT_EQ(std::string(kAccessToken), access_token);
1405   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1406             GetCachedToken(std::string()).status());
1407   EXPECT_EQ("access_token-primary@example.com", func->login_access_token());
1408 }
1409 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiPrimaryUser)1410 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiPrimaryUser) {
1411   SignIn("primary@example.com");
1412   IssueLoginRefreshTokenForAccount("secondary@example.com");
1413   SetAccountState(CreateIds("primary@example.com", "1"), true);
1414   SetAccountState(CreateIds("secondary@example.com", "2"), true);
1415 
1416   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1417   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1418   func->set_extension(extension.get());
1419   func->set_auto_login_access_token(false);
1420   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1421 
1422   RunFunctionAsync(func.get(), "[{\"account\": { \"id\": \"1\" } }]");
1423 
1424   IssueLoginAccessTokenForAccount("primary@example.com");
1425 
1426   scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
1427   std::string access_token;
1428   EXPECT_TRUE(value->GetAsString(&access_token));
1429   EXPECT_EQ(std::string(kAccessToken), access_token);
1430   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1431             GetCachedToken(std::string()).status());
1432   EXPECT_EQ("access_token-primary@example.com", func->login_access_token());
1433 }
1434 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiSecondaryUser)1435 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiSecondaryUser) {
1436   SignIn("primary@example.com");
1437   IssueLoginRefreshTokenForAccount("secondary@example.com");
1438   SetAccountState(CreateIds("primary@example.com", "1"), true);
1439   SetAccountState(CreateIds("secondary@example.com", "2"), true);
1440 
1441   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1442   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1443   func->set_extension(extension.get());
1444   func->set_auto_login_access_token(false);
1445   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1446 
1447   RunFunctionAsync(func.get(), "[{\"account\": { \"id\": \"2\" } }]");
1448 
1449   IssueLoginAccessTokenForAccount("secondary@example.com");
1450 
1451   scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
1452   std::string access_token;
1453   EXPECT_TRUE(value->GetAsString(&access_token));
1454   EXPECT_EQ(std::string(kAccessToken), access_token);
1455   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1456             GetCachedToken("secondary@example.com").status());
1457   EXPECT_EQ("access_token-secondary@example.com", func->login_access_token());
1458 }
1459 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiUnknownUser)1460 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, MultiUnknownUser) {
1461   SignIn("primary@example.com");
1462   IssueLoginRefreshTokenForAccount("secondary@example.com");
1463   SetAccountState(CreateIds("primary@example.com", "1"), true);
1464   SetAccountState(CreateIds("secondary@example.com", "2"), true);
1465 
1466   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1467   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1468   func->set_extension(extension.get());
1469   func->set_auto_login_access_token(false);
1470 
1471   std::string error = utils::RunFunctionAndReturnError(
1472       func.get(), "[{\"account\": { \"id\": \"3\" } }]", browser());
1473   EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
1474 }
1475 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiSecondaryNonInteractiveMintFailure)1476 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1477                        MultiSecondaryNonInteractiveMintFailure) {
1478   SignIn("primary@example.com");
1479   IssueLoginRefreshTokenForAccount("secondary@example.com");
1480   SetAccountState(CreateIds("primary@example.com", "1"), true);
1481   SetAccountState(CreateIds("secondary@example.com", "2"), true);
1482 
1483   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1484   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1485   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE);
1486   std::string error = utils::RunFunctionAndReturnError(
1487       func.get(), "[{\"account\": { \"id\": \"2\" } }]", browser());
1488   EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
1489   EXPECT_FALSE(func->login_ui_shown());
1490   EXPECT_FALSE(func->scope_ui_shown());
1491 }
1492 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiSecondaryNonInteractiveLoginAccessTokenFailure)1493 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1494                        MultiSecondaryNonInteractiveLoginAccessTokenFailure) {
1495   SignIn("primary@example.com");
1496   IssueLoginRefreshTokenForAccount("secondary@example.com");
1497   SetAccountState(CreateIds("primary@example.com", "1"), true);
1498   SetAccountState(CreateIds("secondary@example.com", "2"), true);
1499 
1500   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1501   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1502   func->set_login_access_token_result(false);
1503   std::string error = utils::RunFunctionAndReturnError(
1504       func.get(), "[{\"account\": { \"id\": \"2\" } }]", browser());
1505   EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
1506 }
1507 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,MultiSecondaryInteractiveApprovalAborted)1508 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
1509                        MultiSecondaryInteractiveApprovalAborted) {
1510   SignIn("primary@example.com");
1511   IssueLoginRefreshTokenForAccount("secondary@example.com");
1512   SetAccountState(CreateIds("primary@example.com", "1"), true);
1513   SetAccountState(CreateIds("secondary@example.com", "2"), true);
1514 
1515   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1516   func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
1517   func->set_mint_token_result(TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS);
1518   func->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED);
1519   std::string error = utils::RunFunctionAndReturnError(
1520       func.get(),
1521       "[{\"account\": { \"id\": \"2\" }, \"interactive\": true}]",
1522       browser());
1523   EXPECT_EQ(std::string(errors::kUserRejected), error);
1524   EXPECT_FALSE(func->login_ui_shown());
1525   EXPECT_TRUE(func->scope_ui_shown());
1526 }
1527 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,ScopesDefault)1528 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesDefault) {
1529   SignIn("primary@example.com");
1530   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1531   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1532   func->set_extension(extension.get());
1533   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1534   scoped_ptr<base::Value> value(
1535       utils::RunFunctionAndReturnSingleResult(func.get(), "[{}]", browser()));
1536   std::string access_token;
1537   EXPECT_TRUE(value->GetAsString(&access_token));
1538   EXPECT_EQ(std::string(kAccessToken), access_token);
1539 
1540   const ExtensionTokenKey* token_key = func->GetExtensionTokenKeyForTest();
1541   EXPECT_EQ(2ul, token_key->scopes.size());
1542   EXPECT_TRUE(ContainsKey(token_key->scopes, "scope1"));
1543   EXPECT_TRUE(ContainsKey(token_key->scopes, "scope2"));
1544 }
1545 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,ScopesEmpty)1546 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmpty) {
1547   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1548   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1549   func->set_extension(extension.get());
1550 
1551   std::string error(utils::RunFunctionAndReturnError(
1552       func.get(), "[{\"scopes\": []}]", browser()));
1553 
1554   EXPECT_EQ(errors::kInvalidScopes, error);
1555 }
1556 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,ScopesEmail)1557 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmail) {
1558   SignIn("primary@example.com");
1559   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1560   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1561   func->set_extension(extension.get());
1562   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1563   scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1564       func.get(), "[{\"scopes\": [\"email\"]}]", browser()));
1565   std::string access_token;
1566   EXPECT_TRUE(value->GetAsString(&access_token));
1567   EXPECT_EQ(std::string(kAccessToken), access_token);
1568 
1569   const ExtensionTokenKey* token_key = func->GetExtensionTokenKeyForTest();
1570   EXPECT_EQ(1ul, token_key->scopes.size());
1571   EXPECT_TRUE(ContainsKey(token_key->scopes, "email"));
1572 }
1573 
IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,ScopesEmailFooBar)1574 IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ScopesEmailFooBar) {
1575   SignIn("primary@example.com");
1576   scoped_refptr<FakeGetAuthTokenFunction> func(new FakeGetAuthTokenFunction());
1577   scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
1578   func->set_extension(extension.get());
1579   func->set_mint_token_result(TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS);
1580   scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1581       func.get(), "[{\"scopes\": [\"email\", \"foo\", \"bar\"]}]", browser()));
1582   std::string access_token;
1583   EXPECT_TRUE(value->GetAsString(&access_token));
1584   EXPECT_EQ(std::string(kAccessToken), access_token);
1585 
1586   const ExtensionTokenKey* token_key = func->GetExtensionTokenKeyForTest();
1587   EXPECT_EQ(3ul, token_key->scopes.size());
1588   EXPECT_TRUE(ContainsKey(token_key->scopes, "email"));
1589   EXPECT_TRUE(ContainsKey(token_key->scopes, "foo"));
1590   EXPECT_TRUE(ContainsKey(token_key->scopes, "bar"));
1591 }
1592 
1593 class RemoveCachedAuthTokenFunctionTest : public ExtensionBrowserTest {
1594  protected:
InvalidateDefaultToken()1595   bool InvalidateDefaultToken() {
1596     scoped_refptr<IdentityRemoveCachedAuthTokenFunction> func(
1597         new IdentityRemoveCachedAuthTokenFunction);
1598     func->set_extension(test_util::CreateEmptyExtension(kExtensionId).get());
1599     return utils::RunFunction(
1600         func.get(),
1601         std::string("[{\"token\": \"") + kAccessToken + "\"}]",
1602         browser(),
1603         extension_function_test_utils::NONE);
1604   }
1605 
id_api()1606   IdentityAPI* id_api() {
1607     return IdentityAPI::GetFactoryInstance()->Get(browser()->profile());
1608   }
1609 
SetCachedToken(IdentityTokenCacheValue & token_data)1610   void SetCachedToken(IdentityTokenCacheValue& token_data) {
1611     ExtensionTokenKey key(
1612         kExtensionId, "test@example.com", std::set<std::string>());
1613     id_api()->SetCachedToken(key, token_data);
1614   }
1615 
GetCachedToken()1616   const IdentityTokenCacheValue& GetCachedToken() {
1617     return id_api()->GetCachedToken(ExtensionTokenKey(
1618         kExtensionId, "test@example.com", std::set<std::string>()));
1619   }
1620 };
1621 
IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest,NotFound)1622 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, NotFound) {
1623   EXPECT_TRUE(InvalidateDefaultToken());
1624   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND,
1625             GetCachedToken().status());
1626 }
1627 
IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest,Advice)1628 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, Advice) {
1629   IssueAdviceInfo info;
1630   IdentityTokenCacheValue advice(info);
1631   SetCachedToken(advice);
1632   EXPECT_TRUE(InvalidateDefaultToken());
1633   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE,
1634             GetCachedToken().status());
1635 }
1636 
IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest,NonMatchingToken)1637 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, NonMatchingToken) {
1638   IdentityTokenCacheValue token("non_matching_token",
1639                                 base::TimeDelta::FromSeconds(3600));
1640   SetCachedToken(token);
1641   EXPECT_TRUE(InvalidateDefaultToken());
1642   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1643             GetCachedToken().status());
1644   EXPECT_EQ("non_matching_token", GetCachedToken().token());
1645 }
1646 
IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest,MatchingToken)1647 IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, MatchingToken) {
1648   IdentityTokenCacheValue token(kAccessToken,
1649                                 base::TimeDelta::FromSeconds(3600));
1650   SetCachedToken(token);
1651   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1652             GetCachedToken().status());
1653   EXPECT_TRUE(InvalidateDefaultToken());
1654   EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND,
1655             GetCachedToken().status());
1656 }
1657 
1658 class LaunchWebAuthFlowFunctionTest : public AsyncExtensionBrowserTest {
1659  public:
SetUpCommandLine(CommandLine * command_line)1660   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
1661     AsyncExtensionBrowserTest::SetUpCommandLine(command_line);
1662     // Reduce performance test variance by disabling background networking.
1663     command_line->AppendSwitch(switches::kDisableBackgroundNetworking);
1664   }
1665 };
1666 
IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,UserCloseWindow)1667 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, UserCloseWindow) {
1668   net::SpawnedTestServer https_server(
1669       net::SpawnedTestServer::TYPE_HTTPS,
1670       net::SpawnedTestServer::kLocalhost,
1671       base::FilePath(FILE_PATH_LITERAL(
1672           "chrome/test/data/extensions/api_test/identity")));
1673   ASSERT_TRUE(https_server.Start());
1674   GURL auth_url(https_server.GetURL("files/interaction_required.html"));
1675 
1676   scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1677       new IdentityLaunchWebAuthFlowFunction());
1678   scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
1679   function->set_extension(empty_extension.get());
1680 
1681   WaitForGURLAndCloseWindow popup_observer(auth_url);
1682 
1683   std::string args = "[{\"interactive\": true, \"url\": \"" +
1684       auth_url.spec() + "\"}]";
1685   RunFunctionAsync(function.get(), args);
1686 
1687   popup_observer.Wait();
1688   popup_observer.CloseEmbedderWebContents();
1689 
1690   EXPECT_EQ(std::string(errors::kUserRejected), WaitForError(function.get()));
1691 }
1692 
IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,InteractionRequired)1693 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, InteractionRequired) {
1694   net::SpawnedTestServer https_server(
1695       net::SpawnedTestServer::TYPE_HTTPS,
1696       net::SpawnedTestServer::kLocalhost,
1697       base::FilePath(FILE_PATH_LITERAL(
1698           "chrome/test/data/extensions/api_test/identity")));
1699   ASSERT_TRUE(https_server.Start());
1700   GURL auth_url(https_server.GetURL("files/interaction_required.html"));
1701 
1702   scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1703       new IdentityLaunchWebAuthFlowFunction());
1704   scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
1705   function->set_extension(empty_extension.get());
1706 
1707   std::string args = "[{\"interactive\": false, \"url\": \"" +
1708       auth_url.spec() + "\"}]";
1709   std::string error =
1710       utils::RunFunctionAndReturnError(function.get(), args, browser());
1711 
1712   EXPECT_EQ(std::string(errors::kInteractionRequired), error);
1713 }
1714 
IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,LoadFailed)1715 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, LoadFailed) {
1716   net::SpawnedTestServer https_server(
1717       net::SpawnedTestServer::TYPE_HTTPS,
1718       net::SpawnedTestServer::kLocalhost,
1719       base::FilePath(FILE_PATH_LITERAL(
1720           "chrome/test/data/extensions/api_test/identity")));
1721   ASSERT_TRUE(https_server.Start());
1722   GURL auth_url(https_server.GetURL("files/five_hundred.html"));
1723 
1724   scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1725       new IdentityLaunchWebAuthFlowFunction());
1726   scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
1727   function->set_extension(empty_extension.get());
1728 
1729   std::string args = "[{\"interactive\": true, \"url\": \"" +
1730       auth_url.spec() + "\"}]";
1731   std::string error =
1732       utils::RunFunctionAndReturnError(function.get(), args, browser());
1733 
1734   EXPECT_EQ(std::string(errors::kPageLoadFailure), error);
1735 }
1736 
IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,NonInteractiveSuccess)1737 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, NonInteractiveSuccess) {
1738 #if defined(OS_WIN) && defined(USE_ASH)
1739   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
1740   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
1741     return;
1742 #endif
1743 
1744   scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1745       new IdentityLaunchWebAuthFlowFunction());
1746   scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
1747   function->set_extension(empty_extension.get());
1748 
1749   function->InitFinalRedirectURLPrefixForTest("abcdefghij");
1750   scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1751       function.get(),
1752       "[{\"interactive\": false,"
1753       "\"url\": \"https://abcdefghij.chromiumapp.org/callback#test\"}]",
1754       browser()));
1755 
1756   std::string url;
1757   EXPECT_TRUE(value->GetAsString(&url));
1758   EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1759             url);
1760 }
1761 
IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,InteractiveFirstNavigationSuccess)1762 IN_PROC_BROWSER_TEST_F(
1763     LaunchWebAuthFlowFunctionTest, InteractiveFirstNavigationSuccess) {
1764 #if defined(OS_WIN) && defined(USE_ASH)
1765   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
1766   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
1767     return;
1768 #endif
1769 
1770   scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1771       new IdentityLaunchWebAuthFlowFunction());
1772   scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
1773   function->set_extension(empty_extension.get());
1774 
1775   function->InitFinalRedirectURLPrefixForTest("abcdefghij");
1776   scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1777       function.get(),
1778       "[{\"interactive\": true,"
1779       "\"url\": \"https://abcdefghij.chromiumapp.org/callback#test\"}]",
1780       browser()));
1781 
1782   std::string url;
1783   EXPECT_TRUE(value->GetAsString(&url));
1784   EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1785             url);
1786 }
1787 
IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,DISABLED_InteractiveSecondNavigationSuccess)1788 IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest,
1789                        DISABLED_InteractiveSecondNavigationSuccess) {
1790   net::SpawnedTestServer https_server(
1791       net::SpawnedTestServer::TYPE_HTTPS,
1792       net::SpawnedTestServer::kLocalhost,
1793       base::FilePath(FILE_PATH_LITERAL(
1794           "chrome/test/data/extensions/api_test/identity")));
1795   ASSERT_TRUE(https_server.Start());
1796   GURL auth_url(https_server.GetURL("files/redirect_to_chromiumapp.html"));
1797 
1798   scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1799       new IdentityLaunchWebAuthFlowFunction());
1800   scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
1801   function->set_extension(empty_extension.get());
1802 
1803   function->InitFinalRedirectURLPrefixForTest("abcdefghij");
1804   std::string args = "[{\"interactive\": true, \"url\": \"" +
1805       auth_url.spec() + "\"}]";
1806   scoped_ptr<base::Value> value(
1807       utils::RunFunctionAndReturnSingleResult(function.get(), args, browser()));
1808 
1809   std::string url;
1810   EXPECT_TRUE(value->GetAsString(&url));
1811   EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1812             url);
1813 }
1814 
1815 }  // namespace extensions
1816 
1817 // Tests the chrome.identity API implemented by custom JS bindings .
IN_PROC_BROWSER_TEST_F(ExtensionApiTest,ChromeIdentityJsBindings)1818 IN_PROC_BROWSER_TEST_F(ExtensionApiTest, ChromeIdentityJsBindings) {
1819   ASSERT_TRUE(RunExtensionTest("identity/js_bindings")) << message_;
1820 }
1821