Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CB-7179 (iOS): Add WKWebView support for iOS #271

Merged
merged 15 commits into from
Oct 17, 2018

Conversation

dpa99c
Copy link
Contributor

@dpa99c dpa99c commented Jun 6, 2018

Platforms affected

iOS

What does this PR do?

This PR adds support for WKWebView to the InappBrowser plugin on iOS.
It:

Additional changes in this PR include:

  • Separate UIWebView and WKWebView implementations which are invoked by an intermediate dispatcher dependent on the usewkwebview option.
  • Adds shared cookie pool via CDVWKProcessPoolFactory, enabling app Webview to share cookies with IAB Webviews (pulled from Niklas Merz)
  • Implements WKWebView delegates to make event handlers and script injection work
  • Replaces iframe bridge with WKScriptMessageHandler bridge
  • Updates the automated and manual tests for this plugin to test both webview implementations when running on iOS.

Any feedback/suggestions/bug reports/collaboration to improve the implementation in this PR would be most welcome.

What testing has been done on this change?

The automated and manual tests have been run as outlined here and all tests appear to pass for the iOS platform against both webview implementations.

Note: other platforms have not been tested because they have not been changed.

Notes

  • A restructure of the native iOS implementation was necessary in order to enable the UIWebView and WKWebView implementations to exist side-by-side.
  • No dependency has been added on cordova-plugin-wkwebview-engine for the iOS platform
    • If usewkwebview=yes is set and the WKWebView engine classes don't exist in the project, the 'loaderror' callback will be invoked when attempting to call InappBrowser.open().
    • Conditional pre-processor statements are used to detect the presence of WKWebViewEngine classes at build time to prevent build errors if not present
      • Note: the __has_include macro appears to only work in the device environment.
        • On the iOS Simulator it always evaluates to false.
        • This means the WKWebView implementation only works on devices - on the Simulator usewkwebview=yes will result in a loaderror.
    • The same classes exist in cordova-plugin-ionic-webview as in cordova-plugin-inappbrowser so usewkwebview=yes will work with both.
  • There is currently a fair bit of duplication in the UIWebView vs WKWebView implementations. This could be cleaned up with some refactoring using inheritance, although this is tricky in Objective-C (not my strongest language).
  • clearsessioncache is yet to be implemented in the WKWebView implementation. This is because the httpCookieStore interface was only added in iOS 11 and so to support iOS 10 and below, a different mechanism must be used to find and remove session cookies. This is not trivial and may not even be possible.
  • The WKWebView implementation was initially developed as a separate WKWebView-only version of this plugin: cordova-plugin-inappbrowser-wkwebview
  • A Cordova test project specifically to test switching between Webview implementations can be found here.

Checklist

  • Reported an issue in the JIRA database
  • Commit message follows the format: "CB-3232: (android) Fix bug with resolving file paths", where CB-xxxx is the JIRA ID & "android" is the platform affected.
    • CB-7179 (iOS): Add support to optionally use WKWebView for iOS
  • Added automated test coverage as appropriate for this change.
    • No additional test coverage needed as no functionality has changed, just the implementation.

@dpa99c
Copy link
Contributor Author

dpa99c commented Jun 7, 2018

Travis CI build is failing because, as noted above, the __has_include macro appears to only work in the device environment, so fails when Travis spins up the iOS Simulator 😞

@dpa99c
Copy link
Contributor Author

dpa99c commented Jun 7, 2018

@infil00p @stevengill @agrieve @shazron @purplecabbage Could you guys review this when you get a chance?

@shazron
Copy link
Member

shazron commented Jul 16, 2018

Sorry for the late review. Could you resolve the conflicts before review? Thanks!

@dpa99c dpa99c force-pushed the CB-7179 branch 2 times, most recently from 8e02526 to a3cc42d Compare July 17, 2018 21:22
@dpa99c
Copy link
Contributor Author

dpa99c commented Jul 17, 2018

@shazron I've resolved the merge conflicts and rebased to a single commit.
Hopefully you have time to review before more conflicts arise with new commits to master.

@christianliebel
Copy link

@dpa99c Does “shared cookie pool” mean that the IAB can share cookies with the WebView as well? Unfortunately, there are new merge conflicts…

@shazron Do you have any plans on when this should be merged?

@dpa99c
Copy link
Contributor Author

dpa99c commented Aug 30, 2018

@christianliebel

Does “shared cookie pool” mean that the IAB can share cookies with the WebView as well?

Yes, it uses the CDVWKProcessPoolFactory class from cordova-plugin-wkwebview-engine in order to share cookies between the Cordova app Webview and the IAB Webview so setting a cookie in one makes it available in the other. This is currently enabled by default, but could be made optional.

