Skip to content

Conversation

@khaled-0
Copy link

@khaled-0 khaled-0 commented Jan 20, 2026

This pr adds a way to retrive cookies from webview by using native platform api provided by CookieManager and WKHTTPCookieStore

Addresses flutter/flutter#27795

Pre-Review Checklist

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

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

Footnotes

  1. Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling. 2 3

@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging.

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group.

@khaled-0
Copy link
Author

I don't know how I should go about writing test for this change, so I'm looking for suggestions.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces the getCookies method to WebViewCookieManager, enabling retrieval of cookies from webviews on both Android and iOS/macOS. The implementation is backed by native platform APIs. My review identifies a few critical issues in the platform-specific implementations. On Android, the cookie string parsing is not robust and can fail if cookie values contain certain characters. On the WebKit (iOS/macOS) side, there's an unsafe access to cookie properties that could lead to creating invalid WebViewCookie objects. I've also suggested a small improvement to the WebViewCookie.toString() method for better debuggability.

Comment on lines +102 to +112
final List<WebViewCookie> webViewCookies = List.of([]);
for (final String cookie in cookies.split('; ')) {
final List<String> cookieValue = cookie.split('=');
webViewCookies.add(
WebViewCookie(
name: cookieValue.first,
value: cookieValue.last,
domain: domain.toString(),
),
);
}

Choose a reason for hiding this comment

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

high

The current cookie parsing logic using cookie.split('=') and accessing .first and .last is not robust. If a cookie's value contains an = character, the value will be truncated, and only the part after the last = will be used. This leads to incorrect cookie values.

A safer approach is to find the first occurrence of = to separate the name and value. Also, initializing the list with <WebViewCookie>[] is more idiomatic than List.of([]).

    final List<WebViewCookie> webViewCookies = <WebViewCookie>[];
    for (final String cookie in cookies.split('; ')) {
      final int separatorIndex = cookie.indexOf('=');
      if (separatorIndex == -1) {
        continue;
      }
      webViewCookies.add(
        WebViewCookie(
          name: cookie.substring(0, separatorIndex),
          value: cookie.substring(separatorIndex + 1),
          domain: domain.toString(),
        ),
      );
    }

Copy link
Author

Choose a reason for hiding this comment

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

It won't, because cookies are URL encoded

Comment on lines +94 to +99
return WebViewCookie(
name: props[HttpCookiePropertyKey.name].toString(),
value: props[HttpCookiePropertyKey.value].toString(),
domain: props[HttpCookiePropertyKey.domain].toString(),
path: props[HttpCookiePropertyKey.path].toString(),
);

Choose a reason for hiding this comment

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

high

The current implementation for creating a WebViewCookie from properties is unsafe. It uses .toString() on map values that can be null. If a property like name, value, or domain is missing from the props map, this will result in a WebViewCookie with fields containing the string 'null', which is incorrect. For path, it should fall back to the default value '/' if it's missing.

For required fields like name, value, and domain, if they are missing, the cookie is invalid and should be skipped.

      final Object? name = props[HttpCookiePropertyKey.name];
      final Object? value = props[HttpCookiePropertyKey.value];
      final Object? domain = props[HttpCookiePropertyKey.domain];

      if (name == null || value == null || domain == null) {
        return null;
      }

      return WebViewCookie(
        name: name.toString(),
        value: value.toString(),
        domain: domain.toString(),
        path: props[HttpCookiePropertyKey.path]?.toString() ?? '/',
      );


