identity_apitest.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
1f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// Use of this source code is governed by a BSD-style license that can be
3f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// found in the LICENSE file.
4f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
5f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "base/strings/string_util.h"
6f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "base/strings/stringprintf.h"
7f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "base/values.h"
8f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "chrome/browser/chrome_notification_types.h"
9f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "chrome/browser/extensions/api/identity/identity_api.h"
10f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "chrome/browser/extensions/component_loader.h"
11f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "chrome/browser/extensions/extension_apitest.h"
12f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "chrome/browser/extensions/extension_browsertest.h"
13f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "chrome/browser/extensions/extension_function_test_utils.h"
14d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#include "chrome/browser/extensions/extension_service.h"
15d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#include "chrome/browser/ui/browser.h"
16e6348c336fecc8da9288ea367375a1b1cd2358d2Argyrios Kyrtzidis#include "chrome/browser/ui/browser_window.h"
17f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "chrome/common/chrome_switches.h"
18f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "chrome/common/extensions/api/identity/oauth2_manifest_handler.h"
19802be99a6817aba6edb166b93c133da4358aa783Zhongxing Xu#include "chrome/test/base/in_process_browser_test.h"
20f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek#include "content/public/browser/notification_service.h"
21efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "content/public/browser/notification_source.h"
22aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks#include "content/public/test/test_utils.h"
2355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "extensions/common/id_util.h"
24efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar#include "google_apis/gaia/google_service_auth_error.h"
25d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks#include "google_apis/gaia/oauth2_mint_token_flow.h"
2655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "grit/browser_resources.h"
2755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "net/test/spawned_test_server/spawned_test_server.h"
2855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "testing/gmock/include/gmock/gmock.h"
2921142581d55918beed544a757e4af3bb865b1812Ted Kremenek#include "testing/gtest/include/gtest/gtest.h"
3055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "url/gurl.h"
3155fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth
329b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenekusing testing::_;
3355fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruthusing testing::Return;
3455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruthusing testing::ReturnRef;
359b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek
369b663716449b618ba0390b1dbebc54fa8e971124Ted Kremeneknamespace extensions {
3755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth
38d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaksnamespace {
396cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer
40b99083e60325a28063fb588f458a871151971fdcChandler Carruthnamespace errors = identity_constants;
416a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksnamespace utils = extension_function_test_utils;
4281fb169f42769e02c7425b23885a261c025fd5e6Anna Zaks
43b8e60d9a8ff06110efab37fc123b3c56937367a9Rafael Espindolastatic const char kAccessToken[] = "auth_token";
4455fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruthstatic const char kExtensionId[] = "ext_id";
4555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth
4655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth// This helps us be able to wait until an AsyncExtensionFunction calls
4755fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth// SendResponse.
487fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaksclass SendResponseDelegate
497fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks    : public UIThreadExtensionFunction::DelegateForTests {
50f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek public:
519ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenek  SendResponseDelegate() : should_post_quit_(false) {}
52d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
53f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  virtual ~SendResponseDelegate() {}
54c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu
55ff944a8c481d6c0f1ad2633e4be9bf8b1dd2a09fZhongxing Xu  void set_should_post_quit(bool should_quit) {
563fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks    should_post_quit_ = should_quit;
5775f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  }
5839cf781d62daaec09e443c6e66a01cd7543ffb41Anna Zaks
5939cf781d62daaec09e443c6e66a01cd7543ffb41Anna Zaks  bool HasResponse() {
60e62f048960645b79363408fdead53fec2a063c52Anna Zaks    return response_.get() != NULL;
6139cf781d62daaec09e443c6e66a01cd7543ffb41Anna Zaks  }
62e62f048960645b79363408fdead53fec2a063c52Anna Zaks
6384c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks  bool GetResponse() {
64d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks    EXPECT_TRUE(HasResponse());
65be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek    return *response_.get();
66f39d962cf84f46d2c0512157259ae1d41a1a5173David Blaikie  }
67f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek
68f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek  virtual void OnSendResponse(UIThreadExtensionFunction* function,
695fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose                              bool success,
705fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose                              bool bad_message) OVERRIDE {
715fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    ASSERT_FALSE(bad_message);
725fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    ASSERT_FALSE(HasResponse());
739fcc2ab2ec5e00802880e205568ff3afbd70a773Ted Kremenek    response_.reset(new bool);
749fcc2ab2ec5e00802880e205568ff3afbd70a773Ted Kremenek    *response_ = success;
759fcc2ab2ec5e00802880e205568ff3afbd70a773Ted Kremenek    if (should_post_quit_) {
76f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek      base::MessageLoopForUI::current()->Quit();
77f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek    }
785fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  }
795fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose
805fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose private:
815fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  scoped_ptr<bool> response_;
825fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  bool should_post_quit_;
835fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose};
845fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose
85c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenekclass AsyncExtensionBrowserTest : public ExtensionBrowserTest {
86c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek protected:
87c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  // Asynchronous function runner allows tests to manipulate the browser window
885fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  // after the call happens.
89c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  void RunFunctionAsync(
905fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose      UIThreadExtensionFunction* function,
915fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose      const std::string& args) {
92c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    response_delegate_.reset(new SendResponseDelegate);
93c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    function->set_test_delegate(response_delegate_.get());
945fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    scoped_ptr<base::ListValue> parsed_args(utils::ParseList(args));
955fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    EXPECT_TRUE(parsed_args.get()) <<
965fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose        "Could not parse extension function arguments: " << args;
975fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    function->SetArgs(parsed_args.get());
985fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose
995fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    if (!function->GetExtension()) {
1005fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose      scoped_refptr<Extension> empty_extension(
1015fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose          utils::CreateEmptyExtension());
1025fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose      function->set_extension(empty_extension.get());
1035fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    }
1045fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose
1055fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    function->set_profile(browser()->profile());
1065fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    function->set_has_callback(true);
1075fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    function->Run();
1085fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  }
1095fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose
1105fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  std::string WaitForError(UIThreadExtensionFunction* function) {
1115fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    RunMessageLoopUntilResponse();
1125fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    EXPECT_FALSE(function->GetResultList()) << "Did not expect a result";
1135fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    return function->GetError();
1145fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  }
115c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
116c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  base::Value* WaitForSingleResult(UIThreadExtensionFunction* function) {
117c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    RunMessageLoopUntilResponse();
118c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    EXPECT_TRUE(function->GetError().empty()) << "Unexpected error: "
119c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                                              << function->GetError();
120c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    const base::Value* single_result = NULL;
1213a46f5fd1709f6df03bbb8b0abf84052dc0f39ffJordan Rose    if (function->GetResultList() != NULL &&
122c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek        function->GetResultList()->Get(0, &single_result)) {
123c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      return single_result->DeepCopy();
124c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    }
125c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    return NULL;
126c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  }
127c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
128c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek private:
129c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  void RunMessageLoopUntilResponse() {
130c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    // If the RunImpl of |function| didn't already call SendResponse, run the
131c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    // message loop until they do.
132c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    if (!response_delegate_->HasResponse()) {
133c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      response_delegate_->set_should_post_quit(true);
1345fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose      content::RunMessageLoop();
1355fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    }
1365fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    EXPECT_TRUE(response_delegate_->HasResponse());
1375fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  }
138c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
1395fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  scoped_ptr<SendResponseDelegate> response_delegate_;
1405fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose};
1415fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose
1425fba5a789a238c29ef811a39a39be722443ec1b1Jordan Roseclass TestOAuth2MintTokenFlow : public OAuth2MintTokenFlow {
1435fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose public:
1445fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  enum ResultType {
145c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    ISSUE_ADVICE_SUCCESS,
1465fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    MINT_TOKEN_SUCCESS,
1475fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    MINT_TOKEN_FAILURE,
148c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    MINT_TOKEN_BAD_CREDENTIALS
149c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  };
150c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
151c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  TestOAuth2MintTokenFlow(ResultType result,
152c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek                          OAuth2MintTokenFlow::Delegate* delegate)
153c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    : OAuth2MintTokenFlow(NULL, delegate, OAuth2MintTokenFlow::Parameters()),
154f75560670bcdd59b051149bdece3eac14e313853Ted Kremenek      result_(result),
155f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek      delegate_(delegate) {
156f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  }
157f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
158f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  virtual void Start() OVERRIDE {
159f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek    switch (result_) {
160aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      case ISSUE_ADVICE_SUCCESS: {
161aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        IssueAdviceInfo info;
1624eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose        delegate_->OnIssueAdviceSuccess(info);
1634eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose        break;
1644eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose      }
1654eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose      case MINT_TOKEN_SUCCESS: {
166aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        delegate_->OnMintTokenSuccess(kAccessToken, 3600);
1674eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose        break;
168aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      }
169aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      case MINT_TOKEN_FAILURE: {
170aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        GoogleServiceAuthError error(GoogleServiceAuthError::CONNECTION_FAILED);
171aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        delegate_->OnMintTokenFailure(error);
172aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        break;
173aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      }
174ed8afacb8118b71bcfa8017059e51da325e7691bZhongxing Xu      case MINT_TOKEN_BAD_CREDENTIALS: {
1759c378f705405d37f49795d5e915989de774fe11fTed Kremenek        GoogleServiceAuthError error(
1761d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek            GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
1771d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek        delegate_->OnMintTokenFailure(error);
17845796b10d11869e86c6b85e24df165410536b313Ted Kremenek        break;
17908b86531ade68727c56918f162816075b87c864aJordy Rose      }
180d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu    }
1816a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  }
1826a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
1836a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks private:
1846a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  ResultType result_;
1856a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  OAuth2MintTokenFlow::Delegate* delegate_;
1866a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks};
187cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek
188c4bac8e376b98d633bb00ee5f510d5e58449753cTed KremenekBrowserContextKeyedService* IdentityAPITestFactory(
189c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    content::BrowserContext* profile) {
190d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu  return new IdentityAPI(static_cast<Profile*>(profile));
1911d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek}
1921d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek
193f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek// Waits for a specific GURL to generate a NOTIFICATION_LOAD_STOP event and
1946f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith// saves a pointer to the window embedding the WebContents, which can be later
1956f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith// closed.
196c471e7b44e63ff1b46b480e723c4130aeaef5a8aZhongxing Xuclass WaitForGURLAndCloseWindow : public content::WindowedNotificationObserver {
197d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks public:
198d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  explicit WaitForGURLAndCloseWindow(GURL url)
199d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      : WindowedNotificationObserver(
2003bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks            content::NOTIFICATION_LOAD_STOP,
2013bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks            content::NotificationService::AllSources()),
2023bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks        url_(url) {}
2033bbd8cd831788c506f2980293eb3c7e1b3ca2501Anna Zaks
2041d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  // NotificationObserver:
2051d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  virtual void Observe(int type,
20645796b10d11869e86c6b85e24df165410536b313Ted Kremenek                       const content::NotificationSource& source,
20708b86531ade68727c56918f162816075b87c864aJordy Rose                       const content::NotificationDetails& details) OVERRIDE {
2084eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose    content::NavigationController* web_auth_flow_controller =
209c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek        content::Source<content::NavigationController>(source).ptr();
2101d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    content::WebContents* web_contents =
21145796b10d11869e86c6b85e24df165410536b313Ted Kremenek        web_auth_flow_controller->GetWebContents();
212d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks
213d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks    if (web_contents->GetURL() == url_) {
214d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      // It is safe to keep the pointer here, because we know in a test, that
215d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      // the WebContents won't go away before CloseEmbedderWebContents is
216d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      // called. Don't copy this code to production.
217d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      embedder_web_contents_ = web_contents->GetEmbedderWebContents();
21845796b10d11869e86c6b85e24df165410536b313Ted Kremenek      // Condtionally invoke parent class so that Wait will not exit
219d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks      // until the target URL arrives.
2201d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      content::WindowedNotificationObserver::Observe(type, source, details);
221fda7832b000ff8927386f093b52c067641679469Zhongxing Xu    }
2221d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  }
223ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie
2245fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  // Closes the window embedding the WebContents. The action is separated from
2255fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  // the Observe method to make sure the list of observers is not deleted,
2265fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  // while some event is already being processed. (That causes ASAN failures.)
2275fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  void CloseEmbedderWebContents() {
2285fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose    if (embedder_web_contents_)
2295fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose      embedder_web_contents_->Close();
230c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  }
2315fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose
23245796b10d11869e86c6b85e24df165410536b313Ted Kremenek private:
2331d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  GURL url_;
2345fba5a789a238c29ef811a39a39be722443ec1b1Jordan Rose  content::WebContents* embedder_web_contents_;
2359fcc2ab2ec5e00802880e205568ff3afbd70a773Ted Kremenek};
2369fcc2ab2ec5e00802880e205568ff3afbd70a773Ted Kremenek
237987695a5ddd78beca784d4e503ffbc2dc879181aTed Kremenek}  // namespace
238fda7832b000ff8927386f093b52c067641679469Zhongxing Xu
2391d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenekclass MockGetAuthTokenFunction : public IdentityGetAuthTokenFunction {
240fda7832b000ff8927386f093b52c067641679469Zhongxing Xu public:
2411d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  MockGetAuthTokenFunction() : login_access_token_result_(true),
24245796b10d11869e86c6b85e24df165410536b313Ted Kremenek                               login_ui_result_(true),
2435f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis                               scope_ui_result_(true),
244b219cfc4d75f0a03630b7c4509ef791b7e97b2c8David Blaikie                               login_ui_shown_(false),
245fda7832b000ff8927386f093b52c067641679469Zhongxing Xu                               scope_ui_shown_(false) {
2465f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis  }
247987695a5ddd78beca784d4e503ffbc2dc879181aTed Kremenek
2481d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  void set_login_access_token_result(bool result) {
2491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    login_access_token_result_ = result;
25045796b10d11869e86c6b85e24df165410536b313Ted Kremenek  }
2515f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis
2521c32b81765ed63ae9e3e00e5acef7a4379bba228Anna Zaks  void set_login_ui_result(bool result) {
253fda7832b000ff8927386f093b52c067641679469Zhongxing Xu    login_ui_result_ = result;
2545f83d6f36a7308eef21d87104fd70c421e854448Argyrios Kyrtzidis  }
255987695a5ddd78beca784d4e503ffbc2dc879181aTed Kremenek
256fda7832b000ff8927386f093b52c067641679469Zhongxing Xu  void set_scope_ui_failure(GaiaWebAuthFlow::Failure failure) {
2571d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    scope_ui_result_ = false;
258f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek    scope_ui_failure_ = failure;
259a5245a51593aa45c2a5ef38a10861697d29c7789Anna Zaks  }
260a5245a51593aa45c2a5ef38a10861697d29c7789Anna Zaks
26145796b10d11869e86c6b85e24df165410536b313Ted Kremenek  void set_scope_ui_oauth_error(const std::string& oauth_error) {
2621d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek    scope_ui_result_ = false;
263f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek    scope_ui_failure_ = GaiaWebAuthFlow::OAUTH_ERROR;
264fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek    scope_ui_oauth_error_ = oauth_error;
265fc576514d06c46a7cac49500169411d82f38d04bTed Kremenek  }
266cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor
267aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  bool login_ui_shown() const {
2684eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose    return login_ui_shown_;
2694eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose  }
2704eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose
271a5245a51593aa45c2a5ef38a10861697d29c7789Anna Zaks  bool scope_ui_shown() const {
272a5245a51593aa45c2a5ef38a10861697d29c7789Anna Zaks    return scope_ui_shown_;
273a5245a51593aa45c2a5ef38a10861697d29c7789Anna Zaks  }
2748a660eb1084294a903f6dcc00bf2fa4e3bc92cfcAnna Zaks
2758a660eb1084294a903f6dcc00bf2fa4e3bc92cfcAnna Zaks  virtual void StartLoginAccessTokenRequest() OVERRIDE {
276a5245a51593aa45c2a5ef38a10861697d29c7789Anna Zaks    if (login_access_token_result_) {
2778a660eb1084294a903f6dcc00bf2fa4e3bc92cfcAnna Zaks      OnGetTokenSuccess(login_token_request_.get(), "access_token",
2788a660eb1084294a903f6dcc00bf2fa4e3bc92cfcAnna Zaks          base::Time::Now() + base::TimeDelta::FromHours(1LL));
279a5245a51593aa45c2a5ef38a10861697d29c7789Anna Zaks    } else {
280a5245a51593aa45c2a5ef38a10861697d29c7789Anna Zaks      GoogleServiceAuthError error(
281a5245a51593aa45c2a5ef38a10861697d29c7789Anna Zaks          GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
282a5245a51593aa45c2a5ef38a10861697d29c7789Anna Zaks      OnGetTokenFailure(login_token_request_.get(), error);
2834eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose    }
2844eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose  }
2854eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose
286aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  virtual void ShowLoginPopup() OVERRIDE {
287cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    EXPECT_FALSE(login_ui_shown_);
288cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    login_ui_shown_ = true;
289b8989f27f116ff2400e92a52c067a69846119eb5Benjamin Kramer    if (login_ui_result_)
290cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      SigninSuccess();
291cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    else
292cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      SigninFailed();
293cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor  }
294cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor
295cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor  virtual void ShowOAuthApprovalDialog(
296cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor      const IssueAdviceInfo& issue_advice) OVERRIDE {
297cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor    scope_ui_shown_ = true;
298cb7b1e17b63967317ab5cc55682168cf0380519aDouglas Gregor
29935fa76d0bb6fb8c86159a7506efd094a4fe376d2Ted Kremenek    if (scope_ui_result_) {
3001d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      OnGaiaFlowCompleted(kAccessToken, "3600");
3011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    } else if (scope_ui_failure_ == GaiaWebAuthFlow::SERVICE_AUTH_ERROR) {
3021d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      GoogleServiceAuthError error(GoogleServiceAuthError::CONNECTION_FAILED);
3031d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      OnGaiaFlowFailure(scope_ui_failure_, error, "");
30445796b10d11869e86c6b85e24df165410536b313Ted Kremenek    } else {
30508b86531ade68727c56918f162816075b87c864aJordy Rose      GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
306c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek      OnGaiaFlowFailure(scope_ui_failure_, error, scope_ui_oauth_error_);
307c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek    }
308c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  }
309c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek
310c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  MOCK_CONST_METHOD0(HasLoginToken, bool());
311c4bac8e376b98d633bb00ee5f510d5e58449753cTed Kremenek  MOCK_METHOD1(CreateMintTokenFlow,
31243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis               OAuth2MintTokenFlow* (const std::string& login_access_token));
31345796b10d11869e86c6b85e24df165410536b313Ted Kremenek
3141d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek private:
3151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  ~MockGetAuthTokenFunction() {}
3166a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  bool login_access_token_result_;
3176a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  bool login_ui_result_;
3186a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  bool scope_ui_result_;
3196a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  GaiaWebAuthFlow::Failure scope_ui_failure_;
3206a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  std::string scope_ui_oauth_error_;
3211d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek  bool login_ui_shown_;
32214cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek  bool scope_ui_shown_;
32375f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks};
3248a660eb1084294a903f6dcc00bf2fa4e3bc92cfcAnna Zaks
3258a660eb1084294a903f6dcc00bf2fa4e3bc92cfcAnna Zaksclass MockQueuedMintRequest : public IdentityMintRequestQueue::Request {
32675f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks public:
327b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks  MOCK_METHOD1(StartMintToken, void(IdentityMintRequestQueue::MintType));
32875f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks};
3296a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
3306a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaksclass GetAuthTokenFunctionTest : public AsyncExtensionBrowserTest {
331469ba550f54577f28e23ea42c293308fbcad6609Jordan Rose protected:
332aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  enum OAuth2Fields {
333aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    NONE = 0,
334aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    CLIENT_ID = 1,
335aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    SCOPES = 2,
336aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    AS_COMPONENT = 4
337aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  };
338aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
3396a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  virtual ~GetAuthTokenFunctionTest() {}
3408a660eb1084294a903f6dcc00bf2fa4e3bc92cfcAnna Zaks
3416a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  // Helper to create an extension with specific OAuth2Info fields set.
342aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  // |fields_to_set| should be computed by using fields of Oauth2Fields enum.
34375f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  const Extension* CreateExtension(int fields_to_set) {
34475f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks    const Extension* ext;
34575f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks    base::FilePath manifest_path =
3466a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks        test_data_dir_.AppendASCII("platform_apps/oauth2");
34775f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks    base::FilePath component_manifest_path =
3486a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks        test_data_dir_.AppendASCII("packaged_app/component_oauth2");
349aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    if ((fields_to_set & AS_COMPONENT) == 0)
350aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      ext = LoadExtension(manifest_path);
351c8848f34bbde083b8d89f445eb605eaabf30d6a8Anna Zaks    else
352aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      ext = LoadExtensionAsComponent(component_manifest_path);
353aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    OAuth2Info& oauth2_info =
354aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        const_cast<OAuth2Info&>(OAuth2Info::GetOAuth2Info(ext));
3554eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose    if ((fields_to_set & CLIENT_ID) != 0)
3564eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose      oauth2_info.client_id = "client1";
3574eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose    if ((fields_to_set & SCOPES) != 0) {
358aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      oauth2_info.scopes.push_back("scope1");
359aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      oauth2_info.scopes.push_back("scope2");
360aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    }
361aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return ext;
362aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  }
363aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
364aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  IdentityAPI* id_api() {
365aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks    return IdentityAPI::GetFactoryInstance()->GetForProfile(
366aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks        browser()->profile());
367aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  }
368aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks};
369aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
37075f31c4862643ab09479c979fabf754e7ffe1460Anna ZaksIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
371aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks                       NoClientId) {
372aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
373aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  func->set_extension(CreateExtension(SCOPES));
374aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  std::string error = utils::RunFunctionAndReturnError(
375aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      func.get(), "[{}]", browser());
376aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  EXPECT_EQ(std::string(errors::kInvalidClientId), error);
37775f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  EXPECT_FALSE(func->login_ui_shown());
37875f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  EXPECT_FALSE(func->scope_ui_shown());
379aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks}
38075f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks
381aa5609891df937291bf962dd2fc7deb2ceae292fAnna ZaksIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
382aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks                       NoScopes) {
3834f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
3844f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks  func->set_extension(CreateExtension(CLIENT_ID));
3854f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks  std::string error = utils::RunFunctionAndReturnError(
3864f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks      func.get(), "[{}]", browser());
3874f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks  EXPECT_EQ(std::string(errors::kInvalidScopes), error);
3884f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks  EXPECT_FALSE(func->login_ui_shown());
3894f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks  EXPECT_FALSE(func->scope_ui_shown());
3904f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks}
3916a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
3926a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna ZaksIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
3936a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks                       NonInteractiveNotSignedIn) {
3946a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
3956a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
3964eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose  EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(false));
3976a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  std::string error = utils::RunFunctionAndReturnError(
3981d9cbeb76cf4c36acf5545028e2b2ac207086442Ted Kremenek      func.get(), "[{}]", browser());
399f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
400f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  EXPECT_FALSE(func->login_ui_shown());
401aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  EXPECT_FALSE(func->scope_ui_shown());
402f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek}
403f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
404f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted KremenekIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
405d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks                       NonInteractiveMintFailure) {
406f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
4076a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
4086a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  EXPECT_CALL(*func.get(), HasLoginToken())
4096a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks      .WillOnce(Return(true));
4106a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
4116a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks      TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE, func.get());
4126a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
4136a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  std::string error = utils::RunFunctionAndReturnError(
4146a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks      func.get(), "[{}]", browser());
4156a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
4166a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  EXPECT_FALSE(func->login_ui_shown());
4176a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  EXPECT_FALSE(func->scope_ui_shown());
4186a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks}
4196a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks
4206a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna ZaksIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
4216a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks                       NonInteractiveLoginAccessTokenFailure) {
4226a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
4236a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
424577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek  EXPECT_CALL(*func.get(), HasLoginToken())
4256a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks      .WillOnce(Return(true));
4266a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  func->set_login_access_token_result(false);
4276a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  std::string error = utils::RunFunctionAndReturnError(
428b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks      func.get(), "[{}]", browser());
429b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks  EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
430b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks}
431b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks
43275f31c4862643ab09479c979fabf754e7ffe1460Anna ZaksIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
43375f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks                       NonInteractiveMintAdviceSuccess) {
43475f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
435fbcb3f11fc90e9f00e6074e9b118b8dc11ca604cAnna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
436fbcb3f11fc90e9f00e6074e9b118b8dc11ca604cAnna Zaks  func->set_extension(extension.get());
43775f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(true));
43875f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
439fbcb3f11fc90e9f00e6074e9b118b8dc11ca604cAnna Zaks      TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
440fbcb3f11fc90e9f00e6074e9b118b8dc11ca604cAnna Zaks  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
441b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks  std::string error = utils::RunFunctionAndReturnError(
442fbcb3f11fc90e9f00e6074e9b118b8dc11ca604cAnna Zaks      func.get(), "[{}]", browser());
443fbcb3f11fc90e9f00e6074e9b118b8dc11ca604cAnna Zaks  EXPECT_EQ(std::string(errors::kNoGrant), error);
444fbcb3f11fc90e9f00e6074e9b118b8dc11ca604cAnna Zaks  EXPECT_FALSE(func->login_ui_shown());
445b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks  EXPECT_FALSE(func->scope_ui_shown());
446fbcb3f11fc90e9f00e6074e9b118b8dc11ca604cAnna Zaks
447fbcb3f11fc90e9f00e6074e9b118b8dc11ca604cAnna Zaks  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
44875f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  EXPECT_EQ(
449b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks      IdentityTokenCacheValue::CACHE_STATUS_ADVICE,
450b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks      id_api()->GetCachedToken(extension->id(), oauth2_info.scopes).status());
45175f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks}
4528a660eb1084294a903f6dcc00bf2fa4e3bc92cfcAnna Zaks
45375f31c4862643ab09479c979fabf754e7ffe1460Anna ZaksIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
454b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks                       NonInteractiveMintBadCredentials) {
455b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
45675f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
457b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks  EXPECT_CALL(*func.get(), HasLoginToken())
45875f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks      .WillOnce(Return(true));
4598a660eb1084294a903f6dcc00bf2fa4e3bc92cfcAnna Zaks  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
46075f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks      TestOAuth2MintTokenFlow::MINT_TOKEN_BAD_CREDENTIALS, func.get());
46175f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
4628a660eb1084294a903f6dcc00bf2fa4e3bc92cfcAnna Zaks  std::string error = utils::RunFunctionAndReturnError(
46375f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks      func.get(), "[{}]", browser());
46475f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
465469ba550f54577f28e23ea42c293308fbcad6609Jordan Rose  EXPECT_FALSE(func->login_ui_shown());
466bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks  EXPECT_FALSE(func->scope_ui_shown());
467694a942b0a14e02757a695142c45437eec6e3684Anna Zaks}
468694a942b0a14e02757a695142c45437eec6e3684Anna Zaks
469694a942b0a14e02757a695142c45437eec6e3684Anna ZaksIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
470bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks                       NonInteractiveSuccess) {
471694a942b0a14e02757a695142c45437eec6e3684Anna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
472eaa069075f060f58840af03e0bd5bd75bb27e809Anna Zaks  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
473eaa069075f060f58840af03e0bd5bd75bb27e809Anna Zaks  func->set_extension(extension.get());
474d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
475bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks  EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(true));
476bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
477bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks      TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS, func.get());
478bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
479bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks  scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
480bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks      func.get(), "[{}]", browser()));
481b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks  std::string access_token;
482b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks  EXPECT_TRUE(value->GetAsString(&access_token));
483bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks  EXPECT_EQ(std::string(kAccessToken), access_token);
484bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks  EXPECT_FALSE(func->login_ui_shown());
485bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks  EXPECT_FALSE(func->scope_ui_shown());
486bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks  EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
487371b477836f289f2e9caaab58530f187b51bc86dTed Kremenek            id_api()->GetCachedToken(extension->id(),
488bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks                                     oauth2_info.scopes).status());
489b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks}
490bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks
491bd80231672a7418aa1a99d3dbbe1774205c88f74Anna ZaksIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
492bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks                       InteractiveLoginCanceled) {
493bd80231672a7418aa1a99d3dbbe1774205c88f74Anna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
494b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
4957fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(false));
4967fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  func->set_login_ui_result(false);
497b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks  std::string error = utils::RunFunctionAndReturnError(
4987fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks      func.get(), "[{\"interactive\": true}]", browser());
4997fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
5007fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  EXPECT_TRUE(func->login_ui_shown());
5016a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  EXPECT_FALSE(func->scope_ui_shown());
50275f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks}
503b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks
504255d4d4226b24036ceb11228fbb74286e58620f7Ted KremenekIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
5057fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks                       InteractiveMintBadCredentialsLoginCanceled) {
5067fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
507cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
508cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek  EXPECT_CALL(*func.get(), HasLoginToken())
509b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks      .WillOnce(Return(true));
5107fe8dcef71ae56e43fd7df345db2895f84f2d0caAnna Zaks  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
511b467051a9f212c57335f88f16e839e1dc8afc1c1Anna Zaks      TestOAuth2MintTokenFlow::MINT_TOKEN_BAD_CREDENTIALS, func.get());
512d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
513fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek  func->set_login_ui_result(false);
514fee618af5dd7dee2caaa7347b372eb3dc5fdeffcTed Kremenek  std::string error = utils::RunFunctionAndReturnError(
51514cc9451de4a9539bf79e4e5d63248c2377426dbTed Kremenek      func.get(), "[{\"interactive\": true}]", browser());
516aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
517aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  EXPECT_TRUE(func->login_ui_shown());
518aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  EXPECT_FALSE(func->scope_ui_shown());
519aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks}
520aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks
521c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna ZaksIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
522d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks                       InteractiveLoginSuccessNoToken) {
523d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
524c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
525c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks  EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(false));
526c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks  func->set_login_ui_result(false);
527c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks  std::string error = utils::RunFunctionAndReturnError(
528aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks      func.get(), "[{\"interactive\": true}]", browser());
529aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  EXPECT_EQ(std::string(errors::kUserNotSignedIn), error);
530aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  EXPECT_TRUE(func->login_ui_shown());
531aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  EXPECT_FALSE(func->scope_ui_shown());
5324eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose}
5334eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose
5344eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan RoseIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
535aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks                       InteractiveLoginSuccessMintFailure) {
5366a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
5376a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
538cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek  EXPECT_CALL(*func.get(), HasLoginToken())
539577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek      .WillOnce(Return(false));
540577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek  func->set_login_ui_result(true);
541577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
542577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek      TestOAuth2MintTokenFlow::MINT_TOKEN_FAILURE, func.get());
543694a942b0a14e02757a695142c45437eec6e3684Anna Zaks  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
544694a942b0a14e02757a695142c45437eec6e3684Anna Zaks  std::string error = utils::RunFunctionAndReturnError(
545577f14a34457032523e59dbbbacb88ca2cd4db57Ted Kremenek      func.get(), "[{\"interactive\": true}]", browser());
546cb0a5039c243f5b0c178e70f424adac334e5789bTed Kremenek  EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
547aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  EXPECT_TRUE(func->login_ui_shown());
548aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  EXPECT_FALSE(func->scope_ui_shown());
549469ba550f54577f28e23ea42c293308fbcad6609Jordan Rose}
550b317f8f5ca8737a5bbad97a3f7566a2dbd2ed61bZhongxing Xu
551c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna ZaksIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
552c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks                       InteractiveLoginSuccessLoginAccessTokenFailure) {
553aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
554aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
555c5bdc556f6a65c677e0ed73f918c3000ecad33afAnna Zaks  EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(false));
5569be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek  func->set_login_ui_result(true);
557ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie  func->set_login_access_token_result(false);
558690a7f431d6863a101711e67636d51ddd13f35c5Ted Kremenek  std::string error = utils::RunFunctionAndReturnError(
559ef3643fbbbf66247c5e205497fae0f46e240c143David Blaikie      func.get(), "[{\"interactive\": true}]", browser());
560da17fd50ad485fd2a1fc5c2f055caacf532992daZhongxing Xu  EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
561d07a0d0279c09d1017f8450fce575a94dc9703c0Zhongxing Xu  EXPECT_TRUE(func->login_ui_shown());
562d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks  EXPECT_FALSE(func->scope_ui_shown());
563d38f79543136ba68cd14b1dab0856474df1fbfd5Anna Zaks}
5646b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks
5656b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna ZaksIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
5666b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks                       InteractiveLoginSuccessMintSuccess) {
5676b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
5686b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
5696b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks  EXPECT_CALL(*func.get(), HasLoginToken())
5706b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks      .WillOnce(Return(false));
5716b77ce8824cf62c2cfb61cf2d801eb3fcfbecffeAnna Zaks  func->set_login_ui_result(true);
572db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
573db09a4dee28a4515438af60f2d2b4a83e4965c31Ted Kremenek      TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS, func.get());
574d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
575d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
576d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks      func.get(), "[{\"interactive\": true}]", browser()));
577d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  std::string access_token;
578d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  EXPECT_TRUE(value->GetAsString(&access_token));
579d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  EXPECT_EQ(std::string(kAccessToken), access_token);
580d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  EXPECT_TRUE(func->login_ui_shown());
581d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks  EXPECT_FALSE(func->scope_ui_shown());
582d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks}
583d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks
584d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna ZaksIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
585d95e0b830ed031f2ea0e15e3679cd51b9bf23a9cAnna Zaks                       InteractiveLoginSuccessApprovalAborted) {
5864eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
5874eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
58845796b10d11869e86c6b85e24df165410536b313Ted Kremenek  EXPECT_CALL(*func.get(), HasLoginToken())
58945796b10d11869e86c6b85e24df165410536b313Ted Kremenek      .WillOnce(Return(false));
5904eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose  func->set_login_ui_result(true);
5911eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
5924eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose      TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
5934eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
5944eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose  func->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED);
5954eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose  std::string error = utils::RunFunctionAndReturnError(
5964eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose      func.get(), "[{\"interactive\": true}]", browser());
597fcd783d583d270b7ec1ec3e0fcf83cd93d30e381Ted Kremenek  EXPECT_EQ(std::string(errors::kUserRejected), error);
598402785357ab053dd53f4fdd858b9630a5e0f8badChandler Carruth  EXPECT_TRUE(func->login_ui_shown());
5994eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose  EXPECT_TRUE(func->scope_ui_shown());
6004eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose}
6014eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose
6024eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan RoseIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
6034eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose                       InteractiveLoginSuccessApprovalSuccess) {
60498520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
6054eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
60698520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks  func->set_extension(extension.get());
60798520835eb1aa091429afa06e9f4f7ebe3864d34Anna Zaks  EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(false));
608aa5609891df937291bf962dd2fc7deb2ceae292fAnna Zaks  func->set_login_ui_result(true);
60975f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
6106a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks      TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
6114f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_))
6124f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks      .WillOnce(Return(flow));
6134eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose
6144eff6b5d6a5cbb6bd669854a84365aa61d70819eJordan Rose  scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
6151eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      func.get(), "[{\"interactive\": true}]", browser()));
616f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  std::string access_token;
617a5245a51593aa45c2a5ef38a10861697d29c7789Anna Zaks  EXPECT_TRUE(value->GetAsString(&access_token));
61884c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks  EXPECT_EQ(std::string(kAccessToken), access_token);
61984c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks  EXPECT_TRUE(func->login_ui_shown());
62084c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks  EXPECT_TRUE(func->scope_ui_shown());
62184c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks}
62284c1f4b1edddf74f8080cfc470796c2c498b5d43Anna Zaks
62384c1f4b1edddf74f8080cfc470796c2c498b5d43Anna ZaksIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
6241d26f48dc2eea1c07431ca1519d7034a21b9bcffTed Kremenek                       InteractiveApprovalAborted) {
62558f5ec7d56b1ebf5f90ee11226ebe7663f2821eaTed Kremenek  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
6269fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
6274f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks  EXPECT_CALL(*func.get(), HasLoginToken())
6284f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks      .WillOnce(Return(true));
6294f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
6304f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks      TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
6314f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
6328a660eb1084294a903f6dcc00bf2fa4e3bc92cfcAnna Zaks  func->set_scope_ui_failure(GaiaWebAuthFlow::WINDOW_CLOSED);
6334f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks  std::string error = utils::RunFunctionAndReturnError(
6344f858dfd42c89b67200dac0afc228a0baa323691Anna Zaks      func.get(), "[{\"interactive\": true}]", browser());
635f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  EXPECT_EQ(std::string(errors::kUserRejected), error);
636f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  EXPECT_FALSE(func->login_ui_shown());
637f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  EXPECT_TRUE(func->scope_ui_shown());
638d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis}
639f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
640f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted KremenekIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
6413fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks                       InteractiveApprovalLoadFailed) {
64275f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
6436a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
644a5937bbfd19e61d651a58b0f0ffeef68457902a5Ted Kremenek  EXPECT_CALL(*func.get(), HasLoginToken())
64575d03cffe20b5c945ef04eba208efb0437339997Ted Kremenek      .WillOnce(Return(true));
6463fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
647f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek      TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
6483fd5f370a28552976c52e76c3035d79012d78ddaAnna Zaks  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
649d4aeb8050a1d0fe47c53a73361c8b0b8ac310f46Ted Kremenek  func->set_scope_ui_failure(GaiaWebAuthFlow::LOAD_FAILED);
650d4aeb8050a1d0fe47c53a73361c8b0b8ac310f46Ted Kremenek  std::string error = utils::RunFunctionAndReturnError(
651d4aeb8050a1d0fe47c53a73361c8b0b8ac310f46Ted Kremenek      func.get(), "[{\"interactive\": true}]", browser());
652d4aeb8050a1d0fe47c53a73361c8b0b8ac310f46Ted Kremenek  EXPECT_EQ(std::string(errors::kPageLoadFailure), error);
65375f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  EXPECT_FALSE(func->login_ui_shown());
654f6eafcca7734274d277afa121f2c4fb025a54218Ted Kremenek  EXPECT_TRUE(func->scope_ui_shown());
655f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek}
6566f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith
6573b8a04004afa46057a9af4afbd086be71d619793Ted KremenekIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
658f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek                       InteractiveApprovalInvalidRedirect) {
659c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
660f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
6611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  EXPECT_CALL(*func.get(), HasLoginToken())
662b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek      .WillOnce(Return(true));
663d200187bd27f9ad68699693a6e57f9ee3ff260faJordy Rose  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
664ac3a3e7a402cd349dd2b7d70cd92c5fe702ae831Anna Zaks      TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
6651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
666f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  func->set_scope_ui_failure(GaiaWebAuthFlow::INVALID_REDIRECT);
667f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  std::string error = utils::RunFunctionAndReturnError(
668c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu      func.get(), "[{\"interactive\": true}]", browser());
6693df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek  EXPECT_EQ(std::string(errors::kInvalidRedirect), error);
67034d7734b6ed1d9c0f647405e065251eb67f42badTed Kremenek  EXPECT_FALSE(func->login_ui_shown());
6713b8a04004afa46057a9af4afbd086be71d619793Ted Kremenek  EXPECT_TRUE(func->scope_ui_shown());
672255d4d4226b24036ceb11228fbb74286e58620f7Ted Kremenek}
6731eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
6743df6421150271266b5a90fd4c6bfa6566c38c036Ted KremenekIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
6753df6421150271266b5a90fd4c6bfa6566c38c036Ted Kremenek                       InteractiveApprovalConnectionFailure) {
676bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
677bc46f345838b1c0d420dbd3655c94f5f360fb5b8Ted Kremenek  func->set_extension(CreateExtension(CLIENT_ID | SCOPES));
6786a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  EXPECT_CALL(*func.get(), HasLoginToken())
67975f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks      .WillOnce(Return(true));
6806a86082f3a06a2dcceaaf63f78a0e52d64bcbaa3Anna Zaks  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
68117a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose      TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
6824e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
68317a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  func->set_scope_ui_failure(GaiaWebAuthFlow::SERVICE_AUTH_ERROR);
68475f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  std::string error = utils::RunFunctionAndReturnError(
68517a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose      func.get(), "[{\"interactive\": true}]", browser());
68617a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  EXPECT_TRUE(StartsWithASCII(error, errors::kAuthFailure, false));
68717a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  EXPECT_FALSE(func->login_ui_shown());
68875f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  EXPECT_TRUE(func->scope_ui_shown());
68917a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose}
69017a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
69117a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy RoseIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
69275f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks                       InteractiveApprovalOAuthErrors) {
69375f31c4862643ab09479c979fabf754e7ffe1460Anna Zaks  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
69417a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose
69517a38e2636a8b1ce473fc6504c4b16cb09db29f4Jordy Rose  std::map<std::string, std::string> error_map;
696b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek  error_map.insert(std::make_pair("access_denied", errors::kUserRejected));
697b35a74a40c1d2656a25e560e773ed48bdf49f9c0Ted Kremenek  error_map.insert(std::make_pair("invalid_scope", errors::kInvalidScopes));
698f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  error_map.insert(std::make_pair(
699f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek      "unmapped_error", std::string(errors::kAuthFailure) + "unmapped_error"));
700f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek
701f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek  for (std::map<std::string, std::string>::const_iterator
7029ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenek           it = error_map.begin();
70308b86531ade68727c56918f162816075b87c864aJordy Rose       it != error_map.end();
70445796b10d11869e86c6b85e24df165410536b313Ted Kremenek       ++it) {
70508b86531ade68727c56918f162816075b87c864aJordy Rose    scoped_refptr<MockGetAuthTokenFunction> func(
70608b86531ade68727c56918f162816075b87c864aJordy Rose        new MockGetAuthTokenFunction());
707efceabd2380f49306bc0229583458e93b062094bDaniel Dunbar    func->set_extension(extension.get());
708be1fe1eb12a1cb91c8e3a9fcc2db4dfe989def6cTed Kremenek    EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(true));
70908b86531ade68727c56918f162816075b87c864aJordy Rose    TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
710f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek        TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
711f4381fddf152a63e1ac97185293c47ec0ac2f1a6Ted Kremenek    ON_CALL(*func.get(), CreateMintTokenFlow(_)).WillByDefault(Return(flow));
712f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    func->set_scope_ui_oauth_error(it->first);
713f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    std::string error = utils::RunFunctionAndReturnError(
714f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek        func.get(), "[{\"interactive\": true}]", browser());
715f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    EXPECT_EQ(it->second, error);
716f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek    EXPECT_FALSE(func->login_ui_shown());
7171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    EXPECT_TRUE(func->scope_ui_shown());
718c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  }
7196f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith}
720d2a5bee210218220a57d9f61a66e7f766a21d313Rafael Espindola
721f8ce6991f41d55b6e8526b7a7919771428e2b181Ted KremenekIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
722f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek                       InteractiveApprovalSuccess) {
723f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
724f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
7251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
726f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  func->set_extension(extension.get());
727d2a5bee210218220a57d9f61a66e7f766a21d313Rafael Espindola  EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(true));
7281eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
729710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek      TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
7301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_))
7319c378f705405d37f49795d5e915989de774fe11fTed Kremenek      .WillOnce(Return(flow));
732f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
7331eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
734f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek      func.get(), "[{\"interactive\": true}]", browser()));
735f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  std::string access_token;
736c5619d901a68dc27a9e310a6a831f03efebcd950Zhongxing Xu  EXPECT_TRUE(value->GetAsString(&access_token));
737b8e60d9a8ff06110efab37fc123b3c56937367a9Rafael Espindola  EXPECT_EQ(std::string(kAccessToken), access_token);
738b8e60d9a8ff06110efab37fc123b3c56937367a9Rafael Espindola  EXPECT_FALSE(func->login_ui_shown());
7391ec4a86a867fc04f35d13bc9e33b04cf2171fe41Rafael Espindola  EXPECT_TRUE(func->scope_ui_shown());
740b8e60d9a8ff06110efab37fc123b3c56937367a9Rafael Espindola
7411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
7426f42b62b6194f53bcbc349f5d17388e1936535d7Dylan Noblesmith            id_api()->GetCachedToken(extension->id(),
743b8e60d9a8ff06110efab37fc123b3c56937367a9Rafael Espindola                                     oauth2_info.scopes).status());
7441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
745d2a5bee210218220a57d9f61a66e7f766a21d313Rafael Espindola
746f8ce6991f41d55b6e8526b7a7919771428e2b181Ted KremenekIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, NoninteractiveQueue) {
747f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
7489c378f705405d37f49795d5e915989de774fe11fTed Kremenek  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
7491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  func->set_extension(extension.get());
75045479c88c8a44c55d27c3bd855273bb318082f37Ted Kremenek
7511eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  // Create a fake request to block the queue.
752f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
753f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  std::set<std::string> scopes(oauth2_info.scopes.begin(),
754f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek                               oauth2_info.scopes.end());
7551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  IdentityAPI* id_api =
756f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek      extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(
757f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek          browser()->profile());
758f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  IdentityMintRequestQueue* queue = id_api->mint_queue();
759f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  MockQueuedMintRequest queued_request;
760f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  IdentityMintRequestQueue::MintType type =
761f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek      IdentityMintRequestQueue::MINT_TYPE_NONINTERACTIVE;
7621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
763f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
764f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  queue->RequestStart(type, extension->id(), scopes, &queued_request);
765f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
766f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // The real request will start processing, but wait in the queue behind
767f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // the blocker.
768f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(true));
769f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  RunFunctionAsync(func.get(), "[{}]");
770f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // Verify that we have fetched the login token at this point.
77156b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  testing::Mock::VerifyAndClearExpectations(func.get());
77256b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek
773f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  // The flow will be created after the first queued request clears.
77456b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
77556b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek      TestOAuth2MintTokenFlow::MINT_TOKEN_SUCCESS, func.get());
776f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
777f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek
7781eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  queue->RequestComplete(type, extension->id(), scopes, &queued_request);
779d1289327f7d2126d732e23cc189ecd0aa5d07cbbTed Kremenek
780f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
781f8ce6991f41d55b6e8526b7a7919771428e2b181Ted Kremenek  std::string access_token;
782d2a5bee210218220a57d9f61a66e7f766a21d313Rafael Espindola  EXPECT_TRUE(value->GetAsString(&access_token));
783d2a5bee210218220a57d9f61a66e7f766a21d313Rafael Espindola  EXPECT_EQ(std::string(kAccessToken), access_token);
78456b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  EXPECT_FALSE(func->login_ui_shown());
78556b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  EXPECT_FALSE(func->scope_ui_shown());
78656b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek}
78756b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek
78856b98719b0dbebb33cb228afa888c47156be2381Ted KremenekIN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, InteractiveQueue) {
78956b98719b0dbebb33cb228afa888c47156be2381Ted Kremenek  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
790710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
791710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  func->set_extension(extension.get());
7926cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer
793710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  // Create a fake request to block the queue.
7942289933d3dfad854c006c02738abb1c57d1d587eRafael Espindola  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
795710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  std::set<std::string> scopes(oauth2_info.scopes.begin(),
796710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek                               oauth2_info.scopes.end());
797710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  IdentityAPI* id_api =
798710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek      extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(
7991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump          browser()->profile());
80057a3bbfa9a97f174b0c80b0309e32f4329c4ae1bRafael Espindola  IdentityMintRequestQueue* queue = id_api->mint_queue();
8016cb7c1a43b0c8f739d1f54b7fdae5ede86033496Benjamin Kramer  MockQueuedMintRequest queued_request;
802710ad9343f32b33b336369b20edad1a21a0b3299Ted Kremenek  IdentityMintRequestQueue::MintType type =
8031eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump      IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE;
804d2a5bee210218220a57d9f61a66e7f766a21d313Rafael Espindola
805d2a5bee210218220a57d9f61a66e7f766a21d313Rafael Espindola  EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
806932680ecdeab4c216ce7c0736093d3dcd2f60f6dDaniel Dunbar  queue->RequestStart(type, extension->id(), scopes, &queued_request);
807
808  // The real request will start processing, but wait in the queue behind
809  // the blocker.
810  EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(true));
811  TestOAuth2MintTokenFlow* flow1 = new TestOAuth2MintTokenFlow(
812      TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
813  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow1));
814  RunFunctionAsync(func.get(), "[{\"interactive\": true}]");
815  // Verify that we have fetched the login token and run the first flow.
816  testing::Mock::VerifyAndClearExpectations(func.get());
817  EXPECT_FALSE(func->scope_ui_shown());
818
819  // The UI will be displayed and a token retrieved after the first
820  // queued request clears.
821  queue->RequestComplete(type, extension->id(), scopes, &queued_request);
822
823  scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
824  std::string access_token;
825  EXPECT_TRUE(value->GetAsString(&access_token));
826  EXPECT_EQ(std::string(kAccessToken), access_token);
827  EXPECT_FALSE(func->login_ui_shown());
828  EXPECT_TRUE(func->scope_ui_shown());
829}
830
831IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
832                       InteractiveQueuedNoninteractiveFails) {
833  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
834  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
835  func->set_extension(extension.get());
836
837  // Create a fake request to block the interactive queue.
838  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
839  std::set<std::string> scopes(oauth2_info.scopes.begin(),
840                               oauth2_info.scopes.end());
841  IdentityAPI* id_api =
842      extensions::IdentityAPI::GetFactoryInstance()->GetForProfile(
843          browser()->profile());
844  IdentityMintRequestQueue* queue = id_api->mint_queue();
845  MockQueuedMintRequest queued_request;
846  IdentityMintRequestQueue::MintType type =
847      IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE;
848
849  EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
850  queue->RequestStart(type, extension->id(), scopes, &queued_request);
851
852  // Non-interactive requests fail without hitting GAIA, because a
853  // consent UI is known to be up.
854  EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(true));
855  std::string error = utils::RunFunctionAndReturnError(
856      func.get(), "[{}]", browser());
857  EXPECT_EQ(std::string(errors::kNoGrant), error);
858  EXPECT_FALSE(func->login_ui_shown());
859  EXPECT_FALSE(func->scope_ui_shown());
860
861  queue->RequestComplete(type, extension->id(), scopes, &queued_request);
862}
863
864IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
865                       NonInteractiveCacheHit) {
866  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
867  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
868  func->set_extension(extension.get());
869
870  // pre-populate the cache with a token
871  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
872  IdentityTokenCacheValue token(kAccessToken,
873                                base::TimeDelta::FromSeconds(3600));
874  id_api()->SetCachedToken(extension->id(), oauth2_info.scopes, token);
875
876  // Get a token. Should not require a GAIA request.
877  EXPECT_CALL(*func.get(), HasLoginToken())
878      .WillOnce(Return(true));
879  scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
880      func.get(), "[{}]", browser()));
881  std::string access_token;
882  EXPECT_TRUE(value->GetAsString(&access_token));
883  EXPECT_EQ(std::string(kAccessToken), access_token);
884  EXPECT_FALSE(func->login_ui_shown());
885  EXPECT_FALSE(func->scope_ui_shown());
886}
887
888IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
889                       NonInteractiveIssueAdviceCacheHit) {
890  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
891  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
892  func->set_extension(extension.get());
893
894  // pre-populate the cache with advice
895  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
896  IssueAdviceInfo info;
897  IdentityTokenCacheValue token(info);
898  id_api()->SetCachedToken(extension->id(), oauth2_info.scopes, token);
899
900  // Should return an error without a GAIA request.
901  EXPECT_CALL(*func.get(), HasLoginToken())
902      .WillOnce(Return(true));
903  std::string error = utils::RunFunctionAndReturnError(
904      func.get(), "[{}]", browser());
905  EXPECT_EQ(std::string(errors::kNoGrant), error);
906  EXPECT_FALSE(func->login_ui_shown());
907  EXPECT_FALSE(func->scope_ui_shown());
908}
909
910IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
911                       InteractiveCacheHit) {
912  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
913  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
914  func->set_extension(extension.get());
915
916  // Create a fake request to block the queue.
917  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
918  std::set<std::string> scopes(oauth2_info.scopes.begin(),
919                               oauth2_info.scopes.end());
920  IdentityMintRequestQueue* queue = id_api()->mint_queue();
921  MockQueuedMintRequest queued_request;
922  IdentityMintRequestQueue::MintType type =
923      IdentityMintRequestQueue::MINT_TYPE_INTERACTIVE;
924
925  EXPECT_CALL(queued_request, StartMintToken(type)).Times(1);
926  queue->RequestStart(type, extension->id(), scopes, &queued_request);
927
928  // The real request will start processing, but wait in the queue behind
929  // the blocker.
930  EXPECT_CALL(*func.get(), HasLoginToken()).WillOnce(Return(true));
931  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
932      TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
933  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_)).WillOnce(Return(flow));
934  RunFunctionAsync(func.get(), "[{\"interactive\": true}]");
935
936  // Populate the cache with a token while the request is blocked.
937  IdentityTokenCacheValue token(kAccessToken,
938                                base::TimeDelta::FromSeconds(3600));
939  id_api()->SetCachedToken(extension->id(), oauth2_info.scopes, token);
940
941  // When we wake up the request, it returns the cached token without
942  // displaying a UI, or hitting GAIA.
943
944  queue->RequestComplete(type, extension->id(), scopes, &queued_request);
945
946  scoped_ptr<base::Value> value(WaitForSingleResult(func.get()));
947  std::string access_token;
948  EXPECT_TRUE(value->GetAsString(&access_token));
949  EXPECT_EQ(std::string(kAccessToken), access_token);
950  EXPECT_FALSE(func->login_ui_shown());
951  EXPECT_FALSE(func->scope_ui_shown());
952}
953
954IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest,
955                       LoginInvalidatesTokenCache) {
956  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
957  scoped_refptr<const Extension> extension(CreateExtension(CLIENT_ID | SCOPES));
958  func->set_extension(extension.get());
959
960  // pre-populate the cache with a token
961  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
962  IdentityTokenCacheValue token(kAccessToken,
963                                base::TimeDelta::FromSeconds(3600));
964  id_api()->SetCachedToken(extension->id(), oauth2_info.scopes, token);
965
966  // Because the user is not signed in, the token will be removed,
967  // and we'll hit GAIA for new tokens.
968  EXPECT_CALL(*func.get(), HasLoginToken())
969      .WillOnce(Return(false));
970  func->set_login_ui_result(true);
971  TestOAuth2MintTokenFlow* flow = new TestOAuth2MintTokenFlow(
972      TestOAuth2MintTokenFlow::ISSUE_ADVICE_SUCCESS, func.get());
973  EXPECT_CALL(*func.get(), CreateMintTokenFlow(_))
974      .WillOnce(Return(flow));
975
976  scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
977      func.get(), "[{\"interactive\": true}]", browser()));
978  std::string access_token;
979  EXPECT_TRUE(value->GetAsString(&access_token));
980  EXPECT_EQ(std::string(kAccessToken), access_token);
981  EXPECT_TRUE(func->login_ui_shown());
982  EXPECT_TRUE(func->scope_ui_shown());
983  EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
984            id_api()->GetCachedToken(extension->id(),
985                                     oauth2_info.scopes).status());
986}
987
988IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ComponentWithChromeClientId) {
989  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
990  scoped_refptr<const Extension> extension(
991      CreateExtension(SCOPES | AS_COMPONENT));
992  func->set_extension(extension.get());
993  const OAuth2Info& oauth2_info = OAuth2Info::GetOAuth2Info(extension.get());
994  EXPECT_TRUE(oauth2_info.client_id.empty());
995  EXPECT_FALSE(func->GetOAuth2ClientId().empty());
996  EXPECT_NE("client1", func->GetOAuth2ClientId());
997}
998
999IN_PROC_BROWSER_TEST_F(GetAuthTokenFunctionTest, ComponentWithNormalClientId) {
1000  scoped_refptr<MockGetAuthTokenFunction> func(new MockGetAuthTokenFunction());
1001  scoped_refptr<const Extension> extension(
1002      CreateExtension(CLIENT_ID | SCOPES | AS_COMPONENT));
1003  func->set_extension(extension.get());
1004  EXPECT_EQ("client1", func->GetOAuth2ClientId());
1005}
1006
1007class RemoveCachedAuthTokenFunctionTest : public ExtensionBrowserTest {
1008 protected:
1009  bool InvalidateDefaultToken() {
1010    scoped_refptr<IdentityRemoveCachedAuthTokenFunction> func(
1011        new IdentityRemoveCachedAuthTokenFunction);
1012    func->set_extension(utils::CreateEmptyExtension(kExtensionId).get());
1013    return utils::RunFunction(
1014        func.get(),
1015        std::string("[{\"token\": \"") + kAccessToken + "\"}]",
1016        browser(),
1017        extension_function_test_utils::NONE);
1018  }
1019
1020  IdentityAPI* id_api() {
1021    return IdentityAPI::GetFactoryInstance()->GetForProfile(
1022        browser()->profile());
1023  }
1024
1025  void SetCachedToken(IdentityTokenCacheValue& token_data) {
1026    id_api()->SetCachedToken(extensions::id_util::GenerateId(kExtensionId),
1027                             std::vector<std::string>(), token_data);
1028  }
1029
1030  const IdentityTokenCacheValue& GetCachedToken() {
1031    return id_api()->GetCachedToken(
1032        extensions::id_util::GenerateId(kExtensionId),
1033        std::vector<std::string>());
1034  }
1035};
1036
1037IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, NotFound) {
1038  EXPECT_TRUE(InvalidateDefaultToken());
1039  EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND,
1040            GetCachedToken().status());
1041}
1042
1043IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, Advice) {
1044  IssueAdviceInfo info;
1045  IdentityTokenCacheValue advice(info);
1046  SetCachedToken(advice);
1047  EXPECT_TRUE(InvalidateDefaultToken());
1048  EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_ADVICE,
1049            GetCachedToken().status());
1050}
1051
1052IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, NonMatchingToken) {
1053  IdentityTokenCacheValue token("non_matching_token",
1054                                base::TimeDelta::FromSeconds(3600));
1055  SetCachedToken(token);
1056  EXPECT_TRUE(InvalidateDefaultToken());
1057  EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_TOKEN,
1058            GetCachedToken().status());
1059  EXPECT_EQ("non_matching_token", GetCachedToken().token());
1060}
1061
1062IN_PROC_BROWSER_TEST_F(RemoveCachedAuthTokenFunctionTest, MatchingToken) {
1063  IdentityTokenCacheValue token(kAccessToken,
1064                                base::TimeDelta::FromSeconds(3600));
1065  SetCachedToken(token);
1066  EXPECT_TRUE(InvalidateDefaultToken());
1067  EXPECT_EQ(IdentityTokenCacheValue::CACHE_STATUS_NOTFOUND,
1068            GetCachedToken().status());
1069}
1070
1071class LaunchWebAuthFlowFunctionTest : public AsyncExtensionBrowserTest {
1072 public:
1073  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
1074    // Reduce performance test variance by disabling background networking.
1075    command_line->AppendSwitch(switches::kDisableBackgroundNetworking);
1076  }
1077};
1078
1079IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, UserCloseWindow) {
1080  net::SpawnedTestServer https_server(
1081      net::SpawnedTestServer::TYPE_HTTPS,
1082      net::SpawnedTestServer::kLocalhost,
1083      base::FilePath(FILE_PATH_LITERAL(
1084          "chrome/test/data/extensions/api_test/identity")));
1085  ASSERT_TRUE(https_server.Start());
1086  GURL auth_url(https_server.GetURL("files/interaction_required.html"));
1087
1088  scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1089      new IdentityLaunchWebAuthFlowFunction());
1090  scoped_refptr<Extension> empty_extension(
1091      utils::CreateEmptyExtension());
1092  function->set_extension(empty_extension.get());
1093
1094  WaitForGURLAndCloseWindow popup_observer(auth_url);
1095
1096  std::string args = "[{\"interactive\": true, \"url\": \"" +
1097      auth_url.spec() + "\"}]";
1098  RunFunctionAsync(function.get(), args);
1099
1100  popup_observer.Wait();
1101  popup_observer.CloseEmbedderWebContents();
1102
1103  EXPECT_EQ(std::string(errors::kUserRejected), WaitForError(function.get()));
1104}
1105
1106IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, InteractionRequired) {
1107  net::SpawnedTestServer https_server(
1108      net::SpawnedTestServer::TYPE_HTTPS,
1109      net::SpawnedTestServer::kLocalhost,
1110      base::FilePath(FILE_PATH_LITERAL(
1111          "chrome/test/data/extensions/api_test/identity")));
1112  ASSERT_TRUE(https_server.Start());
1113  GURL auth_url(https_server.GetURL("files/interaction_required.html"));
1114
1115  scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1116      new IdentityLaunchWebAuthFlowFunction());
1117  scoped_refptr<Extension> empty_extension(
1118      utils::CreateEmptyExtension());
1119  function->set_extension(empty_extension.get());
1120
1121  std::string args = "[{\"interactive\": false, \"url\": \"" +
1122      auth_url.spec() + "\"}]";
1123  std::string error =
1124      utils::RunFunctionAndReturnError(function.get(), args, browser());
1125
1126  EXPECT_EQ(std::string(errors::kInteractionRequired), error);
1127}
1128
1129IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, LoadFailed) {
1130  net::SpawnedTestServer https_server(
1131      net::SpawnedTestServer::TYPE_HTTPS,
1132      net::SpawnedTestServer::kLocalhost,
1133      base::FilePath(FILE_PATH_LITERAL(
1134          "chrome/test/data/extensions/api_test/identity")));
1135  ASSERT_TRUE(https_server.Start());
1136  GURL auth_url(https_server.GetURL("files/five_hundred.html"));
1137
1138  scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1139      new IdentityLaunchWebAuthFlowFunction());
1140  scoped_refptr<Extension> empty_extension(
1141      utils::CreateEmptyExtension());
1142  function->set_extension(empty_extension.get());
1143
1144  std::string args = "[{\"interactive\": true, \"url\": \"" +
1145      auth_url.spec() + "\"}]";
1146  std::string error =
1147      utils::RunFunctionAndReturnError(function.get(), args, browser());
1148
1149  EXPECT_EQ(std::string(errors::kPageLoadFailure), error);
1150}
1151
1152IN_PROC_BROWSER_TEST_F(LaunchWebAuthFlowFunctionTest, NonInteractiveSuccess) {
1153  scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1154      new IdentityLaunchWebAuthFlowFunction());
1155  scoped_refptr<Extension> empty_extension(
1156      utils::CreateEmptyExtension());
1157  function->set_extension(empty_extension.get());
1158
1159  function->InitFinalRedirectURLPrefixForTest("abcdefghij");
1160  scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1161      function.get(),
1162      "[{\"interactive\": false,"
1163      "\"url\": \"https://abcdefghij.chromiumapp.org/callback#test\"}]",
1164      browser()));
1165
1166  std::string url;
1167  EXPECT_TRUE(value->GetAsString(&url));
1168  EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1169            url);
1170}
1171
1172IN_PROC_BROWSER_TEST_F(
1173    LaunchWebAuthFlowFunctionTest, InteractiveFirstNavigationSuccess) {
1174  scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1175      new IdentityLaunchWebAuthFlowFunction());
1176  scoped_refptr<Extension> empty_extension(
1177      utils::CreateEmptyExtension());
1178  function->set_extension(empty_extension.get());
1179
1180  function->InitFinalRedirectURLPrefixForTest("abcdefghij");
1181  scoped_ptr<base::Value> value(utils::RunFunctionAndReturnSingleResult(
1182      function.get(),
1183      "[{\"interactive\": true,"
1184      "\"url\": \"https://abcdefghij.chromiumapp.org/callback#test\"}]",
1185      browser()));
1186
1187  std::string url;
1188  EXPECT_TRUE(value->GetAsString(&url));
1189  EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1190            url);
1191}
1192
1193IN_PROC_BROWSER_TEST_F(
1194    LaunchWebAuthFlowFunctionTest, InteractiveSecondNavigationSuccess) {
1195  net::SpawnedTestServer https_server(
1196      net::SpawnedTestServer::TYPE_HTTPS,
1197      net::SpawnedTestServer::kLocalhost,
1198      base::FilePath(FILE_PATH_LITERAL(
1199          "chrome/test/data/extensions/api_test/identity")));
1200  ASSERT_TRUE(https_server.Start());
1201  GURL auth_url(https_server.GetURL("files/redirect_to_chromiumapp.html"));
1202
1203  scoped_refptr<IdentityLaunchWebAuthFlowFunction> function(
1204      new IdentityLaunchWebAuthFlowFunction());
1205  scoped_refptr<Extension> empty_extension(
1206      utils::CreateEmptyExtension());
1207  function->set_extension(empty_extension.get());
1208
1209  function->InitFinalRedirectURLPrefixForTest("abcdefghij");
1210  std::string args = "[{\"interactive\": true, \"url\": \"" +
1211      auth_url.spec() + "\"}]";
1212  scoped_ptr<base::Value> value(
1213      utils::RunFunctionAndReturnSingleResult(function.get(), args, browser()));
1214
1215  std::string url;
1216  EXPECT_TRUE(value->GetAsString(&url));
1217  EXPECT_EQ(std::string("https://abcdefghij.chromiumapp.org/callback#test"),
1218            url);
1219}
1220
1221}  // namespace extensions
1222