123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- // 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_message_token);
- }
- }
-
- 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_message_token = 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)
- {
- PostMessage(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::PostMessage(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
|