123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524 |
- // Copyright 2014 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/web_view/shell/shell_view_controller.h"
- #import <MobileCoreServices/MobileCoreServices.h>
- #import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
- #import "ios/web_view/shell/shell_auth_service.h"
- #import "ios/web_view/shell/shell_autofill_delegate.h"
- #import "ios/web_view/shell/shell_translation_delegate.h"
- #import "ios/web_view/shell/shell_trusted_vault_provider.h"
- #if !defined(__has_feature) || !__has_feature(objc_arc)
- #error "This file requires ARC support."
- #endif
- // Externed accessibility identifier.
- NSString* const kWebViewShellBackButtonAccessibilityLabel = @"Back";
- NSString* const kWebViewShellForwardButtonAccessibilityLabel = @"Forward";
- NSString* const kWebViewShellAddressFieldAccessibilityLabel = @"Address field";
- NSString* const kWebViewShellJavaScriptDialogTextFieldAccessibilityIdentifier =
- @"WebViewShellJavaScriptDialogTextFieldAccessibilityIdentifier";
- @interface ShellViewController () <CWVAutofillDataManagerObserver,
- CWVDownloadTaskDelegate,
- CWVLeakCheckServiceObserver,
- CWVNavigationDelegate,
- CWVUIDelegate,
- CWVScriptCommandHandler,
- CWVSyncControllerDelegate,
- UIScrollViewDelegate,
- UITextFieldDelegate>
- // Header containing navigation buttons and |field|.
- @property(nonatomic, strong) UIView* headerBackgroundView;
- // Header containing navigation buttons and |field|.
- @property(nonatomic, strong) UIView* headerContentView;
- // Button to navigate backwards.
- @property(nonatomic, strong) UIButton* backButton;
- // Button to navigate forwards.
- @property(nonatomic, strong) UIButton* forwardButton;
- // Button that either refresh the page or stops the page load.
- @property(nonatomic, strong) UIButton* reloadOrStopButton;
- // Button that shows the menu
- @property(nonatomic, strong) UIButton* menuButton;
- // Text field used for navigating to URLs.
- @property(nonatomic, strong) UITextField* field;
- // Container for |webView|.
- @property(nonatomic, strong) UIView* contentView;
- // Handles the autofill of the content displayed in |webView|.
- @property(nonatomic, strong) ShellAutofillDelegate* autofillDelegate;
- // Handles the translation of the content displayed in |webView|.
- @property(nonatomic, strong) ShellTranslationDelegate* translationDelegate;
- // The on-going download task if any.
- @property(nonatomic, strong, nullable) CWVDownloadTask* downloadTask;
- // The path to a local file which the download task is writing to.
- @property(nonatomic, strong, nullable) NSString* downloadFilePath;
- // A controller to show a "Share" menu for the downloaded file.
- @property(nonatomic, strong, nullable)
- UIDocumentInteractionController* documentInteractionController;
- // Service that provides authentication to ChromeWebView.
- @property(nonatomic, strong) ShellAuthService* authService;
- // Provides trusted vault functions to ChromeWebView.
- @property(nonatomic, strong) ShellTrustedVaultProvider* trustedVaultProvider;
- // The newly opened popup windows e.g., by JavaScript function "window.open()",
- // HTML "<a target='_blank'>".
- @property(nonatomic, strong) NSMutableArray<CWVWebView*>* popupWebViews;
- // A list of active leak checks. These map to a list of passwords since
- // you can have multiple passwords that map to the same canonical leak check.
- @property(nonatomic, strong)
- NSMutableDictionary<CWVLeakCheckCredential*, NSMutableArray<CWVPassword*>*>*
- pendingLeakChecks;
- - (void)back;
- - (void)forward;
- - (void)reloadOrStop;
- // Disconnects and release the |webView|.
- - (void)removeWebView;
- // Resets translate settings back to default.
- - (void)resetTranslateSettings;
- @end
- @implementation ShellViewController
- @synthesize autofillDelegate = _autofillDelegate;
- @synthesize backButton = _backButton;
- @synthesize contentView = _contentView;
- @synthesize field = _field;
- @synthesize forwardButton = _forwardButton;
- @synthesize reloadOrStopButton = _reloadOrStopButton;
- @synthesize menuButton = _menuButton;
- @synthesize headerBackgroundView = _headerBackgroundView;
- @synthesize headerContentView = _headerContentView;
- @synthesize webView = _webView;
- @synthesize translationDelegate = _translationDelegate;
- @synthesize downloadTask = _downloadTask;
- @synthesize downloadFilePath = _downloadFilePath;
- @synthesize documentInteractionController = _documentInteractionController;
- @synthesize authService = _authService;
- @synthesize trustedVaultProvider = _trustedVaultProvider;
- @synthesize popupWebViews = _popupWebViews;
- @synthesize pendingLeakChecks = _pendingLeakChecks;
- - (void)viewDidLoad {
- [super viewDidLoad];
- self.popupWebViews = [[NSMutableArray alloc] init];
- // View creation.
- self.headerBackgroundView = [[UIView alloc] init];
- self.headerContentView = [[UIView alloc] init];
- self.contentView = [[UIView alloc] init];
- self.backButton = [[UIButton alloc] init];
- self.forwardButton = [[UIButton alloc] init];
- self.reloadOrStopButton = [[UIButton alloc] init];
- self.menuButton = [[UIButton alloc] init];
- self.field = [[UITextField alloc] init];
- // View hierarchy.
- [self.view addSubview:_headerBackgroundView];
- [self.view addSubview:_contentView];
- [_headerBackgroundView addSubview:_headerContentView];
- [_headerContentView addSubview:_backButton];
- [_headerContentView addSubview:_forwardButton];
- [_headerContentView addSubview:_reloadOrStopButton];
- [_headerContentView addSubview:_menuButton];
- [_headerContentView addSubview:_field];
- // Additional view setup.
- _headerBackgroundView.backgroundColor = [UIColor colorWithRed:66.0 / 255.0
- green:133.0 / 255.0
- blue:244.0 / 255.0
- alpha:1.0];
- [_backButton setImage:[UIImage imageNamed:@"ic_back"]
- forState:UIControlStateNormal];
- _backButton.tintColor = [UIColor whiteColor];
- [_backButton addTarget:self
- action:@selector(back)
- forControlEvents:UIControlEventTouchUpInside];
- [_backButton addTarget:self
- action:@selector(logBackStack)
- forControlEvents:UIControlEventTouchDragOutside];
- [_backButton setAccessibilityLabel:kWebViewShellBackButtonAccessibilityLabel];
- [_forwardButton setImage:[UIImage imageNamed:@"ic_forward"]
- forState:UIControlStateNormal];
- _forwardButton.tintColor = [UIColor whiteColor];
- [_forwardButton addTarget:self
- action:@selector(forward)
- forControlEvents:UIControlEventTouchUpInside];
- [_forwardButton addTarget:self
- action:@selector(logForwardStack)
- forControlEvents:UIControlEventTouchDragOutside];
- [_forwardButton
- setAccessibilityLabel:kWebViewShellForwardButtonAccessibilityLabel];
- _reloadOrStopButton.tintColor = [UIColor whiteColor];
- [_reloadOrStopButton addTarget:self
- action:@selector(reloadOrStop)
- forControlEvents:UIControlEventTouchUpInside];
- _menuButton.tintColor = [UIColor whiteColor];
- [_menuButton setImage:[UIImage imageNamed:@"ic_menu"]
- forState:UIControlStateNormal];
- [_menuButton addTarget:self
- action:@selector(showMainMenu)
- forControlEvents:UIControlEventTouchUpInside];
- _field.placeholder = @"Search or type URL";
- _field.backgroundColor = [UIColor whiteColor];
- _field.tintColor = _headerBackgroundView.backgroundColor;
- [_field setContentHuggingPriority:UILayoutPriorityDefaultLow - 1
- forAxis:UILayoutConstraintAxisHorizontal];
- _field.delegate = self;
- _field.layer.cornerRadius = 2.0;
- _field.keyboardType = UIKeyboardTypeWebSearch;
- _field.autocapitalizationType = UITextAutocapitalizationTypeNone;
- _field.clearButtonMode = UITextFieldViewModeWhileEditing;
- _field.autocorrectionType = UITextAutocorrectionTypeNo;
- UIView* spacerView = [[UIView alloc] init];
- spacerView.frame = CGRectMake(0, 0, 8, 8);
- _field.leftViewMode = UITextFieldViewModeAlways;
- _field.leftView = spacerView;
- // Constraints.
- _headerBackgroundView.translatesAutoresizingMaskIntoConstraints = NO;
- [NSLayoutConstraint activateConstraints:@[
- [_headerBackgroundView.topAnchor
- constraintEqualToAnchor:self.view.topAnchor],
- [_headerBackgroundView.leadingAnchor
- constraintEqualToAnchor:self.view.leadingAnchor],
- [_headerBackgroundView.trailingAnchor
- constraintEqualToAnchor:self.view.trailingAnchor],
- [_headerBackgroundView.bottomAnchor
- constraintEqualToAnchor:_headerContentView.bottomAnchor],
- ]];
- _headerContentView.translatesAutoresizingMaskIntoConstraints = NO;
- [NSLayoutConstraint activateConstraints:@[
- [_headerContentView.topAnchor
- constraintEqualToAnchor:_headerBackgroundView.safeAreaLayoutGuide
- .topAnchor],
- [_headerContentView.leadingAnchor
- constraintEqualToAnchor:_headerBackgroundView.safeAreaLayoutGuide
- .leadingAnchor],
- [_headerContentView.trailingAnchor
- constraintEqualToAnchor:_headerBackgroundView.safeAreaLayoutGuide
- .trailingAnchor],
- [_headerContentView.heightAnchor constraintEqualToConstant:56.0],
- ]];
- _contentView.translatesAutoresizingMaskIntoConstraints = NO;
- [NSLayoutConstraint activateConstraints:@[
- [_contentView.topAnchor
- constraintEqualToAnchor:_headerBackgroundView.bottomAnchor],
- [_contentView.leadingAnchor
- constraintEqualToAnchor:self.view.leadingAnchor],
- [_contentView.trailingAnchor
- constraintEqualToAnchor:self.view.trailingAnchor],
- [_contentView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
- ]];
- _backButton.translatesAutoresizingMaskIntoConstraints = NO;
- [NSLayoutConstraint activateConstraints:@[
- [_backButton.leadingAnchor
- constraintEqualToAnchor:_headerContentView.safeAreaLayoutGuide
- .leadingAnchor
- constant:16.0],
- [_backButton.centerYAnchor
- constraintEqualToAnchor:_headerContentView.centerYAnchor],
- ]];
- _forwardButton.translatesAutoresizingMaskIntoConstraints = NO;
- [NSLayoutConstraint activateConstraints:@[
- [_forwardButton.leadingAnchor
- constraintEqualToAnchor:_backButton.trailingAnchor
- constant:16.0],
- [_forwardButton.centerYAnchor
- constraintEqualToAnchor:_headerContentView.centerYAnchor],
- ]];
- _reloadOrStopButton.translatesAutoresizingMaskIntoConstraints = NO;
- [NSLayoutConstraint activateConstraints:@[
- [_reloadOrStopButton.leadingAnchor
- constraintEqualToAnchor:_forwardButton.trailingAnchor
- constant:16.0],
- [_reloadOrStopButton.centerYAnchor
- constraintEqualToAnchor:_headerContentView.centerYAnchor],
- ]];
- _menuButton.translatesAutoresizingMaskIntoConstraints = NO;
- [NSLayoutConstraint activateConstraints:@[
- [_menuButton.leadingAnchor
- constraintEqualToAnchor:_reloadOrStopButton.trailingAnchor
- constant:16.0],
- [_menuButton.centerYAnchor
- constraintEqualToAnchor:_headerContentView.centerYAnchor],
- ]];
- _field.translatesAutoresizingMaskIntoConstraints = NO;
- [NSLayoutConstraint activateConstraints:@[
- [_field.leadingAnchor constraintEqualToAnchor:_menuButton.trailingAnchor
- constant:16.0],
- [_field.centerYAnchor
- constraintEqualToAnchor:_headerContentView.centerYAnchor],
- [_field.trailingAnchor
- constraintEqualToAnchor:_headerContentView.safeAreaLayoutGuide
- .trailingAnchor
- constant:-16.0],
- [_field.heightAnchor constraintEqualToConstant:32.0],
- ]];
- [CWVWebView setUserAgentProduct:@"Dummy/1.0"];
- CWVWebView.chromeContextMenuEnabled = YES;
- _authService = [[ShellAuthService alloc] init];
- CWVSyncController.dataSource = _authService;
- _trustedVaultProvider =
- [[ShellTrustedVaultProvider alloc] initWithAuthService:_authService];
- CWVSyncController.trustedVaultProvider = _trustedVaultProvider;
- _pendingLeakChecks = [NSMutableDictionary dictionary];
- CWVWebViewConfiguration* configuration =
- [CWVWebViewConfiguration defaultConfiguration];
- [configuration.autofillDataManager addObserver:self];
- configuration.syncController.delegate = self;
- [configuration.leakCheckService addObserver:self];
- self.webView = [self createWebViewWithConfiguration:configuration];
- }
- - (void)applicationFinishedRestoringState {
- [super applicationFinishedRestoringState];
- // The scroll view is reset on state restoration. So the delegate must be
- // reassigned.
- self.webView.scrollView.delegate = self;
- }
- - (UIStatusBarStyle)preferredStatusBarStyle {
- return UIStatusBarStyleLightContent;
- }
- - (void)observeValueForKeyPath:(NSString*)keyPath
- ofObject:(id)object
- change:(NSDictionary<NSKeyValueChangeKey, id>*)change
- context:(void*)context {
- if ([keyPath isEqualToString:@"canGoBack"]) {
- _backButton.enabled = [_webView canGoBack];
- } else if ([keyPath isEqualToString:@"canGoForward"]) {
- _forwardButton.enabled = [_webView canGoForward];
- } else if ([keyPath isEqualToString:@"loading"]) {
- NSString* imageName = _webView.loading ? @"ic_stop" : @"ic_reload";
- [_reloadOrStopButton setImage:[UIImage imageNamed:imageName]
- forState:UIControlStateNormal];
- }
- }
- - (void)back {
- if ([_webView canGoBack]) {
- [_webView goBack];
- }
- }
- - (void)logBackStack {
- if (!_webView.canGoBack) {
- return;
- }
- CWVBackForwardList* list = _webView.backForwardList;
- CWVBackForwardListItemArray* backList = list.backList;
- for (size_t i = 0; i < backList.count; i++) {
- CWVBackForwardListItem* item = backList[i];
- NSLog(@"BackStack Item #%ld: <URL='%@', title='%@'>", i, item.URL,
- item.title);
- }
- }
- - (void)forward {
- if ([_webView canGoForward]) {
- [_webView goForward];
- }
- }
- - (void)logForwardStack {
- if (!_webView.canGoForward) {
- return;
- }
- CWVBackForwardList* list = _webView.backForwardList;
- CWVBackForwardListItemArray* forwardList = list.forwardList;
- for (size_t i = 0; i < forwardList.count; i++) {
- CWVBackForwardListItem* item = forwardList[i];
- NSLog(@"ForwardStack Item #%ld: <URL='%@', title='%@'>", i, item.URL,
- item.title);
- }
- }
- - (void)reloadOrStop {
- if (_webView.loading) {
- [_webView stopLoading];
- } else {
- [_webView reload];
- }
- }
- - (void)showAddressData {
- CWVAutofillDataManager* dataManager =
- _webView.configuration.autofillDataManager;
- [dataManager fetchProfilesWithCompletionHandler:^(
- NSArray<CWVAutofillProfile*>* _Nonnull profiles) {
- NSMutableArray<NSString*>* descriptions = [profiles
- valueForKey:NSStringFromSelector(@selector(debugDescription))];
- NSString* message = [descriptions componentsJoinedByString:@"\n\n"];
- UIAlertController* alertController = [self actionSheetWithTitle:@"Addresses"
- message:message];
- for (CWVAutofillProfile* profile in profiles) {
- NSString* title = [NSString
- stringWithFormat:@"Delete %@", @([profiles indexOfObject:profile])];
- UIAlertAction* action =
- [UIAlertAction actionWithTitle:title
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* theAction) {
- [dataManager deleteProfile:profile];
- }];
- [alertController addAction:action];
- }
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Done"
- style:UIAlertActionStyleCancel
- handler:nil]];
- [self presentViewController:alertController animated:YES completion:nil];
- }];
- }
- - (void)showCreditCardData {
- CWVAutofillDataManager* dataManager =
- _webView.configuration.autofillDataManager;
- [dataManager fetchCreditCardsWithCompletionHandler:^(
- NSArray<CWVCreditCard*>* _Nonnull creditCards) {
- NSMutableArray<NSString*>* descriptions = [creditCards
- valueForKey:NSStringFromSelector(@selector(debugDescription))];
- NSString* message = [descriptions componentsJoinedByString:@"\n\n"];
- UIAlertController* alertController =
- [self actionSheetWithTitle:@"Credit cards" message:message];
- __weak ShellViewController* weakSelf = self;
- [alertController
- addAction:[UIAlertAction
- actionWithTitle:@"Manage Google pay cards"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- __weak ShellViewController* strongSelf =
- weakSelf;
- NSString* URL;
- if ([CWVFlags sharedInstance]
- .usesSyncAndWalletSandbox) {
- URL = @"https://pay.sandbox.google.com/"
- @"payments/home#paymentMethods";
- } else {
- URL = @"https://pay.google.com/payments/"
- @"home#paymentMethods";
- }
- NSURLRequest* request = [NSURLRequest
- requestWithURL:[NSURL URLWithString:URL]];
- [strongSelf.webView loadRequest:request];
- }]];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Done"
- style:UIAlertActionStyleCancel
- handler:nil]];
- [self presentViewController:alertController animated:YES completion:nil];
- }];
- }
- - (void)showPasswordData {
- __weak ShellViewController* weakSelf = self;
- CWVAutofillDataManager* dataManager =
- _webView.configuration.autofillDataManager;
- [dataManager fetchPasswordsWithCompletionHandler:^(
- NSArray<CWVPassword*>* _Nonnull passwords) {
- NSMutableArray<NSString*>* descriptions = [NSMutableArray array];
- for (CWVPassword* password in passwords) {
- NSString* description = [NSString
- stringWithFormat:@"%@:\n%@", @([passwords indexOfObject:password]),
- password.debugDescription];
- [descriptions addObject:description];
- }
- NSString* message = [descriptions componentsJoinedByString:@"\n\n"];
- UIAlertController* alertController = [self actionSheetWithTitle:@"Passwords"
- message:message];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Add new"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf showAddNewPasswordDialog];
- }]];
- for (CWVPassword* password in passwords) {
- NSString* title = [NSString
- stringWithFormat:@"Select %@", @([passwords indexOfObject:password])];
- UIAlertAction* action =
- [UIAlertAction actionWithTitle:title
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* theAction) {
- [weakSelf showMenuForPassword:password];
- }];
- [alertController addAction:action];
- }
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Done"
- style:UIAlertActionStyleCancel
- handler:nil]];
- [self presentViewController:alertController animated:YES completion:nil];
- }];
- }
- - (void)showAddNewPasswordDialog {
- CWVAutofillDataManager* dataManager =
- _webView.configuration.autofillDataManager;
- UIAlertController* alertController =
- [UIAlertController alertControllerWithTitle:@"Add password"
- message:nil
- preferredStyle:UIAlertControllerStyleAlert];
- [alertController
- addTextFieldWithConfigurationHandler:^(UITextField* textField) {
- textField.placeholder = @"Username";
- }];
- [alertController
- addTextFieldWithConfigurationHandler:^(UITextField* textField) {
- textField.placeholder = @"Password";
- }];
- [alertController
- addTextFieldWithConfigurationHandler:^(UITextField* textField) {
- textField.placeholder = @"Site";
- }];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Cancel"
- style:UIAlertActionStyleCancel
- handler:nil]];
- __weak UIAlertController* weakAlertController = alertController;
- [alertController
- addAction:[UIAlertAction
- actionWithTitle:@"Done"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- NSString* username =
- weakAlertController.textFields[0].text;
- NSString* password =
- weakAlertController.textFields[1].text;
- NSString* site =
- weakAlertController.textFields[2].text;
- [dataManager addNewPasswordForUsername:username
- password:password
- site:site];
- }]];
- [self presentViewController:alertController animated:YES completion:nil];
- }
- - (void)showMenuForPassword:(CWVPassword*)password {
- UIAlertController* alertController =
- [self actionSheetWithTitle:password.title
- message:password.debugDescription];
- CWVAutofillDataManager* dataManager =
- _webView.configuration.autofillDataManager;
- __weak ShellViewController* weakSelf = self;
- UIAlertAction* update =
- [UIAlertAction actionWithTitle:@"Update"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* theAction) {
- [weakSelf showUpdateDialogForPassword:password];
- }];
- [alertController addAction:update];
- UIAlertAction* delete =
- [UIAlertAction actionWithTitle:@"Delete"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* theAction) {
- [dataManager deletePassword:password];
- }];
- [alertController addAction:delete];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Done"
- style:UIAlertActionStyleCancel
- handler:nil]];
- [self presentViewController:alertController animated:YES completion:nil];
- }
- - (void)showUpdateDialogForPassword:(CWVPassword*)password {
- CWVAutofillDataManager* dataManager =
- _webView.configuration.autofillDataManager;
- UIAlertController* alertController =
- [UIAlertController alertControllerWithTitle:password.title
- message:password.debugDescription
- preferredStyle:UIAlertControllerStyleAlert];
- [alertController
- addTextFieldWithConfigurationHandler:^(UITextField* textField) {
- textField.placeholder = @"New username";
- }];
- [alertController
- addTextFieldWithConfigurationHandler:^(UITextField* textField) {
- textField.placeholder = @"New password";
- }];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Cancel"
- style:UIAlertActionStyleCancel
- handler:nil]];
- __weak UIAlertController* weakAlertController = alertController;
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Done"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- NSString* newUsername =
- weakAlertController.textFields
- .firstObject.text;
- NSString* newPassword =
- weakAlertController.textFields
- .lastObject.text;
- [dataManager
- updatePassword:password
- newUsername:newUsername
- newPassword:newPassword];
- }]];
- [self presentViewController:alertController animated:YES completion:nil];
- }
- - (void)showSyncMenu {
- CWVSyncController* syncController = _webView.configuration.syncController;
- NSString* message = [NSString
- stringWithFormat:@"Passphrase required: %@\nTrusted vault keys required: "
- @"%@\nTrusted vault recoverability degraded: %@",
- @(syncController.passphraseNeeded),
- @(syncController.trustedVaultKeysRequired),
- @(syncController.trustedVaultRecoverabilityDegraded)];
- UIAlertController* alertController = [self actionSheetWithTitle:@"Sync menu"
- message:message];
- CWVIdentity* currentIdentity = syncController.currentIdentity;
- __weak ShellViewController* weakSelf = self;
- if (currentIdentity) {
- NSString* title = [NSString
- stringWithFormat:@"Stop syncing for %@", currentIdentity.email];
- [alertController
- addAction:[UIAlertAction
- actionWithTitle:title
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [syncController stopSyncAndClearIdentity];
- }]];
- if (syncController.passphraseNeeded) {
- [alertController
- addAction:[UIAlertAction
- actionWithTitle:@"Unlock using passphrase"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf showPassphraseUnlockAlert];
- }]];
- } else if (syncController.trustedVaultKeysRequired) {
- [alertController
- addAction:[UIAlertAction
- actionWithTitle:@"Fetch trusted vault keys"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf.trustedVaultProvider
- showFetchKeysFlowForIdentity:
- currentIdentity
- fromViewController:weakSelf];
- }]];
- } else if (syncController.trustedVaultRecoverabilityDegraded) {
- [alertController
- addAction:
- [UIAlertAction
- actionWithTitle:@"Fix degraded recoverability"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf.trustedVaultProvider
- showFixDegradedRecoverabilityFlowForIdentity:
- currentIdentity
- fromViewController:
- weakSelf];
- }]];
- }
- } else {
- for (CWVIdentity* identity in [_authService identities]) {
- NSString* title =
- [NSString stringWithFormat:@"Start sync with %@", identity.email];
- [alertController
- addAction:[UIAlertAction
- actionWithTitle:title
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [syncController
- startSyncWithIdentity:identity];
- }]];
- }
- NSString* sandboxTitle = [CWVFlags sharedInstance].usesSyncAndWalletSandbox
- ? @"Use production sync/wallet"
- : @"Use sandbox sync/wallet";
- [alertController
- addAction:[UIAlertAction actionWithTitle:sandboxTitle
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [CWVFlags sharedInstance]
- .usesSyncAndWalletSandbox ^= YES;
- }]];
- }
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Show autofill data"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf showAddressData];
- }]];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Show credit card data"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf showCreditCardData];
- }]];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Show password data"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf showPasswordData];
- }]];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Check leaked passwords"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf checkLeakedPasswords];
- }]];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Cancel"
- style:UIAlertActionStyleCancel
- handler:nil]];
- [self presentViewController:alertController animated:YES completion:nil];
- }
- - (void)showPassphraseUnlockAlert {
- UIAlertController* alertController =
- [UIAlertController alertControllerWithTitle:@"Unlock sync"
- message:@"Enter passphrase"
- preferredStyle:UIAlertControllerStyleAlert];
- __weak UIAlertController* weakAlertController = alertController;
- CWVSyncController* syncController = _webView.configuration.syncController;
- UIAlertAction* submit = [UIAlertAction
- actionWithTitle:@"Unlock"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- UITextField* textField =
- weakAlertController.textFields.firstObject;
- NSString* passphrase = textField.text;
- BOOL result = [syncController unlockWithPassphrase:passphrase];
- NSLog(@"Sync passphrase unlock result: %d", result);
- }];
- [alertController addAction:submit];
- UIAlertAction* cancel =
- [UIAlertAction actionWithTitle:@"Cancel"
- style:UIAlertActionStyleCancel
- handler:nil];
- [alertController addAction:cancel];
- [alertController
- addTextFieldWithConfigurationHandler:^(UITextField* textField) {
- textField.placeholder = @"passphrase";
- textField.keyboardType = UIKeyboardTypeDefault;
- }];
- [self presentViewController:alertController animated:YES completion:nil];
- }
- - (void)showMainMenu {
- UIAlertController* alertController = [self actionSheetWithTitle:@"Main menu"
- message:nil];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Cancel"
- style:UIAlertActionStyleCancel
- handler:nil]];
- __weak ShellViewController* weakSelf = self;
- // Toggles the incognito mode.
- NSString* incognitoActionTitle = _webView.configuration.persistent
- ? @"Enter incognito"
- : @"Exit incognito";
- [alertController
- addAction:[UIAlertAction actionWithTitle:incognitoActionTitle
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf toggleIncognito];
- }]];
- // Removes the web view from the view hierarchy, releases it, and recreates
- // the web view with the same configuration. This is for testing deallocation
- // and sharing configuration.
- [alertController
- addAction:[UIAlertAction
- actionWithTitle:@"Recreate web view"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- CWVWebViewConfiguration* configuration =
- weakSelf.webView.configuration;
- [weakSelf removeWebView];
- weakSelf.webView = [weakSelf
- createWebViewWithConfiguration:configuration];
- }]];
- // Developers can choose to use system or Chrome context menu in the shell
- // app. This will also recreate the web view.
- BOOL chromeContextMenuEnabled = CWVWebView.chromeContextMenuEnabled;
- NSString* contextMenuSwitchActionTitle = [NSString
- stringWithFormat:@"%@ Chrome context menu",
- chromeContextMenuEnabled ? @"Disable" : @"Enable"];
- [alertController
- addAction:[UIAlertAction
- actionWithTitle:contextMenuSwitchActionTitle
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- CWVWebView.chromeContextMenuEnabled =
- !chromeContextMenuEnabled;
- NSLog(@"Chrome context menu is %@ now.",
- !chromeContextMenuEnabled ? @"OFF" : @"ON");
- CWVWebViewConfiguration* configuration =
- weakSelf.webView.configuration;
- [weakSelf removeWebView];
- weakSelf.field.text = @"";
- weakSelf.webView = [weakSelf
- createWebViewWithConfiguration:configuration];
- }]];
- // Resets all translation settings to default values.
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Reset translate settings"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf resetTranslateSettings];
- }]];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Request translation offer"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf requestTranslationOffer];
- }]];
- // Shows sync menu.
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Sync menu"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf showSyncMenu];
- }]];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Show Certificate Details"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf showCertificateDetails];
- }]];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Evaluate JavaScript"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf showEvaluateJavaScriptUI];
- }]];
- if (self.downloadTask) {
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Cancel download"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [weakSelf.downloadTask cancel];
- }]];
- }
- [self presentViewController:alertController animated:YES completion:nil];
- }
- - (void)showCertificateDetails {
- CWVX509Certificate* certificate = [[_webView visibleSSLStatus] certificate];
- NSString* message;
- if (certificate) {
- message = [NSString stringWithFormat:@"Issuer: %@\nExpires: %@",
- certificate.issuerDisplayName,
- certificate.validExpiry];
- } else {
- message = @"No Certificate";
- }
- UIAlertController* alertController =
- [self actionSheetWithTitle:@"Certificate Details" message:message];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Done"
- style:UIAlertActionStyleCancel
- handler:nil]];
- [self presentViewController:alertController animated:YES completion:nil];
- }
- - (void)checkLeakedPasswords {
- CWVAutofillDataManager* dataManager =
- _webView.configuration.autofillDataManager;
- // Request a check for any password in autofill data manager that is not
- // currently being requested.
- [dataManager fetchPasswordsWithCompletionHandler:^(
- NSArray<CWVPassword*>* _Nonnull passwords) {
- NSMutableArray<CWVLeakCheckCredential*>* credentialsToCheck =
- [NSMutableArray array];
- for (CWVPassword* password in passwords) {
- CWVLeakCheckCredential* credential = [CWVLeakCheckCredential
- canonicalLeakCheckCredentialWithPassword:password];
- NSMutableArray<CWVPassword*>* passwordsForCredential =
- self.pendingLeakChecks[credential];
- if (!passwordsForCredential) {
- passwordsForCredential = [NSMutableArray array];
- self.pendingLeakChecks[credential] = passwordsForCredential;
- [credentialsToCheck addObject:credential];
- }
- [passwordsForCredential addObject:password];
- }
- NSLog(@"Checking leaks for %@ credentials.", @(credentialsToCheck.count));
- [self.webView.configuration.leakCheckService
- checkCredentials:credentialsToCheck];
- }];
- }
- - (void)showEvaluateJavaScriptUI {
- UIAlertController* alertController =
- [UIAlertController alertControllerWithTitle:@"Evaluate JavaScript"
- message:nil
- preferredStyle:UIAlertControllerStyleAlert];
- alertController.popoverPresentationController.sourceView = _menuButton;
- alertController.popoverPresentationController.sourceRect =
- CGRectMake(CGRectGetWidth(_menuButton.bounds) / 2,
- CGRectGetHeight(_menuButton.bounds), 1, 1);
- [alertController
- addTextFieldWithConfigurationHandler:^(UITextField* textField) {
- textField.placeholder = @"alert('Hello')";
- }];
- __weak UIAlertController* weakAlertController = alertController;
- __weak ShellViewController* weakSelf = self;
- [alertController
- addAction:[UIAlertAction
- actionWithTitle:@"Evaluate"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- NSString* javascript =
- weakAlertController.textFields[0].text;
- [weakSelf evaluateJavaScript:javascript];
- }]];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Cancel"
- style:UIAlertActionStyleCancel
- handler:nil]];
- [self presentViewController:alertController animated:YES completion:nil];
- }
- - (void)evaluateJavaScript:(NSString*)javascript {
- [self.webView
- evaluateJavaScript:javascript
- completion:^(id result, BOOL success) {
- NSString* formatString =
- success ? @"JavaScript evaluation finished with result: %@"
- : @"JavaScript evaluation FAILED with result: %@";
- NSLog(formatString, result);
- }];
- }
- - (void)resetTranslateSettings {
- CWVWebViewConfiguration* configuration =
- [CWVWebViewConfiguration defaultConfiguration];
- [configuration.preferences resetTranslationSettings];
- }
- - (void)requestTranslationOffer {
- BOOL offered = [_webView.translationController requestTranslationOffer];
- NSLog(@"Manual translation was offered: %d", offered);
- }
- - (void)toggleIncognito {
- BOOL wasPersistent = _webView.configuration.persistent;
- [self removeWebView];
- CWVWebViewConfiguration* newConfiguration =
- wasPersistent ? [CWVWebViewConfiguration nonPersistentConfiguration]
- : [CWVWebViewConfiguration defaultConfiguration];
- self.webView = [self createWebViewWithConfiguration:newConfiguration];
- }
- - (CWVWebView*)createWebViewWithConfiguration:
- (CWVWebViewConfiguration*)configuration {
- // Set a non empty CGRect to avoid DCHECKs that occur when a load happens
- // after state restoration, and before the view hierarchy is laid out for the
- // first time.
- // https://source.chromium.org/chromium/chromium/src/+/main:ios/web/web_state/ui/crw_web_request_controller.mm;l=518;drc=df887034106ef438611326745a7cd276eedd4953
- CGRect frame = CGRectMake(0, 0, 1, 1);
- CWVWebView* webView = [[CWVWebView alloc] initWithFrame:frame
- configuration:configuration];
- [_contentView addSubview:webView];
- // Gives a restoration identifier so that state restoration works.
- webView.restorationIdentifier = @"webView";
- // Configure delegates.
- webView.navigationDelegate = self;
- webView.UIDelegate = self;
- _translationDelegate = [[ShellTranslationDelegate alloc] init];
- webView.translationController.delegate = _translationDelegate;
- _autofillDelegate = [[ShellAutofillDelegate alloc] init];
- webView.autofillController.delegate = _autofillDelegate;
- webView.scrollView.delegate = self;
- // Constraints.
- webView.translatesAutoresizingMaskIntoConstraints = NO;
- [NSLayoutConstraint activateConstraints:@[
- [webView.topAnchor
- constraintEqualToAnchor:_contentView.safeAreaLayoutGuide.topAnchor],
- [webView.leadingAnchor
- constraintEqualToAnchor:_contentView.safeAreaLayoutGuide.leadingAnchor],
- [webView.trailingAnchor
- constraintEqualToAnchor:_contentView.safeAreaLayoutGuide
- .trailingAnchor],
- [webView.bottomAnchor
- constraintEqualToAnchor:_contentView.safeAreaLayoutGuide.bottomAnchor],
- ]];
- [webView addObserver:self
- forKeyPath:@"canGoBack"
- options:NSKeyValueObservingOptionNew |
- NSKeyValueObservingOptionInitial
- context:nil];
- [webView addObserver:self
- forKeyPath:@"canGoForward"
- options:NSKeyValueObservingOptionNew |
- NSKeyValueObservingOptionInitial
- context:nil];
- [webView addObserver:self
- forKeyPath:@"loading"
- options:NSKeyValueObservingOptionNew |
- NSKeyValueObservingOptionInitial
- context:nil];
- [webView addScriptCommandHandler:self commandPrefix:@"test"];
- [webView
- addMessageHandler:^(NSDictionary* payload) {
- NSLog(@"message handler payload received =\n%@", payload);
- }
- forCommand:@"messageHandlerCommand"];
- return webView;
- }
- - (void)removeWebView {
- [_webView removeFromSuperview];
- [_webView removeObserver:self forKeyPath:@"canGoBack"];
- [_webView removeObserver:self forKeyPath:@"canGoForward"];
- [_webView removeObserver:self forKeyPath:@"loading"];
- [_webView removeScriptCommandHandlerForCommandPrefix:@"test"];
- [_webView removeMessageHandlerForCommand:@"messageHandlerCommand"];
- _webView = nil;
- }
- - (void)dealloc {
- [_webView removeObserver:self forKeyPath:@"canGoBack"];
- [_webView removeObserver:self forKeyPath:@"canGoForward"];
- [_webView removeObserver:self forKeyPath:@"loading"];
- [_webView removeScriptCommandHandlerForCommandPrefix:@"test"];
- [_webView removeMessageHandlerForCommand:@"messageHandlerCommand"];
- }
- - (BOOL)textFieldShouldReturn:(UITextField*)field {
- NSURL* URL = [NSURL URLWithString:field.text];
- if (URL.scheme.length == 0) {
- NSString* enteredText = field.text;
- enteredText =
- [enteredText stringByAddingPercentEncodingWithAllowedCharacters:
- [NSCharacterSet URLQueryAllowedCharacterSet]];
- enteredText = [NSString
- stringWithFormat:@"https://www.google.com/search?q=%@", enteredText];
- URL = [NSURL URLWithString:enteredText];
- }
- NSURLRequest* request = [NSURLRequest requestWithURL:URL];
- [_webView loadRequest:request];
- [field resignFirstResponder];
- [self updateToolbar];
- return YES;
- }
- - (void)updateToolbar {
- // Do not update the URL if the text field is currently being edited.
- if ([_field isFirstResponder]) {
- return;
- }
- [_field setText:[[_webView visibleURL] absoluteString]];
- }
- - (UIAlertController*)actionSheetWithTitle:(nullable NSString*)title
- message:(nullable NSString*)message {
- UIAlertController* alertController = [UIAlertController
- alertControllerWithTitle:title
- message:message
- preferredStyle:UIAlertControllerStyleActionSheet];
- alertController.popoverPresentationController.sourceView = _menuButton;
- alertController.popoverPresentationController.sourceRect =
- CGRectMake(CGRectGetWidth(_menuButton.bounds) / 2,
- CGRectGetHeight(_menuButton.bounds), 1, 1);
- return alertController;
- }
- - (void)closePopupWebView {
- if (self.popupWebViews.count) {
- [self.popupWebViews.lastObject removeFromSuperview];
- [self.popupWebViews removeLastObject];
- }
- }
- #pragma mark CWVUIDelegate methods
- - (CWVWebView*)webView:(CWVWebView*)webView
- createWebViewWithConfiguration:(CWVWebViewConfiguration*)configuration
- forNavigationAction:(CWVNavigationAction*)action {
- NSLog(@"Create new CWVWebView for %@. User initiated? %@", action.request.URL,
- action.userInitiated ? @"Yes" : @"No");
- CWVWebView* newWebView = [self createWebViewWithConfiguration:configuration];
- [self.popupWebViews addObject:newWebView];
- UIButton* closeWindowButton = [[UIButton alloc] init];
- [closeWindowButton setImage:[UIImage imageNamed:@"ic_stop"]
- forState:UIControlStateNormal];
- closeWindowButton.tintColor = [UIColor blackColor];
- closeWindowButton.backgroundColor = [UIColor whiteColor];
- [closeWindowButton addTarget:self
- action:@selector(closePopupWebView)
- forControlEvents:UIControlEventTouchUpInside];
- [newWebView addSubview:closeWindowButton];
- closeWindowButton.translatesAutoresizingMaskIntoConstraints = NO;
- [NSLayoutConstraint activateConstraints:@[
- [closeWindowButton.topAnchor constraintEqualToAnchor:newWebView.topAnchor
- constant:16.0],
- [closeWindowButton.centerXAnchor
- constraintEqualToAnchor:newWebView.centerXAnchor],
- ]];
- return newWebView;
- }
- - (void)webViewDidClose:(CWVWebView*)webView {
- NSLog(@"webViewDidClose");
- }
- - (void)webView:(CWVWebView*)webView
- contextMenuConfigurationForElement:(CWVHTMLElement*)element
- completionHandler:(void (^)(UIContextMenuConfiguration*))
- completionHandler {
- void (^copyHandler)(UIAction*) = ^(UIAction* action) {
- NSDictionary* item = @{
- (NSString*)(UTTypeURL) : element.hyperlink.absoluteString,
- (NSString*)(UTTypeUTF8PlainText) : [element.hyperlink.absoluteString
- dataUsingEncoding:NSUTF8StringEncoding],
- };
- [[UIPasteboard generalPasteboard] setItems:@[ item ]];
- };
- UIContextMenuConfiguration* configuration = [UIContextMenuConfiguration
- configurationWithIdentifier:nil
- previewProvider:^{
- UIViewController* controller = [[UIViewController alloc] init];
- CGRect frame = CGRectMake(10, 200, 200, 21);
- UILabel* label = [[UILabel alloc] initWithFrame:frame];
- label.text = @"iOS13 Preview Page";
- [controller.view addSubview:label];
- return controller;
- }
- actionProvider:^(id _) {
- NSArray* actions = @[
- [UIAction actionWithTitle:@"Copy Link"
- image:nil
- identifier:nil
- handler:copyHandler],
- [UIAction actionWithTitle:@"Cancel"
- image:nil
- identifier:nil
- handler:^(id ignore){
- }]
- ];
- NSString* menuTitle =
- [NSString stringWithFormat:@"iOS13 Context Menu: %@",
- element.hyperlink.absoluteString];
- return [UIMenu menuWithTitle:menuTitle children:actions];
- }];
- completionHandler(configuration);
- }
- - (void)webView:(CWVWebView*)webView
- contextMenuWillCommitWithAnimator:
- (id<UIContextMenuInteractionCommitAnimating>)animator {
- NSLog(@"webView:contextMenuWillCommitWithAnimator:");
- }
- - (void)webView:(CWVWebView*)webView
- runJavaScriptAlertPanelWithMessage:(NSString*)message
- pageURL:(NSURL*)URL
- completionHandler:(void (^)(void))handler {
- UIAlertController* alert =
- [UIAlertController alertControllerWithTitle:nil
- message:message
- preferredStyle:UIAlertControllerStyleAlert];
- [alert addAction:[UIAlertAction actionWithTitle:@"Ok"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- handler();
- }]];
- [self presentViewController:alert animated:YES completion:nil];
- }
- - (void)webView:(CWVWebView*)webView
- runJavaScriptConfirmPanelWithMessage:(NSString*)message
- pageURL:(NSURL*)URL
- completionHandler:(void (^)(BOOL))handler {
- UIAlertController* alert =
- [UIAlertController alertControllerWithTitle:nil
- message:message
- preferredStyle:UIAlertControllerStyleAlert];
- [alert addAction:[UIAlertAction actionWithTitle:@"Ok"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- handler(YES);
- }]];
- [alert addAction:[UIAlertAction actionWithTitle:@"Cancel"
- style:UIAlertActionStyleCancel
- handler:^(UIAlertAction* action) {
- handler(NO);
- }]];
- [self presentViewController:alert animated:YES completion:nil];
- }
- - (void)webView:(CWVWebView*)webView
- runJavaScriptTextInputPanelWithPrompt:(NSString*)prompt
- defaultText:(NSString*)defaultText
- pageURL:(NSURL*)URL
- completionHandler:(void (^)(NSString*))handler {
- UIAlertController* alert =
- [UIAlertController alertControllerWithTitle:nil
- message:prompt
- preferredStyle:UIAlertControllerStyleAlert];
- [alert addTextFieldWithConfigurationHandler:^(UITextField* textField) {
- textField.text = defaultText;
- textField.accessibilityIdentifier =
- kWebViewShellJavaScriptDialogTextFieldAccessibilityIdentifier;
- }];
- __weak UIAlertController* weakAlert = alert;
- [alert addAction:[UIAlertAction
- actionWithTitle:@"Ok"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- NSString* textInput =
- weakAlert.textFields.firstObject.text;
- handler(textInput);
- }]];
- [alert addAction:[UIAlertAction actionWithTitle:@"Cancel"
- style:UIAlertActionStyleCancel
- handler:^(UIAlertAction* action) {
- handler(nil);
- }]];
- [self presentViewController:alert animated:YES completion:nil];
- }
- - (void)webView:(CWVWebView*)webView
- didLoadFavicons:(NSArray<CWVFavicon*>*)favIcons {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- }
- #pragma mark CWVNavigationDelegate methods
- - (BOOL)webView:(CWVWebView*)webView
- shouldStartLoadWithRequest:(NSURLRequest*)request
- navigationType:(CWVNavigationType)navigationType {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- return YES;
- }
- - (BOOL)webView:(CWVWebView*)webView
- shouldContinueLoadWithResponse:(NSURLResponse*)response
- forMainFrame:(BOOL)forMainFrame {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- return YES;
- }
- - (void)webViewDidStartNavigation:(CWVWebView*)webView {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- [self updateToolbar];
- }
- - (void)webViewDidCommitNavigation:(CWVWebView*)webView {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- [self updateToolbar];
- }
- - (void)webViewDidFinishNavigation:(CWVWebView*)webView {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- // TODO(crbug.com/679895): Add some visual indication that the page load has
- // finished.
- [self updateToolbar];
- }
- - (void)webView:(CWVWebView*)webView
- didFailNavigationWithError:(NSError*)error {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- [self updateToolbar];
- }
- - (void)webView:(CWVWebView*)webView
- handleSSLErrorWithHandler:(CWVSSLErrorHandler*)handler {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- [handler displayErrorPageWithHTML:handler.error.localizedDescription];
- if (!handler.overridable) {
- return;
- }
- UIAlertController* alertController =
- [self actionSheetWithTitle:@"SSL error encountered"
- message:@"Would you like to continue anyways?"];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Yes"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [handler overrideErrorAndReloadPage];
- }]];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Cancel"
- style:UIAlertActionStyleCancel
- handler:nil]];
- [self presentViewController:alertController animated:YES completion:nil];
- }
- - (void)webView:(CWVWebView*)webView
- handleLookalikeURLWithHandler:(CWVLookalikeURLHandler*)handler {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- NSString* html =
- [NSString stringWithFormat:@"%@ requested, did you mean %@?",
- handler.requestURL, handler.safeURL];
- [handler displayInterstitialPageWithHTML:html];
- UIAlertController* alertController =
- [self actionSheetWithTitle:@"Lookalike URL encountered"
- message:@"Choose how to proceed."];
- [alertController
- addAction:
- [UIAlertAction
- actionWithTitle:@"Proceed to request URL"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- CWVLookalikeURLHandlerDecision decision =
- CWVLookalikeURLHandlerDecisionProceedToRequestURL;
- [handler commitDecision:decision];
- }]];
- [alertController
- addAction:
- [UIAlertAction
- actionWithTitle:@"Proceed to safe URL"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [handler
- commitDecision:
- CWVLookalikeURLHandlerDecisionProceedToSafeURL];
- }]];
- [alertController
- addAction:
- [UIAlertAction
- actionWithTitle:@"Go back or close"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [handler
- commitDecision:
- CWVLookalikeURLHandlerDecisionGoBackOrClose];
- }]];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Cancel"
- style:UIAlertActionStyleCancel
- handler:nil]];
- [self presentViewController:alertController animated:YES completion:nil];
- }
- - (void)webView:(CWVWebView*)webView
- handleUnsafeURLWithHandler:(CWVUnsafeURLHandler*)handler {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- NSString* html =
- [NSString stringWithFormat:@"%@ requested %@ which might be unsafe.",
- handler.mainFrameURL, handler.requestURL];
- [handler displayInterstitialPageWithHTML:html];
- UIAlertController* alertController =
- [self actionSheetWithTitle:@"Unsafe URL encountered"
- message:@"Choose how to proceed."];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Proceed"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [handler proceed];
- }]];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Go back or close"
- style:UIAlertActionStyleDefault
- handler:^(UIAlertAction* action) {
- [handler goBack];
- }]];
- [alertController
- addAction:[UIAlertAction actionWithTitle:@"Cancel"
- style:UIAlertActionStyleCancel
- handler:nil]];
- [self presentViewController:alertController animated:YES completion:nil];
- }
- - (void)webViewWebContentProcessDidTerminate:(CWVWebView*)webView {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- }
- - (void)webView:(CWVWebView*)webView
- didRequestDownloadWithTask:(CWVDownloadTask*)task {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- self.downloadTask = task;
- NSString* documentDirectoryPath = NSSearchPathForDirectoriesInDomains(
- NSDocumentDirectory, NSUserDomainMask, YES)[0];
- self.downloadFilePath = [documentDirectoryPath
- stringByAppendingPathComponent:task.suggestedFileName];
- task.delegate = self;
- [task startDownloadToLocalFileAtPath:self.downloadFilePath];
- }
- #pragma mark CWVScriptCommandHandler
- - (BOOL)webView:(CWVWebView*)webView
- handleScriptCommand:(nonnull CWVScriptCommand*)command
- fromMainFrame:(BOOL)fromMainFrame {
- NSLog(@"%@ command.content=%@", NSStringFromSelector(_cmd), command.content);
- return YES;
- }
- #pragma mark CWVAutofillDataManagerObserver
- - (void)autofillDataManagerDataDidChange:
- (CWVAutofillDataManager*)autofillDataManager {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- }
- - (void)autofillDataManager:(CWVAutofillDataManager*)autofillDataManager
- didChangePasswordsByAdding:(NSArray<CWVPassword*>*)added
- updating:(NSArray<CWVPassword*>*)updated
- removing:(NSArray<CWVPassword*>*)removed {
- NSLog(@"%@: added %@, updated %@, and removed %@ passwords",
- NSStringFromSelector(_cmd), @(added.count), @(updated.count),
- @(removed.count));
- }
- #pragma mark CWVDownloadTaskDelegate
- - (void)downloadTask:(CWVDownloadTask*)downloadTask
- didFinishWithError:(nullable NSError*)error {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- if (!error) {
- NSURL* url = [NSURL fileURLWithPath:self.downloadFilePath];
- self.documentInteractionController =
- [UIDocumentInteractionController interactionControllerWithURL:url];
- [self.documentInteractionController presentOptionsMenuFromRect:CGRectZero
- inView:self.view
- animated:YES];
- }
- self.downloadTask = nil;
- self.downloadFilePath = nil;
- }
- - (void)downloadTaskProgressDidChange:(CWVDownloadTask*)downloadTask {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- }
- #pragma mark CWVSyncControllerDelegate
- - (void)syncControllerDidStartSync:(CWVSyncController*)syncController {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- }
- - (void)syncController:(CWVSyncController*)syncController
- didFailWithError:(NSError*)error {
- NSLog(@"%@:%@", NSStringFromSelector(_cmd), error);
- }
- - (void)syncControllerDidStopSync:(CWVSyncController*)syncController {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- }
- - (void)syncControllerDidUpdateState:(CWVSyncController*)syncController {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- }
- #pragma mark CWVLeakCheckServiceObserver
- - (void)leakCheckServiceDidChangeState:(CWVLeakCheckService*)leakCheckService {
- NSLog(@"%@:%d", NSStringFromSelector(_cmd), (int)leakCheckService.state);
- if (leakCheckService.state != CWVLeakCheckServiceStateRunning) {
- [self.pendingLeakChecks removeAllObjects];
- }
- }
- - (void)leakCheckService:(CWVLeakCheckService*)leakCheckService
- didCheckCredential:(CWVLeakCheckCredential*)credential
- isLeaked:(BOOL)isLeaked {
- NSMutableArray<CWVPassword*>* passwordsForCredential =
- [self.pendingLeakChecks objectForKey:credential];
- if (!passwordsForCredential) {
- NSLog(@"No passwords for CWVLeakCheckCredential!");
- return;
- }
- [self.pendingLeakChecks removeObjectForKey:credential];
- NSMutableArray<NSString*>* passwordDescriptions = [passwordsForCredential
- valueForKey:NSStringFromSelector(@selector(debugDescription))];
- NSString* passwordsDescription =
- [passwordDescriptions componentsJoinedByString:@"\n\n"];
- NSString* message = [NSString
- stringWithFormat:@"Leak check returned %@ for %@ passwords:\n%@",
- isLeaked ? @"LEAKED" : @"OK",
- @(passwordsForCredential.count), passwordsDescription];
- NSLog(@"%@", message);
- NSLog(@"%@ Leak checks remaining...", @(self.pendingLeakChecks.count));
- }
- #pragma mark UIScrollViewDelegate
- - (void)scrollViewWillBeginDragging:(UIScrollView*)scrollView {
- NSLog(@"%@", NSStringFromSelector(_cmd));
- }
- @end
|