0

Revert "[iOS][MF] Secure filling"

This reverts commit 555dcba9d6.

Reason for revert: probably the cause of compile failures (e.g. https://ci.chromium.org/p/chromium/builders/luci.chromium.ci/ios-uirefresh-simulator/3246 )

Original change's description:
> [iOS][MF] Secure filling
> 
> Observe the last focused field to validate it is secure before filling a password
> 
> Bug: 878388
> Cq-Include-Trybots: luci.chromium.try:ios-simulator-cronet;luci.chromium.try:ios-simulator-full-configs
> Change-Id: Ide4407ea51b315c68c50fa010f256cde93f5eb26
> Reviewed-on: https://chromium-review.googlesource.com/1221217
> Commit-Queue: Javier Ernesto Flores Robles <javierrobles@chromium.org>
> Reviewed-by: Moe Ahmadi <mahmadi@chromium.org>
> Reviewed-by: Gauthier Ambard <gambard@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#593194}

TBR=mahmadi@chromium.org,gambard@chromium.org,javierrobles@chromium.org

Change-Id: Ie272d2622baeda172a802feaf552b1771e436bc5
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 878388
Cq-Include-Trybots: luci.chromium.try:ios-simulator-cronet;luci.chromium.try:ios-simulator-full-configs
Reviewed-on: https://chromium-review.googlesource.com/1238822
Reviewed-by: Frank Liberato <liberato@chromium.org>
Commit-Queue: Frank Liberato <liberato@chromium.org>
Cr-Commit-Position: refs/heads/master@{#593212}
This commit is contained in:
Frank Liberato
2018-09-21 16:27:26 +00:00
committed by Commit Bot
parent 701e5734ec
commit 6f92ed837d
8 changed files with 22 additions and 378 deletions

@ -9,7 +9,6 @@
#import "ios/chrome/browser/autofill/form_input_accessory_view_controller.h"
#import "ios/chrome/browser/ui/autofill/form_input_accessory_mediator.h"
#import "ios/chrome/browser/ui/autofill/manual_fill/manual_fill_accessory_view_controller.h"
#import "ios/chrome/browser/ui/autofill/manual_fill/manual_fill_injection_handler.h"
#import "ios/chrome/browser/ui/autofill/manual_fill/password_coordinator.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
@ -31,11 +30,6 @@
@property(nonatomic, strong)
ManualFillAccessoryViewController* manualFillAccessoryViewController;
// The object in charge of interacting with the web view. Used to fill the data
// in the forms.
@property(nonatomic, strong)
ManualFillInjectionHandler* manualFillInjectionHandler;
// The WebStateList for this instance. Used to instantiate the child
// coordinators lazily.
@property(nonatomic, assign) WebStateList* webStateList;
@ -50,7 +44,6 @@
@synthesize manualFillAccessoryViewController =
_manualFillAccessoryViewController;
@synthesize webStateList = _webStateList;
@synthesize manualFillInjectionHandler = _manualFillInjectionHandler;
- (instancetype)initWithBaseViewController:(UIViewController*)viewController
browserState:
@ -63,9 +56,6 @@
if (self) {
_webStateList = webStateList;
_manualFillInjectionHandler =
[[ManualFillInjectionHandler alloc] initWithWebStateList:webStateList];
_formInputAccessoryViewController =
[[FormInputAccessoryViewController alloc] init];
@ -101,8 +91,7 @@
[[ManualFillPasswordCoordinator alloc]
initWithBaseViewController:self.baseViewController
browserState:self.browserState
webStateList:self.webStateList
injectionHandler:self.manualFillInjectionHandler];
webStateList:self.webStateList];
[self.formInputAccessoryViewController
presentView:passwordCoordinator.viewController.view];
[self.childCoordinators addObject:passwordCoordinator];

@ -8,8 +8,6 @@ source_set("manual_fill") {
sources = [
"credential_password_form.h",
"credential_password_form.mm",
"form_observer_helper.h",
"form_observer_helper.mm",
"manual_fill_injection_handler.h",
"manual_fill_injection_handler.mm",
"password_coordinator.h",
@ -21,7 +19,6 @@ source_set("manual_fill") {
"//base",
"//components/autofill/core/common",
"//components/autofill/ios/browser",
"//components/autofill/ios/form_util",
"//components/keyed_service/core:core",
"//components/password_manager/core/browser",
"//ios/chrome/app/strings:ios_strings_grit",
@ -86,20 +83,13 @@ source_set("unit_tests") {
sources = [
"credential_password_form_unittest.mm",
"credential_unittest.mm",
"form_observer_helper_unittest.mm",
]
deps = [
":manual_fill",
":manual_fill_ui",
"//base:base",
"//components/autofill/core/common:common",
"//components/autofill/ios/form_util:form_util",
"//components/autofill/ios/form_util:test_support",
"//ios/chrome/browser/web_state_list:test_support",
"//ios/chrome/browser/web_state_list:web_state_list",
"//ios/web/public/test/fakes:fakes",
"//testing/gtest:gtest",
"//third_party/ocmock:ocmock",
"//url:url",
]
}

@ -1,28 +0,0 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_FORM_OBSERVER_HELPER_H_
#define IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_FORM_OBSERVER_HELPER_H_
#import <Foundation/Foundation.h>
@protocol FormActivityObserver;
class WebStateList;
// Convenience object to observe updates in forms. It abstracts all the logic
// to observe a web state list and its web states.
@interface FormObserverHelper : NSObject
// The delegate interested in the form activity.
@property(nonatomic, weak) id<FormActivityObserver> delegate;
// Returns a fresh object observing the active web state for the passed list.
- (instancetype)initWithWebStateList:(WebStateList*)webStateList;
// Not available. Use |initWithWebStateList:|.
- (instancetype)init NS_UNAVAILABLE;
@end
#endif // IOS_CHROME_BROWSER_UI_AUTOFILL_MANUAL_FILL_FORM_OBSERVER_HELPER_H_

@ -1,123 +0,0 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/ui/autofill/manual_fill/form_observer_helper.h"
#import "components/autofill/ios/form_util/form_activity_observer_bridge.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
#include "ios/web/public/web_state/web_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface FormObserverHelper ()<FormActivityObserver, WebStateListObserving>
// The WebStateList this instance is observing in order to update the
// active WebState.
@property(nonatomic, assign) WebStateList* webStateList;
// The WebState this instance is observing. Can be nullptr.
@property(nonatomic, assign) web::WebState* webState;
@end
@implementation FormObserverHelper {
// Bridge to observe the web state list from Objective-C.
std::unique_ptr<WebStateListObserverBridge> _webStateListObserver;
// Bridge to observe form activity in |_webState|.
std::unique_ptr<autofill::FormActivityObserverBridge>
_formActivityObserverBridge;
}
@synthesize delegate = _delegate;
- (instancetype)initWithWebStateList:(WebStateList*)webStateList {
DCHECK(webStateList);
self = [super init];
if (self) {
_webStateList = webStateList;
_webStateListObserver = std::make_unique<WebStateListObserverBridge>(self);
_webStateList->AddObserver(_webStateListObserver.get());
web::WebState* webState = webStateList->GetActiveWebState();
if (webState) {
_webState = webState;
_formActivityObserverBridge =
std::make_unique<autofill::FormActivityObserverBridge>(_webState,
self);
}
}
return self;
}
- (void)dealloc {
if (_webState) {
_formActivityObserverBridge.reset();
_webState = nullptr;
}
if (_webStateList) {
_webStateList->RemoveObserver(_webStateListObserver.get());
_webStateListObserver.reset();
_webStateList = nullptr;
}
_formActivityObserverBridge.reset();
}
#pragma mark - FormActivityObserver
- (void)webState:(web::WebState*)webState
didRegisterFormActivity:(const autofill::FormActivityParams&)params
inFrame:(web::WebFrame*)frame {
if ([self.delegate respondsToSelector:@selector
(webState:didRegisterFormActivity:inFrame:)]) {
[self.delegate webState:webState
didRegisterFormActivity:params
inFrame:frame];
}
}
- (void)webState:(web::WebState*)webState
didSubmitDocumentWithFormNamed:(const std::string&)formName
hasUserGesture:(BOOL)hasUserGesture
formInMainFrame:(BOOL)formInMainFrame
inFrame:(web::WebFrame*)frame {
if ([self.delegate respondsToSelector:@selector
(webState:didSubmitDocumentWithFormNamed:hasUserGesture
:formInMainFrame:inFrame:)]) {
[self.delegate webState:webState
didSubmitDocumentWithFormNamed:formName
hasUserGesture:hasUserGesture
formInMainFrame:formInMainFrame
inFrame:frame];
}
}
#pragma mark - CRWWebStateListObserver
- (void)webStateList:(WebStateList*)webStateList
didChangeActiveWebState:(web::WebState*)newWebState
oldWebState:(web::WebState*)oldWebState
atIndex:(int)atIndex
reason:(int)reason {
self.webState = newWebState;
}
#pragma mark - Setters
// Sets the new web state and detaches from the previous web state.
- (void)setWebState:(web::WebState*)webState {
if (_webState) {
_formActivityObserverBridge.reset();
}
_webState = webState;
if (_webState) {
_formActivityObserverBridge =
std::make_unique<autofill::FormActivityObserverBridge>(_webState, self);
}
}
@end

@ -1,154 +0,0 @@
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/ui/autofill/manual_fill/form_observer_helper.h"
#import "components/autofill/ios/form_util/form_activity_observer_bridge.h"
#include "components/autofill/ios/form_util/form_activity_params.h"
#include "components/autofill/ios/form_util/test_form_activity_tab_helper.h"
#import "ios/chrome/browser/web_state_list/fake_web_state_list_delegate.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/chrome/browser/web_state_list/web_state_opener.h"
#import "ios/web/public/test/fakes/test_web_state.h"
#include "testing/platform_test.h"
#import "third_party/ocmock/OCMock/OCMock.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
class ManualFillFormObserverHelperiOSTest : public PlatformTest {
public:
ManualFillFormObserverHelperiOSTest()
: web_state_list_(&web_state_list_delegate_) {}
~ManualFillFormObserverHelperiOSTest() override {}
void SetUp() override {
PlatformTest::SetUp();
_helper =
[[FormObserverHelper alloc] initWithWebStateList:&web_state_list_];
_mockDelegate = OCMProtocolMock(@protocol(FormActivityObserver));
_helper.delegate = _mockDelegate;
}
void TearDown() override {
_helper = nil;
_mockDelegate = nil;
PlatformTest::TearDown();
}
protected:
FakeWebStateListDelegate web_state_list_delegate_;
WebStateList web_state_list_;
FormObserverHelper* _helper;
OCMockObject<FormActivityObserver>* _mockDelegate;
std::unique_ptr<web::TestWebState> CreateWebState(const char* url) {
auto test_web_state = std::make_unique<web::TestWebState>();
test_web_state->SetCurrentURL(GURL(url));
return test_web_state;
}
void AppendNewWebState(const char* url) {
AppendNewWebState(url, WebStateOpener());
}
void AppendNewWebState(const char* url, WebStateOpener opener) {
web_state_list_.InsertWebState(WebStateList::kInvalidIndex,
CreateWebState(url),
WebStateList::INSERT_NO_FLAGS, opener);
}
private:
DISALLOW_COPY_AND_ASSIGN(ManualFillFormObserverHelperiOSTest);
};
// Tests that an observer is correctly created and set up.
TEST_F(ManualFillFormObserverHelperiOSTest, Creation) {}
// Test that the observer delegates one active web state callbacks.
TEST_F(ManualFillFormObserverHelperiOSTest, ObservesWebState) {
AppendNewWebState("https://example.com");
web_state_list_.ActivateWebStateAt(0);
autofill::FormActivityParams params;
params.form_name = "form";
params.field_name = "field";
params.field_identifier = "field_id";
params.field_type = "text";
params.type = "blur";
params.value = "value";
params.input_missing = false;
OCMExpect([_mockDelegate
webState:static_cast<web::WebState*>([OCMArg anyPointer])
didRegisterFormActivity:params
inFrame:static_cast<web::WebFrame*>(
[OCMArg anyPointer])]);
autofill::TestFormActivityTabHelper test_form_activity_tab_helper(
web_state_list_.GetActiveWebState());
test_form_activity_tab_helper.FormActivityRegistered(nullptr, params);
@try {
[_mockDelegate verify];
} @catch (NSException* exception) {
ADD_FAILURE();
}
}
// Test that the observer delegates the callbacks with multiple active web
// state.
TEST_F(ManualFillFormObserverHelperiOSTest, ObservesMultipleWebStates) {
AppendNewWebState("https://example.com");
AppendNewWebState("https://chrome.com");
autofill::TestFormActivityTabHelper test_form_activity_tab_helper0(
web_state_list_.GetWebStateAt(0));
autofill::TestFormActivityTabHelper test_form_activity_tab_helper1(
web_state_list_.GetWebStateAt(1));
web_state_list_.ActivateWebStateAt(0);
autofill::FormActivityParams params;
params.form_name = "form";
params.field_name = "field";
params.field_identifier = "field_id";
params.field_type = "text";
params.type = "focus";
params.value = "value";
params.input_missing = false;
@try {
OCMExpect([_mockDelegate
webState:static_cast<web::WebState*>([OCMArg anyPointer])
didRegisterFormActivity:params
inFrame:static_cast<web::WebFrame*>(
[OCMArg anyPointer])]);
test_form_activity_tab_helper0.FormActivityRegistered(nullptr, params);
[_mockDelegate verify];
web_state_list_.ActivateWebStateAt(1);
OCMExpect([_mockDelegate
webState:static_cast<web::WebState*>([OCMArg anyPointer])
didRegisterFormActivity:params
inFrame:static_cast<web::WebFrame*>(
[OCMArg anyPointer])]);
test_form_activity_tab_helper1.FormActivityRegistered(nullptr, params);
[_mockDelegate verify];
web_state_list_.ActivateWebStateAt(0);
OCMExpect([_mockDelegate
webState:static_cast<web::WebState*>([OCMArg anyPointer])
didRegisterFormActivity:params
inFrame:static_cast<web::WebFrame*>(
[OCMArg anyPointer])]);
test_form_activity_tab_helper0.FormActivityRegistered(nullptr, params);
[_mockDelegate verify];
} @catch (NSException* exception) {
ADD_FAILURE();
}
}

@ -6,75 +6,47 @@
#include "base/mac/foundation_util.h"
#import "components/autofill/ios/browser/js_suggestion_manager.h"
#import "components/autofill/ios/form_util/form_activity_observer_bridge.h"
#include "components/autofill/ios/form_util/form_activity_params.h"
#import "ios/chrome/browser/autofill/form_input_accessory_view_handler.h"
#import "ios/chrome/browser/ui/autofill/manual_fill/form_observer_helper.h"
#import "ios/chrome/browser/web_state_list/web_state_list.h"
#import "ios/web/public/web_state/js/crw_js_injection_receiver.h"
#include "ios/web/public/web_state/web_state.h"
#include "url/gurl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
@interface ManualFillInjectionHandler ()<FormActivityObserver>
// The object in charge of listening to form events and reporting back.
@property(nonatomic, strong) FormObserverHelper* formHelper;
@interface ManualFillInjectionHandler ()
// The WebStateList with the relevant active web state for the injection.
@property(nonatomic, assign) WebStateList* webStateList;
// Convenience getter for the current injection reciever.
@property(nonatomic, readonly) CRWJSInjectionReceiver* injectionReceiver;
// Convenience getter for the current suggestion manager.
@property(nonatomic, readonly) JsSuggestionManager* suggestionManager;
// The WebStateList with the relevant active web state for the injection.
@property(nonatomic, assign) WebStateList* webStateList;
// YES if the last focused element is secure within its web frame. To be secure
// means it has a password type, the web is https and the URL can trusted.
@property(nonatomic, assign) BOOL lastActiveElementIsSecure;
@end
@implementation ManualFillInjectionHandler
@synthesize formHelper = _formHelper;
@synthesize lastActiveElementIsSecure = _lastActiveElementIsSecure;
@synthesize webStateList = _webStateList;
- (instancetype)initWithWebStateList:(WebStateList*)webStateList {
self = [super init];
if (self) {
_webStateList = webStateList;
_formHelper =
[[FormObserverHelper alloc] initWithWebStateList:webStateList];
_formHelper.delegate = self;
}
return self;
}
#pragma mark - ManualFillViewDelegate
- (void)userDidPickContent:(NSString*)content isSecure:(BOOL)isSecure {
if (isSecure && !self.lastActiveElementIsSecure) {
if (isSecure) {
// TODO:(https://crbug.com/878388) implement secure manual fill for
// passwords.
return;
}
[self fillLastSelectedFieldWithString:content];
}
#pragma mark - FormActivityObserver
- (void)webState:(web::WebState*)webState
didRegisterFormActivity:(const autofill::FormActivityParams&)params
inFrame:(web::WebFrame*)frame {
if (params.type != "focus") {
return;
}
web::URLVerificationTrustLevel trustLevel;
const GURL pageURL(webState->GetCurrentURL(&trustLevel));
self.lastActiveElementIsSecure = YES;
if (trustLevel != web::URLVerificationTrustLevel::kAbsolute ||
!pageURL.SchemeIs(url::kHttpsScheme) || !webState->ContentIsHTML() ||
params.field_type != "password") {
self.lastActiveElementIsSecure = NO;
}
}
#pragma mark - Getters
- (CRWJSInjectionReceiver*)injectionReceiver {

@ -7,7 +7,6 @@
#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
@class ManualFillInjectionHandler;
class WebStateList;
// Creates and manages a view controller to present passwords to the user.
@ -18,13 +17,12 @@ class WebStateList;
// The view controller of this coordinator.
@property(nonatomic, readonly) UIViewController* viewController;
// Creates a coordinator that uses a |viewController|, |browserState|,
// |webStateList| and an |injectionHandler|.
- (instancetype)
initWithBaseViewController:(UIViewController*)viewController
browserState:(ios::ChromeBrowserState*)browserState
webStateList:(WebStateList*)webStateList
injectionHandler:(ManualFillInjectionHandler*)injectionHandler;
// Creates a coordinator that uses a |viewController| a |browserState| and
// a |webStateList|.
- (instancetype)initWithBaseViewController:(UIViewController*)viewController
browserState:
(ios::ChromeBrowserState*)browserState
webStateList:(WebStateList*)webStateList;
// Unavailable, use -initWithBaseViewController:browserState:webStateList:.
- (instancetype)initWithBaseViewController:(UIViewController*)viewController

@ -39,22 +39,22 @@
@implementation ManualFillPasswordCoordinator
@synthesize allPasswordsViewController = _allPasswordsViewController;
@synthesize manualFillInjectionHandler = _manualFillInjectionHandler;
@synthesize passwordMediator = _passwordMediator;
@synthesize passwordViewController = _passwordViewController;
@synthesize manualFillInjectionHandler = _manualFillInjectionHandler;
- (instancetype)
initWithBaseViewController:(UIViewController*)viewController
browserState:(ios::ChromeBrowserState*)browserState
webStateList:(WebStateList*)webStateList
injectionHandler:(ManualFillInjectionHandler*)injectionHandler {
- (instancetype)initWithBaseViewController:(UIViewController*)viewController
browserState:
(ios::ChromeBrowserState*)browserState
webStateList:(WebStateList*)webStateList {
self = [super initWithBaseViewController:viewController
browserState:browserState];
if (self) {
_passwordViewController =
[[PasswordViewController alloc] initWithSearchController:nil];
_manualFillInjectionHandler = injectionHandler;
_manualFillInjectionHandler =
[[ManualFillInjectionHandler alloc] initWithWebStateList:webStateList];
auto passwordStore = IOSChromePasswordStoreFactory::GetForBrowserState(
browserState, ServiceAccessType::EXPLICIT_ACCESS);