Skip to content
This repository has been archived by the owner on Feb 22, 2023. It is now read-only.

[webview_flutter] Implement zoom enabled for ios and android #4417

Conversation

NickalasB
Copy link
Contributor

This PR adds the iOS and Android implementations of the soon-to-be added zoomEnabled param on the WebView widget after the platform_interface method was merged in #4404.

If approved and merged, this PR will be followed up with #3325, adding zoomEnabled to the main flutter_webview package as outlined in the instructions on changing Federated Plugins.

List which issues are fixed by this PR. You must list at least one issue.
Implements flutter/flutter#70731
Implements flutter/flutter#48283
Relates to flutter/flutter#48245
Relates to flutter/flutter#60921

If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.

  • No this is not a breaking change

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the relevant style guides and ran the auto-formatter. (Note that unlike the flutter/flutter repo, the flutter/plugins repo does use dart format.)
  • I signed the CLA.
  • The title of the PR starts with the name of the plugin surrounded by square brackets, e.g. [shared_preferences]
  • I listed at least one issue that this PR fixes in the description above.
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy.
  • I updated CHANGELOG.md to add a description of the change.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test exempt.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@google-cla google-cla bot added the cla: yes label Oct 6, 2021
@NickalasB
Copy link
Contributor Author

@stuartmorgan @bparrishMines here's the 2nd PR for this plugin update. Thank you for taking a look!

