Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 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 #import "ios/chrome/browser/passwords/password_controller.h" | 5 #import "ios/chrome/browser/passwords/password_controller.h" |
| 6 | 6 |
| 7 #import <Foundation/Foundation.h> | 7 #import <Foundation/Foundation.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/json/json_reader.h" | 12 #include "base/json/json_reader.h" |
| 13 #include "base/mac/bind_objc_block.h" | 13 #include "base/mac/bind_objc_block.h" |
| 14 #import "base/mac/scoped_nsobject.h" | |
| 15 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 16 #include "base/memory/ref_counted.h" | 15 #include "base/memory/ref_counted.h" |
| 17 #include "base/strings/sys_string_conversions.h" | 16 #include "base/strings/sys_string_conversions.h" |
| 18 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
| 19 #import "base/test/ios/wait_util.h" | 18 #import "base/test/ios/wait_util.h" |
| 20 #include "base/values.h" | 19 #include "base/values.h" |
| 21 #include "components/autofill/core/common/password_form_fill_data.h" | 20 #include "components/autofill/core/common/password_form_fill_data.h" |
| 22 #include "components/password_manager/core/browser/log_manager.h" | 21 #include "components/password_manager/core/browser/log_manager.h" |
| 23 #include "components/password_manager/core/browser/mock_password_store.h" | 22 #include "components/password_manager/core/browser/mock_password_store.h" |
| 24 #include "components/password_manager/core/browser/stub_password_manager_client. h" | 23 #include "components/password_manager/core/browser/stub_password_manager_client. h" |
| 25 #include "components/password_manager/core/common/password_manager_pref_names.h" | 24 #include "components/password_manager/core/common/password_manager_pref_names.h" |
| 26 #include "components/prefs/pref_registry_simple.h" | 25 #include "components/prefs/pref_registry_simple.h" |
| 27 #include "components/prefs/testing_pref_service.h" | 26 #include "components/prefs/testing_pref_service.h" |
| 28 #import "ios/chrome/browser/autofill/form_input_accessory_view_controller.h" | 27 #import "ios/chrome/browser/autofill/form_input_accessory_view_controller.h" |
| 29 #import "ios/chrome/browser/autofill/form_suggestion_controller.h" | 28 #import "ios/chrome/browser/autofill/form_suggestion_controller.h" |
| 30 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" | 29 #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" |
| 31 #import "ios/chrome/browser/passwords/js_password_manager.h" | 30 #import "ios/chrome/browser/passwords/js_password_manager.h" |
| 32 #import "ios/web/public/web_state/web_state.h" | 31 #import "ios/web/public/web_state/web_state.h" |
| 33 #import "ios/web/public/test/web_test_with_web_state.h" | 32 #import "ios/web/public/test/web_test_with_web_state.h" |
| 34 #import "ios/web/public/test/test_web_state.h" | 33 #import "ios/web/public/test/test_web_state.h" |
| 35 #include "testing/gmock/include/gmock/gmock.h" | 34 #include "testing/gmock/include/gmock/gmock.h" |
| 36 #include "testing/gtest/include/gtest/gtest.h" | 35 #include "testing/gtest/include/gtest/gtest.h" |
| 37 #include "testing/gtest_mac.h" | 36 #include "testing/gtest_mac.h" |
| 38 #import "third_party/ocmock/OCMock/OCMock.h" | 37 #import "third_party/ocmock/OCMock/OCMock.h" |
| 39 #import "third_party/ocmock/OCMock/OCPartialMockObject.h" | 38 #import "third_party/ocmock/OCMock/OCPartialMockObject.h" |
| 40 #include "url/gurl.h" | 39 #include "url/gurl.h" |
| 41 | 40 |
| 41 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
| 42 #error "This file requires ARC support." | |
| 43 #endif | |
| 44 | |
| 42 using autofill::PasswordForm; | 45 using autofill::PasswordForm; |
| 43 using autofill::PasswordFormFillData; | 46 using autofill::PasswordFormFillData; |
| 44 using testing::Return; | 47 using testing::Return; |
| 45 | 48 |
| 46 namespace { | 49 namespace { |
| 47 | 50 |
| 48 class MockWebState : public web::TestWebState { | 51 class MockWebState : public web::TestWebState { |
| 49 public: | 52 public: |
| 50 MOCK_CONST_METHOD0(GetBrowserState, web::BrowserState*(void)); | 53 MOCK_CONST_METHOD0(GetBrowserState, web::BrowserState*(void)); |
| 51 }; | 54 }; |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 78 | 81 |
| 79 // Methods not important for testing. | 82 // Methods not important for testing. |
| 80 void OnLogRouterAvailabilityChanged(bool router_can_be_used) override {} | 83 void OnLogRouterAvailabilityChanged(bool router_can_be_used) override {} |
| 81 void SetSuspended(bool suspended) override {} | 84 void SetSuspended(bool suspended) override {} |
| 82 }; | 85 }; |
| 83 | 86 |
| 84 // Creates PasswordController with the given |web_state| and a mock client | 87 // Creates PasswordController with the given |web_state| and a mock client |
| 85 // using the given |store|. If not null, |weak_client| is filled with a | 88 // using the given |store|. If not null, |weak_client| is filled with a |
| 86 // non-owning pointer to the created client. The created controller is | 89 // non-owning pointer to the created client. The created controller is |
| 87 // returned. | 90 // returned. |
| 88 base::scoped_nsobject<PasswordController> CreatePasswordController( | 91 PasswordController* CreatePasswordController( |
| 89 web::WebState* web_state, | 92 web::WebState* web_state, |
| 90 password_manager::PasswordStore* store, | 93 password_manager::PasswordStore* store, |
| 91 MockPasswordManagerClient** weak_client) { | 94 MockPasswordManagerClient** weak_client) { |
| 92 auto client = base::MakeUnique<MockPasswordManagerClient>(store); | 95 auto client = base::MakeUnique<MockPasswordManagerClient>(store); |
| 93 if (weak_client) | 96 if (weak_client) |
| 94 *weak_client = client.get(); | 97 *weak_client = client.get(); |
| 95 return base::scoped_nsobject<PasswordController>([[PasswordController alloc] | 98 return [[PasswordController alloc] initWithWebState:web_state |
| 96 initWithWebState:web_state | 99 passwordsUiDelegate:nil |
| 97 passwordsUiDelegate:nil | 100 client:std::move(client)]; |
| 98 client:std::move(client)]); | |
| 99 } | 101 } |
| 100 | 102 |
| 101 } // namespace | 103 } // namespace |
| 102 | 104 |
| 103 @interface PasswordController ( | 105 @interface PasswordController ( |
| 104 Testing)<CRWWebStateObserver, FormSuggestionProvider> | 106 Testing)<CRWWebStateObserver, FormSuggestionProvider> |
| 105 | 107 |
| 106 - (void)findPasswordFormsWithCompletionHandler: | 108 - (void)findPasswordFormsWithCompletionHandler: |
| 107 (void (^)(const std::vector<PasswordForm>&))completionHandler; | 109 (void (^)(const std::vector<PasswordForm>&))completionHandler; |
| 108 | 110 |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 122 @property(readonly) JsPasswordManager* passwordJsManager; | 124 @property(readonly) JsPasswordManager* passwordJsManager; |
| 123 | 125 |
| 124 @end | 126 @end |
| 125 | 127 |
| 126 // Real FormSuggestionController is wrapped to register the addition of | 128 // Real FormSuggestionController is wrapped to register the addition of |
| 127 // suggestions. | 129 // suggestions. |
| 128 @interface PasswordsTestSuggestionController : FormSuggestionController | 130 @interface PasswordsTestSuggestionController : FormSuggestionController |
| 129 | 131 |
| 130 @property(nonatomic, copy) NSArray* suggestions; | 132 @property(nonatomic, copy) NSArray* suggestions; |
| 131 | 133 |
| 132 - (void)dealloc; | |
| 133 | |
| 134 @end | 134 @end |
| 135 | 135 |
| 136 @implementation PasswordsTestSuggestionController | 136 @implementation PasswordsTestSuggestionController |
| 137 | 137 |
| 138 @synthesize suggestions = _suggestions; | 138 @synthesize suggestions = _suggestions; |
| 139 | 139 |
| 140 - (void)updateKeyboardWithSuggestions:(NSArray*)suggestions { | 140 - (void)updateKeyboardWithSuggestions:(NSArray*)suggestions { |
| 141 self.suggestions = suggestions; | 141 self.suggestions = suggestions; |
| 142 } | 142 } |
| 143 | 143 |
| 144 - (void)dealloc { | |
| 145 [_suggestions release]; | |
| 146 [super dealloc]; | |
| 147 } | |
| 148 | 144 |
| 149 @end | 145 @end |
| 150 | 146 |
| 151 class PasswordControllerTest : public web::WebTestWithWebState { | 147 class PasswordControllerTest : public web::WebTestWithWebState { |
| 152 public: | 148 public: |
| 153 PasswordControllerTest() | 149 PasswordControllerTest() |
| 154 : store_(new testing::NiceMock<password_manager::MockPasswordStore>()) {} | 150 : store_(new testing::NiceMock<password_manager::MockPasswordStore>()) {} |
| 155 | 151 |
| 156 ~PasswordControllerTest() override { store_->ShutdownOnUIThread(); } | 152 ~PasswordControllerTest() override { store_->ShutdownOnUIThread(); } |
| 157 | 153 |
| 158 void SetUp() override { | 154 void SetUp() override { |
| 159 web::WebTestWithWebState::SetUp(); | 155 web::WebTestWithWebState::SetUp(); |
| 160 passwordController_ = | 156 passwordController_ = |
| 161 CreatePasswordController(web_state(), store_.get(), nullptr); | 157 CreatePasswordController(web_state(), store_.get(), nullptr); |
| 162 @autoreleasepool { | 158 @autoreleasepool { |
| 163 // Make sure the temporary array is released after SetUp finishes, | 159 // Make sure the temporary array is released after SetUp finishes, |
| 164 // otherwise [passwordController_ suggestionProvider] will be retained | 160 // otherwise [passwordController_ suggestionProvider] will be retained |
| 165 // until PlatformTest teardown, at which point all Chrome objects are | 161 // until PlatformTest teardown, at which point all Chrome objects are |
| 166 // already gone and teardown may access invalid memory. | 162 // already gone and teardown may access invalid memory. |
| 167 suggestionController_.reset([[PasswordsTestSuggestionController alloc] | 163 suggestionController_ = [[PasswordsTestSuggestionController alloc] |
| 168 initWithWebState:web_state() | 164 initWithWebState:web_state() |
| 169 providers:@[ [passwordController_ suggestionProvider] ]]); | 165 providers:@[ [passwordController_ suggestionProvider] ]]; |
| 170 accessoryViewController_.reset([[FormInputAccessoryViewController alloc] | 166 accessoryViewController_ = [[FormInputAccessoryViewController alloc] |
| 171 initWithWebState:web_state() | 167 initWithWebState:web_state() |
| 172 providers:@[ [suggestionController_ accessoryViewProvider] ]]); | 168 providers:@[ [suggestionController_ accessoryViewProvider] ]]; |
| 173 } | 169 } |
| 174 } | 170 } |
| 175 | 171 |
| 176 protected: | 172 protected: |
| 177 // Helper method for PasswordControllerTest.DontFillReadonly. Tries to load | 173 // Helper method for PasswordControllerTest.DontFillReadonly. Tries to load |
| 178 // |html| and find and fill there a form with hard-coded form data. Returns | 174 // |html| and find and fill there a form with hard-coded form data. Returns |
| 179 // YES on success, NO otherwise. | 175 // YES on success, NO otherwise. |
| 180 BOOL BasicFormFill(NSString* html); | 176 BOOL BasicFormFill(NSString* html); |
| 181 | 177 |
| 182 // Retrieve the current suggestions from suggestionController_ sorted in | 178 // Retrieve the current suggestions from suggestionController_ sorted in |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 211 [OCMockObject partialMockForObject:original_manager]; | 207 [OCMockObject partialMockForObject:original_manager]; |
| 212 __block int failure_count = 0; | 208 __block int failure_count = 0; |
| 213 void (^fail_invocation)(NSInvocation*) = ^(NSInvocation* invocation) { | 209 void (^fail_invocation)(NSInvocation*) = ^(NSInvocation* invocation) { |
| 214 if (failure_count >= target_failure_count) { | 210 if (failure_count >= target_failure_count) { |
| 215 [failing_manager stop]; | 211 [failing_manager stop]; |
| 216 [invocation invokeWithTarget:original_manager]; | 212 [invocation invokeWithTarget:original_manager]; |
| 217 } else { | 213 } else { |
| 218 ++failure_count; | 214 ++failure_count; |
| 219 // Fetches the completion handler from |invocation| and calls it with | 215 // Fetches the completion handler from |invocation| and calls it with |
| 220 // failure status. | 216 // failure status. |
| 221 void (^completionHandler)(BOOL); | 217 __unsafe_unretained void (^completionHandler)(BOOL); |
|
Eugene But (OOO till 7-30)
2016/12/07 18:21:35
Should this be __weal?
stkhapugin
2016/12/08 10:15:46
Actually, no - grabbing arguments from NSInvocatio
| |
| 222 const NSInteger kArgOffset = 1; | 218 const NSInteger kArgOffset = 1; |
| 223 const NSInteger kCompletionHandlerArgIndex = 4; | 219 const NSInteger kCompletionHandlerArgIndex = 4; |
| 224 [invocation getArgument:&completionHandler | 220 [invocation getArgument:&completionHandler |
| 225 atIndex:(kCompletionHandlerArgIndex + kArgOffset)]; | 221 atIndex:(kCompletionHandlerArgIndex + kArgOffset)]; |
| 226 ASSERT_TRUE(completionHandler); | 222 ASSERT_TRUE(completionHandler); |
| 227 completionHandler(NO); | 223 completionHandler(NO); |
| 228 } | 224 } |
| 229 }; | 225 }; |
| 230 [[[failing_manager stub] andDo:fail_invocation] | 226 [[[failing_manager stub] andDo:fail_invocation] |
| 231 fillPasswordForm:[OCMArg any] | 227 fillPasswordForm:[OCMArg any] |
| 232 withUsername:[OCMArg any] | 228 withUsername:[OCMArg any] |
| 233 password:[OCMArg any] | 229 password:[OCMArg any] |
| 234 completionHandler:[OCMArg any]]; | 230 completionHandler:[OCMArg any]]; |
| 235 } | 231 } |
| 236 | 232 |
| 237 // SuggestionController for testing. | 233 // SuggestionController for testing. |
| 238 base::scoped_nsobject<PasswordsTestSuggestionController> | 234 PasswordsTestSuggestionController* suggestionController_; |
| 239 suggestionController_; | |
| 240 | 235 |
| 241 // FormInputAccessoryViewController for testing. | 236 // FormInputAccessoryViewController for testing. |
| 242 base::scoped_nsobject<FormInputAccessoryViewController> | 237 FormInputAccessoryViewController* accessoryViewController_; |
| 243 accessoryViewController_; | |
| 244 | 238 |
| 245 // PasswordController for testing. | 239 // PasswordController for testing. |
| 246 base::scoped_nsobject<PasswordController> passwordController_; | 240 PasswordController* passwordController_; |
| 247 | 241 |
| 248 scoped_refptr<password_manager::PasswordStore> store_; | 242 scoped_refptr<password_manager::PasswordStore> store_; |
| 249 }; | 243 }; |
| 250 | 244 |
| 251 struct PasswordFormTestData { | 245 struct PasswordFormTestData { |
| 252 const char* const page_location; | 246 const char* const page_location; |
| 253 const char* const json_string; | 247 const char* const json_string; |
| 254 const char* const expected_origin; | 248 const char* const expected_origin; |
| 255 const char* const expected_action; | 249 const char* const expected_action; |
| 256 const char* const expected_username_element; | 250 const char* const expected_username_element; |
| (...skipping 1002 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1259 // The test case below does not need the heavy fixture from above, but it | 1253 // The test case below does not need the heavy fixture from above, but it |
| 1260 // needs to use MockWebState. | 1254 // needs to use MockWebState. |
| 1261 TEST(PasswordControllerTestSimple, SaveOnNonHTMLLandingPage) { | 1255 TEST(PasswordControllerTestSimple, SaveOnNonHTMLLandingPage) { |
| 1262 TestChromeBrowserState::Builder builder; | 1256 TestChromeBrowserState::Builder builder; |
| 1263 std::unique_ptr<TestChromeBrowserState> browser_state(builder.Build()); | 1257 std::unique_ptr<TestChromeBrowserState> browser_state(builder.Build()); |
| 1264 MockWebState web_state; | 1258 MockWebState web_state; |
| 1265 ON_CALL(web_state, GetBrowserState()) | 1259 ON_CALL(web_state, GetBrowserState()) |
| 1266 .WillByDefault(testing::Return(browser_state.get())); | 1260 .WillByDefault(testing::Return(browser_state.get())); |
| 1267 | 1261 |
| 1268 MockPasswordManagerClient* weak_client = nullptr; | 1262 MockPasswordManagerClient* weak_client = nullptr; |
| 1269 base::scoped_nsobject<PasswordController> passwordController = | 1263 PasswordController* passwordController = |
| 1270 CreatePasswordController(&web_state, nullptr, &weak_client); | 1264 CreatePasswordController(&web_state, nullptr, &weak_client); |
| 1271 static_cast<TestingPrefServiceSimple*>(weak_client->GetPrefs()) | 1265 static_cast<TestingPrefServiceSimple*>(weak_client->GetPrefs()) |
| 1272 ->registry() | 1266 ->registry() |
| 1273 ->RegisterBooleanPref( | 1267 ->RegisterBooleanPref( |
| 1274 password_manager::prefs::kPasswordManagerSavingEnabled, true); | 1268 password_manager::prefs::kPasswordManagerSavingEnabled, true); |
| 1275 | 1269 |
| 1276 // Use a mock LogManager to detect that OnPasswordFormsRendered has been | 1270 // Use a mock LogManager to detect that OnPasswordFormsRendered has been |
| 1277 // called. TODO(crbug.com/598672): this is a hack, we should modularize the | 1271 // called. TODO(crbug.com/598672): this is a hack, we should modularize the |
| 1278 // code better to allow proper unit-testing. | 1272 // code better to allow proper unit-testing. |
| 1279 MockLogManager log_manager; | 1273 MockLogManager log_manager; |
| 1280 EXPECT_CALL(log_manager, IsLoggingActive()).WillRepeatedly(Return(true)); | 1274 EXPECT_CALL(log_manager, IsLoggingActive()).WillRepeatedly(Return(true)); |
| 1281 EXPECT_CALL(log_manager, | 1275 EXPECT_CALL(log_manager, |
| 1282 LogSavePasswordProgress( | 1276 LogSavePasswordProgress( |
| 1283 "Message: \"PasswordManager::OnPasswordFormsRendered\"\n")); | 1277 "Message: \"PasswordManager::OnPasswordFormsRendered\"\n")); |
| 1284 EXPECT_CALL(log_manager, | 1278 EXPECT_CALL(log_manager, |
| 1285 LogSavePasswordProgress(testing::Ne( | 1279 LogSavePasswordProgress(testing::Ne( |
| 1286 "Message: \"PasswordManager::OnPasswordFormsRendered\"\n"))) | 1280 "Message: \"PasswordManager::OnPasswordFormsRendered\"\n"))) |
| 1287 .Times(testing::AnyNumber()); | 1281 .Times(testing::AnyNumber()); |
| 1288 EXPECT_CALL(*weak_client, GetLogManager()) | 1282 EXPECT_CALL(*weak_client, GetLogManager()) |
| 1289 .WillRepeatedly(Return(&log_manager)); | 1283 .WillRepeatedly(Return(&log_manager)); |
| 1290 | 1284 |
| 1291 web_state.SetContentIsHTML(false); | 1285 web_state.SetContentIsHTML(false); |
| 1292 web_state.SetCurrentURL(GURL("https://example.com")); | 1286 web_state.SetCurrentURL(GURL("https://example.com")); |
| 1293 [passwordController webStateDidLoadPage:&web_state]; | 1287 [passwordController webStateDidLoadPage:&web_state]; |
| 1294 } | 1288 } |
| OLD | NEW |