| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h" | 5 #include "chrome/browser/extensions/api/identity/gaia_web_auth_flow.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/message_loop/message_loop.h" | 9 #include "base/message_loop/message_loop.h" |
| 10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| (...skipping 24 matching lines...) Expand all Loading... |
| 35 ubertoken_error_(ubertoken_error_state) {} | 35 ubertoken_error_(ubertoken_error_state) {} |
| 36 | 36 |
| 37 void Start() override { | 37 void Start() override { |
| 38 if (ubertoken_error_.state() == GoogleServiceAuthError::NONE) | 38 if (ubertoken_error_.state() == GoogleServiceAuthError::NONE) |
| 39 OnUbertokenSuccess("fake_ubertoken"); | 39 OnUbertokenSuccess("fake_ubertoken"); |
| 40 else | 40 else |
| 41 OnUbertokenFailure(ubertoken_error_); | 41 OnUbertokenFailure(ubertoken_error_); |
| 42 } | 42 } |
| 43 | 43 |
| 44 private: | 44 private: |
| 45 scoped_ptr<WebAuthFlow> CreateWebAuthFlow(GURL url) override { | 45 std::unique_ptr<WebAuthFlow> CreateWebAuthFlow(GURL url) override { |
| 46 return scoped_ptr<WebAuthFlow>(new FakeWebAuthFlow(this)); | 46 return std::unique_ptr<WebAuthFlow>(new FakeWebAuthFlow(this)); |
| 47 } | 47 } |
| 48 | 48 |
| 49 GoogleServiceAuthError ubertoken_error_; | 49 GoogleServiceAuthError ubertoken_error_; |
| 50 }; | 50 }; |
| 51 | 51 |
| 52 class MockGaiaWebAuthFlowDelegate : public GaiaWebAuthFlow::Delegate { | 52 class MockGaiaWebAuthFlowDelegate : public GaiaWebAuthFlow::Delegate { |
| 53 public: | 53 public: |
| 54 MOCK_METHOD3(OnGaiaFlowFailure, | 54 MOCK_METHOD3(OnGaiaFlowFailure, |
| 55 void(GaiaWebAuthFlow::Failure failure, | 55 void(GaiaWebAuthFlow::Failure failure, |
| 56 GoogleServiceAuthError service_error, | 56 GoogleServiceAuthError service_error, |
| 57 const std::string& oauth_error)); | 57 const std::string& oauth_error)); |
| 58 MOCK_METHOD2(OnGaiaFlowCompleted, | 58 MOCK_METHOD2(OnGaiaFlowCompleted, |
| 59 void(const std::string& access_token, | 59 void(const std::string& access_token, |
| 60 const std::string& expiration)); | 60 const std::string& expiration)); |
| 61 }; | 61 }; |
| 62 | 62 |
| 63 class IdentityGaiaWebAuthFlowTest : public testing::Test { | 63 class IdentityGaiaWebAuthFlowTest : public testing::Test { |
| 64 public: | 64 public: |
| 65 IdentityGaiaWebAuthFlowTest() | 65 IdentityGaiaWebAuthFlowTest() |
| 66 : ubertoken_error_state_(GoogleServiceAuthError::NONE), | 66 : ubertoken_error_state_(GoogleServiceAuthError::NONE), |
| 67 fake_ui_thread_(content::BrowserThread::UI, &message_loop_) {} | 67 fake_ui_thread_(content::BrowserThread::UI, &message_loop_) {} |
| 68 | 68 |
| 69 virtual void TearDown() { | 69 virtual void TearDown() { |
| 70 testing::Test::TearDown(); | 70 testing::Test::TearDown(); |
| 71 base::RunLoop loop; | 71 base::RunLoop loop; |
| 72 loop.RunUntilIdle(); // Run tasks so FakeWebAuthFlows get deleted. | 72 loop.RunUntilIdle(); // Run tasks so FakeWebAuthFlows get deleted. |
| 73 } | 73 } |
| 74 | 74 |
| 75 scoped_ptr<TestGaiaWebAuthFlow> CreateTestFlow() { | 75 std::unique_ptr<TestGaiaWebAuthFlow> CreateTestFlow() { |
| 76 ExtensionTokenKey token_key( | 76 ExtensionTokenKey token_key( |
| 77 "extension_id", "account_id", std::set<std::string>()); | 77 "extension_id", "account_id", std::set<std::string>()); |
| 78 return scoped_ptr<TestGaiaWebAuthFlow>(new TestGaiaWebAuthFlow( | 78 return std::unique_ptr<TestGaiaWebAuthFlow>(new TestGaiaWebAuthFlow( |
| 79 &delegate_, &token_key, "fake.client.id", ubertoken_error_state_)); | 79 &delegate_, &token_key, "fake.client.id", ubertoken_error_state_)); |
| 80 } | 80 } |
| 81 | 81 |
| 82 std::string GetFinalTitle(const std::string& fragment) { | 82 std::string GetFinalTitle(const std::string& fragment) { |
| 83 return std::string("Loading id.client.fake:/extension_id#") + fragment; | 83 return std::string("Loading id.client.fake:/extension_id#") + fragment; |
| 84 } | 84 } |
| 85 | 85 |
| 86 GoogleServiceAuthError GetNoneServiceError() { | 86 GoogleServiceAuthError GetNoneServiceError() { |
| 87 return GoogleServiceAuthError(GoogleServiceAuthError::NONE); | 87 return GoogleServiceAuthError(GoogleServiceAuthError::NONE); |
| 88 } | 88 } |
| 89 | 89 |
| 90 void set_ubertoken_error( | 90 void set_ubertoken_error( |
| 91 GoogleServiceAuthError::State ubertoken_error_state) { | 91 GoogleServiceAuthError::State ubertoken_error_state) { |
| 92 ubertoken_error_state_ = ubertoken_error_state; | 92 ubertoken_error_state_ = ubertoken_error_state; |
| 93 } | 93 } |
| 94 | 94 |
| 95 protected: | 95 protected: |
| 96 testing::StrictMock<MockGaiaWebAuthFlowDelegate> delegate_; | 96 testing::StrictMock<MockGaiaWebAuthFlowDelegate> delegate_; |
| 97 GoogleServiceAuthError::State ubertoken_error_state_; | 97 GoogleServiceAuthError::State ubertoken_error_state_; |
| 98 base::MessageLoop message_loop_; | 98 base::MessageLoop message_loop_; |
| 99 content::TestBrowserThread fake_ui_thread_; | 99 content::TestBrowserThread fake_ui_thread_; |
| 100 }; | 100 }; |
| 101 | 101 |
| 102 TEST_F(IdentityGaiaWebAuthFlowTest, OAuthError) { | 102 TEST_F(IdentityGaiaWebAuthFlowTest, OAuthError) { |
| 103 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); | 103 std::unique_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); |
| 104 flow->Start(); | 104 flow->Start(); |
| 105 EXPECT_CALL(delegate_, OnGaiaFlowFailure( | 105 EXPECT_CALL(delegate_, OnGaiaFlowFailure( |
| 106 GaiaWebAuthFlow::OAUTH_ERROR, | 106 GaiaWebAuthFlow::OAUTH_ERROR, |
| 107 GoogleServiceAuthError(GoogleServiceAuthError::NONE), | 107 GoogleServiceAuthError(GoogleServiceAuthError::NONE), |
| 108 "access_denied")); | 108 "access_denied")); |
| 109 flow->OnAuthFlowTitleChange(GetFinalTitle("error=access_denied")); | 109 flow->OnAuthFlowTitleChange(GetFinalTitle("error=access_denied")); |
| 110 } | 110 } |
| 111 | 111 |
| 112 TEST_F(IdentityGaiaWebAuthFlowTest, Token) { | 112 TEST_F(IdentityGaiaWebAuthFlowTest, Token) { |
| 113 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); | 113 std::unique_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); |
| 114 flow->Start(); | 114 flow->Start(); |
| 115 EXPECT_CALL(delegate_, OnGaiaFlowCompleted("fake_access_token", "")); | 115 EXPECT_CALL(delegate_, OnGaiaFlowCompleted("fake_access_token", "")); |
| 116 flow->OnAuthFlowTitleChange(GetFinalTitle("access_token=fake_access_token")); | 116 flow->OnAuthFlowTitleChange(GetFinalTitle("access_token=fake_access_token")); |
| 117 } | 117 } |
| 118 | 118 |
| 119 TEST_F(IdentityGaiaWebAuthFlowTest, TokenAndExpiration) { | 119 TEST_F(IdentityGaiaWebAuthFlowTest, TokenAndExpiration) { |
| 120 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); | 120 std::unique_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); |
| 121 flow->Start(); | 121 flow->Start(); |
| 122 EXPECT_CALL(delegate_, OnGaiaFlowCompleted("fake_access_token", "3600")); | 122 EXPECT_CALL(delegate_, OnGaiaFlowCompleted("fake_access_token", "3600")); |
| 123 flow->OnAuthFlowTitleChange( | 123 flow->OnAuthFlowTitleChange( |
| 124 GetFinalTitle("access_token=fake_access_token&expires_in=3600")); | 124 GetFinalTitle("access_token=fake_access_token&expires_in=3600")); |
| 125 } | 125 } |
| 126 | 126 |
| 127 TEST_F(IdentityGaiaWebAuthFlowTest, ExtraFragmentParametersSuccess) { | 127 TEST_F(IdentityGaiaWebAuthFlowTest, ExtraFragmentParametersSuccess) { |
| 128 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); | 128 std::unique_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); |
| 129 flow->Start(); | 129 flow->Start(); |
| 130 EXPECT_CALL(delegate_, | 130 EXPECT_CALL(delegate_, |
| 131 OnGaiaFlowCompleted("fake_access_token", "3600")); | 131 OnGaiaFlowCompleted("fake_access_token", "3600")); |
| 132 flow->OnAuthFlowTitleChange(GetFinalTitle("chaff1=stuff&" | 132 flow->OnAuthFlowTitleChange(GetFinalTitle("chaff1=stuff&" |
| 133 "expires_in=3600&" | 133 "expires_in=3600&" |
| 134 "chaff2=and&" | 134 "chaff2=and&" |
| 135 "nonerror=fake_error&" | 135 "nonerror=fake_error&" |
| 136 "chaff3=nonsense&" | 136 "chaff3=nonsense&" |
| 137 "access_token=fake_access_token&" | 137 "access_token=fake_access_token&" |
| 138 "chaff4=")); | 138 "chaff4=")); |
| 139 } | 139 } |
| 140 | 140 |
| 141 TEST_F(IdentityGaiaWebAuthFlowTest, ExtraFragmentParametersError) { | 141 TEST_F(IdentityGaiaWebAuthFlowTest, ExtraFragmentParametersError) { |
| 142 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); | 142 std::unique_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); |
| 143 flow->Start(); | 143 flow->Start(); |
| 144 EXPECT_CALL(delegate_, OnGaiaFlowFailure( | 144 EXPECT_CALL(delegate_, OnGaiaFlowFailure( |
| 145 GaiaWebAuthFlow::OAUTH_ERROR, | 145 GaiaWebAuthFlow::OAUTH_ERROR, |
| 146 GoogleServiceAuthError(GoogleServiceAuthError::NONE), | 146 GoogleServiceAuthError(GoogleServiceAuthError::NONE), |
| 147 "fake_error")); | 147 "fake_error")); |
| 148 flow->OnAuthFlowTitleChange(GetFinalTitle("chaff1=stuff&" | 148 flow->OnAuthFlowTitleChange(GetFinalTitle("chaff1=stuff&" |
| 149 "expires_in=3600&" | 149 "expires_in=3600&" |
| 150 "chaff2=and&" | 150 "chaff2=and&" |
| 151 "error=fake_error&" | 151 "error=fake_error&" |
| 152 "chaff3=nonsense&" | 152 "chaff3=nonsense&" |
| 153 "access_token=fake_access_token&" | 153 "access_token=fake_access_token&" |
| 154 "chaff4=")); | 154 "chaff4=")); |
| 155 } | 155 } |
| 156 | 156 |
| 157 TEST_F(IdentityGaiaWebAuthFlowTest, TitleSpam) { | 157 TEST_F(IdentityGaiaWebAuthFlowTest, TitleSpam) { |
| 158 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); | 158 std::unique_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); |
| 159 flow->Start(); | 159 flow->Start(); |
| 160 flow->OnAuthFlowTitleChange( | 160 flow->OnAuthFlowTitleChange( |
| 161 "Loading https://extension_id.chromiumapp.org/#error=non_final_title"); | 161 "Loading https://extension_id.chromiumapp.org/#error=non_final_title"); |
| 162 flow->OnAuthFlowTitleChange("I'm feeling entitled."); | 162 flow->OnAuthFlowTitleChange("I'm feeling entitled."); |
| 163 flow->OnAuthFlowTitleChange(""); | 163 flow->OnAuthFlowTitleChange(""); |
| 164 flow->OnAuthFlowTitleChange( | 164 flow->OnAuthFlowTitleChange( |
| 165 "Loading id.client.fake:/bad_extension_id#error=non_final_title"); | 165 "Loading id.client.fake:/bad_extension_id#error=non_final_title"); |
| 166 flow->OnAuthFlowTitleChange( | 166 flow->OnAuthFlowTitleChange( |
| 167 "Loading bad.id.client.fake:/extension_id#error=non_final_title"); | 167 "Loading bad.id.client.fake:/extension_id#error=non_final_title"); |
| 168 EXPECT_CALL(delegate_, OnGaiaFlowCompleted("fake_access_token", "")); | 168 EXPECT_CALL(delegate_, OnGaiaFlowCompleted("fake_access_token", "")); |
| 169 flow->OnAuthFlowTitleChange(GetFinalTitle("access_token=fake_access_token")); | 169 flow->OnAuthFlowTitleChange(GetFinalTitle("access_token=fake_access_token")); |
| 170 } | 170 } |
| 171 | 171 |
| 172 TEST_F(IdentityGaiaWebAuthFlowTest, EmptyFragment) { | 172 TEST_F(IdentityGaiaWebAuthFlowTest, EmptyFragment) { |
| 173 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); | 173 std::unique_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); |
| 174 flow->Start(); | 174 flow->Start(); |
| 175 EXPECT_CALL( | 175 EXPECT_CALL( |
| 176 delegate_, | 176 delegate_, |
| 177 OnGaiaFlowFailure( | 177 OnGaiaFlowFailure( |
| 178 GaiaWebAuthFlow::INVALID_REDIRECT, | 178 GaiaWebAuthFlow::INVALID_REDIRECT, |
| 179 GoogleServiceAuthError(GoogleServiceAuthError::NONE), | 179 GoogleServiceAuthError(GoogleServiceAuthError::NONE), |
| 180 "")); | 180 "")); |
| 181 flow->OnAuthFlowTitleChange(GetFinalTitle("")); | 181 flow->OnAuthFlowTitleChange(GetFinalTitle("")); |
| 182 } | 182 } |
| 183 | 183 |
| 184 TEST_F(IdentityGaiaWebAuthFlowTest, JunkFragment) { | 184 TEST_F(IdentityGaiaWebAuthFlowTest, JunkFragment) { |
| 185 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); | 185 std::unique_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); |
| 186 flow->Start(); | 186 flow->Start(); |
| 187 EXPECT_CALL( | 187 EXPECT_CALL( |
| 188 delegate_, | 188 delegate_, |
| 189 OnGaiaFlowFailure( | 189 OnGaiaFlowFailure( |
| 190 GaiaWebAuthFlow::INVALID_REDIRECT, | 190 GaiaWebAuthFlow::INVALID_REDIRECT, |
| 191 GoogleServiceAuthError(GoogleServiceAuthError::NONE), | 191 GoogleServiceAuthError(GoogleServiceAuthError::NONE), |
| 192 "")); | 192 "")); |
| 193 flow->OnAuthFlowTitleChange(GetFinalTitle("thisisjustabunchofjunk")); | 193 flow->OnAuthFlowTitleChange(GetFinalTitle("thisisjustabunchofjunk")); |
| 194 } | 194 } |
| 195 | 195 |
| 196 TEST_F(IdentityGaiaWebAuthFlowTest, NoFragment) { | 196 TEST_F(IdentityGaiaWebAuthFlowTest, NoFragment) { |
| 197 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); | 197 std::unique_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); |
| 198 flow->Start(); | 198 flow->Start(); |
| 199 // This won't be recognized as an interesting title. | 199 // This won't be recognized as an interesting title. |
| 200 flow->OnAuthFlowTitleChange("Loading id.client.fake:/extension_id"); | 200 flow->OnAuthFlowTitleChange("Loading id.client.fake:/extension_id"); |
| 201 } | 201 } |
| 202 | 202 |
| 203 TEST_F(IdentityGaiaWebAuthFlowTest, Host) { | 203 TEST_F(IdentityGaiaWebAuthFlowTest, Host) { |
| 204 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); | 204 std::unique_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); |
| 205 flow->Start(); | 205 flow->Start(); |
| 206 // These won't be recognized as interesting titles. | 206 // These won't be recognized as interesting titles. |
| 207 flow->OnAuthFlowTitleChange( | 207 flow->OnAuthFlowTitleChange( |
| 208 "Loading id.client.fake://extension_id#access_token=fake_access_token"); | 208 "Loading id.client.fake://extension_id#access_token=fake_access_token"); |
| 209 flow->OnAuthFlowTitleChange( | 209 flow->OnAuthFlowTitleChange( |
| 210 "Loading id.client.fake://extension_id/#access_token=fake_access_token"); | 210 "Loading id.client.fake://extension_id/#access_token=fake_access_token"); |
| 211 flow->OnAuthFlowTitleChange( | 211 flow->OnAuthFlowTitleChange( |
| 212 "Loading " | 212 "Loading " |
| 213 "id.client.fake://host/extension_id/#access_token=fake_access_token"); | 213 "id.client.fake://host/extension_id/#access_token=fake_access_token"); |
| 214 } | 214 } |
| 215 | 215 |
| 216 TEST_F(IdentityGaiaWebAuthFlowTest, UbertokenFailure) { | 216 TEST_F(IdentityGaiaWebAuthFlowTest, UbertokenFailure) { |
| 217 set_ubertoken_error(GoogleServiceAuthError::CONNECTION_FAILED); | 217 set_ubertoken_error(GoogleServiceAuthError::CONNECTION_FAILED); |
| 218 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); | 218 std::unique_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); |
| 219 EXPECT_CALL( | 219 EXPECT_CALL( |
| 220 delegate_, | 220 delegate_, |
| 221 OnGaiaFlowFailure( | 221 OnGaiaFlowFailure( |
| 222 GaiaWebAuthFlow::SERVICE_AUTH_ERROR, | 222 GaiaWebAuthFlow::SERVICE_AUTH_ERROR, |
| 223 GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED), | 223 GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED), |
| 224 "")); | 224 "")); |
| 225 flow->Start(); | 225 flow->Start(); |
| 226 } | 226 } |
| 227 | 227 |
| 228 TEST_F(IdentityGaiaWebAuthFlowTest, AuthFlowFailure) { | 228 TEST_F(IdentityGaiaWebAuthFlowTest, AuthFlowFailure) { |
| 229 scoped_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); | 229 std::unique_ptr<TestGaiaWebAuthFlow> flow = CreateTestFlow(); |
| 230 flow->Start(); | 230 flow->Start(); |
| 231 EXPECT_CALL( | 231 EXPECT_CALL( |
| 232 delegate_, | 232 delegate_, |
| 233 OnGaiaFlowFailure( | 233 OnGaiaFlowFailure( |
| 234 GaiaWebAuthFlow::WINDOW_CLOSED, | 234 GaiaWebAuthFlow::WINDOW_CLOSED, |
| 235 GoogleServiceAuthError(GoogleServiceAuthError::NONE), | 235 GoogleServiceAuthError(GoogleServiceAuthError::NONE), |
| 236 "")); | 236 "")); |
| 237 flow->OnAuthFlowFailure(WebAuthFlow::WINDOW_CLOSED); | 237 flow->OnAuthFlowFailure(WebAuthFlow::WINDOW_CLOSED); |
| 238 } | 238 } |
| 239 | 239 |
| 240 } // namespace extensions | 240 } // namespace extensions |
| OLD | NEW |