Skip to content

[iOS] Prepare CWVWebView web embedder for use in iOS #26957

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

Merged
merged 14 commits into from
Feb 27, 2025

Conversation

kylehickinson
Copy link
Collaborator

@kylehickinson kylehickinson commented Dec 10, 2024

This is the split-up contents of #24657. This PR in particular only adds the CWVWebView API and exposes it to the iOS app but does not actually contain the code that uses CWVWebView in the iOS app. There is a shell target added (WebShell) for simple tests, for more comprehensive tests involving multiple tabs, please use the ios-cwvwebview-impl branch

Resolves brave/brave-browser#42838

Submitter Checklist:

  • I confirm that no security/privacy review is needed and no other type of reviews are needed, or that I have requested them
  • There is a ticket for my issue
  • Used Github auto-closing keywords in the PR description above
  • Wrote a good PR/commit description
  • Squashed any review feedback or "fixup" commits before merge, so that history is a record of what happened in the repo, not your PR
  • Added appropriate labels (QA/Yes or QA/No; release-notes/include or release-notes/exclude; OS/...) to the associated issue
  • Checked the PR locally:
    • npm run test -- brave_browser_tests, npm run test -- brave_unit_tests wiki
    • npm run presubmit wiki, npm run gn_check, npm run tslint
  • Ran git rebase master (if needed)

Reviewer Checklist:

  • A security review is not needed, or a link to one is included in the PR description
  • New files have MPL-2.0 license header
  • Adequate test coverage exists to prevent regressions
  • Major classes, functions and non-trivial code blocks are well-commented
  • Changes in component dependencies are properly reflected in gn
  • Code follows the style guide
  • Test plan is specified in PR before merging

After-merge Checklist:

Test Plan:

@kylehickinson kylehickinson added CI/skip-android Do not run CI builds for Android CI/skip-macos-x64 Do not run CI builds for macOS x64 CI/skip-windows-x64 Do not run CI builds for Windows x64 CI/skip-macos-arm64 Do not run CI builds for macOS arm64 CI/skip-teamcity Do not run builds in TeamCity labels Dec 10, 2024
@kylehickinson kylehickinson self-assigned this Dec 10, 2024
@kylehickinson kylehickinson requested review from a team as code owners December 10, 2024 18:15
@kylehickinson kylehickinson force-pushed the ios-cwvwebview-core branch 2 times, most recently from 66c250f to 18f7570 Compare January 13, 2025 14:48
@kylehickinson kylehickinson requested a review from a team as a code owner January 13, 2025 14:48
@kylehickinson kylehickinson force-pushed the ios-cwvwebview-core branch 2 times, most recently from 58f7166 to dbd74e5 Compare January 24, 2025 20:15
Copy link
Contributor

Chromium major version is behind target branch (132.0.6834.111 vs 133.0.6943.27). Please rebase.

@github-actions github-actions bot added the chromium-version-mismatch The Chromium version on the PR branch does not match the version on the target branch label Jan 27, 2025
@github-actions github-actions bot removed the chromium-version-mismatch The Chromium version on the PR branch does not match the version on the target branch label Jan 27, 2025
@@ -0,0 +1,2 @@
# Common linting false posititives from Obj-C syntax in headers
filter=-readability/casting,-whitespace/parens,-whitespace/operators
Copy link
Collaborator

Choose a reason for hiding this comment

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

why do we have an issue with this if upstream doesn't have it in their config?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Im not sure, we have the same issue in our own ios folder https://github.com/brave/brave-core/blob/master/ios/CPPLINT.cfg

Copy link
Collaborator

Choose a reason for hiding this comment

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

what specifically is triggering it?

Copy link
Collaborator Author

@kylehickinson kylehickinson Jan 30, 2025

Choose a reason for hiding this comment

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

src/brave/chromium_src/ios/web_view/internal/cwv_web_view_configuration_internal.h:34:  (cpplint) Using C-style cast.  Use reinterpret_cast<CWVWebView*>(...) instead  [readability/casting] [4]

src/brave/chromium_src/ios/web_view/internal/cwv_web_view_internal.h:15:  (cpplint) Using C-style cast.  Use reinterpret_cast<NSData*>(...) instead  [readability/casting] [4]
** Presubmit Messages: 1 **

The actual lines it references don't make sense. For instance the first one is just a standard Obj-C method:

- (void)registerWebView:(CWVWebView*)webView;

The second is

