Created
October 17, 2020 00:25
-
-
Save tarruda/554962f987f7f3a1a94d2c1c76c880a8 to your computer and use it in GitHub Desktop.
This patch modifies electron's intercept*Protocol APIs to allow passing an array of URL patterns as second argument (same format as webRequest)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
commit 6defd383ae86a65a4cdcc8ec47f4aabf7aac69a6 | |
Author: Thiago Padilha <thiagopadilha@cloud.upwork.com> | |
Date: Fri Oct 16 19:10:26 2020 -0300 | |
OTA-10843: Implement URL patterns for intercept*Protocol | |
By passing an array of URL patterns (same syntax as webRequest), it is now | |
possible to filter which URLs are passed to intercept*Protocol handlers. | |
diff --git a/shell/browser/api/electron_api_protocol_ns.cc b/shell/browser/api/electron_api_protocol_ns.cc | |
index 6b1c4e016..7413ab252 100644 | |
--- a/shell/browser/api/electron_api_protocol_ns.cc | |
+++ b/shell/browser/api/electron_api_protocol_ns.cc | |
@@ -172,14 +172,15 @@ void ProtocolNS::RegisterURLLoaderFactories( | |
content::ContentBrowserClient::NonNetworkURLLoaderFactoryMap* factories) { | |
for (const auto& it : handlers_) { | |
factories->emplace(it.first, std::make_unique<ElectronURLLoaderFactory>( | |
- it.second.first, it.second.second)); | |
+ it.second.first, it.second.second.first)); | |
} | |
} | |
ProtocolError ProtocolNS::RegisterProtocol(ProtocolType type, | |
const std::string& scheme, | |
const ProtocolHandler& handler) { | |
- const bool added = base::TryEmplace(handlers_, scheme, type, handler).second; | |
+ const bool added = base::TryEmplace(handlers_, scheme, type, | |
+ std::make_pair(handler, std::set<URLPattern>())).second; | |
return added ? ProtocolError::OK : ProtocolError::REGISTERED; | |
} | |
@@ -197,9 +198,11 @@ bool ProtocolNS::IsProtocolRegistered(const std::string& scheme) { | |
ProtocolError ProtocolNS::InterceptProtocol(ProtocolType type, | |
const std::string& scheme, | |
- const ProtocolHandler& handler) { | |
+ const ProtocolHandler& handler, | |
+ std::set<URLPattern> patterns) { | |
const bool added = | |
- base::TryEmplace(intercept_handlers_, scheme, type, handler).second; | |
+ base::TryEmplace(intercept_handlers_, scheme, type, | |
+ std::make_pair(handler, std::move(patterns))).second; | |
return added ? ProtocolError::OK : ProtocolError::INTERCEPTED; | |
} | |
@@ -254,6 +257,30 @@ void ProtocolNS::HandleOptionalCallback(gin::Arguments* args, | |
} | |
} | |
+std::set<URLPattern> ProtocolNS::ParseURLPatterns(gin::Arguments *args) { | |
+ std::set<URLPattern> rv; | |
+ std::set<std::string> filter_patterns; | |
+ | |
+ if (!args->GetNext(&filter_patterns)) { | |
+ return rv; | |
+ } | |
+ | |
+ for (const std::string& filter_pattern : filter_patterns) { | |
+ URLPattern pattern(URLPattern::SCHEME_ALL); | |
+ const URLPattern::ParseResult result = pattern.Parse(std::move(filter_pattern)); | |
+ if (result == URLPattern::ParseResult::kSuccess) { | |
+ rv.insert(pattern); | |
+ } else { | |
+ const char* error_type = URLPattern::GetParseResultString(result); | |
+ args->ThrowTypeError("Invalid url pattern " + filter_pattern + ": " + | |
+ error_type); | |
+ break; | |
+ } | |
+ } | |
+ | |
+ return rv; | |
+} | |
+ | |
// static | |
gin::Handle<ProtocolNS> ProtocolNS::Create( | |
v8::Isolate* isolate, | |
diff --git a/shell/browser/api/electron_api_protocol_ns.h b/shell/browser/api/electron_api_protocol_ns.h | |
index febbd34eb..12d729db1 100644 | |
--- a/shell/browser/api/electron_api_protocol_ns.h | |
+++ b/shell/browser/api/electron_api_protocol_ns.h | |
@@ -9,6 +9,7 @@ | |
#include <vector> | |
#include "content/public/browser/content_browser_client.h" | |
+#include "extensions/common/url_pattern.h" | |
#include "gin/handle.h" | |
#include "shell/browser/api/trackable_object.h" | |
#include "shell/browser/net/electron_url_loader_factory.h" | |
@@ -67,7 +68,8 @@ class ProtocolNS : public mate::TrackableObject<ProtocolNS> { | |
ProtocolError InterceptProtocol(ProtocolType type, | |
const std::string& scheme, | |
- const ProtocolHandler& handler); | |
+ const ProtocolHandler& handler, | |
+ std::set<URLPattern> url_pattern); | |
void UninterceptProtocol(const std::string& scheme, gin::Arguments* args); | |
bool IsProtocolIntercepted(const std::string& scheme); | |
@@ -86,12 +88,15 @@ class ProtocolNS : public mate::TrackableObject<ProtocolNS> { | |
void InterceptProtocolFor(const std::string& scheme, | |
const ProtocolHandler& handler, | |
gin::Arguments* args) { | |
- HandleOptionalCallback(args, InterceptProtocol(type, scheme, handler)); | |
+ HandleOptionalCallback(args, InterceptProtocol(type, scheme, handler, | |
+ ParseURLPatterns(args))); | |
} | |
// Be compatible with old interface, which accepts optional callback. | |
void HandleOptionalCallback(gin::Arguments* args, ProtocolError error); | |
+ std::set<URLPattern> ParseURLPatterns(gin::Arguments* args); | |
+ | |
HandlersMap handlers_; | |
HandlersMap intercept_handlers_; | |
}; | |
diff --git a/shell/browser/net/electron_url_loader_factory.h b/shell/browser/net/electron_url_loader_factory.h | |
index a7d7b4916..5582219fe 100644 | |
--- a/shell/browser/net/electron_url_loader_factory.h | |
+++ b/shell/browser/net/electron_url_loader_factory.h | |
@@ -9,6 +9,7 @@ | |
#include <string> | |
#include <utility> | |
+#include "extensions/common/url_pattern.h" | |
#include "mojo/public/cpp/bindings/pending_receiver.h" | |
#include "mojo/public/cpp/bindings/pending_remote.h" | |
#include "mojo/public/cpp/bindings/receiver_set.h" | |
@@ -36,7 +37,8 @@ using ProtocolHandler = | |
// scheme => (type, handler). | |
using HandlersMap = | |
- std::map<std::string, std::pair<ProtocolType, ProtocolHandler>>; | |
+ std::map<std::string, std::pair<ProtocolType, | |
+ std::pair<ProtocolHandler, std::set<URLPattern>>>>; | |
// Implementation of URLLoaderFactory. | |
class ElectronURLLoaderFactory : public network::mojom::URLLoaderFactory { | |
diff --git a/shell/browser/net/proxying_url_loader_factory.cc b/shell/browser/net/proxying_url_loader_factory.cc | |
index 47df711b9..bf619bf6a 100644 | |
--- a/shell/browser/net/proxying_url_loader_factory.cc | |
+++ b/shell/browser/net/proxying_url_loader_factory.cc | |
@@ -10,6 +10,7 @@ | |
#include "base/strings/string_util.h" | |
#include "content/public/browser/browser_context.h" | |
#include "extensions/browser/extension_navigation_ui_data.h" | |
+#include "extensions/common/url_pattern.h" | |
#include "mojo/public/cpp/bindings/binding.h" | |
#include "net/base/completion_repeating_callback.h" | |
#include "net/base/load_flags.h" | |
@@ -18,6 +19,24 @@ | |
#include "shell/browser/net/asar/asar_url_loader.h" | |
#include "shell/common/options_switches.h" | |
+ | |
+namespace { | |
+ | |
+// Test whether the URL of |request| matches |patterns|. | |
+bool MatchesFilterCondition(const network::ResourceRequest& original_request, | |
+ const std::set<URLPattern>& patterns) { | |
+ if (patterns.empty()) | |
+ return true; | |
+ | |
+ for (const auto& pattern : patterns) { | |
+ if (pattern.MatchesURL(original_request.url)) | |
+ return true; | |
+ } | |
+ return false; | |
+} | |
+ | |
+} | |
+ | |
namespace electron { | |
ProxyingURLLoaderFactory::InProgressRequest::FollowRedirectParams:: | |
FollowRedirectParams() = default; | |
@@ -684,6 +703,7 @@ ProxyingURLLoaderFactory::ProxyingURLLoaderFactory( | |
navigation_ui_data_(std::move(navigation_ui_data)), | |
navigation_id_(std::move(navigation_id)), | |
loader_factory_type_(loader_factory_type) { | |
+ | |
target_factory_.Bind(std::move(target_factory_remote)); | |
target_factory_.set_disconnect_handler(base::BindOnce( | |
&ProxyingURLLoaderFactory::OnTargetFactoryError, base::Unretained(this))); | |
@@ -730,13 +750,16 @@ void ProxyingURLLoaderFactory::CreateLoaderAndStart( | |
// Check if user has intercepted this scheme. | |
auto it = intercepted_handlers_.find(request.url.scheme()); | |
if (it != intercepted_handlers_.end()) { | |
- // <scheme, <type, handler>> | |
- it->second.second.Run( | |
- request, base::BindOnce(&ElectronURLLoaderFactory::StartLoading, | |
- std::move(loader), routing_id, request_id, | |
- options, request, std::move(client), | |
- traffic_annotation, this, it->second.first)); | |
- return; | |
+ auto url_patterns = it->second.second.second; | |
+ if (MatchesFilterCondition(original_request, url_patterns)) { | |
+ // <scheme, <type, handler>> | |
+ it->second.second.first.Run( | |
+ request, base::BindOnce(&ElectronURLLoaderFactory::StartLoading, | |
+ std::move(loader), routing_id, request_id, | |
+ options, request, std::move(client), | |
+ traffic_annotation, this, it->second.first)); | |
+ return; | |
+ } | |
} | |
// Intercept file:// protocol to support asar archives. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment