Ingen beskrivning

ReactWebView.cpp 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright (c) Microsoft Corporation. All rights reserved.
  2. // Licensed under the MIT License.
  3. #include "pch.h"
  4. #include "JSValueXaml.h"
  5. #include "ReactWebView.h"
  6. #include "ReactWebView.g.cpp"
  7. namespace winrt {
  8. using namespace Microsoft::ReactNative;
  9. using namespace Windows::Data::Json;
  10. using namespace Windows::Foundation;
  11. using namespace Windows::UI;
  12. using namespace Windows::UI::Popups;
  13. using namespace Windows::UI::Xaml;
  14. using namespace Windows::UI::Xaml::Controls;
  15. using namespace Windows::UI::Xaml::Input;
  16. using namespace Windows::UI::Xaml::Media;
  17. } // namespace winrt
  18. namespace winrt::ReactNativeWebView::implementation {
  19. ReactWebView::ReactWebView(winrt::IReactContext const& reactContext) : m_reactContext(reactContext) {
  20. #ifdef CHAKRACORE_UWP
  21. m_webView = winrt::WebView(winrt::WebViewExecutionMode::SeparateProcess);
  22. #else
  23. m_webView = winrt::WebView();
  24. #endif
  25. RegisterEvents();
  26. }
  27. winrt::WebView ReactWebView::GetView() {
  28. return m_webView;
  29. }
  30. void ReactWebView::RegisterEvents() {
  31. m_navigationStartingRevoker = m_webView.NavigationStarting(
  32. winrt::auto_revoke, [ref = get_weak()](auto const& sender, auto const& args) {
  33. if (auto self = ref.get()) {
  34. self->OnNavigationStarting(sender, args);
  35. }
  36. });
  37. m_navigationCompletedRevoker = m_webView.NavigationCompleted(
  38. winrt::auto_revoke, [ref = get_weak()](auto const& sender, auto const& args) {
  39. if (auto self = ref.get()) {
  40. self->OnNavigationCompleted(sender, args);
  41. }
  42. });
  43. m_navigationFailedRevoker = m_webView.NavigationFailed(
  44. winrt::auto_revoke, [ref = get_weak()](auto const& sender, auto const& args) {
  45. if (auto self = ref.get()) {
  46. self->OnNavigationFailed(sender, args);
  47. }
  48. });
  49. m_scriptNotifyRevoker = m_webView.ScriptNotify(
  50. winrt::auto_revoke, [ref = get_weak()](auto const& sender, auto const& args) {
  51. if (auto self = ref.get()) {
  52. self->OnScriptNotify(sender, args);
  53. }
  54. });
  55. m_permissionReguestRevoker = m_webView.PermissionRequested(
  56. winrt::auto_revoke, [ref = get_weak()](auto const& sender, auto const& args) {
  57. if (auto self = ref.get()) {
  58. self->OnPremissionRequested(sender, args);
  59. }
  60. });
  61. }
  62. void ReactWebView::WriteWebViewNavigationEventArg(winrt::IJSValueWriter const& eventDataWriter) {
  63. auto tag = m_webView.GetValue(winrt::FrameworkElement::TagProperty()).as<winrt::IPropertyValue>().GetInt64();
  64. WriteProperty(eventDataWriter, L"canGoBack", m_webView.CanGoBack());
  65. WriteProperty(eventDataWriter, L"canGoForward", m_webView.CanGoForward());
  66. WriteProperty(eventDataWriter, L"loading", !m_webView.IsLoaded());
  67. WriteProperty(eventDataWriter, L"target", tag);
  68. WriteProperty(eventDataWriter, L"title", m_webView.DocumentTitle());
  69. if (auto uri = m_webView.Source()) {
  70. WriteProperty(eventDataWriter, L"url", uri.AbsoluteCanonicalUri());
  71. }
  72. }
  73. void ReactWebView::OnNavigationStarting(winrt::WebView const& webView, winrt::WebViewNavigationStartingEventArgs const& /*args*/) {
  74. m_reactContext.DispatchEvent(
  75. webView,
  76. L"topLoadingStart",
  77. [&](winrt::IJSValueWriter const& eventDataWriter) noexcept {
  78. eventDataWriter.WriteObjectBegin();
  79. WriteWebViewNavigationEventArg(eventDataWriter);
  80. eventDataWriter.WriteObjectEnd();
  81. });
  82. }
  83. void ReactWebView::OnNavigationCompleted(winrt::WebView const& webView, winrt::WebViewNavigationCompletedEventArgs const& /*args*/) {
  84. m_reactContext.DispatchEvent(
  85. webView,
  86. L"topLoadingFinish",
  87. [&](winrt::IJSValueWriter const& eventDataWriter) noexcept {
  88. eventDataWriter.WriteObjectBegin();
  89. WriteWebViewNavigationEventArg(eventDataWriter);
  90. eventDataWriter.WriteObjectEnd();
  91. });
  92. winrt::hstring windowAlert = L"window.alert = function (msg) {window.external.notify(`{\"type\":\"__alert\",\"message\":\"${msg}\"}`)};";
  93. winrt::hstring postMessage = L"window.ReactNativeWebView = {postMessage: function (data) {window.external.notify(String(data))}};";
  94. m_webView.InvokeScriptAsync(L"eval", { windowAlert + postMessage });
  95. }
  96. void ReactWebView::OnNavigationFailed(winrt::IInspectable const& /*sender*/, winrt::WebViewNavigationFailedEventArgs const& args) {
  97. m_reactContext.DispatchEvent(
  98. m_webView,
  99. L"topLoadingError",
  100. [&](winrt::IJSValueWriter const& eventDataWriter) noexcept {
  101. auto httpCode = static_cast<int32_t>(args.WebErrorStatus());
  102. eventDataWriter.WriteObjectBegin();
  103. {
  104. WriteProperty(eventDataWriter, L"code", httpCode);
  105. WriteWebViewNavigationEventArg(eventDataWriter);
  106. }
  107. eventDataWriter.WriteObjectEnd();
  108. });
  109. }
  110. void ReactWebView::OnScriptNotify(winrt::IInspectable const& /*sender*/, winrt::Windows::UI::Xaml::Controls::NotifyEventArgs const& args) {
  111. winrt::JsonObject jsonObject;
  112. if (winrt::JsonObject::TryParse(args.Value(), jsonObject) && jsonObject.HasKey(L"type")) {
  113. auto type = jsonObject.GetNamedString(L"type");
  114. if (type == L"__alert") {
  115. auto dialog = winrt::MessageDialog(jsonObject.GetNamedString(L"message"));
  116. dialog.Commands().Append(winrt::UICommand(L"OK"));
  117. dialog.ShowAsync();
  118. return;
  119. }
  120. }
  121. PostMessage(winrt::hstring(args.Value()));
  122. }
  123. void ReactWebView::OnPremissionRequested(winrt::WebView const& webView, winrt::WebViewPermissionRequestedEventArgs const& args)
  124. {
  125. if (args.PermissionRequest().PermissionType() == WebViewPermissionType::ImmersiveView) {
  126. // WebGL permission request
  127. // https://docs.microsoft.com/en-us/microsoft-edge/webvr/webvr-in-webview
  128. args.PermissionRequest().Allow();
  129. }
  130. args.PermissionRequest().Deny();
  131. }
  132. void ReactWebView::PostMessage(winrt::hstring const& message) {
  133. m_reactContext.DispatchEvent(
  134. m_webView,
  135. L"topMessage",
  136. [&](winrt::Microsoft::ReactNative::IJSValueWriter const& eventDataWriter) noexcept {
  137. eventDataWriter.WriteObjectBegin();
  138. {
  139. WriteProperty(eventDataWriter, L"data", message);
  140. }
  141. eventDataWriter.WriteObjectEnd();
  142. });
  143. }
  144. } // namespace winrt::ReactNativeWebView::implementation