From b51a4dc54e9c2098e1aea3af63b6bfa2453a318e Mon Sep 17 00:00:00 2001 From: Sean Kelly Date: Wed, 30 Dec 2015 11:02:52 -0800 Subject: [PATCH] CB-7786 Support mediaPlaybackRequiresUserAction on Android This closes #132 --- CONTRIBUTING.md | 29 ++++++++++++++++++++++++++++- README.md | 5 +++-- src/android/InAppBrowser.java | 21 ++++++++++++++++----- tests/resources/video.html | 3 +++ tests/tests.js | 13 +++++++++++-- 5 files changed, 61 insertions(+), 10 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4c8e6a5..39378f2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,7 +26,7 @@ Anyone can contribute to Cordova. And we need your contributions. There are multiple ways to contribute: report bugs, improve the docs, and contribute code. -For instructions on this, start with the +For instructions on this, start with the [contribution overview](http://cordova.apache.org/contribute/). The details are explained there, but the important items are: @@ -35,3 +35,30 @@ The details are explained there, but the important items are: - Run the tests so your patch doesn't break existing functionality. We look forward to your contributions! + +The notes on [Commit Workflow](https://github.com/apache/cordova-coho/blob/master/docs/committer-workflow.md#commit-workflow) can be helpful even if you are not a committer. + +## Running plugin tests + +* clone and install [cordova-plugin-test-framework](https://github.com/apache/cordova-plugin-test-framework) +``` +git clone git@github.com:apache/cordova-plugin-test-framework.git +``` +* edit ```cordova-plugin-test-framework/www/assets/index.html``` and add the following line +``` + +``` +* create test project +``` +cordova create plugintest +cd plugintest +cordova platform add android +cordova plugin add ../cordova-plugin-inappbrowser +cordova plugin add ../cordova-plugin-inappbrowser/tests +cordova plugin add ../cordova-plugin-test-framework +``` +* edit ```config.xml``` and replace `````` with `````` +* run application +``` +cordova run +``` diff --git a/README.md b/README.md index e83dff1..8e8f5f4 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ instance, or the system browser. - __clearsessioncache__: set to `yes` to have the session cookie cache cleared before the new window is opened - __zoom__: set to `yes` to show Android browser's zoom controls, set to `no` to hide them. Default value is `yes`. - __hardwareback__: set to `yes` to use the hardware back button to navigate backwards through the `InAppBrowser`'s history. If there is no previous page, the `InAppBrowser` will close. The default value is `yes`, so you must set it to `no` if you want the back button to simply close the InAppBrowser. + - __mediaPlaybackRequiresUserAction__: Set to `yes` to prevent HTML5 audio or video from autoplaying (defaults to `no`). iOS only: @@ -110,7 +111,7 @@ instance, or the system browser. - __clearsessioncache__: set to `yes` to have the session cookie cache cleared before the new window is opened - __toolbar__: set to `yes` or `no` to turn the toolbar on or off for the InAppBrowser (defaults to `yes`) - __enableViewportScale__: Set to `yes` or `no` to prevent viewport scaling through a meta tag (defaults to `no`). - - __mediaPlaybackRequiresUserAction__: Set to `yes` or `no` to prevent HTML5 audio or video from autoplaying (defaults to `no`). + - __mediaPlaybackRequiresUserAction__: Set to `yes` to prevent HTML5 audio or video from autoplaying (defaults to `no`). - __allowInlineMediaPlayback__: Set to `yes` or `no` to allow in-line HTML5 media playback, displaying within the browser window rather than a device-specific playback interface. The HTML's `video` element must also include the `webkit-playsinline` attribute (defaults to `no`) - __keyboardDisplayRequiresUserAction__: Set to `yes` or `no` to open the keyboard when form elements receive focus via JavaScript's `focus()` call (defaults to `yes`). - __suppressesIncrementalRendering__: Set to `yes` or `no` to wait until all new view content is received before being rendered (defaults to `no`). @@ -174,7 +175,7 @@ opened with `target='_blank'`. The rules might look like these Windows 8.0, 8.1 and Windows Phone 8.1 don't support remote urls to be opened in the Cordova WebView so remote urls are always showed in the system's web browser if opened with `target='_self'`. -On Windows 10 if the URL is NOT in the white list and is opened with `target='_self'` it will be showed in the system's web browser instead of InAppBrowser popup. +On Windows 10 if the URL is NOT in the white list and is opened with `target='_self'` it will be showed in the system's web browser instead of InAppBrowser popup. Similar to Firefox OS IAB window visual behaviour can be overridden via `inAppBrowserWrap`/`inAppBrowserWrapFullscreen` CSS classes diff --git a/src/android/InAppBrowser.java b/src/android/InAppBrowser.java index 7415364..e119a44 100644 --- a/src/android/InAppBrowser.java +++ b/src/android/InAppBrowser.java @@ -85,6 +85,7 @@ public class InAppBrowser extends CordovaPlugin { private static final String CLEAR_ALL_CACHE = "clearcache"; private static final String CLEAR_SESSION_CACHE = "clearsessioncache"; private static final String HARDWARE_BACK_BUTTON = "hardwareback"; + private static final String MEDIA_PLAYBACK_REQUIRES_USER_ACTION = "mediaPlaybackRequiresUserAction"; private InAppBrowserDialog dialog; private WebView inAppWebView; @@ -96,6 +97,7 @@ public class InAppBrowser extends CordovaPlugin { private boolean clearAllCache = false; private boolean clearSessionCache = false; private boolean hadwareBackButton = true; + private boolean mediaPlaybackRequiresUserGesture = false; /** * Executes the request and returns PluginResult. @@ -473,6 +475,8 @@ public class InAppBrowser extends CordovaPlugin { showLocationBar = true; showZoomControls = true; openWindowHidden = false; + mediaPlaybackRequiresUserGesture = false; + if (features != null) { Boolean show = features.get(LOCATION); if (show != null) { @@ -490,6 +494,10 @@ public class InAppBrowser extends CordovaPlugin { if (hardwareBack != null) { hadwareBackButton = hardwareBack.booleanValue(); } + Boolean mediaPlayback = features.get(MEDIA_PLAYBACK_REQUIRES_USER_ACTION); + if (mediaPlayback != null) { + mediaPlaybackRequiresUserGesture = mediaPlayback.booleanValue(); + } Boolean cache = features.get(CLEAR_ALL_CACHE); if (cache != null) { clearAllCache = cache.booleanValue(); @@ -660,6 +668,10 @@ public class InAppBrowser extends CordovaPlugin { settings.setBuiltInZoomControls(showZoomControls); settings.setPluginState(android.webkit.WebSettings.PluginState.ON); + if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { + settings.setMediaPlaybackRequiresUserGesture(mediaPlaybackRequiresUserGesture); + } + //Toggle whether this is enabled or not! Bundle appSettings = cordova.getActivity().getIntent().getExtras(); boolean enableDatabase = appSettings == null ? true : appSettings.getBoolean("InAppBrowserStorageEnabled", true); @@ -896,7 +908,7 @@ public class InAppBrowser extends CordovaPlugin { Log.d(LOG_TAG, "Should never happen"); } } - + /** * On received http auth request. */ @@ -912,7 +924,7 @@ public class InAppBrowser extends CordovaPlugin { } catch (IllegalAccessException e) { } catch (InvocationTargetException e) { } - + if (pluginManager == null) { try { Field pmf = webView.getClass().getField("pluginManager"); @@ -921,14 +933,13 @@ public class InAppBrowser extends CordovaPlugin { } catch (IllegalAccessException e) { } } - + if (pluginManager != null && pluginManager.onReceivedHttpAuthRequest(webView, new CordovaHttpAuthHandler(handler), host, realm)) { return; } - + // By default handle 401 like we'd normally do! super.onReceivedHttpAuthRequest(view, handler, host, realm); } } } - diff --git a/tests/resources/video.html b/tests/resources/video.html index 64ea3d1..4f167f8 100644 --- a/tests/resources/video.html +++ b/tests/resources/video.html @@ -38,5 +38,8 @@ + diff --git a/tests/tests.js b/tests/tests.js index 67dd4b6..706f3a8 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -423,7 +423,11 @@ exports.defineManualTests = function (contentEl, createActionButton) { var video_tag_tests = '

