react-native-windows 0.70.0-preview.2 → 0.70.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/Libraries/Core/ReactNativeVersion.js +1 -1
  2. package/Microsoft.ReactNative/JSDispatcherWriter.cpp +60 -22
  3. package/Microsoft.ReactNative/JSDispatcherWriter.h +5 -3
  4. package/Microsoft.ReactNative/Pch/pch.h +0 -1
  5. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +1 -0
  6. package/Microsoft.ReactNative/TurboModulesProvider.cpp +146 -84
  7. package/Microsoft.ReactNative/TurboModulesProvider.h +5 -0
  8. package/Microsoft.ReactNative/Views/ViewManagerBase.cpp +4 -2
  9. package/Microsoft.ReactNative.Cxx/JSI/LongLivedJsiValue.h +84 -0
  10. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems +1 -0
  11. package/Microsoft.ReactNative.Cxx/Microsoft.ReactNative.Cxx.vcxitems.filters +3 -0
  12. package/Mso/src/dispatchQueue/uiScheduler_winrt.cpp +6 -1
  13. package/PropertySheets/Generated/PackageVersion.g.props +2 -2
  14. package/Shared/InstanceManager.cpp +29 -0
  15. package/Shared/InstanceManager.h +14 -0
  16. package/Shared/Modules/HttpModule.cpp +4 -2
  17. package/Shared/Networking/IHttpResource.h +1 -1
  18. package/Shared/Networking/IRedirectEventSource.h +18 -0
  19. package/Shared/Networking/IWinRTHttpRequestFactory.h +22 -0
  20. package/Shared/Networking/OriginPolicyHttpFilter.cpp +47 -16
  21. package/Shared/Networking/OriginPolicyHttpFilter.h +16 -3
  22. package/Shared/Networking/RedirectHttpFilter.cpp +283 -0
  23. package/Shared/Networking/RedirectHttpFilter.h +97 -0
  24. package/Shared/Networking/WinRTHttpResource.cpp +207 -154
  25. package/Shared/Networking/WinRTHttpResource.h +17 -4
  26. package/Shared/OInstance.cpp +16 -1
  27. package/Shared/OInstance.h +4 -13
  28. package/Shared/Shared.vcxitems +4 -0
  29. package/Shared/Shared.vcxitems.filters +12 -0
  30. package/package.json +8 -8