Unfortunately, there are new merge conflicts…

Since the master branch is being continually updated, this PR branch will undoubtedly get out of sync with it. But there's no point in me continually resolving merge conflicts if this PR is never going to be reviewed/merged.

@shazron If cordova-plugin-wkwebview-engine is integrated into cordova-ios@5, maybe it would make sense to align this PR with cordova-ios@5?

This would eliminate the need for the __has_include Objective-C macro which is used to detect the conditional presence of the cordova-plugin-wkwebview-engine classes in the build, but which only appears to work in the device environment so is currently causing the Travis CI build to fail due to tests failing in the Simulator.

@janpio
Copy link
Member

janpio commented Aug 30, 2018

Just an aside: master is being updated mainly because other PRs were reviewed and merged.

@ghost
Copy link

ghost commented Sep 3, 2018

Hi, any news when this PR will be merged and released into a new version?

@janpio
Copy link
Member

janpio commented Sep 3, 2018

As soon as 1) @dpa99c had the time to fix the conflicts, 2) someone or multiple ones from Apache Cordova (or the community, like you @rafaelberrocalj!) had time to test and review (hopefully with Approval), 3) then someone from Apache Cordova who takes the responsibility of merging the PR and finally 4) someone from Apache Cordova creates a new release of the plugin.

@dpa99c
Copy link
Contributor Author

dpa99c commented Sep 3, 2018

I have done my part and resolved the existing merge conflicts.
Hopefully the rest of the steps can follow before more conflicts arise.

Copy link
Member

@janpio janpio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-Obj-C parts of the PR look good. Left 2 comments.

README.md Outdated
@@ -136,9 +136,10 @@ instance, or the system browser.

iOS supports these additional options:

- __usewkwebview__: set to `yes` to use WKWebView engine for the InappBrowser. Omit or set to `no` (default) to use UIWebView. Note: this requires that a WKWebView engine plugin be installed in the Cordova project (e.g. [cordova-plugin-wkwebview-engine](https://github.com/apache/cordova-plugin-wkwebview-engine) or [cordova-plugin-ionic-webview](https://github.com/ionic-team/cordova-plugin-ionic-webview)).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What will happen if no WKWebView plugin is installed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If usewkwebview=yes and no WKWebView plugin is installed, the loaderror callback will be invoked with the error message "usewkwebview option specified but cordova-plugin-wkwebview-engine not present"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, got it.

2 suggestions:

  1. Change "this" in the note to "Using usewkwebview=yes requires ..."
  2. Change the loaderror callback to not refer to the specific plugin, but just mention "... but no plugin that supplies a WKWebView engine present" (or similar)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I've made tweaks based on those suggestions

@@ -76,11 +76,31 @@
<config-file target="config.xml" parent="/*">
<feature name="InAppBrowser">
<param name="ios-package" value="CDVInAppBrowser" />
<param name="onload" value="true" />
Copy link
Member

@janpio janpio Sep 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this onload param do? Couldn't find it anywhere else.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

onload specifies whether to initialize the plugin when the app controller initializes. There's some docs about it here.
It ensures that pluginInitialize() is called on app startup, rather than the first plugin invocation.

Copy link
Member

@janpio janpio Sep 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I learned something, thanks ;)

Why this change? Could this have any side effects?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It just ensures that the default values defined by pluginInitialize() are set right away at app startup.
I don't remember the exact reason it was needed (it's been a few months since I created this PR) but I'm pretty sure it was necessary.
The change is minimal and will not cause side effects.

@shazron
Copy link
Member

shazron commented Sep 8, 2018

Travis is failing with:

/var/folders/my/m6ynh3bn6tq06h7xr3js0z7r0000gn/T/tmp-38722rDILqkxoJNN/platforms/ios/HelloCordova/Plugins/cordova-plugin-inappbrowser/CDVUIInAppBrowser.m:255:39: error: use of undeclared identifier 'baseWindowLevel'

            [tmpWindow setWindowLevel:baseWindowLevel+1];

@janpio
Copy link
Member

janpio commented Sep 8, 2018

(Oh great, I think that is from another PR.)

@dpa99c
Copy link
Contributor Author

dpa99c commented Sep 8, 2018

@shazron This change was added by PR #284 which is present on master and I have merged into this branch to resolve the merge conflict.

@shazron
Copy link
Member

shazron commented Sep 9, 2018

@dpa99c Unfortunately the build issue remains, do you have the ability to fix it? It might be a merge issue that removed something, not sure what. I tested this locally by installing the plugin from your branch and the error is still there.

@dpa99c
Copy link
Contributor Author