Video tag

' + '
' + - 'Expected result: open successfully in InAppBrowser with an embedded video that works after clicking the "play" button.'; + 'Expected result: open successfully in InAppBrowser with an embedded video plays automatically on iOS and Android.' + + '
' + + 'Expected result: open successfully in InAppBrowser with an embedded video plays automatically on iOS and Android.' + + '
' + + 'Expected result: open successfully in InAppBrowser with an embedded video does not play automatically on iOS and Android but rather works after clicking the "play" button.'; var local_with_anchor_tag_tests = '

Local with anchor tag

' + '
' + @@ -611,6 +615,12 @@ exports.defineManualTests = function (contentEl, createActionButton) { createActionButton('Remote Video', function () { doOpen(videohtml, '_blank'); }, 'openRemoteVideo'); + createActionButton('Remote Need User No Video', function () { + doOpen(videohtml, '_blank', 'mediaPlaybackRequiresUserAction=no'); + }, 'openRemoteNeedUserNoVideo'); + createActionButton('Remote Need User Yes Video', function () { + doOpen(videohtml, '_blank', 'mediaPlaybackRequiresUserAction=yes'); + }, 'openRemoteNeedUserYesVideo'); //Local With Anchor Tag createActionButton('Anchor1', function () { @@ -620,4 +630,3 @@ exports.defineManualTests = function (contentEl, createActionButton) { doOpen(localhtml + '#anchor2', '_blank'); }, 'openAnchor2'); }; -