@@ -0,0 +1,84 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ #pragma once
4
+ #ifndef MICROSOFT_REACTNATIVE_JSI_LONGLIVEDJSIVALUE_
5
+ #define MICROSOFT_REACTNATIVE_JSI_LONGLIVEDJSIVALUE_
6
+
7
+ #include <ReactCommon/LongLivedObject.h>
8
+ #include <jsi/jsi.h>
9
+
10
+ namespace winrt::Microsoft::ReactNative {
11
+
12
+ // Wrap up JSI Runtime into a LongLivedObject
13
+ struct LongLivedJsiRuntime : facebook::react::LongLivedObject {
14
+ static std::weak_ptr<LongLivedJsiRuntime> CreateWeak(
15
+ std::shared_ptr<facebook::react::LongLivedObjectCollection> const &longLivedObjectCollection,
16
+ facebook::jsi::Runtime &runtime) noexcept {
17
+ auto value = std::shared_ptr<LongLivedJsiRuntime>(new LongLivedJsiRuntime(longLivedObjectCollection, runtime));
18
+ longLivedObjectCollection->add(value);
19
+ return value;
20
+ }
21
+
22
+ facebook::jsi::Runtime &Runtime() {
23
+ return runtime_;
24
+ }
25
+
26
+ public: // LongLivedObject overrides
27
+ void allowRelease() override {
28
+ if (auto longLivedObjectCollection = longLivedObjectCollection_.lock()) {
29
+ if (longLivedObjectCollection != nullptr) {
30
+ longLivedObjectCollection->remove(this);
31
+ return;
32
+ }
33
+ }
34
+ LongLivedObject::allowRelease();
35
+ }
36
+
37
+ protected:
38
+ LongLivedJsiRuntime(
39
+ std::shared_ptr<facebook::react::LongLivedObjectCollection> const &longLivedObjectCollection,
40
+ facebook::jsi::Runtime &runtime)
41
+ : longLivedObjectCollection_(longLivedObjectCollection), runtime_(runtime) {}
42
+
43
+ LongLivedJsiRuntime(LongLivedJsiRuntime const &) = delete;
44
+
45
+ private:
46
+ // Use a weak reference to the collection to avoid reference loops
47
+ std::weak_ptr<facebook::react::LongLivedObjectCollection> longLivedObjectCollection_;
48
+ facebook::jsi::Runtime &runtime_;
49
+ };
50
+
51
+ // Wrap up a JSI Value into a LongLivedObject.
52
+ template <typename TValue>
53
+ struct LongLivedJsiValue : LongLivedJsiRuntime {
54
+ static std::weak_ptr<LongLivedJsiValue<TValue>> CreateWeak(
55
+ std::shared_ptr<facebook::react::LongLivedObjectCollection> const &longLivedObjectCollection,
56
+ facebook::jsi::Runtime &runtime,
57
+ TValue &&value) noexcept {
58
+ auto valueWrapper = std::shared_ptr<LongLivedJsiValue<TValue>>(
59
+ new LongLivedJsiValue<TValue>(longLivedObjectCollection, runtime, std::forward<TValue>(value)));
60
+ longLivedObjectCollection->add(valueWrapper);
61
+ return valueWrapper;
62
+ }
63
+
64
+ TValue &Value() {
65
+ return value_;
66
+ }
67
+
68
+ protected:
69
+ template <typename TValue2>
70
+ LongLivedJsiValue(
71
+ std::shared_ptr<facebook::react::LongLivedObjectCollection> const &longLivedObjectCollection,
72
+ facebook::jsi::Runtime &runtime,
73
+ TValue2 &&value)
74
+ : LongLivedJsiRuntime(longLivedObjectCollection, runtime), value_(std::forward<TValue2>(value)) {}
75
+
76
+ private:
77
+ TValue value_;
78
+ };
79
+
80
+ using LongLivedJsiFunction = LongLivedJsiValue<facebook::jsi::Function>;
81
+
82
+ } // namespace winrt::Microsoft::ReactNative
83
+
84
+ #endif // MICROSOFT_REACTNATIVE_JSI_LONGLIVEDJSIVALUE_
@@ -39,6 +39,7 @@
39
39
  <ClInclude Include="$(JSI_SourcePath)\jsi\jsi.h" />
40
40
  <ClInclude Include="$(MSBuildThisFileDirectory)CoreApp.h" />
41
41
  <ClInclude Include="$(MSBuildThisFileDirectory)DesktopWindowBridge.h" />
42
+ <ClInclude Include="$(MSBuildThisFileDirectory)JSI\LongLivedJsiValue.h" />
42
43
  <ClInclude Include="$(MSBuildThisFileDirectory)JSI\NodeApiJsiRuntime.h" />
43
44
  <ClInclude Include="$(MSBuildThisFileDirectory)TurboModuleProvider.h" />
44
45
  <ClInclude Include="$(CallInvoker_SourcePath)\ReactCommon\CallInvoker.h" />
@@ -158,6 +158,9 @@
158
158
  </ClInclude>
159
159
  <ClInclude Include="$(Bridging_SourcePath)\CallbackWrapper.h" />
160
160
  <ClInclude Include="$(MSBuildThisFileDirectory)CoreApp.h" />
161
+ <ClInclude Include="$(MSBuildThisFileDirectory)JSI\LongLivedJsiValue.h">
162
+ <Filter>TurboModule</Filter>
163
+ </ClInclude>
161
164
  </ItemGroup>
162
165
  <ItemGroup>
163
166
  <Filter Include="JSI">
@@ -289,7 +289,12 @@ void UISchedulerWinRT::AwaitTermination() noexcept {
289
289
  return queue;
290
290
  }
291
291
 
