| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/payments/payment_request_manager.h" | 5 #import "ios/chrome/browser/payments/payment_request_manager.h" |
| 6 | 6 |
| 7 #include "base/ios/ios_util.h" | 7 #include "base/ios/ios_util.h" |
| 8 #import "base/ios/weak_nsobject.h" | |
| 9 #import "base/mac/bind_objc_block.h" | 8 #import "base/mac/bind_objc_block.h" |
| 10 #include "base/mac/foundation_util.h" | 9 #include "base/mac/foundation_util.h" |
| 11 #include "base/mac/scoped_nsobject.h" | |
| 12 #include "base/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
| 13 #include "base/strings/sys_string_conversions.h" | 11 #include "base/strings/sys_string_conversions.h" |
| 14 #import "base/values.h" | 12 #import "base/values.h" |
| 15 #include "components/autofill/core/browser/autofill_manager.h" | 13 #include "components/autofill/core/browser/autofill_manager.h" |
| 16 #include "components/autofill/core/browser/personal_data_manager.h" | 14 #include "components/autofill/core/browser/personal_data_manager.h" |
| 17 #include "components/autofill/ios/browser/autofill_driver_ios.h" | 15 #include "components/autofill/ios/browser/autofill_driver_ios.h" |
| 18 #include "ios/chrome/browser/autofill/personal_data_manager_factory.h" | 16 #include "ios/chrome/browser/autofill/personal_data_manager_factory.h" |
| 19 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" | 17 #include "ios/chrome/browser/browser_state/chrome_browser_state.h" |
| 20 #import "ios/chrome/browser/payments/js_payment_request_manager.h" | 18 #import "ios/chrome/browser/payments/js_payment_request_manager.h" |
| 21 #include "ios/chrome/browser/payments/payment_request.h" | 19 #include "ios/chrome/browser/payments/payment_request.h" |
| 22 #import "ios/chrome/browser/payments/payment_request_coordinator.h" | 20 #import "ios/chrome/browser/payments/payment_request_coordinator.h" |
| 23 #include "ios/web/public/favicon_status.h" | 21 #include "ios/web/public/favicon_status.h" |
| 24 #include "ios/web/public/navigation_item.h" | 22 #include "ios/web/public/navigation_item.h" |
| 25 #include "ios/web/public/navigation_manager.h" | 23 #include "ios/web/public/navigation_manager.h" |
| 26 #include "ios/web/public/payments/payment_request.h" | 24 #include "ios/web/public/payments/payment_request.h" |
| 27 #include "ios/web/public/ssl_status.h" | 25 #include "ios/web/public/ssl_status.h" |
| 28 #import "ios/web/public/url_scheme_util.h" | 26 #import "ios/web/public/url_scheme_util.h" |
| 29 #import "ios/web/public/web_state/crw_web_view_proxy.h" | 27 #import "ios/web/public/web_state/crw_web_view_proxy.h" |
| 30 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h" | 28 #import "ios/web/public/web_state/js/crw_js_injection_receiver.h" |
| 31 #include "ios/web/public/web_state/url_verification_constants.h" | 29 #include "ios/web/public/web_state/url_verification_constants.h" |
| 32 #include "ios/web/public/web_state/web_state.h" | 30 #include "ios/web/public/web_state/web_state.h" |
| 33 #import "ios/web/public/web_state/web_state_observer_bridge.h" | 31 #import "ios/web/public/web_state/web_state_observer_bridge.h" |
| 34 | 32 |
| 33 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 34 #error "This file requires ARC support." |
| 35 #endif |
| 36 |
| 35 namespace { | 37 namespace { |
| 36 // Command prefix for injected JavaScript. | 38 // Command prefix for injected JavaScript. |
| 37 const std::string kCommandPrefix = "paymentRequest"; | 39 const std::string kCommandPrefix = "paymentRequest"; |
| 38 | 40 |
| 39 // Time interval between attempts to unblock the webview's JS event queue. | 41 // Time interval between attempts to unblock the webview's JS event queue. |
| 40 const NSTimeInterval kNoopInterval = 0.1; | 42 const NSTimeInterval kNoopInterval = 0.1; |
| 41 | 43 |
| 42 // Time interval before closing the UI if the page has not yet called | 44 // Time interval before closing the UI if the page has not yet called |
| 43 // PaymentResponse.complete(). | 45 // PaymentResponse.complete(). |
| 44 const NSTimeInterval kTimeoutInterval = 60.0; | 46 const NSTimeInterval kTimeoutInterval = 60.0; |
| 45 | 47 |
| 46 } // namespace | 48 } // namespace |
| 47 | 49 |
| 48 @interface PaymentRequestManager ()<CRWWebStateObserver, | 50 @interface PaymentRequestManager ()<CRWWebStateObserver, |
| 49 PaymentRequestCoordinatorDelegate> { | 51 PaymentRequestCoordinatorDelegate> { |
| 50 // View controller used to present the PaymentRequest view controller. | 52 // View controller used to present the PaymentRequest view controller. |
| 51 base::WeakNSObject<UIViewController> _baseViewController; | 53 __weak UIViewController* _baseViewController; |
| 52 | 54 |
| 53 // PersonalDataManager used to manage user credit cards and addresses. | 55 // PersonalDataManager used to manage user credit cards and addresses. |
| 54 autofill::PersonalDataManager* _personalDataManager; | 56 autofill::PersonalDataManager* _personalDataManager; |
| 55 | 57 |
| 56 // Object that owns an instance of web::PaymentRequest as provided by the page | 58 // Object that owns an instance of web::PaymentRequest as provided by the page |
| 57 // invoking the PaymentRequest API. Also caches credit cards and addresses | 59 // invoking the PaymentRequest API. Also caches credit cards and addresses |
| 58 // provided by the _personalDataManager and manages selected ones for the | 60 // provided by the _personalDataManager and manages selected ones for the |
| 59 // current PaymentRequest flow. | 61 // current PaymentRequest flow. |
| 60 std::unique_ptr<PaymentRequest> _paymentRequest; | 62 std::unique_ptr<PaymentRequest> _paymentRequest; |
| 61 | 63 |
| 62 // WebState for the tab this object is attached to. | 64 // WebState for the tab this object is attached to. |
| 63 web::WebState* _webState; | 65 web::WebState* _webState; |
| 64 | 66 |
| 65 // Observer for |_webState|. | 67 // Observer for |_webState|. |
| 66 std::unique_ptr<web::WebStateObserverBridge> _webStateObserver; | 68 std::unique_ptr<web::WebStateObserverBridge> _webStateObserver; |
| 67 | 69 |
| 68 // Object that manages JavaScript injection into the web view. | 70 // Object that manages JavaScript injection into the web view. |
| 69 base::WeakNSObject<JSPaymentRequestManager> _paymentRequestJsManager; | 71 __weak JSPaymentRequestManager* _paymentRequestJsManager; |
| 70 | 72 |
| 71 // Boolean to track if the current WebState is enabled (JS callback is set | 73 // Boolean to track if the current WebState is enabled (JS callback is set |
| 72 // up). | 74 // up). |
| 73 BOOL _webStateEnabled; | 75 BOOL _webStateEnabled; |
| 74 | 76 |
| 75 // Boolean to track if the script has been injected in the current page. This | 77 // Boolean to track if the script has been injected in the current page. This |
| 76 // is a faster check than asking the JS controller. | 78 // is a faster check than asking the JS controller. |
| 77 BOOL _isScriptInjected; | 79 BOOL _isScriptInjected; |
| 78 | 80 |
| 79 // True when close has been called and the PaymentRequest coordinator has | 81 // True when close has been called and the PaymentRequest coordinator has |
| 80 // been destroyed. | 82 // been destroyed. |
| 81 BOOL _closed; | 83 BOOL _closed; |
| 82 | 84 |
| 83 // Coordinator used to create and present the PaymentRequest view controller. | 85 // Coordinator used to create and present the PaymentRequest view controller. |
| 84 base::scoped_nsobject<PaymentRequestCoordinator> _paymentRequestCoordinator; | 86 PaymentRequestCoordinator* _paymentRequestCoordinator; |
| 85 | 87 |
| 86 // Timer used to periodically unblock the webview's JS event queue. | 88 // Timer used to periodically unblock the webview's JS event queue. |
| 87 base::scoped_nsobject<NSTimer> _unblockEventQueueTimer; | 89 NSTimer* _unblockEventQueueTimer; |
| 88 | 90 |
| 89 // Timer used to close the UI if the page does not call | 91 // Timer used to close the UI if the page does not call |
| 90 // PaymentResponse.complete() in a timely fashion. | 92 // PaymentResponse.complete() in a timely fashion. |
| 91 base::scoped_nsobject<NSTimer> _paymentResponseTimeoutTimer; | 93 NSTimer* _paymentResponseTimeoutTimer; |
| 92 } | 94 } |
| 93 | 95 |
| 94 // Synchronous method executed by -asynchronouslyEnablePaymentRequest: | 96 // Synchronous method executed by -asynchronouslyEnablePaymentRequest: |
| 95 - (void)doEnablePaymentRequest:(BOOL)enabled; | 97 - (void)doEnablePaymentRequest:(BOOL)enabled; |
| 96 | 98 |
| 97 // Initialize the PaymentRequest JavaScript. | 99 // Initialize the PaymentRequest JavaScript. |
| 98 - (void)initializeWebViewForPaymentRequest; | 100 - (void)initializeWebViewForPaymentRequest; |
| 99 | 101 |
| 100 // Handler for injected JavaScript callbacks. | 102 // Handler for injected JavaScript callbacks. |
| 101 - (BOOL)handleScriptCommand:(const base::DictionaryValue&)JSONCommand; | 103 - (BOOL)handleScriptCommand:(const base::DictionaryValue&)JSONCommand; |
| (...skipping 27 matching lines...) Expand all Loading... |
| 129 @implementation PaymentRequestManager | 131 @implementation PaymentRequestManager |
| 130 | 132 |
| 131 @synthesize enabled = _enabled; | 133 @synthesize enabled = _enabled; |
| 132 @synthesize webState = _webState; | 134 @synthesize webState = _webState; |
| 133 @synthesize browserState = _browserState; | 135 @synthesize browserState = _browserState; |
| 134 | 136 |
| 135 - (instancetype)initWithBaseViewController:(UIViewController*)viewController | 137 - (instancetype)initWithBaseViewController:(UIViewController*)viewController |
| 136 browserState: | 138 browserState: |
| 137 (ios::ChromeBrowserState*)browserState { | 139 (ios::ChromeBrowserState*)browserState { |
| 138 if ((self = [super init])) { | 140 if ((self = [super init])) { |
| 139 _baseViewController.reset(viewController); | 141 _baseViewController = viewController; |
| 140 | 142 |
| 141 _browserState = browserState; | 143 _browserState = browserState; |
| 142 | 144 |
| 143 _personalDataManager = | 145 _personalDataManager = |
| 144 autofill::PersonalDataManagerFactory::GetForBrowserState( | 146 autofill::PersonalDataManagerFactory::GetForBrowserState( |
| 145 browserState->GetOriginalChromeBrowserState()); | 147 browserState->GetOriginalChromeBrowserState()); |
| 146 } | 148 } |
| 147 return self; | 149 return self; |
| 148 } | 150 } |
| 149 | 151 |
| 150 - (instancetype)init { | 152 - (instancetype)init { |
| 151 NOTREACHED(); | 153 NOTREACHED(); |
| 152 return nil; | 154 return nil; |
| 153 } | 155 } |
| 154 | 156 |
| 155 - (void)setWebState:(web::WebState*)webState { | 157 - (void)setWebState:(web::WebState*)webState { |
| 156 [self disconnectWebState]; | 158 [self disconnectWebState]; |
| 157 if (webState) { | 159 if (webState) { |
| 158 _paymentRequestJsManager.reset( | 160 _paymentRequestJsManager = |
| 159 base::mac::ObjCCastStrict<JSPaymentRequestManager>( | 161 base::mac::ObjCCastStrict<JSPaymentRequestManager>( |
| 160 [webState->GetJSInjectionReceiver() | 162 [webState->GetJSInjectionReceiver() |
| 161 instanceOfClass:[JSPaymentRequestManager class]])); | 163 instanceOfClass:[JSPaymentRequestManager class]]); |
| 162 _webState = webState; | 164 _webState = webState; |
| 163 _webStateObserver.reset(new web::WebStateObserverBridge(webState, self)); | 165 _webStateObserver.reset(new web::WebStateObserverBridge(webState, self)); |
| 164 [self enableCurrentWebState]; | 166 [self enableCurrentWebState]; |
| 165 } else { | 167 } else { |
| 166 _webState = nullptr; | 168 _webState = nullptr; |
| 167 } | 169 } |
| 168 } | 170 } |
| 169 | 171 |
| 170 - (void)enablePaymentRequest:(BOOL)enabled { | 172 - (void)enablePaymentRequest:(BOOL)enabled { |
| 171 // Asynchronously enables PaymentRequest, so that some preferences | 173 // Asynchronously enables PaymentRequest, so that some preferences |
| 172 // (UIAccessibilityIsVoiceOverRunning(), for example) have time to synchronize | 174 // (UIAccessibilityIsVoiceOverRunning(), for example) have time to synchronize |
| 173 // with their own notifications. | 175 // with their own notifications. |
| 174 base::WeakNSObject<PaymentRequestManager> weakSelf(self); | 176 __weak PaymentRequestManager* weakSelf = self; |
| 175 dispatch_async(dispatch_get_main_queue(), ^{ | 177 dispatch_async(dispatch_get_main_queue(), ^{ |
| 176 [weakSelf doEnablePaymentRequest:enabled]; | 178 [weakSelf doEnablePaymentRequest:enabled]; |
| 177 }); | 179 }); |
| 178 } | 180 } |
| 179 | 181 |
| 180 - (void)doEnablePaymentRequest:(BOOL)enabled { | 182 - (void)doEnablePaymentRequest:(BOOL)enabled { |
| 181 BOOL changing = _enabled != enabled; | 183 BOOL changing = _enabled != enabled; |
| 182 if (changing) { | 184 if (changing) { |
| 183 if (!enabled) { | 185 if (!enabled) { |
| 184 [self dismissUI]; | 186 [self dismissUI]; |
| (...skipping 23 matching lines...) Expand all Loading... |
| 208 [self dismissUI]; | 210 [self dismissUI]; |
| 209 } | 211 } |
| 210 | 212 |
| 211 - (void)enableCurrentWebState { | 213 - (void)enableCurrentWebState { |
| 212 if (![self webState]) { | 214 if (![self webState]) { |
| 213 return; | 215 return; |
| 214 } | 216 } |
| 215 | 217 |
| 216 if (_enabled) { | 218 if (_enabled) { |
| 217 if (!_webStateEnabled) { | 219 if (!_webStateEnabled) { |
| 218 base::WeakNSObject<PaymentRequestManager> weakSelf(self); | 220 __weak PaymentRequestManager* weakSelf = self; |
| 219 auto callback = | 221 auto callback = base::BindBlockArc( |
| 220 base::BindBlock(^bool(const base::DictionaryValue& JSON, | 222 ^bool(const base::DictionaryValue& JSON, const GURL& originURL, |
| 221 const GURL& originURL, bool userIsInteracting) { | 223 bool userIsInteracting) { |
| 222 base::scoped_nsobject<PaymentRequestManager> strongSelf( | |
| 223 [weakSelf retain]); | |
| 224 // |originURL| and |userIsInteracting| aren't used. | 224 // |originURL| and |userIsInteracting| aren't used. |
| 225 return [strongSelf handleScriptCommand:JSON]; | 225 return [weakSelf handleScriptCommand:JSON]; |
| 226 }); | 226 }); |
| 227 [self webState]->AddScriptCommandCallback(callback, kCommandPrefix); | 227 [self webState]->AddScriptCommandCallback(callback, kCommandPrefix); |
| 228 | 228 |
| 229 _webStateEnabled = YES; | 229 _webStateEnabled = YES; |
| 230 } | 230 } |
| 231 } else { | 231 } else { |
| 232 [self disableCurrentWebState]; | 232 [self disableCurrentWebState]; |
| 233 } | 233 } |
| 234 } | 234 } |
| 235 | 235 |
| 236 - (void)disableCurrentWebState { | 236 - (void)disableCurrentWebState { |
| 237 if (_webStateEnabled) { | 237 if (_webStateEnabled) { |
| 238 _webState->RemoveScriptCommandCallback(kCommandPrefix); | 238 _webState->RemoveScriptCommandCallback(kCommandPrefix); |
| 239 _webStateEnabled = NO; | 239 _webStateEnabled = NO; |
| 240 } | 240 } |
| 241 } | 241 } |
| 242 | 242 |
| 243 - (void)disconnectWebState { | 243 - (void)disconnectWebState { |
| 244 if (_webState) { | 244 if (_webState) { |
| 245 _paymentRequestJsManager.reset(); | 245 _paymentRequestJsManager = nil; |
| 246 _webStateObserver.reset(); | 246 _webStateObserver.reset(); |
| 247 [self disableCurrentWebState]; | 247 [self disableCurrentWebState]; |
| 248 } | 248 } |
| 249 } | 249 } |
| 250 | 250 |
| 251 - (void)initializeWebViewForPaymentRequest { | 251 - (void)initializeWebViewForPaymentRequest { |
| 252 if (_enabled) { | 252 if (_enabled) { |
| 253 DCHECK(_webStateEnabled); | 253 DCHECK(_webStateEnabled); |
| 254 | 254 |
| 255 [_paymentRequestJsManager inject]; | 255 [_paymentRequestJsManager inject]; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 307 UIImage* pageFavicon = nil; | 307 UIImage* pageFavicon = nil; |
| 308 web::NavigationItem* navigationItem = | 308 web::NavigationItem* navigationItem = |
| 309 [self webState]->GetNavigationManager()->GetVisibleItem(); | 309 [self webState]->GetNavigationManager()->GetVisibleItem(); |
| 310 if (navigationItem && !navigationItem->GetFavicon().image.IsEmpty()) | 310 if (navigationItem && !navigationItem->GetFavicon().image.IsEmpty()) |
| 311 pageFavicon = navigationItem->GetFavicon().image.ToUIImage(); | 311 pageFavicon = navigationItem->GetFavicon().image.ToUIImage(); |
| 312 NSString* pageTitle = base::SysUTF16ToNSString([self webState]->GetTitle()); | 312 NSString* pageTitle = base::SysUTF16ToNSString([self webState]->GetTitle()); |
| 313 NSString* pageHost = | 313 NSString* pageHost = |
| 314 base::SysUTF8ToNSString([self webState]->GetLastCommittedURL().host()); | 314 base::SysUTF8ToNSString([self webState]->GetLastCommittedURL().host()); |
| 315 autofill::AutofillManager* autofillManager = | 315 autofill::AutofillManager* autofillManager = |
| 316 autofill::AutofillDriverIOS::FromWebState(_webState)->autofill_manager(); | 316 autofill::AutofillDriverIOS::FromWebState(_webState)->autofill_manager(); |
| 317 _paymentRequestCoordinator.reset([[PaymentRequestCoordinator alloc] | 317 _paymentRequestCoordinator = [[PaymentRequestCoordinator alloc] |
| 318 initWithBaseViewController:_baseViewController]); | 318 initWithBaseViewController:_baseViewController]; |
| 319 [_paymentRequestCoordinator setPaymentRequest:_paymentRequest.get()]; | 319 [_paymentRequestCoordinator setPaymentRequest:_paymentRequest.get()]; |
| 320 [_paymentRequestCoordinator setAutofillManager:autofillManager]; | 320 [_paymentRequestCoordinator setAutofillManager:autofillManager]; |
| 321 [_paymentRequestCoordinator setBrowserState:_browserState]; | 321 [_paymentRequestCoordinator setBrowserState:_browserState]; |
| 322 [_paymentRequestCoordinator setPageFavicon:pageFavicon]; | 322 [_paymentRequestCoordinator setPageFavicon:pageFavicon]; |
| 323 [_paymentRequestCoordinator setPageTitle:pageTitle]; | 323 [_paymentRequestCoordinator setPageTitle:pageTitle]; |
| 324 [_paymentRequestCoordinator setPageHost:pageHost]; | 324 [_paymentRequestCoordinator setPageHost:pageHost]; |
| 325 [_paymentRequestCoordinator setDelegate:self]; | 325 [_paymentRequestCoordinator setDelegate:self]; |
| 326 | 326 |
| 327 [_paymentRequestCoordinator start]; | 327 [_paymentRequestCoordinator start]; |
| 328 | 328 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 DLOG(ERROR) << "JS message parameter 'payment_details' is invalid"; | 369 DLOG(ERROR) << "JS message parameter 'payment_details' is invalid"; |
| 370 return NO; | 370 return NO; |
| 371 } | 371 } |
| 372 | 372 |
| 373 [_paymentRequestCoordinator updatePaymentDetails:paymentDetails]; | 373 [_paymentRequestCoordinator updatePaymentDetails:paymentDetails]; |
| 374 | 374 |
| 375 return YES; | 375 return YES; |
| 376 } | 376 } |
| 377 | 377 |
| 378 - (void)setUnblockEventQueueTimer { | 378 - (void)setUnblockEventQueueTimer { |
| 379 _unblockEventQueueTimer.reset( | 379 _unblockEventQueueTimer = |
| 380 [[NSTimer scheduledTimerWithTimeInterval:kNoopInterval | 380 [NSTimer scheduledTimerWithTimeInterval:kNoopInterval |
| 381 target:_paymentRequestJsManager | 381 target:_paymentRequestJsManager |
| 382 selector:@selector(executeNoop) | 382 selector:@selector(executeNoop) |
| 383 userInfo:nil | 383 userInfo:nil |
| 384 repeats:YES] retain]); | 384 repeats:YES]; |
| 385 } | 385 } |
| 386 | 386 |
| 387 - (void)setPaymentResponseTimeoutTimer { | 387 - (void)setPaymentResponseTimeoutTimer { |
| 388 _paymentResponseTimeoutTimer.reset( | 388 _paymentResponseTimeoutTimer = |
| 389 [[NSTimer scheduledTimerWithTimeInterval:kTimeoutInterval | 389 [NSTimer scheduledTimerWithTimeInterval:kTimeoutInterval |
| 390 target:self | 390 target:self |
| 391 selector:@selector(handleResponseComplete) | 391 selector:@selector(handleResponseComplete) |
| 392 userInfo:nil | 392 userInfo:nil |
| 393 repeats:NO] retain]); | 393 repeats:NO]; |
| 394 } | 394 } |
| 395 | 395 |
| 396 - (void)dismissUI { | 396 - (void)dismissUI { |
| 397 [_paymentRequestCoordinator stop]; | 397 [_paymentRequestCoordinator stop]; |
| 398 _paymentRequestCoordinator.reset(); | 398 _paymentRequestCoordinator = nil; |
| 399 } | 399 } |
| 400 | 400 |
| 401 - (BOOL)webStateContentIsSecureHTML { | 401 - (BOOL)webStateContentIsSecureHTML { |
| 402 if (![self webState]) { | 402 if (![self webState]) { |
| 403 return NO; | 403 return NO; |
| 404 } | 404 } |
| 405 | 405 |
| 406 if (!web::UrlHasWebScheme([self webState]->GetLastCommittedURL()) || | 406 if (!web::UrlHasWebScheme([self webState]->GetLastCommittedURL()) || |
| 407 ![self webState]->ContentIsHTML()) { | 407 ![self webState]->ContentIsHTML()) { |
| 408 return NO; | 408 return NO; |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 450 - (void)webState:(web::WebState*)webState | 450 - (void)webState:(web::WebState*)webState |
| 451 didCommitNavigationWithDetails: | 451 didCommitNavigationWithDetails: |
| 452 (const web::LoadCommittedDetails&)load_details { | 452 (const web::LoadCommittedDetails&)load_details { |
| 453 [self dismissUI]; | 453 [self dismissUI]; |
| 454 _isScriptInjected = NO; | 454 _isScriptInjected = NO; |
| 455 [self enableCurrentWebState]; | 455 [self enableCurrentWebState]; |
| 456 [self initializeWebViewForPaymentRequest]; | 456 [self initializeWebViewForPaymentRequest]; |
| 457 } | 457 } |
| 458 | 458 |
| 459 @end | 459 @end |
| OLD | NEW |