@override
String toString() {
return 'WebViewCookie{name: $name, domain: $domain, path: $path}';

Choose a reason for hiding this comment

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

medium

The toString() implementation omits the value of the cookie. Including the value would be very helpful for debugging purposes.

Suggested change
return 'WebViewCookie{name: $name, domain: $domain, path: $path}';
return 'WebViewCookie{name: $name, value: $value, domain: $domain, path: $path}';

Copy link
Author

Choose a reason for hiding this comment

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

no.

Copy link
Contributor

Choose a reason for hiding this comment

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

toString more often than not, is for debugging only (sometimes the compiler will optimize this override out). I wonder what is WebViewCookie toString for (is it still debug-only?) and why value shouldn't be included?

@stuartmorgan-g
Copy link
Collaborator

  • All existing and new tests are passing.

Please follow these instructions so that CI can run.

I don't know how I should go about writing test for this change, so I'm looking for suggestions.

What specifically are you looking for in terms of guidance here? Have you looked at the existing tests (native and Dart) for these packages? We have significant test coverage, so there should be clear examples to follow.

@stuartmorgan-g stuartmorgan-g added the federated: all_changes PR that contains changes for all packages for a federated plugin change label Jan 20, 2026
@khaled-0
Copy link
Author

@stuartmorgan-g all relevant tests are passing now
I have added cookie related tests as well

@stuartmorgan-g stuartmorgan-g added triage-ios Should be looked at in iOS triage triage-android Should be looked at in Android triage labels Jan 21, 2026
@stuartmorgan-g
Copy link
Collaborator

Adding to the review triage queues.

The tool-created changes to webview_flutter_web can be reverted since there are no actual changes in that package.

/// This is a no op on iOS versions below 11.
Future<void> setCookie(WebViewCookie cookie) => platform.setCookie(cookie);

/// Gets a list of existing cookie for all or specified domain for all WebViews.
Copy link
Contributor

Choose a reason for hiding this comment

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

What does "all WebViews" mean? All webviews in the app or in the device?

Copy link
Author

Choose a reason for hiding this comment

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

in the app. should be obvious. I used existing comments as a reference


@override
String toString() {
return 'WebViewCookie{name: $name, domain: $domain, path: $path}';
Copy link
Contributor

Choose a reason for hiding this comment

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

toString more often than not, is for debugging only (sometimes the compiler will optimize this override out). I wonder what is WebViewCookie toString for (is it still debug-only?) and why value shouldn't be included?

}

/// Gets a list of existing cookie for all or specified domain for all WebViews.
/// Android: Entire domain must be provided alongside scheme
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: this needs a new line after the first paragraph.

Copy link
Contributor

Choose a reason for hiding this comment

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

Same question regarding all WebViews. Also, something like sounds a bit more explicit about how to get cookies for all domains:

Gets a list of existing cookies for all WebViews for the specified domain, or for all domains if domain is not specified.


/// Gets a list of existing cookie for all or specified domain for all WebViews.
/// Android: Entire domain must be provided alongside scheme
/// iOS: ignores scheme and supports partial match based on host
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: missing periods at the end of both sentences (here and everywhere). Also macOS?

Copy link
Author

Choose a reason for hiding this comment

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

iOS and MacOS, I'll update the comments

domain: String?,
completion: @escaping (Result<[HTTPCookie], any Error>) -> Void
) {
if domain == nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

uber nit: could you get rid of the ! by using if let / guard let?

}

pigeonInstance.getAllCookies { cookies in
completion(.success(cookies.filter { $0.domain.contains(domain!) }))
Copy link
Contributor

Choose a reason for hiding this comment

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

if we're doing the filtering ourselves, then why do we have the limitation that Android can only do full domain matching (And also does this have to be part of the API? since the caller can do that themselves too)?

Copy link
Author

Choose a reason for hiding this comment

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

we're only doing the filtering on ios/macos side. (to match behavior on both platform)

Android has no way of getting cookies for all domain so passing a specific domain is necessary.

await webViewController.runJavaScriptReturningResult('document.cookie')
as String;
final Uri? domain = Uri.tryParse(
(await webViewController.currentUrl()) ?? '',
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm this changes the behavior of the sample app I think? If currentUrl is null before the change the page would be empty right?

Copy link
Author

@khaled-0 khaled-0 Jan 22, 2026

Choose a reason for hiding this comment

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

well yes kinda, it would print all the cookies for all domain if currentUrl is null for ios/macos

@mdebbar mdebbar removed their request for review January 22, 2026 15:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

federated: all_changes PR that contains changes for all packages for a federated plugin change p: webview_flutter platform-android platform-ios platform-macos platform-web triage-android Should be looked at in Android triage triage-ios Should be looked at in iOS triage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants