├── ndll ├── Android │ └── .gitignore ├── Linux │ └── .gitignore ├── Linux64 │ └── .gitignore ├── Mac │ └── .gitignore ├── Mac64 │ └── .gitignore ├── Windows │ └── .gitignore └── iPhone │ ├── .gitignore │ ├── libwebviewex.iphonesim.a.hash │ ├── libwebviewex.iphoneos-64.a.hash │ ├── libwebviewex.iphoneos-v7.a.hash │ ├── libwebviewex.iphonesim-64.a.hash │ ├── libwebviewex.iphoneos-64.a │ ├── libwebviewex.iphoneos-v7.a │ ├── libwebviewex.iphonesim.a │ └── libwebviewex.iphonesim-64.a ├── .gitignore ├── install.sh ├── assets ├── extensions_webview_close_hdpi.png ├── extensions_webview_close_ldpi.png ├── extensions_webview_close_mdpi.png └── extensions_webview_close_xhdpi.png ├── dependencies └── webview │ ├── project.properties │ ├── res │ ├── drawable-hdpi │ │ └── close.png │ ├── drawable-ldpi │ │ └── close.png │ ├── drawable-mdpi │ │ └── close.png │ ├── drawable-xhdpi │ │ └── close.png │ ├── layout │ │ ├── activity_web_view_fullscreen.xml │ │ └── activity_web_view_floating.xml │ └── values │ │ └── styles.xml │ ├── build.xml │ ├── AndroidManifest.xml │ ├── build.gradle │ └── src │ └── extensions │ └── webview │ ├── WebViewExtension.java │ └── WebViewActivity.java ├── project ├── include │ └── WebViewEx.h ├── build.xml ├── common │ └── ExternalInterface.cpp └── ios │ └── WebViewEx.mm ├── haxelib.json ├── include.xml ├── extension └── webview │ ├── AndroidCallbackHelper.hx │ └── WebView.hx ├── LICENSE.md └── README.md /ndll/Android/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ndll/Linux/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ndll/Linux64/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ndll/Mac/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ndll/Mac64/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ndll/Windows/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ndll/iPhone/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ndll/iPhone/libwebviewex.iphonesim.a.hash: -------------------------------------------------------------------------------- 1 | 3039e97fb50f4aab24820fd7c0bbd11a -------------------------------------------------------------------------------- /ndll/iPhone/libwebviewex.iphoneos-64.a.hash: -------------------------------------------------------------------------------- 1 | a3d37be92020118efc118446b7927307 -------------------------------------------------------------------------------- /ndll/iPhone/libwebviewex.iphoneos-v7.a.hash: -------------------------------------------------------------------------------- 1 | 1e7e9307ee35cfa6a3bbd8432872fa95 -------------------------------------------------------------------------------- /ndll/iPhone/libwebviewex.iphonesim-64.a.hash: -------------------------------------------------------------------------------- 1 | 0b25b90d3c22386bce4fcbeaed1972e8 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | project/obj 2 | *.zip 3 | *.sublime-project 4 | *.sublime-workspace 5 | *.DS_Store -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | dir=`dirname "$0"` 3 | cd "$dir" 4 | haxelib remove extension-webview 5 | haxelib local extension-webview.zip 6 | -------------------------------------------------------------------------------- /ndll/iPhone/libwebviewex.iphoneos-64.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaxeExtension/extension-webview/HEAD/ndll/iPhone/libwebviewex.iphoneos-64.a -------------------------------------------------------------------------------- /ndll/iPhone/libwebviewex.iphoneos-v7.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaxeExtension/extension-webview/HEAD/ndll/iPhone/libwebviewex.iphoneos-v7.a -------------------------------------------------------------------------------- /ndll/iPhone/libwebviewex.iphonesim.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaxeExtension/extension-webview/HEAD/ndll/iPhone/libwebviewex.iphonesim.a -------------------------------------------------------------------------------- /assets/extensions_webview_close_hdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaxeExtension/extension-webview/HEAD/assets/extensions_webview_close_hdpi.png -------------------------------------------------------------------------------- /assets/extensions_webview_close_ldpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaxeExtension/extension-webview/HEAD/assets/extensions_webview_close_ldpi.png -------------------------------------------------------------------------------- /assets/extensions_webview_close_mdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaxeExtension/extension-webview/HEAD/assets/extensions_webview_close_mdpi.png -------------------------------------------------------------------------------- /ndll/iPhone/libwebviewex.iphonesim-64.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaxeExtension/extension-webview/HEAD/ndll/iPhone/libwebviewex.iphonesim-64.a -------------------------------------------------------------------------------- /assets/extensions_webview_close_xhdpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaxeExtension/extension-webview/HEAD/assets/extensions_webview_close_xhdpi.png -------------------------------------------------------------------------------- /dependencies/webview/project.properties: -------------------------------------------------------------------------------- 1 | android.library=true 2 | target=android-::ANDROID_TARGET_SDK_VERSION:: 3 | android.library.reference.1=../extension-api 4 | -------------------------------------------------------------------------------- /dependencies/webview/res/drawable-hdpi/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaxeExtension/extension-webview/HEAD/dependencies/webview/res/drawable-hdpi/close.png -------------------------------------------------------------------------------- /dependencies/webview/res/drawable-ldpi/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaxeExtension/extension-webview/HEAD/dependencies/webview/res/drawable-ldpi/close.png -------------------------------------------------------------------------------- /dependencies/webview/res/drawable-mdpi/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaxeExtension/extension-webview/HEAD/dependencies/webview/res/drawable-mdpi/close.png -------------------------------------------------------------------------------- /dependencies/webview/res/drawable-xhdpi/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HaxeExtension/extension-webview/HEAD/dependencies/webview/res/drawable-xhdpi/close.png -------------------------------------------------------------------------------- /project/include/WebViewEx.h: -------------------------------------------------------------------------------- 1 | #ifndef WebViewEx 2 | #define WebViewEx 3 | 4 | namespace webviewex { 5 | void init(value _onDestroyedCallback, value _onURLChangingCallback, bool withPopup); 6 | void navigate(const char *url); 7 | void loadHtml(const char *html); 8 | void destroy(); 9 | } 10 | 11 | #endif -------------------------------------------------------------------------------- /dependencies/webview/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /haxelib.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "extension-webview", 3 | "url": "https://github.com/openfl/extension-webview", 4 | "license": "MIT", 5 | "contributors":["singmajesty","fbricker"], 6 | "tags": ["webview","api","android", "ios"], 7 | "description": "WebView / OpenFL extension for Android + iOS.", 8 | "version": "1.2.4", 9 | "releasenote": "Add gradle support" 10 | } 11 | -------------------------------------------------------------------------------- /include.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 |
8 | 9 |
10 | 11 | 12 |
13 | 14 |
15 | -------------------------------------------------------------------------------- /extension/webview/AndroidCallbackHelper.hx: -------------------------------------------------------------------------------- 1 | package extension.webview; 2 | 3 | class AndroidCallbackHelper { 4 | 5 | public function new() { 6 | 7 | } 8 | 9 | public function onClose() { 10 | if (WebView.onClose!=null) { 11 | WebView.onClose(); 12 | } 13 | } 14 | 15 | public function onURLChanging(url : String) { 16 | if (WebView.onURLChanging!=null) { 17 | WebView.onURLChanging(url); 18 | } 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /dependencies/webview/res/layout/activity_web_view_fullscreen.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /dependencies/webview/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /dependencies/webview/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /dependencies/webview/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | maven { 4 | url "https://repo1.maven.org/maven2/" 5 | } 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.1.0' 9 | } 10 | } 11 | 12 | apply plugin: 'com.android.library' 13 | 14 | android { 15 | sourceSets { 16 | main { 17 | manifest.srcFile 'AndroidManifest.xml' 18 | java.srcDirs = ['src'] 19 | res.srcDirs = ['res'] 20 | } 21 | } 22 | compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION) 23 | buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION 24 | } 25 | 26 | dependencies { 27 | compile project(':deps:extension-api') 28 | } 29 | -------------------------------------------------------------------------------- /project/build.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /dependencies/webview/res/layout/activity_web_view_floating.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 15 | 16 | 17 | 22 | 23 | -------------------------------------------------------------------------------- /project/common/ExternalInterface.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "WebViewEx.h" 5 | 6 | using namespace webviewex; 7 | 8 | #ifdef HX_WINDOWS 9 | typedef wchar_t OSChar; 10 | #define val_os_string val_wstring 11 | #else 12 | typedef char OSChar; 13 | #define val_os_string val_string 14 | #endif 15 | 16 | extern "C" { 17 | int webviewex_register_prims(){ 18 | return 0; 19 | } 20 | } 21 | 22 | void webviewAPIInit (value _onDestroyedCallback, value _onURLChangingCallback, value withPopup) { init(_onDestroyedCallback, _onURLChangingCallback, val_bool(withPopup)); } 23 | DEFINE_PRIM (webviewAPIInit, 3); 24 | 25 | void webviewAPINavigate (value url) { navigate(val_string(url)); } 26 | DEFINE_PRIM (webviewAPINavigate, 1); 27 | 28 | void webviewAPILoadHtml (value html) { loadHtml(val_string(html)); } 29 | DEFINE_PRIM (webviewAPILoadHtml, 1); 30 | 31 | void webviewAPIDestroy(){ destroy(); } 32 | DEFINE_PRIM (webviewAPIDestroy, 0); 33 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | License 2 | ======= 3 | 4 | The MIT License (MIT) 5 | 6 | Copyright (c) 2013 SempaiGames (http://www.sempaigames.com) 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # extension-webview 2 | 3 | A minimalistic OpenFL extension for displaying native WebViews on iOS and Android outputs. 4 | 5 | ### Main Features 6 | 7 | * Full-screen and Popup mode. 8 | * Popup mode has a close button on the top-left corner. 9 | * Whitelist validation (the webview will close if the user goes to a non-whitelisted URL). 10 | * Blacklist validation (the webview will close if the user goes to a blacklisted URL). 11 | * onClose event (Android and iOS). 12 | * onURLChanging events for controling the WebView (Android and iOS). 13 | * On non-supported platforms, this extensions has no effect (makes nothing). 14 | 15 | ### Simple use Example 16 | 17 | ```haxe 18 | // This example show a simple sharing of a text using the Share Class. 19 | 20 | import extension.webview.WebView; 21 | 22 | class SimpleExample { 23 | function new(){ 24 | WebView.onClose=onClose; 25 | WebView.onURLChanging=onURLChanging; 26 | } 27 | 28 | function onClose(){ 29 | trace("WebView has been closed!"); 30 | } 31 | 32 | function onURLChanging(url:String){ 33 | trace("WebView is about to open: "+url); 34 | } 35 | 36 | function shareStuff(){ 37 | WebView.open('http://www.puralax.com/help',true); 38 | 39 | // Example using whitelist: 40 | // WebView.open('http://www.puralax.com/help',true,['(http|https)://www.puralax.com/help(.*)','http://www.sempaigames.com/(.*)']); 41 | 42 | // Example using blacklist: 43 | // WebView.open('http://www.puralax.com/help',true,null,['(http|https)://(.*)facebook.com(.*)']); 44 | } 45 | } 46 | 47 | ``` 48 | 49 | ### How to Install 50 | 51 | ```bash 52 | haxelib install extension-webview 53 | ``` 54 | 55 | ### Thanks to... 56 | 57 | The original iOS implementation is based on Suat Eyrice's extension NME WebView (https://github.com/SuatEyrice/NMEWebview). 58 | 59 | ### License 60 | 61 | The MIT License (MIT) - [LICENSE.md](LICENSE.md) 62 | 63 | Copyright © 2013 SempaiGames (http://www.sempaigames.com) 64 | 65 | Author: Matías Rossi && Federico Bricker 66 | -------------------------------------------------------------------------------- /dependencies/webview/src/extensions/webview/WebViewExtension.java: -------------------------------------------------------------------------------- 1 | package extensions.webview; 2 | 3 | import android.util.Log; 4 | import android.content.Intent; 5 | import org.haxe.extension.Extension; 6 | import org.haxe.lime.HaxeObject; 7 | import org.json.JSONArray; 8 | import org.json.JSONException; 9 | import org.json.JSONObject; 10 | 11 | public class WebViewExtension extends Extension { 12 | 13 | public static final String EXTRA_URL = "extensions.webviewex.EXTRA_URL"; 14 | public static final String EXTRA_HTML = "extensions.webviewex.EXTRA_HTML"; 15 | public static final String EXTRA_FLOATING = "extensions.webviewex.EXTRA_FLOATING"; 16 | public static final String EXTRA_URL_WHITELIST = "extensions.webviewex.EXTRA_URL_WHITELIST"; 17 | public static final String EXTRA_URL_BLACKLIST = "extensions.webviewex.EXTRA_URL_BLACKLIST"; 18 | public static final String EXTRA_USE_WIDE_PORT = "extensions.webviewex.EXTRA_USE_WIDE_PORT"; 19 | public static final String EXTRA_MEDIA_PLAYBACK_REQUIRES_USER_GESTURE = "extensions.webviewex.EXTRA_MEDIA_PLAYBACK_REQUIRES_USER_GESTURE"; 20 | public static boolean active = false; 21 | 22 | public static HaxeObject callback; 23 | 24 | public static void open(String json) { 25 | 26 | try { 27 | 28 | JSONObject obj = new JSONObject(json); 29 | String url = obj.getString("url"); 30 | boolean floating = obj.getBoolean("floating"); 31 | 32 | JSONArray jsonUrlWhitelist = obj.getJSONArray("urlWhitelist"); 33 | String[] urlWhitelist = new String[jsonUrlWhitelist.length()]; 34 | for (int i=0; i 2 | #include 3 | #include 4 | 5 | typedef void (*OnUrlChangingFunctionType)(NSString *); 6 | typedef void (*OnCloseClickedFunctionType)(); 7 | 8 | @interface WebViewDelegate : NSObject 9 | @property (nonatomic) OnUrlChangingFunctionType onUrlChanging; 10 | @property (nonatomic) OnCloseClickedFunctionType onCloseClicked; 11 | @end 12 | 13 | @implementation WebViewDelegate 14 | @synthesize onUrlChanging; 15 | @synthesize onCloseClicked; 16 | 17 | - (void)webView:(WKWebView *)instance decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { 18 | NSString *url = [navigationAction.request.URL query]; 19 | onUrlChanging([[navigationAction.request URL] absoluteString]); 20 | 21 | decisionHandler(WKNavigationActionPolicyAllow); 22 | } 23 | 24 | - (void) onCloseButtonClicked:(UIButton *)closeButton { 25 | onCloseClicked(); 26 | } 27 | @end 28 | 29 | namespace webviewex { 30 | WKWebView *instance; 31 | UIButton *closeButton; 32 | WebViewDelegate *webViewDelegate; 33 | AutoGCRoot *onDestroyedCallback = 0; 34 | AutoGCRoot *onURLChangingCallback = 0; 35 | void init(value, value, bool); 36 | void navigate(const char *); 37 | void destroy(); 38 | void onUrlChanging(NSString *); 39 | 40 | void init(value _onDestroyedCallback, value _onURLChangingCallback, bool withPopup) { 41 | if(instance != nil) destroy(); 42 | 43 | onDestroyedCallback = new AutoGCRoot(_onDestroyedCallback); 44 | onURLChangingCallback = new AutoGCRoot(_onURLChangingCallback); 45 | 46 | webViewDelegate = [[WebViewDelegate alloc] init]; 47 | webViewDelegate.onUrlChanging = &onUrlChanging; 48 | webViewDelegate.onCloseClicked = &destroy; 49 | 50 | CGRect screen = [[UIScreen mainScreen] bounds]; 51 | CGFloat screenScale = [[UIScreen mainScreen] scale]; 52 | 53 | NSString *dpi = @"mdpi"; 54 | int padding = 58; 55 | 56 | if(screenScale > 1.0) { 57 | dpi = @"xhdpi"; 58 | padding = 59; 59 | } 60 | 61 | padding /= 4; 62 | if(!withPopup) padding = 0; 63 | 64 | WKWebViewConfiguration *webViewConfiguration = [[WKWebViewConfiguration alloc] init]; 65 | webViewConfiguration.allowsInlineMediaPlayback = YES; 66 | webViewConfiguration.ignoresViewportScaleLimits = YES; 67 | 68 | instance = [[WKWebView alloc] initWithFrame:CGRectMake(padding, padding, screen.size.width - (padding * 2), screen.size.height - (padding * 2)) configuration: webViewConfiguration]; 69 | [webViewConfiguration release]; 70 | 71 | instance.navigationDelegate = webViewDelegate; 72 | 73 | [[[UIApplication sharedApplication] keyWindow] addSubview:instance]; 74 | 75 | if (withPopup) { 76 | UIImage *closeImage = [[UIImage alloc] initWithContentsOfFile: [[NSBundle mainBundle] pathForResource: [NSString stringWithFormat:@"assets/assets/extensions_webview_close_%@.png", dpi] ofType: nil]]; 77 | closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; 78 | [closeButton setImage:closeImage forState:UIControlStateNormal]; 79 | closeButton.adjustsImageWhenHighlighted = NO; 80 | closeButton.frame = CGRectMake(0, 0, padding*2, padding*2); 81 | [closeButton addTarget:webViewDelegate action:@selector(onCloseButtonClicked:) forControlEvents:UIControlEventTouchUpInside]; 82 | [[[UIApplication sharedApplication] keyWindow] addSubview:closeButton]; 83 | } 84 | } 85 | 86 | void navigate (const char *url) { 87 | NSURL *_url = [[NSURL alloc] initWithString: [[NSString alloc] initWithUTF8String:url]]; 88 | NSURLRequest *req = [[NSURLRequest alloc] initWithURL:_url]; 89 | [instance loadRequest:req]; 90 | } 91 | 92 | void loadHtml (const char *html){ 93 | [instance loadHTMLString:[NSString stringWithUTF8String:html] baseURL: nil]; 94 | } 95 | 96 | void destroy(){ 97 | if(instance==nil) return; 98 | val_call0(onDestroyedCallback->get()); 99 | [instance stopLoading]; 100 | [instance removeFromSuperview]; 101 | if(closeButton != nil) { 102 | [closeButton removeFromSuperview]; 103 | } 104 | [instance release]; 105 | instance=nil; 106 | } 107 | 108 | void onUrlChanging (NSString *url) { 109 | val_call1(onURLChangingCallback->get(), alloc_string([url cStringUsingEncoding:NSUTF8StringEncoding])); 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /extension/webview/WebView.hx: -------------------------------------------------------------------------------- 1 | package extension.webview; 2 | 3 | import haxe.Json; 4 | #if (openfl < "4.0.0") 5 | import openfl.utils.JNI; 6 | #else 7 | import lime.system.JNI; 8 | #end 9 | 10 | class WebView { 11 | 12 | private static var initialized :Bool = false; 13 | 14 | private static var APIInit:Dynamic=null; 15 | private static var APISetCallback:Dynamic=null; 16 | private static var APINavigate:Dynamic=null; 17 | private static var APIDestroy:Dynamic=null; 18 | private static var APILoadHtml:Dynamic=null; 19 | 20 | #if ios 21 | private static var listener:WebViewListener; 22 | #end 23 | 24 | #if android 25 | private static var _open :String -> Void = null; 26 | private static var _openHtml :String -> Void = null; 27 | #end 28 | 29 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 31 | 32 | public static var onClose:Void->Void=null; 33 | public static var onURLChanging:String->Void=null; 34 | 35 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 37 | 38 | public static function open ( 39 | url: String = null, 40 | floating :Bool = false, 41 | ?urlWhitelist :Array, 42 | ?urlBlacklist :Array, 43 | ?useWideViewPort :Bool = false, // Android only 44 | ?mediaPlaybackRequiresUserGesture :Bool = true // Android only 45 | ) :Void { 46 | init(); 47 | if(urlWhitelist!=null) urlWhitelist.push(url); 48 | 49 | #if android 50 | if (urlWhitelist==null) { 51 | urlWhitelist = []; 52 | } 53 | if (urlBlacklist==null) { 54 | urlBlacklist = []; 55 | } 56 | var obj = { 57 | url : url, 58 | floating : floating, 59 | urlWhitelist : urlWhitelist, 60 | urlBlacklist : urlBlacklist, 61 | useWideViewPort : useWideViewPort, 62 | mediaPlaybackRequiresUserGesture : mediaPlaybackRequiresUserGesture 63 | } 64 | _open(Json.stringify(obj)); 65 | #elseif ios 66 | if (listener == null) listener = new WebViewListener(urlWhitelist, urlBlacklist); 67 | APICall("init", [listener, floating]); 68 | navigate(url); 69 | #end 70 | } 71 | 72 | public static function openHtml( 73 | html:String, 74 | floating:Bool=false, 75 | ?useWideViewPort :Bool = false, // Android only 76 | ?mediaPlaybackRequiresUserGesture :Bool = true // Android only 77 | ) :Void { 78 | init(); 79 | #if android 80 | var obj = { 81 | html : html, 82 | floating : floating, 83 | useWideViewPort : useWideViewPort, 84 | mediaPlaybackRequiresUserGesture : mediaPlaybackRequiresUserGesture 85 | } 86 | _openHtml(Json.stringify(obj)); 87 | #elseif ios 88 | if (listener == null) listener = new WebViewListener(null, null); 89 | APICall("init", [listener, floating]); 90 | APICall("loadHtml", [html]); 91 | #end 92 | } 93 | 94 | #if ios 95 | public static function navigate(url:String):Void { 96 | if (url==null) return; 97 | if (listener != null) APICall("navigate", [url]); 98 | } 99 | 100 | public static function close():Void { 101 | if (listener != null) APICall("destroy"); 102 | } 103 | #end 104 | 105 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 106 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 107 | 108 | private static function init():Void { 109 | if(initialized == true) return; 110 | initialized = true; 111 | try { 112 | #if android 113 | _open = JNI.createStaticMethod("extensions/webview/WebViewExtension", "open", "(Ljava/lang/String;)V"); 114 | _openHtml = JNI.createStaticMethod("extensions/webview/WebViewExtension", "openHtml", "(Ljava/lang/String;)V"); 115 | var _callbackFunc = JNI.createStaticMethod("extensions/webview/WebViewExtension", "setCallback", "(Lorg/haxe/lime/HaxeObject;)V"); 116 | _callbackFunc(new AndroidCallbackHelper()); 117 | 118 | #elseif ios 119 | APIInit = cpp.Lib.load("webviewex","webviewAPIInit", 3); 120 | APINavigate = cpp.Lib.load("webviewex","webviewAPINavigate", 1); 121 | APILoadHtml = cpp.Lib.load("webviewex","webviewAPILoadHtml", 1); 122 | APIDestroy = cpp.Lib.load("webviewex","webviewAPIDestroy", 0); 123 | #end 124 | 125 | } catch(e:Dynamic) { 126 | trace("INIT Exception: "+e); 127 | } 128 | } 129 | 130 | private static function APICall(method:String, args:Array = null):Void { 131 | init(); 132 | try{ 133 | #if android 134 | if (method == "init") { 135 | try { 136 | APIInit(args[1] == true); 137 | } catch (e :Dynamic) { 138 | APIInit(args[1] == true); 139 | } 140 | } 141 | if (method == "callback") APISetCallback(args[0]); 142 | if (method == "navigate") APINavigate(args[0]); 143 | if (method == "destroy") APIDestroy(); 144 | #elseif ios 145 | if (method == "init") APIInit(args[0].onClose, args[0].onURLChanging, args[1]); 146 | if (method == "navigate") APINavigate(args[0]); 147 | if (method == "loadHtml") APILoadHtml(args[0]); 148 | if (method == "destroy") APIDestroy(); 149 | #end 150 | } catch(e:Dynamic) { 151 | trace("APICall Exception [" + method + ", " + args + "]: "+e); 152 | } 153 | } 154 | 155 | } 156 | 157 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 158 | //////////////////////////////////////////////////////////////////////////////////////////////////////////////// 159 | #if ios 160 | class WebViewListener { 161 | 162 | public var urlWhitelist :Array; 163 | public var urlBlacklist :Array; 164 | 165 | public function new(urlWhitelist :Array, urlBlacklist :Array) { 166 | this.urlBlacklist=urlBlacklist; 167 | this.urlWhitelist=urlWhitelist; 168 | } 169 | 170 | public function onClose():Void { 171 | if(WebView.onClose!=null) WebView.onClose(); 172 | } 173 | 174 | private function find(urls :Array, url:String):Bool{ 175 | for(regex in urls){ 176 | var r = new EReg(regex,""); 177 | if(r.match(url)) return true; 178 | } 179 | return false; 180 | } 181 | 182 | public function onURLChanging(url:Dynamic):Void { 183 | if(urlWhitelist!=null){ 184 | if(!find(urlWhitelist,url)){ 185 | WebView.close(); 186 | return; 187 | } 188 | } 189 | if(urlBlacklist!=null){ 190 | if(find(urlBlacklist,url)){ 191 | WebView.close(); 192 | return; 193 | } 194 | } 195 | if(WebView.onURLChanging!=null) WebView.onURLChanging(url); 196 | } 197 | } 198 | #end 199 | -------------------------------------------------------------------------------- /dependencies/webview/src/extensions/webview/WebViewActivity.java: -------------------------------------------------------------------------------- 1 | package extensions.webview; 2 | 3 | import java.util.regex.PatternSyntaxException; 4 | 5 | import android.os.Bundle; 6 | import android.app.Activity; 7 | import android.content.res.Configuration; 8 | import android.util.Log; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.view.Window; 12 | import android.webkit.WebView; 13 | import android.webkit.WebSettings; 14 | import android.webkit.WebViewClient; 15 | import android.widget.FrameLayout; 16 | import org.haxe.lime.HaxeObject; 17 | 18 | public class WebViewActivity extends Activity { 19 | 20 | private static final String TAG = "WebViewActivity"; 21 | 22 | protected FrameLayout webViewPlaceholder; 23 | protected WebView webView; 24 | 25 | protected String url; 26 | protected String html; 27 | protected boolean floating; 28 | protected String[] urlWhitelist; 29 | protected String[] urlBlacklist; 30 | protected boolean useWideViewPort; 31 | protected boolean mediaPlaybackRequiresUserGesture; 32 | protected HaxeObject callback; 33 | 34 | protected int layoutResource; 35 | 36 | @Override 37 | public void onCreate(Bundle savedInstanceState) 38 | { 39 | super.onCreate(savedInstanceState); 40 | 41 | // Load parameters from intent 42 | Bundle extras = getIntent().getExtras(); 43 | url = extras.getString(WebViewExtension.EXTRA_URL, "about:blank"); 44 | html = extras.getString(WebViewExtension.EXTRA_HTML, "null"); 45 | floating = extras.getBoolean(WebViewExtension.EXTRA_FLOATING); 46 | urlWhitelist = extras.getStringArray(WebViewExtension.EXTRA_URL_WHITELIST); 47 | urlBlacklist = extras.getStringArray(WebViewExtension.EXTRA_URL_BLACKLIST); 48 | useWideViewPort = extras.getBoolean(WebViewExtension.EXTRA_USE_WIDE_PORT); 49 | mediaPlaybackRequiresUserGesture = extras.getBoolean(WebViewExtension.EXTRA_MEDIA_PLAYBACK_REQUIRES_USER_GESTURE); 50 | callback = WebViewExtension.callback; 51 | 52 | getWindow().requestFeature(Window.FEATURE_NO_TITLE); 53 | 54 | if (floating) { 55 | layoutResource = R.layout.activity_web_view_floating; 56 | } else { 57 | layoutResource = R.layout.activity_web_view_fullscreen; 58 | } 59 | 60 | // Initialize the UI 61 | initUI(); 62 | } 63 | 64 | protected void initUI() 65 | { 66 | // Load layout from resources 67 | setContentView(layoutResource); 68 | 69 | // Retrieve UI elements 70 | webViewPlaceholder = ((FrameLayout)findViewById(R.id.webViewPlaceholder)); 71 | 72 | // Initialize the WebView if necessary 73 | if (webView == null) 74 | { 75 | // Create the webview 76 | webView = new WebView(this); 77 | WebSettings webSettings = webView.getSettings(); 78 | webSettings.setJavaScriptEnabled(true); 79 | webSettings.setDomStorageEnabled(true); 80 | webView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 81 | webView.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY); 82 | webView.setScrollbarFadingEnabled(true); 83 | webSettings.setLoadsImagesAutomatically(true); 84 | 85 | webSettings.setUseWideViewPort(useWideViewPort); 86 | if (android.os.Build.VERSION.SDK_INT>16) { 87 | //TODO: need to call this using reflection 88 | //webSettings.setMediaPlaybackRequiresUserGesture(mediaPlaybackRequiresUserGesture); 89 | } 90 | 91 | // Add the callback to handle new page loads 92 | webView.setWebViewClient( 93 | 94 | new WebViewClient() { 95 | 96 | @Override 97 | public boolean shouldOverrideUrlLoading (WebView view, String url) { 98 | 99 | Log.d(TAG, "shouldOverrideUrlLoading(): url = " + url); 100 | 101 | callback.call("onURLChanging", new Object[] {url}); 102 | 103 | if (WebViewActivity.this.urlWhitelist == null) { 104 | 105 | Log.d(TAG, "urlWhitelist is null"); 106 | 107 | } else if (WebViewActivity.this.urlWhitelist.length == 0) { 108 | 109 | Log.d(TAG, "urlWhitelist is empty"); 110 | 111 | } else { 112 | 113 | boolean whitelisted = false; 114 | 115 | for (String whitelistedUrl : WebViewActivity.this.urlWhitelist) { 116 | 117 | try { 118 | 119 | if (url.matches(whitelistedUrl)) { 120 | 121 | Log.d(TAG, "URL matches with whitelist entry: '" + whitelistedUrl + "'."); 122 | whitelisted = true; 123 | 124 | } 125 | 126 | } catch (PatternSyntaxException ex) { 127 | 128 | Log.e(TAG, "Regular expression '" + whitelistedUrl + "' is not valid."); 129 | 130 | } 131 | 132 | } 133 | 134 | if (! whitelisted) { 135 | 136 | Log.d(TAG, "URL is not whitelisted. Closing view..."); 137 | // call onClose( with args ) ??? 138 | finish(); 139 | return true; 140 | 141 | } 142 | 143 | } 144 | 145 | if (WebViewActivity.this.urlBlacklist == null) { 146 | 147 | Log.d(TAG, "urlBlacklist is null"); 148 | 149 | } else for (String blacklistedUrl : WebViewActivity.this.urlBlacklist) { 150 | 151 | try { 152 | 153 | if (url.matches(blacklistedUrl)) { 154 | 155 | Log.d(TAG, "URL matches with blacklist entry: '" + blacklistedUrl + "'. Closing view..."); 156 | // call onClose( with args ) ??? 157 | finish(); 158 | return true; 159 | 160 | } 161 | 162 | } catch (PatternSyntaxException ex) { 163 | 164 | Log.e(TAG, "Regular expression '" + blacklistedUrl + "' is not valid."); 165 | 166 | } 167 | 168 | } 169 | 170 | return false; 171 | } 172 | 173 | } 174 | 175 | ); 176 | 177 | // Load the page 178 | callback.call("onURLChanging", new Object[] {url}); 179 | if(url=="about:blank" && html!="null") webView.loadData(html, "text/html", null); 180 | else webView.loadUrl(url); 181 | } 182 | 183 | // Attach the WebView to its placeholder 184 | webViewPlaceholder.addView(webView); 185 | } 186 | 187 | @Override 188 | public void onConfigurationChanged(Configuration newConfig) 189 | { 190 | 191 | Log.d(TAG, "onConfigurationChanged (newConfig = " + newConfig.toString() + ")"); 192 | 193 | if (webView != null) 194 | { 195 | // Remove the WebView from the old placeholder 196 | webViewPlaceholder.removeView(webView); 197 | } 198 | 199 | super.onConfigurationChanged(newConfig); 200 | 201 | // Reinitialize the UI 202 | initUI(); 203 | } 204 | 205 | @Override 206 | protected void onSaveInstanceState(Bundle outState) 207 | { 208 | super.onSaveInstanceState(outState); 209 | 210 | // Save the state of the WebView 211 | webView.saveState(outState); 212 | } 213 | 214 | @Override 215 | protected void onRestoreInstanceState(Bundle savedInstanceState) 216 | { 217 | super.onRestoreInstanceState(savedInstanceState); 218 | 219 | // Restore the state of the WebView 220 | webView.restoreState(savedInstanceState); 221 | } 222 | 223 | @Override 224 | public void onBackPressed() { 225 | if (webView.canGoBack()) 226 | webView.goBack(); 227 | else 228 | super.onBackPressed(); 229 | } 230 | 231 | public void onClosePressed(View view) { 232 | callback.call("onClose", new Object[] {}); 233 | finish(); 234 | } 235 | 236 | @Override 237 | public void finish(){ 238 | super.finish(); 239 | WebViewExtension.active=false; 240 | webView.clearHistory(); 241 | webView.loadUrl("about:blank"); 242 | webViewPlaceholder.removeView(webView); 243 | } 244 | 245 | 246 | } 247 | --------------------------------------------------------------------------------