mirror of
https://github.com/status-im/react-native-webview.git
synced 2025-02-24 17:58:39 +00:00
* Manage to build webview using Visual Studio * WebView in content of UserControl * Destructor not needed * Example app tested * Add messagingEnabled prop * WebViewBridge * Message posting * Store bridge as instance variable * Use bridge if messagingEnabled * Free event delegate * PostMessage api uses string message * script.notify() usage removed * Debug log removed * Bridge reference added * Base for web allowed object implemented c++/winrt * Bribge works * "Microsoft.Windows.CppWinRT" version="2.0.200729.8" * Update bridge implementation * version changes * Reference fix * WebView prj builds * yarn lock update * Platfrom version update * NuGet package reference updated * Messaging test added into example app * Typo fix * try_as() to as() calls * WebView.PostMessage() not supported anymore, use injectJavaScript * Fix WebView.postMessage to work using injectJavascript * Eval postMessage fix * postMessage via injectJavascript * Example fixed to handle postMessage call
163 lines
6.4 KiB
C++
163 lines
6.4 KiB
C++
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
#include "pch.h"
|
|
#include "JSValueXaml.h"
|
|
#include "ReactWebView.h"
|
|
#include "ReactWebView.g.cpp"
|
|
|
|
|
|
|
|
namespace winrt {
|
|
using namespace Microsoft::ReactNative;
|
|
using namespace Windows::Data::Json;
|
|
using namespace Windows::Foundation;
|
|
using namespace Windows::UI;
|
|
using namespace Windows::UI::Popups;
|
|
using namespace Windows::UI::Xaml;
|
|
using namespace Windows::UI::Xaml::Controls;
|
|
using namespace Windows::UI::Xaml::Input;
|
|
using namespace Windows::UI::Xaml::Media;
|
|
} // namespace winrt
|
|
|
|
namespace winrt::ReactNativeWebView::implementation {
|
|
|
|
ReactWebView::ReactWebView(winrt::IReactContext const& reactContext) : m_reactContext(reactContext) {
|
|
#ifdef CHAKRACORE_UWP
|
|
m_webView = winrt::WebView(winrt::WebViewExecutionMode::SeparateProcess);
|
|
#else
|
|
m_webView = winrt::WebView();
|
|
#endif
|
|
this->Content(m_webView);
|
|
RegisterEvents();
|
|
}
|
|
|
|
ReactWebView::~ReactWebView()
|
|
{
|
|
if (m_messagingEnabled) {
|
|
m_webBridge.MessagePostEvent(m_messageToken);
|
|
}
|
|
}
|
|
|
|
void ReactWebView::RegisterEvents() {
|
|
m_navigationStartingRevoker = m_webView.NavigationStarting(
|
|
winrt::auto_revoke, [ref = get_weak()](auto const& sender, auto const& args) {
|
|
if (auto self = ref.get()) {
|
|
self->OnNavigationStarting(sender, args);
|
|
}
|
|
|
|
});
|
|
|
|
m_navigationCompletedRevoker = m_webView.NavigationCompleted(
|
|
winrt::auto_revoke, [ref = get_weak()](auto const& sender, auto const& args) {
|
|
if (auto self = ref.get()) {
|
|
self->OnNavigationCompleted(sender, args);
|
|
}
|
|
});
|
|
|
|
m_navigationFailedRevoker = m_webView.NavigationFailed(
|
|
winrt::auto_revoke, [ref = get_weak()](auto const& sender, auto const& args) {
|
|
if (auto self = ref.get()) {
|
|
self->OnNavigationFailed(sender, args);
|
|
}
|
|
});
|
|
}
|
|
|
|
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());
|
|
WriteProperty(eventDataWriter, L"target", tag);
|
|
WriteProperty(eventDataWriter, L"title", sender.DocumentTitle());
|
|
if (auto uri = sender.Source()) {
|
|
WriteProperty(eventDataWriter, L"url", uri.AbsoluteCanonicalUri());
|
|
}
|
|
}
|
|
|
|
void ReactWebView::OnNavigationStarting(winrt::WebView const& webView, winrt::WebViewNavigationStartingEventArgs const& /*args*/) {
|
|
m_reactContext.DispatchEvent(
|
|
*this,
|
|
L"topLoadingStart",
|
|
[&](winrt::IJSValueWriter const& eventDataWriter) noexcept {
|
|
eventDataWriter.WriteObjectBegin();
|
|
WriteWebViewNavigationEventArg(webView, eventDataWriter);
|
|
eventDataWriter.WriteObjectEnd();
|
|
});
|
|
|
|
if (m_messagingEnabled) {
|
|
m_webBridge = WebBridge();
|
|
m_messageToken = m_webBridge.MessagePostEvent([this](const auto&, hstring const& message)
|
|
{
|
|
this->OnMessagePosted(message);
|
|
});
|
|
webView.AddWebAllowedObject(L"__REACT_WEB_VIEW_BRIDGE", m_webBridge);
|
|
}
|
|
}
|
|
|
|
void ReactWebView::OnMessagePosted(hstring const& message)
|
|
{
|
|
HandleMessageFromJS(message);
|
|
}
|
|
|
|
void ReactWebView::OnNavigationCompleted(winrt::WebView const& webView, winrt::WebViewNavigationCompletedEventArgs const& /*args*/) {
|
|
m_reactContext.DispatchEvent(
|
|
*this,
|
|
L"topLoadingFinish",
|
|
[&](winrt::IJSValueWriter const& eventDataWriter) noexcept {
|
|
eventDataWriter.WriteObjectBegin();
|
|
WriteWebViewNavigationEventArg(webView, eventDataWriter);
|
|
eventDataWriter.WriteObjectEnd();
|
|
});
|
|
|
|
if (m_messagingEnabled) {
|
|
winrt::hstring windowAlert = L"window.alert = function (msg) {__REACT_WEB_VIEW_BRIDGE.postMessage(`{\"type\":\"__alert\",\"message\":\"${msg}\"}`)};";
|
|
winrt::hstring postMessage = L"window.ReactNativeWebView = {postMessage: function (data) {__REACT_WEB_VIEW_BRIDGE.postMessage(String(data))}};";
|
|
webView.InvokeScriptAsync(L"eval", { windowAlert + postMessage });
|
|
}
|
|
}
|
|
|
|
void ReactWebView::OnNavigationFailed(winrt::IInspectable const& /*sender*/, winrt::WebViewNavigationFailedEventArgs const& args) {
|
|
m_reactContext.DispatchEvent(
|
|
*this,
|
|
L"topLoadingError",
|
|
[&](winrt::IJSValueWriter const& eventDataWriter) noexcept {
|
|
auto httpCode = static_cast<int32_t>(args.WebErrorStatus());
|
|
eventDataWriter.WriteObjectBegin();
|
|
{
|
|
WriteProperty(eventDataWriter, L"code", httpCode);
|
|
WriteWebViewNavigationEventArg(m_webView, eventDataWriter);
|
|
}
|
|
eventDataWriter.WriteObjectEnd();
|
|
});
|
|
}
|
|
|
|
void ReactWebView::HandleMessageFromJS(winrt::hstring const& message) {
|
|
winrt::JsonObject jsonObject;
|
|
if (winrt::JsonObject::TryParse(message, jsonObject) && jsonObject.HasKey(L"type")) {
|
|
auto type = jsonObject.GetNamedString(L"type");
|
|
if (type == L"__alert") {
|
|
auto dialog = winrt::MessageDialog(jsonObject.GetNamedString(L"message"));
|
|
dialog.Commands().Append(winrt::UICommand(L"OK"));
|
|
dialog.ShowAsync();
|
|
return;
|
|
}
|
|
}
|
|
|
|
m_reactContext.DispatchEvent(
|
|
*this,
|
|
L"topMessage",
|
|
[&](winrt::Microsoft::ReactNative::IJSValueWriter const& eventDataWriter) noexcept {
|
|
eventDataWriter.WriteObjectBegin();
|
|
{
|
|
WriteProperty(eventDataWriter, L"data", message);
|
|
}
|
|
eventDataWriter.WriteObjectEnd();
|
|
});
|
|
}
|
|
|
|
void ReactWebView::SetMessagingEnabled(bool enabled) {
|
|
m_messagingEnabled = enabled;
|
|
}
|
|
|
|
} // namespace winrt::ReactNativeWebView::implementation
|