blob: e28d53ddc437ddbf054d3be5c36b07d068bdf31d [file] [log] [blame]
// Copyright 2015 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/interstitials/html_web_interstitial_impl.h"
#include <utility>
#include "base/logging.h"
#include "base/strings/sys_string_conversions.h"
#import "ios/web/public/interstitials/web_interstitial_delegate.h"
#import "ios/web/public/web_state/ui/crw_web_view_content_view.h"
#import "ios/web/public/web_view_creation_util.h"
#import "ios/web/web_state/ui/web_view_js_utils.h"
#import "ios/web/web_state/web_state_impl.h"
#import "net/base/mac/url_conversions.h"
#include "ui/gfx/geometry/size.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
// The delegate of the web view that is used to display the HTML content.
// It intercepts JavaScript-triggered commands and forwards them
// to the interstitial.
@interface CRWWebInterstitialImplWKWebViewDelegate
: NSObject<WKNavigationDelegate>
// Initializes a CRWWebInterstitialImplWKWebViewDelegate which will
// forward JavaScript commands from its WKWebView to |interstitial|.
- (instancetype)initWithInterstitial:
(web::HtmlWebInterstitialImpl*)interstitial;
@end
@implementation CRWWebInterstitialImplWKWebViewDelegate {
web::HtmlWebInterstitialImpl* _interstitial;
}
- (instancetype)initWithInterstitial:
(web::HtmlWebInterstitialImpl*)interstitial {
self = [super init];
if (self)
_interstitial = interstitial;
return self;
}
- (BOOL)shouldStartLoadWithRequest:(NSURLRequest*)request {
NSString* requestString = [[request URL] absoluteString];
// If the request is a JavaScript-triggered command, parse it and forward the
// command to |interstitial_|.
NSString* const commandPrefix = @"js-command:";
if ([requestString hasPrefix:commandPrefix]) {
DCHECK(_interstitial);
_interstitial->CommandReceivedFromWebView(
[requestString substringFromIndex:commandPrefix.length]);
return NO;
}
return YES;
}
#pragma mark -
#pragma mark WKNavigationDelegate methods
- (void)webView:(WKWebView*)webView
decidePolicyForNavigationAction:(WKNavigationAction*)navigationAction
decisionHandler:
(void (^)(WKNavigationActionPolicy))decisionHandler {
decisionHandler([self shouldStartLoadWithRequest:navigationAction.request]
? WKNavigationActionPolicyAllow
: WKNavigationActionPolicyCancel);
}
@end
#pragma mark -
namespace web {
// static
WebInterstitial* WebInterstitial::CreateHtmlInterstitial(
WebState* web_state,
bool new_navigation,
const GURL& url,
std::unique_ptr<HtmlWebInterstitialDelegate> delegate) {
WebStateImpl* web_state_impl = static_cast<WebStateImpl*>(web_state);
return new HtmlWebInterstitialImpl(web_state_impl, new_navigation, url,
std::move(delegate));
}
HtmlWebInterstitialImpl::HtmlWebInterstitialImpl(
WebStateImpl* web_state,
bool new_navigation,
const GURL& url,
std::unique_ptr<HtmlWebInterstitialDelegate> delegate)
: WebInterstitialImpl(web_state, new_navigation, url),
delegate_(std::move(delegate)) {
DCHECK(delegate_);
}
HtmlWebInterstitialImpl::~HtmlWebInterstitialImpl() {
}
void HtmlWebInterstitialImpl::CommandReceivedFromWebView(NSString* command) {
delegate_->CommandReceived(base::SysNSStringToUTF8(command));
}
CRWContentView* HtmlWebInterstitialImpl::GetContentView() const {
return content_view_;
}
void HtmlWebInterstitialImpl::PrepareForDisplay() {
if (!content_view_) {
web_view_delegate_ = [[CRWWebInterstitialImplWKWebViewDelegate alloc]
initWithInterstitial:this];
web_view_ =
web::BuildWKWebView(CGRectZero, GetWebStateImpl()->GetBrowserState());
[web_view_ setNavigationDelegate:web_view_delegate_];
[web_view_ setAutoresizingMask:(UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleHeight)];
NSString* html = base::SysUTF8ToNSString(delegate_->GetHtmlContents());
[web_view_ loadHTMLString:html baseURL:net::NSURLWithGURL(GetUrl())];
content_view_ =
[[CRWWebViewContentView alloc] initWithWebView:web_view_
scrollView:[web_view_ scrollView]];
}
}
WebInterstitialDelegate* HtmlWebInterstitialImpl::GetDelegate() const {
return delegate_.get();
}
void HtmlWebInterstitialImpl::ExecuteJavaScript(
NSString* script,
JavaScriptResultBlock completion_handler) {
web::ExecuteJavaScript(web_view_, script, completion_handler);
}
} // namespace web