react-native-webview.git

ReactWebViewManager.cpp 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include "pch.h"
  2. #include "ReactWebViewManager.h"
  3. #include "NativeModules.h"
  4. namespace winrt {
  5. using namespace Microsoft::ReactNative;
  6. using namespace Windows::Foundation;
  7. using namespace Windows::Foundation::Collections;
  8. using namespace Windows::UI::Xaml;
  9. using namespace Windows::UI::Xaml::Controls;
  10. }
  11. namespace winrt::ReactNativeWebView::implementation {
  12. ReactWebViewManager::ReactWebViewManager() {}
  13. // IViewManager
  14. winrt::hstring ReactWebViewManager::Name() noexcept {
  15. return L"RCTWebView";
  16. }
  17. winrt::FrameworkElement ReactWebViewManager::CreateView() noexcept {
  18. auto webView = winrt::WebView();
  19. m_webView = winrt::make_weak(webView);
  20. RegisterEvents();
  21. return webView;
  22. }
  23. void ReactWebViewManager::RegisterEvents() {
  24. if (auto webView = m_webView.get()) {
  25. m_navigationCompletedRevoker = webView.NavigationCompleted(
  26. winrt::auto_revoke, [=](auto const& sender, auto const& args) {
  27. OnNavigationCompleted(sender, args);
  28. });
  29. }
  30. }
  31. // IViewManagerWithReactContext
  32. winrt::IReactContext ReactWebViewManager::ReactContext() noexcept {
  33. return m_reactContext;
  34. }
  35. void ReactWebViewManager::ReactContext(IReactContext reactContext) noexcept {
  36. m_reactContext = reactContext;
  37. }
  38. // IViewManagerWithNativeProperties
  39. IMapView<hstring, ViewManagerPropertyType> ReactWebViewManager::NativeProps() noexcept {
  40. auto nativeProps = winrt::single_threaded_map<hstring, ViewManagerPropertyType>();
  41. nativeProps.Insert(L"source", ViewManagerPropertyType::Map);
  42. return nativeProps.GetView();
  43. }
  44. void ReactWebViewManager::UpdateProperties(
  45. FrameworkElement const& view,
  46. IJSValueReader const& propertyMapReader) noexcept {
  47. if (auto webView = view.try_as<winrt::WebView>()) {
  48. const JSValueObject& propertyMap = JSValue::ReadObjectFrom(propertyMapReader);
  49. for (auto const& pair : propertyMap) {
  50. auto const& propertyName = pair.first;
  51. auto const& propertyValue = pair.second;
  52. if (propertyName == "source") {
  53. if (!propertyValue.IsNull()) {
  54. auto const& srcMap = propertyValue.Object();
  55. auto uriString = srcMap.at("uri").String();
  56. // non-uri sources not yet supported
  57. if (uriString.length() == 0) {
  58. continue;
  59. }
  60. bool isPackagerAsset = false;
  61. if (srcMap.find("__packager_asset") != srcMap.end()) {
  62. isPackagerAsset = srcMap.at("__packager_asset").Boolean();
  63. }
  64. if (isPackagerAsset && uriString.find("assets") == 0) {
  65. uriString.replace(0, 6, "ms-appx://");
  66. }
  67. SetSource(winrt::Uri(to_hstring(uriString)));
  68. }
  69. }
  70. }
  71. }
  72. }
  73. void ReactWebViewManager::SetSource(winrt::Uri const& uri) {
  74. if (auto webView = m_webView.get()) {
  75. auto tag = webView.GetValue(winrt::FrameworkElement::TagProperty()).as<winrt::IPropertyValue>().GetInt64();
  76. m_reactContext.DispatchEvent(
  77. webView,
  78. L"topLoadingStart",
  79. [webView, tag, uri](winrt::IJSValueWriter const& eventDataWriter) noexcept {
  80. eventDataWriter.WriteObjectBegin();
  81. {
  82. WriteProperty(eventDataWriter, L"canGoBack", webView.CanGoBack());
  83. WriteProperty(eventDataWriter, L"canGoForward", webView.CanGoForward());
  84. WriteProperty(eventDataWriter, L"loading", false);
  85. WriteProperty(eventDataWriter, L"target", tag);
  86. WriteProperty(eventDataWriter, L"title", webView.DocumentTitle());
  87. WriteProperty(eventDataWriter, L"url", uri.ToString());
  88. }
  89. eventDataWriter.WriteObjectEnd();
  90. });
  91. webView.Navigate(uri);
  92. }
  93. }
  94. // IViewManagerWithExportedEventTypeConstants
  95. ConstantProvider ReactWebViewManager::ExportedCustomBubblingEventTypeConstants() noexcept {
  96. return nullptr;
  97. }
  98. ConstantProvider ReactWebViewManager::ExportedCustomDirectEventTypeConstants() noexcept {
  99. return [](winrt::IJSValueWriter const& constantWriter) {
  100. WriteCustomDirectEventTypeConstant(constantWriter, "onLoadingStart");
  101. WriteCustomDirectEventTypeConstant(constantWriter, "onLoad");
  102. WriteCustomDirectEventTypeConstant(constantWriter, "onLoadingFinish");
  103. };
  104. }
  105. // IViewManagerWithCommands
  106. IMapView<hstring, int64_t> ReactWebViewManager::Commands() noexcept {
  107. auto commands = winrt::single_threaded_map<hstring, int64_t>();
  108. commands.Insert(L"goForward", 0);
  109. commands.Insert(L"goBack", 1);
  110. commands.Insert(L"reload", 2);
  111. return commands.GetView();
  112. }
  113. void ReactWebViewManager::DispatchCommand(
  114. FrameworkElement const& view,
  115. int64_t commandId,
  116. winrt::IJSValueReader const& commandArgsReader) noexcept {
  117. if (auto webView = view.try_as<winrt::WebView>()) {
  118. switch (commandId) {
  119. case 0: // goForward
  120. webView.GoForward();
  121. break;
  122. case 1: // goBack
  123. webView.GoBack();
  124. break;
  125. case 2: // reload
  126. webView.Refresh();
  127. break;
  128. }
  129. }
  130. }
  131. void ReactWebViewManager::OnNavigationCompleted(winrt::WebView const& webView, winrt::WebViewNavigationCompletedEventArgs const& args) {
  132. m_reactContext.DispatchEvent(
  133. webView,
  134. L"topLoadingFinish",
  135. [webView, args](winrt::IJSValueWriter const& eventDataWriter) noexcept {
  136. eventDataWriter.WriteObjectBegin();
  137. {
  138. auto tag = webView.GetValue(winrt::FrameworkElement::TagProperty()).as<winrt::IPropertyValue>().GetInt64();
  139. WriteProperty(eventDataWriter, L"canGoBack", webView.CanGoBack());
  140. WriteProperty(eventDataWriter, L"canGoForward", webView.CanGoForward());
  141. WriteProperty(eventDataWriter, L"loading", false);
  142. WriteProperty(eventDataWriter, L"target", tag);
  143. WriteProperty(eventDataWriter, L"title", webView.DocumentTitle());
  144. WriteProperty(eventDataWriter, L"url", args.Uri().ToString());
  145. }
  146. eventDataWriter.WriteObjectEnd();
  147. });
  148. }
  149. } // namespace winrt::ReactWebView::implementation