+ (BOOL)_isRestoreDataValid:(NSData*)data;

Copy link
Collaborator

Choose a reason for hiding this comment

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

cc @goodov if you have any ideas?

@@ -0,0 +1,4 @@
include_rules = [
"+brave/components/https_upgrade_exceptions/browser",
"+brave/ios/browser/application_context",
Copy link
Collaborator

Choose a reason for hiding this comment

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

this can probably go in chromium_src/ios/chrome/browser/DEPS

// (usually by crashing, though possibly by other means).
- (void)webViewWebContentProcessDidTerminate:(CWVWebView*)webView;

+- (BOOL)webView:(CWVWebView*)webView shouldBlockUniversalLinksForRequest:(NSURLRequest*)request;
Copy link
Collaborator

Choose a reason for hiding this comment

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

#define webViewWebContentProcessDidTerminate webView:(CWVWebView*)webView didRequestHTTPAuthForProtectionSpace... rest of methods we add... webViewWebContentProcessDidTerminate

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We can't use chromium_src overrides for these public headers because they are copied into the BraveCore framework target (public headers folder), so they have to be patched at rest

#pragma mark - Autofill

- (CWVAutofillController*)autofillController {
+ BRAVE_NOP_SERVICE
Copy link
Collaborator

Choose a reason for hiding this comment

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

can we override AutofillAgent to be a no-op?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We could be this is still to ensure you cant access it from the CWVWebView property

}

[self attachSecurityInterstitialHelpersToWebStateIfNecessary];
+ BRAVE_ATTACH_TAB_HELPERS
Copy link
Collaborator

Choose a reason for hiding this comment

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

why are we attaching general tab helpers here? Shouldn't this happen automatically through BrowserWebStateListDelegate if we are adding them in upstream AttachTabHelpers?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

None of the ios/web_view parts go through Browser/WebStateList

#pragma mark - Translation

- (CWVTranslationController*)translationController {
+ BRAVE_NOP_SERVICE
Copy link
Collaborator

Choose a reason for hiding this comment

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

same as below

}()

@dynamicMemberLookup
class WebViewModel: ObservableObject {
Copy link
Collaborator

Choose a reason for hiding this comment

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

What is the class for/what does it do? Please add comments

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sorry this was just thrown together to demonstrate the CWVWebView in a small shell app. This code specifically model glue for SwiftUI so the shell UI updates properly when observable properties change

Copy link
Collaborator

Choose a reason for hiding this comment

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

oic, this was the thing I was asking about to run

Copy link
Collaborator

Choose a reason for hiding this comment

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

can you add comments explaining?

return (cachedProtobufStorage != nil || cachedSessionStorage != nil);
}

+ (id)objectFromValue:(const base::Value*)value {
Copy link
Collaborator

Choose a reason for hiding this comment

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

why does this need to be a method on CWVWebView? Can't we just use NSObjectFromValue directly?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Its a function in an anonymous namespace defined in cwv_web_view.mm and not exposed in cwv_web_view_internal.h so this seemed like the easiest solution: https://source.chromium.org/chromium/chromium/src/+/main:ios/web_view/internal/cwv_web_view.mm;l=114

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we should keep the same name and not drop NS?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It'd be against typical Obj-C naming conventions, you don't include the class prefixes in the method naming

Copy link
Collaborator

Choose a reason for hiding this comment

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

this is effectively private since it's internal, right? It can only be used within CWVWebView?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Correct

"//brave/ios/web_view/public/cwv_ssl_status_extras.h",
"//brave/ios/web_view/public/cwv_x509_certificate_extras.h",
"//brave/ios/web_view/public/cwv_web_view_extras.h",

Copy link
Collaborator

Choose a reason for hiding this comment

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

empty line?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

To separate the //brave specific extras and the headers coming from Chromium's //ios/web_view

* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
// Copyright (c) 2019 The Brave Authors. All rights reserved.
Copy link
Collaborator

Choose a reason for hiding this comment

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

we backdated it?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This file was moved into the web subdirectory to match chromium, but its been around since 2019


/// A list of default website preferences.
OBJC_EXPORT
@interface DefaultHostContentSettings : NSObject
Copy link
Collaborator

Choose a reason for hiding this comment

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

this is fine for now, but we should really have an api wrapper for host content settings map in general

features.push_back(
security_interstitials::IOSSecurityInterstitialJavaScriptFeature::
GetInstance());
features.push_back(translate::TranslateJavaScriptFeature::GetInstance());
Copy link
Collaborator

Choose a reason for hiding this comment

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

I thought we weren't using chromium translate?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We actually are now but not through JavaScriptFeature, this is actually supposed to be removed though until we can properly support it as a JavaScriptFeature

}));
}

