Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…t-native-webview

* 'master' of https://github.com/react-native-webview/react-native-webview:
  chore(docs): Update Instructions for Windows WebView Scrolling (react-native-webview#1927)
  chore(docs): Add multiDex error to the common issues section (react-native-webview#1921)
  chore(release): 11.3.1 [skip ci]
  fix(windows): Check UAP contract version before calling FrameworkElement.IsLoaded (react-native-webview#1858)
  fix(android:) enable DRM protected content (react-native-webview#1862)
  chore(release): 11.3.0 [skip ci]
  feat(ios): Add support for `limitsNavigationsToAppBoundDomains` (react-native-webview#1662)
  chore(release): 11.2.6 [skip ci]
  fix(ios): Add missing nullability specifiers; fix if block warning (react-native-webview#1898)
  chore(release): 11.2.5 [skip ci]
  chore(docs): Clarify that navigationType and isTopFrame is iOS only (react-native-webview#1880)
  chore(docs): fixed "postMessage" url in Reference.md (react-native-webview#1913)
  fix(iOS): webview retain cycle (react-native-webview#1916)
  chore(release): 11.2.4 [skip ci]
  fix(iOS): Send cookies with resource requests (react-native-webview#1803)
  chore(release): 11.2.3 [skip ci]
  fix(android): Fix full=screen video when in modals (react-native-webview#1748 by @cristianoccazinsp)
  chore(release): 11.2.2 [skip ci]
  fix(windows): Resolve Deploy Issue (react-native-webview#1850)
  • Loading branch information
Bogdan committed Mar 23, 2021
2 parents 49b8910 + 9d9fda8 commit e34e1ea
Show file tree
Hide file tree
Showing 13 changed files with 140 additions and 26 deletions.
1 change: 1 addition & 0 deletions README.md
Expand Up @@ -76,6 +76,7 @@ For more, read the [API Reference](./docs/Reference.md) and [Guide](./docs/Guide
## Common issues

- If you're getting `Invariant Violation: Native component for "RNCWebView does not exist"` it likely means you forgot to run `react-native link` or there was some error with the linking process
- If you encounter a build error during the task `:app:mergeDexRelease`, you need to enable multidex support in `android/app/build.gradle` as discussed in [this issue](https://github.com/react-native-webview/react-native-webview/issues/1344#issuecomment-650544648)

## Contributing

Expand Down
Expand Up @@ -736,8 +736,25 @@ public void onShowCustomView(View view, CustomViewCallback callback) {
}

mVideoView.setBackgroundColor(Color.BLACK);
getRootView().addView(mVideoView, FULLSCREEN_LAYOUT_PARAMS);
mWebView.setVisibility(View.GONE);

// since RN's Modals interfere with the View hierarchy
// we will decide which View to Hide if the hierarchy
// does not match (i.e., the webview is within a Modal)
// NOTE: We could use mWebView.getRootView() instead of getRootView()
// but that breaks the Modal's styles and layout, so we need this to render
// in the main View hierarchy regardless.
ViewGroup rootView = getRootView();
rootView.addView(mVideoView, FULLSCREEN_LAYOUT_PARAMS);

// Different root views, we are in a Modal
if(rootView.getRootView() != mWebView.getRootView()){
mWebView.getRootView().setVisibility(View.GONE);
}

// Same view hierarchy (no Modal), just hide the webview then
else{
mWebView.setVisibility(View.GONE);
}

mReactContext.addLifecycleEventListener(this);
}
Expand All @@ -748,14 +765,17 @@ public void onHideCustomView() {
return;
}

mVideoView.setVisibility(View.GONE);
getRootView().removeView(mVideoView);
mCustomViewCallback.onCustomViewHidden();
// same logic as above
ViewGroup rootView = getRootView();

mVideoView = null;
mCustomViewCallback = null;
if(rootView.getRootView() != mWebView.getRootView()){
mWebView.getRootView().setVisibility(View.VISIBLE);
}

mWebView.setVisibility(View.VISIBLE);
// Same view hierarchy (no Modal)
else{
mWebView.setVisibility(View.VISIBLE);
}


if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
Expand All @@ -770,6 +790,15 @@ public void onHideCustomView() {
mReactContext.getCurrentActivity().setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}


rootView.removeView(mVideoView);
mCustomViewCallback.onCustomViewHidden();

mVideoView = null;
mCustomViewCallback = null;

mReactContext.getCurrentActivity().setRequestedOrientation(initialRequestedOrientation);

mReactContext.removeLifecycleEventListener(this);
}
};
Expand Down Expand Up @@ -1122,6 +1151,8 @@ public void onPermissionRequest(final PermissionRequest request) {
permissions.add(Manifest.permission.RECORD_AUDIO);
} else if (requestedResources[i].equals(PermissionRequest.RESOURCE_VIDEO_CAPTURE)) {
permissions.add(Manifest.permission.CAMERA);
} else if(requestedResources[i].equals(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID)) {
permissions.add(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID);
}
// TODO: RESOURCE_MIDI_SYSEX, RESOURCE_PROTECTED_MEDIA_ID.
}
Expand All @@ -1134,6 +1165,8 @@ public void onPermissionRequest(final PermissionRequest request) {
grantedPermissions.add(PermissionRequest.RESOURCE_AUDIO_CAPTURE);
} else if (permissions.get(i).equals(Manifest.permission.CAMERA)) {
grantedPermissions.add(PermissionRequest.RESOURCE_VIDEO_CAPTURE);
} else if (permissions.get(i).equals(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID)) {
grantedPermissions.add(PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID);
}
}

Expand Down
15 changes: 11 additions & 4 deletions apple/RNCWebView.h
Expand Up @@ -20,8 +20,11 @@
@end

@interface RNCWeakScriptMessageDelegate : NSObject<WKScriptMessageHandler>
@property (nonatomic, weak) id<WKScriptMessageHandler> scriptDelegate;
- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;

@property (nonatomic, weak, nullable) id<WKScriptMessageHandler> scriptDelegate;

- (nullable instancetype)initWithDelegate:(id<WKScriptMessageHandler> _Nullable)scriptDelegate;

@end

@interface RNCWebView : RCTView
Expand Down Expand Up @@ -66,13 +69,17 @@
@property (nonatomic, copy) NSString * _Nullable allowingReadAccessToURL;
@property (nonatomic, assign) BOOL pullToRefreshEnabled;
#if !TARGET_OS_OSX
@property (nonatomic, weak) UIRefreshControl * refreshControl;
@property (nonatomic, weak) UIRefreshControl * _Nullable refreshControl;
#endif

#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 /* iOS 13 */
@property (nonatomic, assign) WKContentMode contentMode;
#endif

#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000 /* iOS 14 */
@property (nonatomic, assign) BOOL limitsNavigationsToAppBoundDomains;
#endif

+ (void)setClientAuthenticationCredential:(nullable NSURLCredential*)credential;
+ (void)setCustomCertificatesForHost:(nullable NSDictionary *)certificates;
- (void)postMessage:(NSString *_Nullable)message;
Expand All @@ -85,7 +92,7 @@
- (void)stopLoading;
#if !TARGET_OS_OSX
- (void)addPullToRefreshControl;
- (void)pullToRefresh:(UIRefreshControl *)refreshControl;
- (void)pullToRefresh:(UIRefreshControl *_Nonnull)refreshControl;
#endif

@end
24 changes: 23 additions & 1 deletion apple/RNCWebView.m
Expand Up @@ -245,6 +245,16 @@ - (WKWebViewConfiguration *)setUpWkWebViewConfig
}
#endif

#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000 /* iOS 14 */
if (@available(iOS 14.0, *)) {
if ([wkWebViewConfig respondsToSelector:@selector(limitsNavigationsToAppBoundDomains)]) {
if (_limitsNavigationsToAppBoundDomains) {
wkWebViewConfig.limitsNavigationsToAppBoundDomains = YES;
}
}
}
#endif

// Shim the HTML5 history API:
[wkWebViewConfig.userContentController addScriptMessageHandler:[[RNCWeakScriptMessageDelegate alloc] initWithDelegate:self]
name:HistoryShimName];
Expand Down Expand Up @@ -331,6 +341,7 @@ - (void)setAllowsBackForwardNavigationGestures:(BOOL)allowsBackForwardNavigation
- (void)removeFromSuperview
{
if (_webView) {
[_webView.configuration.userContentController removeScriptMessageHandlerForName:HistoryShimName];
[_webView.configuration.userContentController removeScriptMessageHandlerForName:MessageHandlerName];
[_webView removeObserver:self forKeyPath:@"estimatedProgress"];
[_webView removeFromSuperview];
Expand Down Expand Up @@ -543,6 +554,16 @@ - (void)visitSource
}
[_webView loadHTMLString:html baseURL:baseURL];
return;
}
//Add cookie for subsequent resource requests sent by page itself, if cookie was set in headers on WebView
NSString *headerCookie = [RCTConvert NSString:_source[@"headers"][@"cookie"]];
if(headerCookie) {
NSDictionary *headers = [NSDictionary dictionaryWithObjectsAndKeys:headerCookie,@"Set-Cookie",nil];
NSURL *urlString = [NSURL URLWithString:_source[@"uri"]];
NSArray *httpCookies = [NSHTTPCookie cookiesWithResponseHeaderFields:headers forURL:urlString];
for (NSHTTPCookie *httpCookie in httpCookies) {
[_webView.configuration.websiteDataStore.httpCookieStore setCookie:httpCookie completionHandler:nil];
}
}

NSURLRequest *request = [self requestForSource:_source];
Expand Down Expand Up @@ -1053,7 +1074,8 @@ - (void) webView:(WKWebView *)webView
return;
}

if ([error.domain isEqualToString:@"WebKitErrorDomain"] && error.code == 102 || [error.domain isEqualToString:@"WebKitErrorDomain"] && error.code == 101) {
if ([error.domain isEqualToString:@"WebKitErrorDomain"] &&
(error.code == 102 || error.code == 101)) {
// Error code 102 "Frame load interrupted" is raised by the WKWebView
// when the URL is from an http redirect. This is a common pattern when
// implementing OAuth with a WebView.
Expand Down
4 changes: 4 additions & 0 deletions apple/RNCWebViewManager.m
Expand Up @@ -90,6 +90,10 @@ - (RCTUIView *)view
RCT_EXPORT_VIEW_PROPERTY(contentMode, WKContentMode)
#endif

#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000 /* iOS 14 */
RCT_EXPORT_VIEW_PROPERTY(limitsNavigationsToAppBoundDomains, BOOL)
#endif

/**
* Expose methods to enable messaging the webview.
*/
Expand Down
2 changes: 2 additions & 0 deletions docs/Getting-Started.md
Expand Up @@ -83,6 +83,8 @@ Add `#include "winrt/ReactNativeWebView.h"`.

Add `PackageProviders().Append(winrt::ReactNativeWebView::ReactPackageProvider());` before `InitializeComponent();`.

Note if you want to enable scroll with Touch for the WebView component you must disable perspective for your app using [ReactRootView.IsPerspectiveEnabled](https://microsoft.github.io/react-native-windows/docs/ReactRootView#isperspectiveenabled).

## 3. Import the webview into your component

```js
Expand Down
28 changes: 24 additions & 4 deletions docs/Reference.md
Expand Up @@ -73,6 +73,7 @@ This document lays out the current public properties and methods for the React N
- [`pullToRefreshEnabled`](Reference.md#pullToRefreshEnabled)
- [`ignoreSilentHardwareSwitch`](Reference.md#ignoreSilentHardwareSwitch)
- [`onFileDownload`](Reference.md#onFileDownload)
- [`limitsNavigationsToAppBoundDomains`](Reference.md#limitsNavigationsToAppBoundDomains)
- [`autoManageStatusBarEnabled`](Reference.md#autoManageStatusBarEnabled)
- [`setSupportMultipleWindows`](Reference.md#setSupportMultipleWindows)

Expand All @@ -88,7 +89,7 @@ This document lays out the current public properties and methods for the React N
- [`clearCache`](Reference.md#clearCache)
- [`clearHistory`](Reference.md#clearHistory)
- [`requestFocus`](Reference.md#requestFocus)
- [`postMessage`](Reference.md#postMessage)
- [`postMessage`](Reference.md#postmessagestr)

---

Expand Down Expand Up @@ -550,7 +551,7 @@ The `navState` object includes these properties:
canGoBack
canGoForward
loading
navigationType
navigationType (iOS only)
target
title
url
Expand Down Expand Up @@ -729,8 +730,8 @@ canGoBack
canGoForward
lockIdentifier
mainDocumentURL (iOS only)
navigationType
isTopFrame
navigationType (iOS only)
isTopFrame (iOS only)
```

---
Expand Down Expand Up @@ -1314,6 +1315,25 @@ Example:

---

### `limitsNavigationsToAppBoundDomains`[](#props-index)<!-- Link generated with jump2header -->

If true indicates to WebKit that a WKWebView will only navigate to app-bound domains. Only applicable for iOS 14 or greater.

Once set, any attempt to navigate away from an app-bound domain will fail with the error “App-bound domain failure.”
Applications can specify up to 10 “app-bound” domains using a new Info.plist key `WKAppBoundDomains`. For more information see [App-Bound Domains](https://webkit.org/blog/10882/app-bound-domains/).

| Type | Required | Platform |
| ------- | -------- | -------- |
| boolean | No | iOS |

Example:

```jsx
<WebView limitsNavigationsToAppBoundDomains={true} />
```

---

### `autoManageStatusBarEnabled`

If set to `true`, the status bar will be automatically hidden/shown by WebView, specifically when full screen video is being watched. If `false`, WebView will not manage the status bar at all. The default value is `true`.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -8,7 +8,7 @@
"Thibault Malbranche <malbranche.thibault@gmail.com>"
],
"license": "MIT",
"version": "11.2.1",
"version": "11.3.1",
"homepage": "https://github.com/react-native-webview/react-native-webview#readme",
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
Expand Down
12 changes: 12 additions & 0 deletions src/WebViewTypes.ts
Expand Up @@ -332,6 +332,7 @@ export interface IOSNativeWebViewProps extends CommonNativeWebViewProps {
injectedJavaScriptForMainFrameOnly?: boolean;
injectedJavaScriptBeforeContentLoadedForMainFrameOnly?: boolean;
onFileDownload?: (event: FileDownloadEvent) => void;
limitsNavigationsToAppBoundDomains?: boolean;
}

export interface MacOSNativeWebViewProps extends CommonNativeWebViewProps {
Expand Down Expand Up @@ -614,6 +615,17 @@ export interface IOSWebViewProps extends WebViewSharedProps {
* If not provided, the default is to let the webview try to render the file.
*/
onFileDownload?: (event: FileDownloadEvent) => void;

/**
* A Boolean value which, when set to `true`, indicates to WebKit that a WKWebView
* will only navigate to app-bound domains. Once set, any attempt to navigate away
* from an app-bound domain will fail with the error “App-bound domain failure.”
*
* Applications can specify up to 10 “app-bound” domains using a new
* Info.plist key `WKAppBoundDomains`.
* @platform ios
*/
limitsNavigationsToAppBoundDomains?: boolean;
}

export interface MacOSWebViewProps extends WebViewSharedProps {
Expand Down
3 changes: 1 addition & 2 deletions windows/ReactNativeWebView.sln
Expand Up @@ -34,7 +34,7 @@ EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9
..\node_modules\react-native-windows\ReactWindowsCore\ReactWindowsCore.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4
..\node_modules\react-native-windows\ReactWindowsCore\ReactWindowsCore-Items.vcxitems*{11c084a3-a57c-4296-a679-cac17b603144}*SharedItemsImports = 4
..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4
..\node_modules\react-native-windows\Mso\Mso.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4
..\node_modules\react-native-windows\Shared\Shared.vcxitems*{2d5d43d9-cffc-4c40-b4cd-02efb4e2742b}*SharedItemsImports = 4
Expand All @@ -44,7 +44,6 @@ Global
..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{c38970c0-5fbf-4d69-90d8-cbac225ae895}*SharedItemsImports = 9
..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{da8b35b3-da00-4b02-bde6-6a397b3fd46b}*SharedItemsImports = 9
..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
..\node_modules\react-native-windows\Mso\Mso.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
..\node_modules\react-native-windows\Shared\Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4
Expand Down
7 changes: 4 additions & 3 deletions windows/ReactNativeWebView/ReactNativeWebView.vcxproj
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.200316.3\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.200316.3\build\native\Microsoft.Windows.CppWinRT.props')" />
<Import Project="$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.200316.3\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.200316.3\build\native\Microsoft.Windows.CppWinRT.props')" />
<PropertyGroup Label="Globals">
<CppWinRTOptimized>true</CppWinRTOptimized>
<CppWinRTRootNamespaceAutoMerge>true</CppWinRTRootNamespaceAutoMerge>
Expand Down Expand Up @@ -89,6 +89,7 @@
<DisableSpecificWarnings>28204</DisableSpecificWarnings>
<PreprocessorDefinitions>_WINRT_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalUsingDirectories>$(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories)</AdditionalUsingDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
Expand Down Expand Up @@ -153,12 +154,12 @@
<ImportGroup Label="ExtensionTargets">
<Import Project="$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.200316.3\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.200316.3\build\native\Microsoft.Windows.CppWinRT.targets')" />
</ImportGroup>
<Target Name="Deploy"/>
<Target Name="Deploy" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.200316.3\build\native\Microsoft.Windows.CppWinRT.props')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.200316.3\build\native\Microsoft.Windows.CppWinRT.props'))" />
<Error Condition="!Exists('$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.200316.3\build\native\Microsoft.Windows.CppWinRT.targets')" Text="$([System.String]::Format('$(ErrorText)', '$(SolutionDir)packages\Microsoft.Windows.CppWinRT.2.0.200316.3\build\native\Microsoft.Windows.CppWinRT.targets'))" />
</Target>
</Project>
</Project>
17 changes: 14 additions & 3 deletions windows/ReactNativeWebView/ReactWebView.cpp
Expand Up @@ -5,8 +5,8 @@
#include "JSValueXaml.h"
#include "ReactWebView.h"
#include "ReactWebView.g.cpp"


#include <winrt/Windows.Foundation.Metadata.h>
#include <optional>

namespace winrt {
using namespace Microsoft::ReactNative;
Expand Down Expand Up @@ -63,11 +63,22 @@ namespace winrt::ReactNativeWebView::implementation {
});
}

bool Is17763OrHigher() {
static std::optional<bool> hasUniversalAPIContract_v7;

if (!hasUniversalAPIContract_v7.has_value()) {
hasUniversalAPIContract_v7 = winrt::Windows::Foundation::Metadata::ApiInformation::IsApiContractPresent(L"Windows.Foundation.UniversalApiContract", 7);
}
return hasUniversalAPIContract_v7.value();
}

void ReactWebView::WriteWebViewNavigationEventArg(winrt::WebView const& sender, winrt::IJSValueWriter const& eventDataWriter) {
auto tag = this->GetValue(winrt::FrameworkElement::TagProperty()).as<winrt::IPropertyValue>().GetInt64();
WriteProperty(eventDataWriter, L"canGoBack", sender.CanGoBack());
WriteProperty(eventDataWriter, L"canGoForward", sender.CanGoForward());
WriteProperty(eventDataWriter, L"loading", !sender.IsLoaded());
if (Is17763OrHigher()) {
WriteProperty(eventDataWriter, L"loading", !sender.IsLoaded());
}
WriteProperty(eventDataWriter, L"target", tag);
WriteProperty(eventDataWriter, L"title", sender.DocumentTitle());
if (auto uri = sender.Source()) {
Expand Down

0 comments on commit e34e1ea

Please sign in to comment.