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 |