- (WKWebView*)underlyingWebView {
Copy link
Collaborator

Choose a reason for hiding this comment

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

why aren't we just exposing the CRWWebController as an attribute and then we can also use that for createPDF, etc...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

As per DM:

  • We don't want to expose CRWWebController as its essentially the WKWebView handler, which we want to avoid using and overtime will use it less (for when we eventually can support a use_blink build)
  • We can't expose CRWWebController as-is, would have to wrap it anyways

Copy link
Collaborator

Choose a reason for hiding this comment

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

discussed in DM, but maybe this should be internalWebView or something?

config_provider.UpdateScripts();
}

- (void)createPDF:(void (^)(NSData* _Nullable))completionHandler {
Copy link
Collaborator

Choose a reason for hiding this comment

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

createFullPagePdf to match upstream method. It's much easier to find things when names match

Copy link
Collaborator

@bridiver bridiver left a comment

Choose a reason for hiding this comment

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

lgtm after removing https upgrade code that needs fixes in desktop first

Copy link
Contributor

[puLL-Merge] - brave/brave-core@26957

Description

This PR adds support for CWVWebView (Chromium WebView) integration in Brave iOS, allowing Brave to reuse Chromium's WebKit implementation while adding Brave-specific features and customizations. The changes include:

  1. Integration of CWVWebView functionality into Brave's codebase
  2. Implementation of Brave-specific web features and protections
  3. Addition of a WebShell test app for validating web view functionality
  4. Override and extension of Chromium's web view implementation
Changes

Changes

By File Category:

Core Web Client Changes:

  • brave_web_client.h/mm: Updates web client implementation to support Brave features
  • brave_web_main_parts.h/mm: Modified web main parts initialization

WebView Extensions:

  • cwv_web_view_extras.h/mm: Adds Brave-specific functionality to CWVWebView
  • cwv_ssl_status_extras.h/mm: Extended SSL status functionality
  • cwv_x509_certificate_extras.h/mm: Additional certificate handling capabilities

Build & Project Config:

  • Added new WebShell.xcscheme
  • Modified Client.xcodeproj to include WebShell target
  • Updated various BUILD.gn and DEPS files

Test App:

  • Added WebShell test application with SwiftUI implementation
  • WebShellApp.swift: Main app entry point
  • ContentView.swift: UI implementation for testing web view features
sequenceDiagram
    participant App as WebShell App
    participant Core as BraveCoreMain
    participant WebView as CWVWebView
    participant Client as WebClient
    
    App->>Core: Initialize
    Core->>Client: Configure WebClient
    App->>Core: Get WebViewConfiguration
    Core-->>App: Return configuration
    App->>WebView: Create with configuration
    WebView->>Client: Setup navigation handlers
    WebView->>WebView: Attach Brave features
    App->>WebView: Load initial URL
    WebView->>Client: Process navigation
Loading

Security Hotspots

  1. JavascriptFeature implementations - these need to be carefully reviewed as they offer direct page script access
  2. SSL certificate and error handling - critical security UI elements must accurately reflect security states
  3. Universal link handling - proper URL validation needed to prevent malicious redirects

Possible Issues

  1. Memory management for browser state cleanup between regular and private browsing
  2. Performance impact of additional security checks during navigation
  3. Compatibility concerns with existing Chrome iOS features when using Brave's modifications

@kylehickinson kylehickinson merged commit 1f2ba13 into master Feb 27, 2025
18 checks passed
@kylehickinson kylehickinson deleted the ios-cwvwebview-core branch February 27, 2025 17:01
@github-actions github-actions bot added this to the 1.78.x - Nightly milestone Feb 27, 2025
@brave-builds
Copy link
Collaborator

Released in v1.78.4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CI/skip-android Do not run CI builds for Android CI/skip-macos-arm64 Do not run CI builds for macOS arm64 CI/skip-macos-x64 Do not run CI builds for macOS x64 CI/skip-teamcity Do not run builds in TeamCity CI/skip-windows-x64 Do not run CI builds for Windows x64 puLL-Merge
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add support for using Chromium's web embedder CWVWebView
4 participants