dpa99c commented Sep 9, 2018

@shazron you were right - I missed a line from that PR when resolving the merge conflict - I've updated this PR branch to correct this and Travis CI build is no longer failing because of this.

However, the Travis job is still failing because the tests are building/running against the iOS 9.3 SDK, however the new WKWebView implementation uses some properties of the WKWebViewConfiguration class which were only introduced in the iOS 10 SDK, such as ignoresViewportScaleLimits.
Use of these properties is necessary to support options currently supported by the UIWebView implementation (enableviewportscale, allowinlinemediaplayback, mediaplaybackrequiresuseraction ).

Is building against iOS 9 SDK still a mandatory requirement for cordova-plugin-inappbrowser?

@shazron
Copy link
Member

shazron commented Sep 10, 2018

We should update it to test only against the iOS 10 SDK, and make a note of it in the release notes, and also bump a minor version at least.

@ghost
Copy link

ghost commented Sep 17, 2018

Hi, can i test this pull request somehow in config.xml?
I know it's possible use a github url/branch but i don't know a pull request.

@NiklasMerz
Copy link
Member

NiklasMerz commented Sep 17, 2018

You can install the plugin from the branch which this pull request is based on via:

cordova plugin add https://github.com/dpa99c/cordova-plugin-inappbrowser#CB-7179

@ghost
Copy link

ghost commented Sep 17, 2018

With this changes i still need to use https://github.com/apache/cordova-plugin-wkwebview-engine ?

@dpa99c
Copy link
Contributor Author

dpa99c commented Sep 17, 2018

@rafaelberrocalj yes, if you want to use the WKWebView implementation, you'll need the WKWebView engine plugin

@janpio
Copy link
Member

janpio commented Oct 3, 2018

Ok thanks, so the iOS 9.3 test I readded should probably fail.

But currently both are failing:

...
cordova-paramedic: waiting for test results
appium: Error: [execute(null,[])] getaddrinfo ENOTFOUND ondemand.saucelabs.com ondemand.saucelabs.com:80
cordova-paramedic: Tests failed to complete; ending appium session. The error is:
Error: waitForTests: Seems like device not connected to local server in 540 secs
    at null._onTimeout (/private/tmp/paramedic/lib/paramedic.js:467:24)
    at Timer.listOnTimeout (timers.js:92:15)
...

*sigh (Investigating)

@janpio
Copy link
Member

janpio commented Oct 3, 2018

And as it came it's gone - now the tests are just failing because they don't get their results from Saucelabs :/

@janpio
Copy link
Member

janpio commented Oct 3, 2018

Confirmed that the switch to Xcode8.3 is not the cause for the test failures:
#312

@dpa99c
Copy link
Contributor Author

dpa99c commented Oct 4, 2018

Confirmed that the switch to Xcode8.3 is not the cause for the test failures:
#312

OK, there must be something preventing the tests running via cordova-paramedic because when I manually start them in the Simulator, they all pass. Will setup cordova-paramedic and investigate.

@dpa99c
Copy link
Contributor Author

dpa99c commented Oct 5, 2018

@janpio I think I've figured out why the tests are failing in this PR, even in Xcode 8.3/iOS 10:

This PR requires that cordova-plugin-wkwebview-engine be present in the Cordova project so its classes can be used by the WKWebView implementation in this PR. This means the main Cordova Webview is using WKWebView instead of UIWebView. And this seems to screw up cordova-paramedic - it can no longer communicate its results back to the local server.

I confirmed this by running cordova-paramedic against your janpio-xcode8.3 branch first without cordova-plugin-wkwebview-engine present (i.e. using UIWebView):

screenshot 2018-10-05 at 21 06 20

Then with cordova-plugin-wkwebview-engine present (i.e. using WKWebView):

screenshot 2018-10-05 at 21 17 41

As you can see, in this second case the tests timed out while trying to connect to the local server, leading to the same error observed in the Travis CI logs. However, as you can see from the Simulator screenshot, all the tests passed.

I then ran the cordova-paramedic against the branch for this PR:

screenshot 2018-10-05 at 21 34 05

As you can see, a similar result: all tests passed in the Simulator, but tests failed due to a timeout connecting to the local server.

The upshot is that it seems currently cordova-paramedic is not compatible when the main Cordova Webview is WKWebView and this presents a problem for this PR which requires it to be so.

I'm guessing since UIWebView is now deprecated in iOS 12, we'll be moving at some point to make WKWebView the default Cordova Webview (in cordova-ios@5 ??), so at some point cordova-paramedic is going to need to be fixed to work with WKWebView.

@dpa99c
Copy link
Contributor Author

