// Copyright (c) 2015 GitHub, Inc. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. #include "shell/browser/api/atom_api_web_request.h" #include #include #include #include "base/task/post_task.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" #include "shell/browser/atom_browser_context.h" #include "shell/browser/net/atom_network_delegate.h" #include "shell/common/native_mate_converters/net_converter.h" #include "shell/common/native_mate_converters/once_callback.h" #include "shell/common/native_mate_converters/value_converter.h" using content::BrowserThread; namespace electron { namespace api { namespace { template void CallNetworkDelegateMethod( URLRequestContextGetter* url_request_context_getter, Method method, Event type, URLPatterns patterns, Listener listener) { // Force creating network delegate. url_request_context_getter->GetURLRequestContext(); // Then call the method. auto* network_delegate = url_request_context_getter->network_delegate(); (network_delegate->*method)(type, std::move(patterns), std::move(listener)); } } // namespace WebRequest::WebRequest(v8::Isolate* isolate, AtomBrowserContext* browser_context) : browser_context_(browser_context) { Init(isolate); } WebRequest::~WebRequest() {} template void WebRequest::SetSimpleListener(mate::Arguments* args) { SetListener( &AtomNetworkDelegate::SetSimpleListenerInIO, type, args); } template void WebRequest::SetResponseListener(mate::Arguments* args) { SetListener( &AtomNetworkDelegate::SetResponseListenerInIO, type, args); } template void WebRequest::SetListener(Method method, Event type, mate::Arguments* args) { // { urls }. URLPatterns patterns; mate::Dictionary dict; std::set filter_patterns; if (args->GetNext(&dict) && !dict.Get("urls", &filter_patterns)) { args->ThrowError( "onBeforeRequest parameter 'filter' must have property 'urls'."); return; } URLPattern pattern(URLPattern::SCHEME_ALL); for (const std::string& filter_pattern : filter_patterns) { const URLPattern::ParseResult result = pattern.Parse(filter_pattern); if (result == URLPattern::ParseResult::kSuccess) { patterns.insert(pattern); } else { const char* error_type = URLPattern::GetParseResultString(result); args->ThrowError("Invalid url pattern " + filter_pattern + ": " + error_type); } } // Function or null. v8::Local value; Listener listener; if (!args->GetNext(&listener) && !(args->GetNext(&value) && value->IsNull())) { args->ThrowError("Must pass null or a Function"); return; } auto* url_request_context_getter = static_cast( browser_context_->GetRequestContext()); if (!url_request_context_getter) return; base::PostTaskWithTraits( FROM_HERE, {BrowserThread::IO}, base::BindOnce(&CallNetworkDelegateMethod, base::RetainedRef(url_request_context_getter), method, type, std::move(patterns), std::move(listener))); } // static mate::Handle WebRequest::Create( v8::Isolate* isolate, AtomBrowserContext* browser_context) { return mate::CreateHandle(isolate, new WebRequest(isolate, browser_context)); } // static void WebRequest::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { prototype->SetClassName(mate::StringToV8(isolate, "WebRequest")); mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetMethod("onBeforeRequest", &WebRequest::SetResponseListener< AtomNetworkDelegate::kOnBeforeRequest>) .SetMethod("onBeforeSendHeaders", &WebRequest::SetResponseListener< AtomNetworkDelegate::kOnBeforeSendHeaders>) .SetMethod("onHeadersReceived", &WebRequest::SetResponseListener< AtomNetworkDelegate::kOnHeadersReceived>) .SetMethod( "onSendHeaders", &WebRequest::SetSimpleListener) .SetMethod("onBeforeRedirect", &WebRequest::SetSimpleListener< AtomNetworkDelegate::kOnBeforeRedirect>) .SetMethod("onResponseStarted", &WebRequest::SetSimpleListener< AtomNetworkDelegate::kOnResponseStarted>) .SetMethod( "onCompleted", &WebRequest::SetSimpleListener) .SetMethod("onErrorOccurred", &WebRequest::SetSimpleListener< AtomNetworkDelegate::kOnErrorOccurred>); } } // namespace api } // namespace electron