@github-actions github-actions bot added p: webview_flutter Edits files for a webview_flutter plugin platform-android platform-ios labels Oct 6, 2021
@@ -63,6 +63,17 @@ - (void)webView:(WKWebView *)webView
}

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
if (!self.shouldEnableZoom) {
Copy link
Contributor

Choose a reason for hiding this comment

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

What would happen if shouldEnableZoom was changed without the page reloading? Shouldn't this also be called for the current webpage along with every call to didFinishNavigation.

Copy link
Contributor Author

@NickalasB NickalasB Oct 7, 2021

Choose a reason for hiding this comment

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

That makes sense but I'm not totally sure where you are suggesting I should also make this check? Inside decidePolicyForNavigationAction?

Copy link
Contributor

Choose a reason for hiding this comment

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

This workaround actually makes me question if this feature should even be supported by iOS directly. I'm leaning towards that a platform shouldn't support a feature from the platform interface unless it is directly supported by the API or there is a reasonable workaround. And I wouldn't consider running java script as a reasonable workaround.

@stuartmorgan Do we have a policy for this already?

cc @mvanbeusekom

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, the WKWebView API doesn't provide a built-in way of toggling whether or not zoom is enabled. This workaround was intended to at least allow Flutter devs to toggle that on both Android and iOS. The original intention of this work was strictly to ENABLE zoom for Android as that functionality is currently missing. My background is in Android but in my research, I couldn't find a cleaner way of DISABLING zoom for iOS.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

One other proposal, although it would require reverting #4404, is to just enable zooming for Android, and not make it togglable in the Flutter WebView. That would basically only require code-changes to webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/WebViewBuilder.java. Could just be me but it doesn't seem like there are many valid use-cases for disabling zoom... which is probably why the WKWebView API doesn't provide a way to do it. Again, appreciate the team helping move this forward so we can get off our fork.

Copy link
Contributor

Choose a reason for hiding this comment

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

And I wouldn't consider running java script as a reasonable workaround.

I can see this either way. I spent years working on a project that attempted to make UIWebView usable in a browser context though, and basically everything had to be done with JS in that case, so my judgement on this may well be skewed.

In this case, my take was:

  • The code being run here seems pretty benign. I.e., I would not expect it to have much likelihood of causing problems for pages.
  • It's only run if the plugin client explicitly turns off zoom. I would not expect that to be common, so problems would be relegated to edge cases of edge cases.

Given that my feeling is that it's reasonable to provide a best-effort implementation rather than nothing, as if someone is explicitly trying to turn on this behavior they presumably would want it to work on iOS too.

@stuartmorgan Do we have a policy for this already?

We don't have an explicit policy. There are obvious cases where we would say no, like use of private API on iOS, but this isn't doing anything like that, and using JS as a polyfill for OS web view limitations is something that definitely has a history of being relatively common on iOS, so I don't think this is a clear-cut case of "unreasonable".

Copy link
Contributor

Choose a reason for hiding this comment

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

That makes sense. Then I'm fine with the current implementation of the feature. I would just make it clear how the feature works on iOS in the followup PR for webview_flutter.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you both!

@stuartmorgan stuartmorgan self-requested a review October 7, 2021 20:05
Copy link
Contributor

@bparrishMines bparrishMines left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@stuartmorgan stuartmorgan left a comment

Choose a reason for hiding this comment

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

Mostly looks good, but I'm not seeing any iOS tests here. The iOS part of this needs test coverage as well.

@NickalasB
Copy link
Contributor Author

@stuartmorgan I noticed there are no existing iOS tests in the flutter_webview_wkwebview package so I wasn't totally sure where to start with that.

@bparrishMines
Copy link
Contributor

@NickalasB Ios tests are found in plugins/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/. Since you said you were more familiar with Android, let me know if you need help with writing the tests or you would like me to write them.

@NickalasB
Copy link
Contributor Author

NickalasB commented Oct 14, 2021

@NickalasB Ios tests are found in plugins/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerTests/. Since you said you were more familiar with Android, let me know if you need help with writing the tests or you would like me to write them.

@bparrishMines Lol. Knowing where the tests are definitely helps! I'd like to take a stab at them myself. If I get stuck I will definitely take you up on your offer to help. Thank you!

@stuartmorgan
Copy link
Contributor

@bparrishMines Lol. Knowing where the tests are definitely helps!

This is documented at https://github.com/flutter/flutter/wiki/Plugin-Tests#types-of-tests; suggestions for how to make that easier to find are welcome (although it may just be that since the original PR predates that page, you just never saw the newer version of the contribution guide that links there).

@NickalasB
Copy link
Contributor Author

NickalasB commented Oct 14, 2021

@bparrishMines alright- after looking at the test classes, I do think I could use some help constructing the tests. I think this is basically along the lines of the correct assertion below in pseudocode but I also realize it's way off...

- (void)testWebViewWebEvaluateJavaScriptSourceIsCorrectWhenShouldEnableZoomIsFalse {
	given self.navigationDelegate.shouldEnableZoom == false;
	when webview.didFinishNavigation;
	then XCTAssertEqual(webView.javaScriptString,
      					@"var meta = document.createElement('meta');"
        				@"meta.name = 'viewport';"
        				@"meta.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0,"
        				@"user-scalable=no';"
       					@"var head = document.getElementsByTagName('head')[0];head.appendChild(meta);");
}

Again- thank you for the help here

@bparrishMines
Copy link
Contributor

@NickalasB That solution looks fine. You could also pass the test NavigationDelegate a mock WkWebView and use verify to check that evaluateJavaScript was called when didFinishNavigation was called.

OCMClassMock(WKWebView.class);
OCMVerify([_mockWebView evaluateJavaScript:/*check parameters*/]);

@NickalasB
Copy link
Contributor Author

@NickalasB That solution looks fine. You could also pass the test NavigationDelegate a mock WkWebView and use verify to check that evaluateJavaScript was called when didFinishNavigation was called.

OCMClassMock(WKWebView.class);
OCMVerify([_mockWebView evaluateJavaScript:/*check parameters*/]);

@bparrishMines @stuartmorgan Finally figured out a way to write the iOS tests. Apologize for the churn. My lack of experience with OC didn't help.

iOS tests added in 74addca

(cherry picked from commit 5238f60)
* master:
  [webview] Fix typos in the README (flutter#4249)
  [google_sign_in] add serverAuthCode to GoogleSignInAccount (flutter#4180)
  [ci] Update macOS Cirrus image to Xcode 13 (flutter#4429)
  [shared_preferences] Switch to new analysis options (flutter#4384)
  [flutter_plugin_android_lifecycle] remove placeholder dart file (flutter#4413)
  [camera] Run iOS methods on UI thread by default (flutter#4140)
  [ci] Always run all `format` steps (flutter#4427)
  [flutter_plugin_tools] Fix license-check on Windows (flutter#4425)
  [google_maps_flutter] Clean Java test, consolidate Marker example. (flutter#4400)
  [image_picker][android] suppress unchecked warning (flutter#4408)
  [ci] Replace Firebase Test Lab deprecated Pixel 4 device with Pixel 5 (flutter#4436)
  [image_picker_for_web] Added support for maxWidth, maxHeight and imageQuality  (flutter#4389)
  Bump compileSdkVersion to 31 (flutter#4432)
  [camera] Update [CameraOrientationTests testOrientationNotifications] unit test to work on Xcode 13 (flutter#4426)
  Update integration_test README  (flutter#3824)
  [webview_flutter] Adjust test URLs again (flutter#4407)
  [google_sign_in] Add serverAuthCode attribute to google_sign_in_platform_interface user data (flutter#4179)
  [camera] Add filter for unsupported cameras on Android (flutter#4418)
Copy link
Contributor

@stuartmorgan stuartmorgan left a comment

Choose a reason for hiding this comment

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

Minor nits, but otherwise LGTM

* Formatting and minor test cleanup
* master:
  Implement Android WebView api with pigeon (Java portion) (flutter#4441)
  [in_app_purchase] Update to the latest pkg:json_serializable (flutter#4434)
  Implement Android WebView api with pigeon (Dart portion)  (flutter#4435)
  upgraded usage of BinaryMessenger (flutter#4451)
  [flutter_plugin_tools] Fix pubspec-check on Windows (flutter#4428)
  Use OpenJDK 11 in CI jobs  (flutter#4419)
  [google_sign_in] remove the commented out code in tests (flutter#4442)
@NickalasB
Copy link
Contributor Author

Comments addressed @stuartmorgan. Thank you again

Copy link
Contributor

@stuartmorgan stuartmorgan left a comment

Choose a reason for hiding this comment

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

LGTM!

@stuartmorgan
Copy link
Contributor

The iOS failure is a Cirrus bug that we're waiting for them to resolve; once that's green we can get this landed!

@bparrishMines This is one of the PRs I was mentioning that I want to go ahead and land as it's already done; it should be easy to fold into your PR though.

@stuartmorgan stuartmorgan added last mile waiting for tree to go green (Use "autosubmit") This PR is approved and tested, but waiting for the tree to be green to land. labels Oct 27, 2021
@fluttergithubbot fluttergithubbot merged commit bb62aaa into flutter:master Oct 27, 2021
@NickalasB NickalasB deleted the implement_zoomEnabled_for_ios_and_android branch October 27, 2021 23:16
NickalasB added a commit to NickalasB/plugins that referenced this pull request Oct 27, 2021
* master:
  [ci.yaml] Main branch support (flutter#4440)
  [video_player] Initialize player when size and duration become available (flutter#4438)
  [webview_flutter] Implement zoom enabled for ios and android (flutter#4417)
  Partial revert of "upgraded usage of BinaryMessenger (flutter#4451)" (flutter#4453)
hofmannfelix pushed a commit to hofmannfelix/plugins that referenced this pull request Oct 30, 2021
…ideo_src_on_same_controller

* commit '76e84c0679dbab7bfaaaa553b17bb0dbdb9a3c33': (537 commits)
  [video_player] Initialize player when size and duration become available (flutter#4438)
  [webview_flutter] Implement zoom enabled for ios and android (flutter#4417)
  Partial revert of "upgraded usage of BinaryMessenger (flutter#4451)" (flutter#4453)
  Implement Android WebView api with pigeon (Java portion) (flutter#4441)
  [in_app_purchase] Update to the latest pkg:json_serializable (flutter#4434)
  Implement Android WebView api with pigeon (Dart portion)  (flutter#4435)
  upgraded usage of BinaryMessenger (flutter#4451)
  [flutter_plugin_tools] Fix pubspec-check on Windows (flutter#4428)
  Use OpenJDK 11 in CI jobs  (flutter#4419)
  [google_sign_in] remove the commented out code in tests (flutter#4442)
  [webview] Fix typos in the README (flutter#4249)
  [google_sign_in] add serverAuthCode to GoogleSignInAccount (flutter#4180)
  [ci] Update macOS Cirrus image to Xcode 13 (flutter#4429)
  [shared_preferences] Switch to new analysis options (flutter#4384)
  [flutter_plugin_android_lifecycle] remove placeholder dart file (flutter#4413)
  [camera] Run iOS methods on UI thread by default (flutter#4140)
  [ci] Always run all `format` steps (flutter#4427)
  [flutter_plugin_tools] Fix license-check on Windows (flutter#4425)
  [google_maps_flutter] Clean Java test, consolidate Marker example. (flutter#4400)
  [image_picker][android] suppress unchecked warning (flutter#4408)
  ...

# Conflicts:
#	packages/video_player/video_player/pubspec.yaml
#	packages/video_player/video_player_web/lib/video_player_web.dart
#	packages/video_player/video_player_web/pubspec.yaml
amantoux pushed a commit to amantoux/plugins that referenced this pull request Dec 11, 2021
KyleFin pushed a commit to KyleFin/plugins that referenced this pull request Dec 21, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
cla: yes p: webview_flutter Edits files for a webview_flutter plugin platform-android platform-ios waiting for tree to go green (Use "autosubmit") This PR is approved and tested, but waiting for the tree to be green to land.
Projects
None yet
4 participants