292
- auto dispatcher = DispatcherQueue::GetForCurrentThread();
292
+ decltype(DispatcherQueue::GetForCurrentThread()) dispatcher{nullptr};
293
+ try {
294
+ dispatcher = DispatcherQueue::GetForCurrentThread();
295
+ } catch (winrt::hresult_error const &) {
296
+ }
297
+
293
298
  if (!dispatcher) {
294
299
  return queue;
295
300
  }
@@ -10,10 +10,10 @@
10
10
  -->
11
11
  <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
12
12
  <PropertyGroup>
13
- <ReactNativeWindowsVersion>0.70.0-preview.2</ReactNativeWindowsVersion>
13
+ <ReactNativeWindowsVersion>0.70.1</ReactNativeWindowsVersion>
14
14
  <ReactNativeWindowsMajor>0</ReactNativeWindowsMajor>
15
15
  <ReactNativeWindowsMinor>70</ReactNativeWindowsMinor>
16
- <ReactNativeWindowsPatch>0</ReactNativeWindowsPatch>
16
+ <ReactNativeWindowsPatch>1</ReactNativeWindowsPatch>
17
17
  <ReactNativeWindowsCanary>false</ReactNativeWindowsCanary>
18
18
  </PropertyGroup>
19
19
  </Project>
@@ -41,6 +41,35 @@ std::shared_ptr<InstanceWrapper> CreateReactInstance(
41
41
  std::move(jsBundleBasePath),
42
42
  std::move(cxxModules),
43
43
  std::move(turboModuleRegistry),
44
+ nullptr,
45
+ std::move(callback),
46
+ std::move(jsQueue),
47
+ std::move(nativeQueue),
48
+ std::move(devSettings),
49
+ GetSharedDevManager());
50
+
51
+ return inner;
52
+ }
53
+
54
+ std::shared_ptr<InstanceWrapper> CreateReactInstance(
55
+ std::shared_ptr<Instance> &&instance,
56
+ std::string &&jsBundleBasePath,
57
+ std::vector<
58
+ std::tuple<std::string, facebook::xplat::module::CxxModule::Provider, std::shared_ptr<MessageQueueThread>>>
59
+ &&cxxModules,
60
+ std::shared_ptr<TurboModuleRegistry> turboModuleRegistry,
61
+ std::shared_ptr<facebook::react::LongLivedObjectCollection> longLivedObjectCollection,
62
+ std::unique_ptr<InstanceCallback> &&callback,
63
+ std::shared_ptr<MessageQueueThread> jsQueue,
64
+ std::shared_ptr<MessageQueueThread> nativeQueue,
65
+ std::shared_ptr<DevSettings> devSettings) noexcept {
66
+ // Now create the instance
67
+ std::shared_ptr<InstanceWrapper> inner = InstanceImpl::MakeNoBundle(
68
+ std::move(instance),
69
+ std::move(jsBundleBasePath),
70
+ std::move(cxxModules),
71
+ std::move(turboModuleRegistry),
72
+ std::move(longLivedObjectCollection),
44
73
  std::move(callback),
45
74
  std::move(jsQueue),
46
75
  std::move(nativeQueue),
@@ -4,6 +4,7 @@
4
4
  #pragma once
5
5
 
6
6
  #include <Logging.h>
7
+ #include <ReactCommon/LongLivedObject.h>
7
8
  #include <cxxreact/CxxModule.h>
8
9
  #include <cxxreact/JSBigString.h>
9
10
  #include <map>
@@ -51,6 +52,19 @@ std::shared_ptr<InstanceWrapper> CreateReactInstance(
51
52
  std::shared_ptr<MessageQueueThread> nativeQueue,
52
53
  std::shared_ptr<DevSettings> devSettings) noexcept;
53
54
 
55
+ std::shared_ptr<InstanceWrapper> CreateReactInstance(
56
+ std::shared_ptr<Instance> &&instance,
57
+ std::string &&jsBundleRelativePath,
58
+ std::vector<
59
+ std::tuple<std::string, facebook::xplat::module::CxxModule::Provider, std::shared_ptr<MessageQueueThread>>>
60
+ &&cxxModules,
61
+ std::shared_ptr<TurboModuleRegistry> turboModuleRegistry,
62
+ std::shared_ptr<facebook::react::LongLivedObjectCollection> longLivedObjectCollection,
63
+ std::unique_ptr<InstanceCallback> &&callback,
64
+ std::shared_ptr<MessageQueueThread> jsQueue,
65
+ std::shared_ptr<MessageQueueThread> nativeQueue,
66
+ std::shared_ptr<DevSettings> devSettings) noexcept;
67
+
54
68
  std::shared_ptr<InstanceWrapper> CreateReactInstance(
55
69
  std::shared_ptr<Instance> &&instance,
56
70
  std::string &&jsBundleBasePath,
@@ -72,9 +72,11 @@ static void SetUpHttpResource(
72
72
  };
73
73
  resource->SetOnData(std::move(onDataDynamic));
74
74
 
75
- resource->SetOnError([weakReactInstance](int64_t requestId, string &&message) {
75
+ resource->SetOnError([weakReactInstance](int64_t requestId, string &&message, bool isTimeout) {
76
76
  dynamic args = dynamic::array(requestId, std::move(message));
77
- // TODO: isTimeout errorArgs.push_back(true);
77
+ if (isTimeout) {
78
+ args.push_back(true);
79
+ }
78
80
 
79
81
  SendEvent(weakReactInstance, completedResponse, std::move(args));
80
82
  });
@@ -96,7 +96,7 @@ struct IHttpResource {
96
96
  virtual void SetOnData(std::function<void(int64_t requestId, std::string &&responseData)> &&handler) noexcept = 0;
97
97
  virtual void SetOnData(std::function<void(int64_t requestId, folly::dynamic &&responseData)> &&handler) noexcept = 0;
98
98
  virtual void SetOnError(
99
- std::function<void(int64_t requestId, std::string &&errorMessage /*, bool isTimeout*/)> &&handler) noexcept = 0;
99
+ std::function<void(int64_t requestId, std::string &&errorMessage, bool isTimeout)> &&handler) noexcept = 0;
100
100
  };
101
101
 
102
102
  } // namespace Microsoft::React::Networking
@@ -0,0 +1,18 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ #pragma once
5
+
6
+ #include <winrt/Windows.Foundation.h>
7
+ #include <winrt/Windows.Web.Http.h>
8
+ #include <winrt/base.h>
9
+
10
+ namespace Microsoft::React::Networking {
11
+
12
+ struct IRedirectEventSource : winrt::implements<IRedirectEventSource, winrt::Windows::Foundation::IInspectable> {
13
+ virtual bool OnRedirecting(
14
+ winrt::Windows::Web::Http::HttpRequestMessage const &request,
15
+ winrt::Windows::Web::Http::HttpResponseMessage const &response) noexcept = 0;
16
+ };
17
+
18
+ } // namespace Microsoft::React::Networking
@@ -0,0 +1,22 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ #pragma once
5
+
6
+ #include <winrt/Windows.Foundation.Collections.h>
7
+ #include <winrt/Windows.Foundation.h>
8
+ #include <winrt/Windows.Web.Http.h>
9
+
10
+ namespace Microsoft::React::Networking {
11
+
12
+ struct IWinRTHttpRequestFactory {
13
+ virtual ~IWinRTHttpRequestFactory() noexcept {}
14
+
15
+ virtual winrt::Windows::Foundation::IAsyncOperation<winrt::Windows::Web::Http::HttpRequestMessage> CreateRequest(
16
+ winrt::Windows::Web::Http::HttpMethod &&method,
17
+ winrt::Windows::Foundation::Uri &&uri,
18
+ winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Windows::Foundation::IInspectable>
19
+ props) noexcept = 0;
20
+ };
21
+
22
+ } // namespace Microsoft::React::Networking
@@ -11,10 +11,6 @@
11
11
  #include <boost/algorithm/string.hpp>
12
12
  #include <boost/lexical_cast/try_lexical_convert.hpp>
13
13
 
14
- // Windows API
15
- #include <winrt/Windows.Foundation.Collections.h>
16
- #include <winrt/Windows.Web.Http.Headers.h>
17
-
18
14
  // Standard Library
19
15
  #include <queue>
20
16
  #include <regex>
@@ -28,6 +24,7 @@ using winrt::to_hstring;
28
24
  using winrt::Windows::Foundation::IInspectable;
29
25
  using winrt::Windows::Foundation::IPropertyValue;
30
26
  using winrt::Windows::Foundation::Uri;
27
+ using winrt::Windows::Foundation::Collections::IMap;
31
28
  using winrt::Windows::Web::Http::HttpMethod;
32
29
  using winrt::Windows::Web::Http::HttpRequestMessage;
33
30
  using winrt::Windows::Web::Http::HttpResponseMessage;
@@ -119,7 +116,7 @@ bool OriginPolicyHttpFilter::ConstWcharComparer::operator()(const wchar_t *a, co
119
116
  }
120
117
 
121
118
  /*static*/ bool OriginPolicyHttpFilter::IsSameOrigin(Uri const &u1, Uri const &u2) noexcept {
122
- return u1.SchemeName() == u2.SchemeName() && u1.Host() == u2.Host() && u1.Port() == u2.Port();
119
+ return (u1 && u2) && u1.SchemeName() == u2.SchemeName() && u1.Host() == u2.Host() && u1.Port() == u2.Port();
123
120
  }
124
121
 
125
122
  /*static*/ bool OriginPolicyHttpFilter::IsSimpleCorsRequest(HttpRequestMessage const &request) noexcept {
@@ -374,7 +371,7 @@ bool OriginPolicyHttpFilter::ConstWcharComparer::operator()(const wchar_t *a, co
374
371
  }
375
372
  }
376
373
 
377
- OriginPolicyHttpFilter::OriginPolicyHttpFilter(IHttpFilter &&innerFilter) : m_innerFilter{std::move(innerFilter)} {}
374
+ OriginPolicyHttpFilter::OriginPolicyHttpFilter(IHttpFilter const &innerFilter) : m_innerFilter{innerFilter} {}
378
375
 
379
376
  OriginPolicyHttpFilter::OriginPolicyHttpFilter()
380
377
  : OriginPolicyHttpFilter(winrt::Windows::Web::Http::Filters::HttpBaseProtocolFilter{}) {}
@@ -443,21 +440,24 @@ OriginPolicy OriginPolicyHttpFilter::ValidateRequest(HttpRequestMessage const &r
443
440
  void OriginPolicyHttpFilter::ValidateAllowOrigin(
444
441
  hstring const &allowedOrigin,
445
442
  hstring const &allowCredentials,
446
- IInspectable const &iRequestArgs) const {
443
+ IMap<hstring, IInspectable> props) const {
447
444
  // 4.10.1-2 - null allow origin
448
445
  if (L"null" == allowedOrigin)
449
446
  throw hresult_error{
450
447
  E_INVALIDARG,
451
448
  L"Response header Access-Control-Allow-Origin has a value of [null] which differs from the supplied origin"};
452
449
 
453
- bool withCredentials = iRequestArgs.as<RequestArgs>()->WithCredentials;
450
+ bool withCredentials = props.Lookup(L"RequestArgs").as<RequestArgs>()->WithCredentials;
454
451
  // 4.10.3 - valid wild card allow origin
455
452
  if (!withCredentials && L"*" == allowedOrigin)
456
453
  return;
457
454
 
458
455
  // We assume the source (request) origin is not "*", "null", or empty string. Valid URI is expected
459
456
  // 4.10.4 - Mismatched allow origin
460
- if (allowedOrigin.empty() || !IsSameOrigin(s_origin, Uri{allowedOrigin})) {
457
+ auto taintedOriginProp = props.TryLookup(L"TaintedOrigin");
458
+ auto taintedOrigin = taintedOriginProp && winrt::unbox_value<bool>(taintedOriginProp);
459
+ auto origin = taintedOrigin ? nullptr : s_origin;
460
+ if (allowedOrigin.empty() || !IsSameOrigin(origin, Uri{allowedOrigin})) {
461
461
  hstring errorMessage;
462
462
  if (allowedOrigin.empty())
463
463
  errorMessage = L"No valid origin in response";
@@ -511,14 +511,14 @@ void OriginPolicyHttpFilter::ValidatePreflightResponse(
511
511
 
512
512
  auto controlValues = ExtractAccessControlValues(response.Headers());
513
513
 
514
- auto iRequestArgs = request.Properties().Lookup(L"RequestArgs");
514
+ auto props = request.Properties();
515
515
  // Check if the origin is allowed in conjuction with the withCredentials flag
516
516
  // CORS preflight should always exclude credentials although the subsequent CORS request may include credentials.
517
- ValidateAllowOrigin(controlValues.AllowedOrigin, controlValues.AllowedCredentials, iRequestArgs);
517
+ ValidateAllowOrigin(controlValues.AllowedOrigin, controlValues.AllowedCredentials, props);
518
518
 
519
519
  // See https://fetch.spec.whatwg.org/#cors-preflight-fetch, section 4.8.7.5
520
520
  // Check if the request method is allowed
521
- bool withCredentials = iRequestArgs.as<RequestArgs>()->WithCredentials;
521
+ bool withCredentials = props.Lookup(L"RequestArgs").as<RequestArgs>()->WithCredentials;
522
522
  bool requestMethodAllowed = false;
523
523
  for (const auto &method : controlValues.AllowedMethods) {
524
524
  if (L"*" == method) {
@@ -579,8 +579,8 @@ void OriginPolicyHttpFilter::ValidateResponse(HttpResponseMessage const &respons
579
579
  if (originPolicy == OriginPolicy::SimpleCrossOriginResourceSharing ||
580
580
  originPolicy == OriginPolicy::CrossOriginResourceSharing) {
581
581
  auto controlValues = ExtractAccessControlValues(response.Headers());
582
- auto withCredentials =
583
- response.RequestMessage().Properties().Lookup(L"RequestArgs").try_as<RequestArgs>()->WithCredentials;
582
+ auto props = response.RequestMessage().Properties();
583
+ auto withCredentials = props.Lookup(L"RequestArgs").try_as<RequestArgs>()->WithCredentials;
584
584
 
585
585
  if (GetRuntimeOptionBool("Http.StrictOriginCheckSimpleCors") &&
586
586
  originPolicy == OriginPolicy::SimpleCrossOriginResourceSharing) {
@@ -595,8 +595,7 @@ void OriginPolicyHttpFilter::ValidateResponse(HttpResponseMessage const &respons
595
595
  throw hresult_error{E_INVALIDARG, L"The server does not support CORS or the origin is not allowed"};
596
596
  }
597
597
  } else {
598
- auto iRequestArgs = response.RequestMessage().Properties().Lookup(L"RequestArgs");
599
- ValidateAllowOrigin(controlValues.AllowedOrigin, controlValues.AllowedCredentials, iRequestArgs);
598
+ ValidateAllowOrigin(controlValues.AllowedOrigin, controlValues.AllowedCredentials, props);
600
599
  }
601
600
 
602
601
  if (originPolicy == OriginPolicy::SimpleCrossOriginResourceSharing) {
@@ -684,6 +683,38 @@ ResponseOperation OriginPolicyHttpFilter::SendPreflightAsync(HttpRequestMessage
684
683
  co_return {co_await m_innerFilter.SendRequestAsync(preflightRequest)};
685
684
  }
686
685
 
686
+ #pragma region IRedirectEventSource
687
+
688
+ bool OriginPolicyHttpFilter::OnRedirecting(
689
+ HttpRequestMessage const &request,
690
+ HttpResponseMessage const &response) noexcept {
691
+ // Consider the following scenario.
692
+ // User signs in to http://a.com and visits a page that makes CORS request to http://b.com with origin=http://a.com.
693
+ // Http://b.com reponds with a redirect to http://a.com. The browser follows the redirect to http://a.com with
694
+ // origin=http://a.com. Since the origin matches the URL, the request is authorized at http://a.com, but it actually
695
+ // allows http://b.com to bypass the CORS check at http://a.com since the redirected URL is from http://b.com.
696
+ if (!IsSameOrigin(response.Headers().Location(), request.RequestUri()) &&
697
+ !IsSameOrigin(s_origin, request.RequestUri())) {
698
+ // By masking the origin field in the request header, we make it impossible for the server to set a single value for
699
+ // the access-control-allow-origin header. It means, the only way to support redirect is that server allows access
700
+ // from all sites through wildcard.
701
+ request.Headers().Insert(L"Origin", L"null");
702
+
703
+ auto props = request.Properties();
704
+ // Look for 'RequestArgs' key to ensure we are redirecting the main request.
705
+ if (auto iReqArgs = props.TryLookup(L"RequestArgs")) {
706
+ props.Insert(L"TaintedOrigin", winrt::box_value(true));
707
+ } else {
708
+ // Abort redirection if the request is either preflight or extraneous.
709
+ return false;
710
+ }
711
+ }
712
+
713
+ return true;
714
+ }
715
+
716
+ #pragma endregion IRedirectEventSource
717
+
687
718
  #pragma region IHttpFilter
688
719
 
689
720
  ResponseOperation OriginPolicyHttpFilter::SendRequestAsync(HttpRequestMessage const &request) {
@@ -3,11 +3,14 @@
3
3
 
4
4
  #pragma once
5
5
 
6
+ #include "IRedirectEventSource.h"
6
7
  #include "OriginPolicy.h"
7
8
 
8
9
  // Windows API
10
+ #include <winrt/Windows.Foundation.Collections.h>
9
11
  #include <winrt/Windows.Foundation.h>
10
12
  #include <winrt/Windows.Web.Http.Filters.h>
13
+ #include <winrt/Windows.Web.Http.Headers.h>
11
14
  #include <winrt/Windows.Web.Http.h>
12
15
 
13
16
  // Standard Library
@@ -16,7 +19,8 @@
16
19
  namespace Microsoft::React::Networking {
17
20
 
18
21
  class OriginPolicyHttpFilter
19
- : public winrt::implements<OriginPolicyHttpFilter, winrt::Windows::Web::Http::Filters::IHttpFilter> {
22
+ : public winrt::
23
+ implements<OriginPolicyHttpFilter, winrt::Windows::Web::Http::Filters::IHttpFilter, IRedirectEventSource> {
20
24
  public:
21
25
  struct ConstWcharComparer {
22
26
  bool operator()(const wchar_t *, const wchar_t *) const;
@@ -75,7 +79,7 @@ class OriginPolicyHttpFilter
75
79
  winrt::Windows::Web::Http::HttpResponseMessage const &response,
76
80
  bool removeAll);
77
81
 
78
- OriginPolicyHttpFilter(winrt::Windows::Web::Http::Filters::IHttpFilter &&innerFilter);
82
+ OriginPolicyHttpFilter(winrt::Windows::Web::Http::Filters::IHttpFilter const &innerFilter);
79
83
 
80
84
  OriginPolicyHttpFilter();
81
85
 
@@ -92,13 +96,22 @@ class OriginPolicyHttpFilter
92
96
  void ValidateAllowOrigin(
93
97
  winrt::hstring const &allowedOrigin,
94
98
  winrt::hstring const &allowCredentials,
95
- winrt::Windows::Foundation::IInspectable const &iArgs) const;
99
+ winrt::Windows::Foundation::Collections::IMap<winrt::hstring, winrt::Windows::Foundation::IInspectable> props)
100
+ const;
96
101
 
97
102
  winrt::Windows::Foundation::IAsyncOperationWithProgress<
98
103
  winrt::Windows::Web::Http::HttpResponseMessage,
99
104
  winrt::Windows::Web::Http::HttpProgress>
100
105
  SendPreflightAsync(winrt::Windows::Web::Http::HttpRequestMessage const &request) const;
101
106
 
107
+ #pragma region IRedirectEventSource
108
+
109
+ bool OnRedirecting(
110
+ winrt::Windows::Web::Http::HttpRequestMessage const &request,
111
+ winrt::Windows::Web::Http::HttpResponseMessage const &response) noexcept override;
112
+
113
+ #pragma endregion IRedirectEventSource
114
+
102
115
  #pragma region IHttpFilter
103
116
 
104
117
  winrt::Windows::Foundation::IAsyncOperationWithProgress<