Merge pull request #3053 from AMoraga/feature/wkwebview

[iOS] Replace UIWebView with WKWebView
diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
index 4d18eaa..86f7fdc 100644
--- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
+++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj
@@ -612,6 +612,7 @@
 		D334510D1D3E19B80083598A /* WXCanvasModule.m in Sources */ = {isa = PBXBuildFile; fileRef = D334510B1D3E19B80083598A /* WXCanvasModule.m */; };
 		D362F94F1C83EDA20003F546 /* WXWebViewModule.h in Headers */ = {isa = PBXBuildFile; fileRef = D362F94D1C83EDA20003F546 /* WXWebViewModule.h */; };
 		D362F9501C83EDA20003F546 /* WXWebViewModule.m in Sources */ = {isa = PBXBuildFile; fileRef = D362F94E1C83EDA20003F546 /* WXWebViewModule.m */; };
+		D38316662396AC7F00533310 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D38316652396AC7F00533310 /* WebKit.framework */; };
 		D3FC0DF81C508B2A002B9E31 /* WXTimerModule.m in Sources */ = {isa = PBXBuildFile; fileRef = D3FC0DF61C508B2A002B9E31 /* WXTimerModule.m */; };
 		D735F1B022D761F800B53CDF /* log_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = D735F1AB22D761F800B53CDF /* log_utils.h */; };
 		D735F1B122D761F800B53CDF /* log_utils.h in Headers */ = {isa = PBXBuildFile; fileRef = D735F1AB22D761F800B53CDF /* log_utils.h */; };
@@ -1357,6 +1358,7 @@
 		D334510B1D3E19B80083598A /* WXCanvasModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXCanvasModule.m; sourceTree = "<group>"; };
 		D362F94D1C83EDA20003F546 /* WXWebViewModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXWebViewModule.h; sourceTree = "<group>"; };
 		D362F94E1C83EDA20003F546 /* WXWebViewModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXWebViewModule.m; sourceTree = "<group>"; };
+		D38316652396AC7F00533310 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/WebKit.framework; sourceTree = DEVELOPER_DIR; };
 		D3FC0DF51C508B2A002B9E31 /* WXTimerModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXTimerModule.h; sourceTree = "<group>"; };
 		D3FC0DF61C508B2A002B9E31 /* WXTimerModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXTimerModule.m; sourceTree = "<group>"; };
 		D735F1AB22D761F800B53CDF /* log_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log_utils.h; sourceTree = "<group>"; };
@@ -1411,6 +1413,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				D38316662396AC7F00533310 /* WebKit.framework in Frameworks */,
 				74EF31C01DE5ED6F00667A07 /* libstdc++.tbd in Frameworks */,
 				DC9867441D826D1E000AF388 /* GLKit.framework in Frameworks */,
 				740938FB1D3D0E1700DBB801 /* AVKit.framework in Frameworks */,
@@ -2066,6 +2069,7 @@
 		A5818E244F9E235722E3B938 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
+				D38316652396AC7F00533310 /* WebKit.framework */,
 				DCA446231EFA5AFE00D0CFA8 /* UIKit.framework */,
 				74EF31BE1DE5ED5900667A07 /* libstdc++.tbd */,
 				DC9867431D826D1E000AF388 /* GLKit.framework */,
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.h b/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.h
index 97800a6..41db2e2 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.h
+++ b/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.h
@@ -18,8 +18,9 @@
  */
 
 #import "WXComponent.h"
+#import <WebKit/WebKit.h>
 
-@interface WXWebComponent : WXComponent<UIWebViewDelegate>
+@interface WXWebComponent : WXComponent<WKNavigationDelegate>
 
 - (void)notifyWebview:(NSDictionary *) data;
 
diff --git a/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.m b/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.m
index cd10078..1b37c28 100644
--- a/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.m
+++ b/ios/sdk/WeexSDK/Sources/Component/WXWebComponent.m
@@ -26,7 +26,7 @@
 
 #import <JavaScriptCore/JavaScriptCore.h>
 
-@interface WXWebView : UIWebView
+@interface WXWebView : WKWebView
 
 @end
 
@@ -84,17 +84,27 @@
     return self;
 }
 
+- (WKWebViewConfiguration *)baseConfiguration {
+    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
+    NSString *scalesPageToFitScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
+    WKUserScript *userScript = [[WKUserScript alloc] initWithSource:scalesPageToFitScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
+    WKUserContentController *userContentController = [[WKUserContentController alloc] init];
+    [userContentController addUserScript:userScript];
+    configuration.userContentController = userContentController;
+    configuration.allowsInlineMediaPlayback = YES;
+    
+    return configuration;
+}
+
 - (UIView *)loadView
 {
-    return [[WXWebView alloc] init];
+    return [[WXWebView alloc] initWithFrame:self.view.frame configuration:[self baseConfiguration]];
 }
 
 - (void)viewDidLoad
 {
     _webview = (WXWebView *)self.view;
-    _webview.delegate = self;
-    _webview.allowsInlineMediaPlayback = YES;
-    _webview.scalesPageToFit = YES;
+    _webview.navigationDelegate = self;
     [_webview setBackgroundColor:[UIColor clearColor]];
     _webview.opaque = NO;
     _jsContext = [_webview valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
@@ -254,56 +264,61 @@
 
 #pragma mark Webview Delegate
 
-- (NSMutableDictionary<NSString *, id> *)baseInfo
-{
+- (void)baseInfoWithCompletion:(void (^)(NSMutableDictionary<NSString *, id> *data))completion {
     NSMutableDictionary<NSString *, id> *info = [NSMutableDictionary new];
-    [info setObject:self.webview.request.URL.absoluteString ?: @"" forKey:@"url"];
-    [info setObject:[self.webview stringByEvaluatingJavaScriptFromString:@"document.title"] ?: @"" forKey:@"title"];
+    [info setObject:self.webview.URL.absoluteString ?: @"" forKey:@"url"];
     [info setObject:@(self.webview.canGoBack) forKey:@"canGoBack"];
     [info setObject:@(self.webview.canGoForward) forKey:@"canGoForward"];
-    return info;
+    [self.webview evaluateJavaScript:@"document.title" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
+        [info setObject:result ? result : @"" forKey:@"title"];
+        if (completion) {
+            completion(result);
+        }
+    }];
 }
 
-- (void)webViewDidStartLoad:(UIWebView *)webView
+- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
 {
     
 }
 
-- (void)webViewDidFinishLoad:(UIWebView *)webView
+- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
 {
     if (_finishLoadEvent) {
-        NSDictionary *data = [self baseInfo];
-        [self fireEvent:@"pagefinish" params:data domChanges:@{@"attrs": @{@"src":self.webview.request.URL.absoluteString}}];
+        [self baseInfoWithCompletion:^(NSMutableDictionary<NSString *,id> *data) {
+            [self fireEvent:@"pagefinish" params:data domChanges:@{@"attrs": @{@"src":self.webview.URL.absoluteString}}];
+        }];
     }
 }
 
-- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
+- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error
 {
     if (_failLoadEvent) {
-        NSMutableDictionary *data = [self baseInfo];
-        [data setObject:[error localizedDescription] forKey:@"errorMsg"];
-        [data setObject:[NSString stringWithFormat:@"%ld", (long)error.code] forKey:@"errorCode"];
-        
-        NSString * urlString = error.userInfo[NSURLErrorFailingURLStringErrorKey];
-        if (urlString) {
-            // webview.request may not be the real error URL, must get from error.userInfo
-            [data setObject:urlString forKey:@"url"];
-            if (![urlString hasPrefix:@"http"]) {
-                return;
+        [self baseInfoWithCompletion:^(NSMutableDictionary<NSString *,id> *data) {
+            [data setObject:[error localizedDescription] forKey:@"errorMsg"];
+            [data setObject:[NSString stringWithFormat:@"%ld", (long)error.code] forKey:@"errorCode"];
+            
+            NSString * urlString = error.userInfo[NSURLErrorFailingURLStringErrorKey];
+            if (urlString) {
+                // webview.request may not be the real error URL, must get from error.userInfo
+                [data setObject:urlString forKey:@"url"];
+                if (![urlString hasPrefix:@"http"]) {
+                    return;
+                }
             }
-        }
-        [self fireEvent:@"error" params:data];
+            [self fireEvent:@"error" params:data];
+        }];
     }
 }
 
-- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
-{
-    if (_startLoadEvent) {
-        NSMutableDictionary<NSString *, id> *data = [NSMutableDictionary new];
-        [data setObject:request.URL.absoluteString ?:@"" forKey:@"url"];
-        [self fireEvent:@"pagestart" params:data];
-    }
-    return YES;
+- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
+       if (_startLoadEvent) {
+           NSMutableDictionary<NSString *, id> *data = [NSMutableDictionary new];
+           [data setObject:navigationAction.request.URL.absoluteString ?:@"" forKey:@"url"];
+           [self fireEvent:@"pagestart" params:data];
+       }
+
+       decisionHandler(WKNavigationActionPolicyAllow);
 }
 
 @end
diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXVersion.m b/ios/sdk/WeexSDK/Sources/Utility/WXVersion.m
index 002b48b..d07a4d9 100644
--- a/ios/sdk/WeexSDK/Sources/Utility/WXVersion.m
+++ b/ios/sdk/WeexSDK/Sources/Utility/WXVersion.m
@@ -20,8 +20,8 @@
 #import "WXVersion.h"
 #import "WXDefine.h"
 
-static const char* WeexSDKBuildTime = "2019-10-09 13:07:35 UTC";
-static const unsigned long WeexSDKBuildTimestamp = 1570626455;
+static const char* WeexSDKBuildTime = "2019-12-03 14:45:27 UTC";
+static const unsigned long WeexSDKBuildTimestamp = 1575384327;
 
 NSString* GetWeexSDKVersion(void)
 {