dpa99c commented Oct 9, 2018

Thanks to @knight9999 for helping to resolve apache/cordova-paramedic#52, Travis tests are now passing for iOS.

But failing on other platforms for some reason.

@dpa99c
Copy link
Contributor Author

dpa99c commented Oct 16, 2018

@shazron @janpio What's now blocking this PR?

All merge conflicts with master are currently resolved and the Travis CI tests are now passing for iOS. The Travis tests for "browser-edge" and "android-6.0" failed on the last run due to timeout/connectivity issues, but then the tests are currently failing on master for similar reasons.

<platform name="ios">
<!-- The WKWebView implementation for inappbrowser requires the presence of this plugin -->
<dependency id="cordova-plugin-wkwebview-engine" />
<dependency id="cordova-plugin-wkwebview-engine-allowfileaccess" url="https://github.com/knight9999/cordova-plugin-wkwebview-engine-allowfileaccess.git" />
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can’t have this dependency, even in a test ... what if knight9999 makes a commit to master? It could break our tests ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without the code in that plugin, cordova-paramedic tests fail with WKWebView.
What do you suggest? Bundle the plugin code inside tests/ within this plugin?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The plugin itself is only 2 lines. There are a couple things we could do.

  1. Ask @knight9999 to publish the allowfileaccess plugin to npm, and have our test depend on that published version.
  2. make the wk-allowfileaccess a cordova supported plugin, and also do suggestion 1, but replace Ken with 'we'
  3. revisit the decision to not allow file access directly in the wkwebview plugin, could we just default to NO, but allow the developer to turn it on? ( This would require a firm warning about app store rejection possibilities, so it might make things too easy for developers and lead to rejections. )
  4. Include it in the paramedic repo as a spec plugin, as suggested by Ken [1]

[1] apache/cordova-paramedic#52

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@knight9999 Ken, any preference in Jesse's above options?
This isn't something I can resolve myself to unblock this PR: all of the above require action on the part of Cordova maintainers and it has wider implications in terms of test support for WKWebView on iOS, i.e. for cordova-plugin-wkwebview-engine and cordova-ios@5.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I have updated my plugin to change author 'Apache Cordovaand licenseApache-2.0`.
But I think it is better to change github repository before publishing to npm. Now I am asking this to cordova members.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@svanzoest
Copy link

So the websites you display in the InAppBrowser were using local storage, which was not there after the switch to WKWebView? How did you solve this @svanzoest?

We used https://github.com/MaKleSoft/cordova-plugin-migrate-localstorage however that did not migrate the inappbrowser localstorage. @geeetarguy plans to make a PR against that repo so it will migrate inappbrowser localstorage as well.

This PR is now available MaKleSoft/cordova-plugin-migrate-localstorage#4

@purplecabbage
Copy link
Contributor

Every other way of doing this is messy and involves crazy git rebasing, so I am gonna just merge this as is, and see if I can address my concern about the test dependency in another pr.
Thanks for all you work on this @dpa99c !!

@purplecabbage purplecabbage merged commit 10a0669 into apache:master Oct 17, 2018
@dpa99c
Copy link
Contributor Author

dpa99c commented Oct 17, 2018

@purplecabbage great, thanks for unblocking this. I will be on standby to help resolve any issues with the new implementation.

@jonathanli2
Copy link
Contributor

Hi,
After upgrading our ios Fiori client application to the new inappbrowser, somehow, the content in the main webview (UIWebview or WKWebView) is disabled and cannot response to user actions. The same app works normal when using inappbrowser version 2.0.x.

I submitted an issue for this at
#334

The testing projects are shared at
https://sap-my.sharepoint.com/:f:/p/jonathan_li/EmulfDR6x9RBuQdj5u1-NrwBYchculWO6RAfoC_NTM8XLw?e=YzzUkh

Any idea for this issue?

Thanks
Jonathan

@jonathanli2
Copy link
Contributor

I created a simple iOS UIWebView cordova app with just inappbrowser plugin added into the project, and it can repeat the same issue.

The project (basictest.zip) is shared at the folder of
https://sap-my.sharepoint.com/:f:/p/jonathan_li/EmulfDR6x9RBuQdj5u1-NrwBYchculWO6RAfoC_NTM8XLw?e=YzzUkh

The project (basictest.zip) only has a simple openInappbrowser button, once index.html is opened, then clicking toolbar's done button to close the inappbrowser. After the inappbrowser is closed. Clicking on the main UIWebView's openInappbrowser button again will do nothing, it seems the main UIWebView is disabled.

This indicates the issue is in the new inappbrowser plugin's implementation.

Thanks
Jonathan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants