| // Copyright 2017 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #import "ios/web_view/internal/web_view_web_state_policy_decider.h" |
| |
| #import "ios/web_view/internal/cwv_navigation_action_internal.h" |
| #import "ios/web_view/internal/cwv_navigation_response_internal.h" |
| #import "ios/web_view/internal/cwv_navigation_type_internal.h" |
| #import "ios/web_view/public/cwv_navigation_delegate.h" |
| #import "ios/web_view/public/cwv_web_view.h" |
| |
| namespace ios_web_view { |
| |
| WebViewWebStatePolicyDecider::WebViewWebStatePolicyDecider( |
| web::WebState* web_state, |
| CWVWebView* web_view) |
| : web::WebStatePolicyDecider(web_state), web_view_(web_view) {} |
| |
| void WebViewWebStatePolicyDecider::ShouldAllowRequest( |
| NSURLRequest* request, |
| web::WebStatePolicyDecider::RequestInfo request_info, |
| web::WebStatePolicyDecider::PolicyDecisionCallback callback) { |
| id<CWVNavigationDelegate> delegate = web_view_.navigationDelegate; |
| |
| // CWVNavigationType is virtually the same as ui::PageTransition. But |
| // ui::PageTransition must not be used in the public API of //ios/web_view |
| // because its API must be in pure Objective-C. It cannot use a type defined |
| // in a C++ header //ui/base/page_transition_types.h. |
| CWVNavigationType navigation_type = |
| CWVNavigationTypeFromPageTransition(request_info.transition_type); |
| |
| if ([delegate respondsToSelector:@selector |
| (webView:decidePolicyForNavigationAction:decisionHandler:)]) { |
| CWVNavigationAction* navigation_action = [[CWVNavigationAction alloc] |
| initWithRequest:request |
| userInitiated:request_info.is_user_initiated |
| navigationType:navigation_type]; |
| |
| __block web::WebStatePolicyDecider::PolicyDecisionCallback block_callback = |
| std::move(callback); |
| |
| [delegate webView:web_view_ |
| decidePolicyForNavigationAction:navigation_action |
| decisionHandler:^(CWVNavigationActionPolicy policy) { |
| switch (policy) { |
| case CWVNavigationActionPolicyCancel: |
| std::move(block_callback) |
| .Run(web::WebStatePolicyDecider:: |
| PolicyDecision::Cancel()); |
| break; |
| case CWVNavigationActionPolicyAllow: |
| std::move(block_callback) |
| .Run(web::WebStatePolicyDecider:: |
| PolicyDecision::Allow()); |
| break; |
| } |
| }]; |
| return; |
| } |
| |
| // Deprected API, will consider using asynchronous API |
| // `-[CWVNavigationDelegate |
| // webView:decidePolicyForNavigationAction:decisionHandler:]` first. |
| if ([delegate respondsToSelector:@selector |
| (webView:shouldStartLoadWithRequest:navigationType:)]) { |
| BOOL allow = [delegate webView:web_view_ |
| shouldStartLoadWithRequest:request |
| navigationType:navigation_type]; |
| if (!allow) { |
| return std::move(callback).Run( |
| web::WebStatePolicyDecider::PolicyDecision::Cancel()); |
| } |
| } |
| |
| std::move(callback).Run(web::WebStatePolicyDecider::PolicyDecision::Allow()); |
| } |
| |
| void WebViewWebStatePolicyDecider::ShouldAllowResponse( |
| NSURLResponse* response, |
| web::WebStatePolicyDecider::ResponseInfo response_info, |
| web::WebStatePolicyDecider::PolicyDecisionCallback callback) { |
| id<CWVNavigationDelegate> delegate = web_view_.navigationDelegate; |
| if ([delegate respondsToSelector:@selector |
| (webView:decidePolicyForNavigationResponse:decisionHandler:)]) { |
| CWVNavigationResponse* cwv_navigation_response = |
| [[CWVNavigationResponse alloc] |
| initWithResponse:response |
| forMainFrame:response_info.for_main_frame]; |
| |
| __block web::WebStatePolicyDecider::PolicyDecisionCallback block_callback = |
| std::move(callback); |
| |
| [delegate webView:web_view_ |
| decidePolicyForNavigationResponse:cwv_navigation_response |
| decisionHandler:^( |
| CWVNavigationResponsePolicy policy) { |
| switch (policy) { |
| case CWVNavigationResponsePolicyCancel: |
| std::move(block_callback) |
| .Run(web::WebStatePolicyDecider:: |
| PolicyDecision::Cancel()); |
| break; |
| case CWVNavigationResponsePolicyAllow: |
| std::move(block_callback) |
| .Run(web::WebStatePolicyDecider:: |
| PolicyDecision::Allow()); |
| break; |
| } |
| }]; |
| return; |
| } |
| |
| // Deprected API, will consider using asynchronous API |
| // `-[CWVNavigationDelegate |
| // webView:decidePolicyForNavigationResponse:decisionHandler:]` first. |
| if ([delegate respondsToSelector:@selector |
| (webView:shouldContinueLoadWithResponse:forMainFrame:)]) { |
| BOOL allow = [delegate webView:web_view_ |
| shouldContinueLoadWithResponse:response |
| forMainFrame:response_info.for_main_frame]; |
| if (!allow) { |
| return std::move(callback).Run( |
| web::WebStatePolicyDecider::PolicyDecision::Cancel()); |
| }; |
| } |
| |
| std::move(callback).Run(web::WebStatePolicyDecider::PolicyDecision::Allow()); |
| } |
| |
| } // namespace ios_web_view |