From e8d4abe78fcaafccbf265ed33db7afe12f91d010 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 15 Sep 2016 15:59:40 +0200 Subject: [PATCH 001/148] Adding net module and URLRequest class. --- atom/browser/api/atom_api_net.cc | 65 ++++++++++++++++++++++++ atom/browser/api/atom_api_net.h | 37 ++++++++++++++ atom/browser/api/atom_api_url_request.cc | 39 ++++++++++++++ atom/browser/api/atom_api_url_request.h | 37 ++++++++++++++ atom/common/node_bindings.cc | 1 + filenames.gypi | 5 ++ lib/browser/api/exports/electron.js | 6 +++ lib/browser/api/net.js | 13 +++++ 8 files changed, 203 insertions(+) create mode 100644 atom/browser/api/atom_api_net.cc create mode 100644 atom/browser/api/atom_api_net.h create mode 100644 atom/browser/api/atom_api_url_request.cc create mode 100644 atom/browser/api/atom_api_url_request.h create mode 100644 lib/browser/api/net.js diff --git a/atom/browser/api/atom_api_net.cc b/atom/browser/api/atom_api_net.cc new file mode 100644 index 0000000000..ee1b437392 --- /dev/null +++ b/atom/browser/api/atom_api_net.cc @@ -0,0 +1,65 @@ +// Copyright (c) 2013 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/api/atom_api_net.h" +#include "atom/browser/api/atom_api_url_request.h" +#include "native_mate/dictionary.h" +#include "atom/common/node_includes.h" + +namespace atom { + +namespace api { + +Net::Net(v8::Isolate* isolate) { + Init(isolate); +} + +Net::~Net() { +} + + +// static +v8::Local Net::Create(v8::Isolate* isolate) { + return mate::CreateHandle(isolate, new Net(isolate)).ToV8(); +} + +// static +void Net::BuildPrototype(v8::Isolate* isolate, + v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "Net")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) + .SetProperty("URLRequest", &Net::URLRequest); +} + +v8::Local Net::URLRequest(v8::Isolate* isolate) { + return URLRequest::GetConstructor(isolate)->GetFunction(); +} + + + +} // namespace api + +} // namespace atom + + +namespace { + +using atom::api::Net; +using atom::api::URLRequest; + +void Initialize(v8::Local exports, v8::Local unused, + v8::Local context, void* priv) { + + v8::Isolate* isolate = context->GetIsolate(); + + URLRequest::SetConstructor(isolate, base::Bind(URLRequest::New)); + + mate::Dictionary dict(isolate, exports); + dict.Set("net", Net::Create(isolate)); + +} + +} // namespace + +NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_net, Initialize) \ No newline at end of file diff --git a/atom/browser/api/atom_api_net.h b/atom/browser/api/atom_api_net.h new file mode 100644 index 0000000000..dd97bb9653 --- /dev/null +++ b/atom/browser/api/atom_api_net.h @@ -0,0 +1,37 @@ +// Copyright (c) 2013 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_API_ATOM_API_NET_H_ +#define ATOM_BROWSER_API_ATOM_API_NET_H_ + +#include "atom/browser/api/event_emitter.h" + +namespace atom { + +namespace api { + +class Net : public mate::EventEmitter { + +public: + static v8::Local Create(v8::Isolate* isolate); + + static void BuildPrototype(v8::Isolate* isolate, + v8::Local prototype); + + v8::Local URLRequest(v8::Isolate* isolate); +protected: + Net(v8::Isolate* isolate); + ~Net() override; + +private: + + DISALLOW_COPY_AND_ASSIGN(Net); +}; + +} // namespace api + +} // namespace atom + + +#endif // ATOM_BROWSER_API_ATOM_API_NET_H_ \ No newline at end of file diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc new file mode 100644 index 0000000000..8862fbaee2 --- /dev/null +++ b/atom/browser/api/atom_api_url_request.cc @@ -0,0 +1,39 @@ +// Copyright (c) 2013 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/api/atom_api_url_request.h" + +namespace atom { + +namespace api { + +URLRequest::URLRequest(v8::Isolate* isolate) { + Init(isolate); +} + +URLRequest::~URLRequest() { +} + +// static +mate::WrappableBase* URLRequest::New(mate::Arguments* args) { + + return new URLRequest(args->isolate()); +} + + +// static +void URLRequest::BuildPrototype(v8::Isolate* isolate, + v8::Local prototype) { + prototype->SetClassName(mate::StringToV8(isolate, "WebRequest")); + mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) + .SetMethod("start", &URLRequest::start); +} + +void URLRequest::start() { + +} + +} // namespace mate + +} // namepsace mate \ No newline at end of file diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h new file mode 100644 index 0000000000..3d07b0712b --- /dev/null +++ b/atom/browser/api/atom_api_url_request.h @@ -0,0 +1,37 @@ +// Copyright (c) 2013 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_API_ATOM_API_URL_REQUEST_H_ +#define ATOM_BROWSER_API_ATOM_API_URL_REQUEST_H_ + +#include "atom/browser/api/trackable_object.h" +#include "native_mate/handle.h" + +namespace atom { + +namespace api { + + +class URLRequest : public mate::TrackableObject { + public: + static mate::WrappableBase* New(mate::Arguments* args); + + static void BuildPrototype(v8::Isolate* isolate, + v8::Local prototype); + + void start(); + + protected: + URLRequest(v8::Isolate* isolate); + ~URLRequest() override; + + private: + DISALLOW_COPY_AND_ASSIGN(URLRequest); +}; + +} // namepsace api + +} // namepsace atom + +#endif // ATOM_BROWSER_API_ATOM_API_URL_REQUEST_H_ \ No newline at end of file diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index a049be23a6..e869d2a703 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -39,6 +39,7 @@ REFERENCE_MODULE(atom_browser_debugger); REFERENCE_MODULE(atom_browser_desktop_capturer); REFERENCE_MODULE(atom_browser_download_item); REFERENCE_MODULE(atom_browser_menu); +REFERENCE_MODULE(atom_browser_net); REFERENCE_MODULE(atom_browser_power_monitor); REFERENCE_MODULE(atom_browser_power_save_blocker); REFERENCE_MODULE(atom_browser_protocol); diff --git a/filenames.gypi b/filenames.gypi index 9c4b42f622..db6bd23d68 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -23,6 +23,7 @@ 'lib/browser/api/menu-item.js', 'lib/browser/api/menu-item-roles.js', 'lib/browser/api/navigation-controller.js', + 'lib/browser/api/net.js', 'lib/browser/api/power-monitor.js', 'lib/browser/api/power-save-blocker.js', 'lib/browser/api/protocol.js', @@ -116,6 +117,8 @@ 'atom/browser/api/atom_api_menu_views.h', 'atom/browser/api/atom_api_menu_mac.h', 'atom/browser/api/atom_api_menu_mac.mm', + 'atom/browser/api/atom_api_net.cc', + 'atom/browser/api/atom_api_net.h', 'atom/browser/api/atom_api_power_monitor.cc', 'atom/browser/api/atom_api_power_monitor.h', 'atom/browser/api/atom_api_power_save_blocker.cc', @@ -134,6 +137,8 @@ 'atom/browser/api/atom_api_system_preferences_win.cc', 'atom/browser/api/atom_api_tray.cc', 'atom/browser/api/atom_api_tray.h', + 'atom/browser/api/atom_api_url_request.cc', + 'atom/browser/api/atom_api_url_request.h', 'atom/browser/api/atom_api_web_contents.cc', 'atom/browser/api/atom_api_web_contents.h', 'atom/browser/api/atom_api_web_contents_mac.mm', diff --git a/lib/browser/api/exports/electron.js b/lib/browser/api/exports/electron.js index c47c046906..a96f5a711b 100644 --- a/lib/browser/api/exports/electron.js +++ b/lib/browser/api/exports/electron.js @@ -107,6 +107,12 @@ Object.defineProperties(exports, { return require('../web-contents') } }, + //net: { + // enumerable: true, + // get: function () { + // return require('../net') + // } + //}, // The internal modules, invisible unless you know their names. NavigationController: { diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js new file mode 100644 index 0000000000..98e8104e92 --- /dev/null +++ b/lib/browser/api/net.js @@ -0,0 +1,13 @@ +'use strict' + +const binding = process.atomBinding('net') +const {URLRequest} = binding + +// Public API. +Object.defineProperties(exports, { + URLRequest: { + enumerable: true, + value: URLRequest + } +}) + \ No newline at end of file From 7521aeea09c994e4afef3c00d457246054798fee Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Mon, 19 Sep 2016 11:21:09 +0200 Subject: [PATCH 002/148] Implement URLRequest::Delegate, handle thread sync. --- atom/browser/api/atom_api_net.cc | 1 + atom/browser/api/atom_api_url_request.cc | 67 ++++++++++++++++++-- atom/browser/api/atom_api_url_request.h | 21 ++++-- atom/browser/net/atom_url_request.cc | 81 ++++++++++++++++++++++++ atom/browser/net/atom_url_request.h | 52 +++++++++++++++ filenames.gypi | 2 + lib/browser/api/exports/electron.js | 12 ++-- lib/browser/api/net.js | 15 ++--- 8 files changed, 229 insertions(+), 22 deletions(-) create mode 100644 atom/browser/net/atom_url_request.cc create mode 100644 atom/browser/net/atom_url_request.h diff --git a/atom/browser/api/atom_api_net.cc b/atom/browser/api/atom_api_net.cc index ee1b437392..1559cee4ca 100644 --- a/atom/browser/api/atom_api_net.cc +++ b/atom/browser/api/atom_api_net.cc @@ -57,6 +57,7 @@ void Initialize(v8::Local exports, v8::Local unused, mate::Dictionary dict(isolate, exports); dict.Set("net", Net::Create(isolate)); + dict.Set("Net", Net::GetConstructor(isolate)->GetFunction()); } diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 8862fbaee2..44b4581ef4 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -3,13 +3,20 @@ // found in the LICENSE file. #include "atom/browser/api/atom_api_url_request.h" +#include "atom/browser/api/atom_api_session.h" + +#include "native_mate/dictionary.h" +#include "atom/browser/net/atom_url_request.h" + namespace atom { namespace api { -URLRequest::URLRequest(v8::Isolate* isolate) { - Init(isolate); +URLRequest::URLRequest(v8::Isolate* isolate, + v8::Local wrapper) + : weak_ptr_factory_(this) { + InitWith(isolate, wrapper); } URLRequest::~URLRequest() { @@ -18,20 +25,72 @@ URLRequest::~URLRequest() { // static mate::WrappableBase* URLRequest::New(mate::Arguments* args) { - return new URLRequest(args->isolate()); + v8::Local options; + args->GetNext(&options); + mate::Dictionary dict(args->isolate(), options); + std::string url; + dict.Get("url", &url); + std::string method; + dict.Get("method", &method); + std::string session_name; + dict.Get("session", &session_name); + + auto session = Session::FromPartition(args->isolate(), session_name); + + auto browser_context = session->browser_context(); + + //auto url_request_context_getter = browser_context->url_request_context_getter(); + // auto url_request_context = url_request_context_getter->GetURLRequestContext(); + + //auto net_url_request = url_request_context->CreateRequest(GURL(url), + // net::RequestPriority::DEFAULT_PRIORITY, + // nullptr); + // net_url_request->set_method(method); + + // auto atom_url_request = new URLRequest(args->isolate(), args->GetThis(), net_url_request.release()); + + auto api_url_request = new URLRequest(args->isolate(), args->GetThis()); + auto weak_ptr = api_url_request->weak_ptr_factory_.GetWeakPtr(); + auto atom_url_request = AtomURLRequest::create(browser_context, url, weak_ptr); + + atom_url_request->set_method(method); + + api_url_request->atom_url_request_ = atom_url_request; + + + return api_url_request; } // static void URLRequest::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { - prototype->SetClassName(mate::StringToV8(isolate, "WebRequest")); + prototype->SetClassName(mate::StringToV8(isolate, "URLRequest")); mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) + .MakeDestroyable() .SetMethod("start", &URLRequest::start); } void URLRequest::start() { + pin(); + atom_url_request_->Start(); +} +void URLRequest::stop() { + +} +void URLRequest::OnResponseStarted() { + Emit("response-started"); +} + +void URLRequest::pin() { + if (wrapper_.IsEmpty()) { + wrapper_.Reset(isolate(), GetWrapper()); + } +} + +void URLRequest::unpin() { + wrapper_.Reset(); } } // namespace mate diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 3d07b0712b..474b13a748 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -7,13 +7,15 @@ #include "atom/browser/api/trackable_object.h" #include "native_mate/handle.h" +#include "net/url_request/url_request_context.h" namespace atom { +class AtomURLRequest; + namespace api { - -class URLRequest : public mate::TrackableObject { +class URLRequest : public mate::EventEmitter { public: static mate::WrappableBase* New(mate::Arguments* args); @@ -21,12 +23,23 @@ class URLRequest : public mate::TrackableObject { v8::Local prototype); void start(); - + void stop(); + void OnResponseStarted(); protected: - URLRequest(v8::Isolate* isolate); + URLRequest(v8::Isolate* isolate, + v8::Local wrapper); ~URLRequest() override; + + private: + void pin(); + void unpin(); + + scoped_refptr atom_url_request_; + v8::Global wrapper_; + base::WeakPtrFactory weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(URLRequest); }; diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc new file mode 100644 index 0000000000..50aee48653 --- /dev/null +++ b/atom/browser/net/atom_url_request.cc @@ -0,0 +1,81 @@ +// Copyright (c) 2013 GitHub, Inc. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/net/atom_url_request.h" +#include "atom/browser/api/atom_api_url_request.h" +#include "atom/browser/atom_browser_context.h" +#include "base/callback.h" +#include "content/public/browser/browser_thread.h" + +namespace atom { + +AtomURLRequest::AtomURLRequest(base::WeakPtr delegate) + : delegate_(delegate) { +} + +AtomURLRequest::~AtomURLRequest() { +} + +scoped_refptr AtomURLRequest::create( + AtomBrowserContext* browser_context, + const std::string& url, + base::WeakPtr delegate) { + + + auto url_request_context_getter = browser_context->url_request_context_getter(); + auto url_request_context = url_request_context_getter->GetURLRequestContext(); + + auto net_url_request = url_request_context->CreateRequest(GURL(url), + net::RequestPriority::DEFAULT_PRIORITY, + nullptr); + // net_url_request->set_method(method); + + scoped_refptr atom_url_request = new AtomURLRequest(delegate); + + net_url_request->set_delegate(atom_url_request.get()); + + atom_url_request->url_request_ = std::move(net_url_request); + + return atom_url_request; + +} + +void AtomURLRequest::Start() { + // post to io thread + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&AtomURLRequest::StartOnIOThread, this)); +} + +void AtomURLRequest::StartOnIOThread() { + url_request_->Start(); +} + + +void AtomURLRequest::set_method(const std::string& method) { + url_request_->set_method(method); +} + +void AtomURLRequest::OnResponseStarted(net::URLRequest* request) +{ + // post to main thread + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegeteResponseStarted, this)); +} + +void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) +{ + // post to main thread +} + +void AtomURLRequest::InformDelegeteResponseStarted() { + if (delegate_) { + delegate_->OnResponseStarted(); + } +} + + +} // namespace atom \ No newline at end of file diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h new file mode 100644 index 0000000000..e581008eb4 --- /dev/null +++ b/atom/browser/net/atom_url_request.h @@ -0,0 +1,52 @@ +// Copyright (c) 2013 GitHub, Inc. +// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_NET_ATOM_URL_REQUEST_H_ +#define ATOM_BROWSER_NET_ATOM_URL_REQUEST_H_ + +#include "base/memory/ref_counted.h" +#include "net/url_request/url_request.h" + +namespace atom { + +class AtomBrowserContext; + +namespace api { + class URLRequest; +} + +class AtomURLRequest : public base::RefCountedThreadSafe, + public net::URLRequest::Delegate { +public: + static scoped_refptr create( + AtomBrowserContext* browser_context, + const std::string& url, + base::WeakPtr delegate); + + void Start(); + void set_method(const std::string& method); + +protected: + // Overrides of net::URLRequest::Delegate + virtual void OnResponseStarted(net::URLRequest* request) override; + virtual void OnReadCompleted(net::URLRequest* request, int bytes_read) override; + +private: + friend class base::RefCountedThreadSafe; + void StartOnIOThread(); + void InformDelegeteResponseStarted(); + + AtomURLRequest(base::WeakPtr delegate); + virtual ~AtomURLRequest(); + + base::WeakPtr delegate_; + std::unique_ptr url_request_; + + DISALLOW_COPY_AND_ASSIGN(AtomURLRequest); + }; + +} // namespace atom + +#endif // ATOM_BROWSER_NET_ATOM_URL_REQUEST_H_ \ No newline at end of file diff --git a/filenames.gypi b/filenames.gypi index db6bd23d68..20375c6f4e 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -238,6 +238,8 @@ 'atom/browser/net/atom_network_delegate.h', 'atom/browser/net/atom_ssl_config_service.cc', 'atom/browser/net/atom_ssl_config_service.h', + 'atom/browser/net/atom_url_request.cc', + 'atom/browser/net/atom_url_request.h', 'atom/browser/net/atom_url_request_job_factory.cc', 'atom/browser/net/atom_url_request_job_factory.h', 'atom/browser/net/http_protocol_handler.cc', diff --git a/lib/browser/api/exports/electron.js b/lib/browser/api/exports/electron.js index a96f5a711b..09d5b0e47a 100644 --- a/lib/browser/api/exports/electron.js +++ b/lib/browser/api/exports/electron.js @@ -107,12 +107,12 @@ Object.defineProperties(exports, { return require('../web-contents') } }, - //net: { - // enumerable: true, - // get: function () { - // return require('../net') - // } - //}, + net: { + enumerable: true, + get: function () { + return require('../net') + } + }, // The internal modules, invisible unless you know their names. NavigationController: { diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 98e8104e92..c443a8ee9e 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -1,13 +1,12 @@ 'use strict' +const {EventEmitter} = require('events') const binding = process.atomBinding('net') -const {URLRequest} = binding +const {net, Net} = binding +const {URLRequest} = net -// Public API. -Object.defineProperties(exports, { - URLRequest: { - enumerable: true, - value: URLRequest - } -}) +Object.setPrototypeOf(Net.prototype, EventEmitter.prototype) +Object.setPrototypeOf(URLRequest.prototype, EventEmitter.prototype) + +module.exports = net \ No newline at end of file From 81eab9887be50ed653ea1d7819890363e4fa4b72 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Mon, 19 Sep 2016 15:06:13 +0200 Subject: [PATCH 003/148] Adding URLResponse to emit response events, implementing status code. --- atom/browser/api/atom_api_menu.cc | 3 +- atom/browser/api/atom_api_url_request.cc | 78 +++++++++++++++++++----- atom/browser/api/atom_api_url_request.h | 22 +++++-- atom/browser/net/atom_url_request.cc | 59 +++++++++++++++--- atom/browser/net/atom_url_request.h | 13 +++- lib/browser/api/net.js | 42 +++++++++++++ 6 files changed, 185 insertions(+), 32 deletions(-) diff --git a/atom/browser/api/atom_api_menu.cc b/atom/browser/api/atom_api_menu.cc index 627ce601f5..0de2dffc77 100644 --- a/atom/browser/api/atom_api_menu.cc +++ b/atom/browser/api/atom_api_menu.cc @@ -191,7 +191,8 @@ using atom::api::Menu; void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { v8::Isolate* isolate = context->GetIsolate(); - Menu::SetConstructor(isolate, base::Bind(&Menu::New)); + Menu::thehub + SetConstructor(isolate, base::Bind(&Menu::New)); mate::Dictionary dict(isolate, exports); dict.Set("Menu", Menu::GetConstructor(isolate)->GetFunction()); diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 44b4581ef4..f31c07cbba 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -39,16 +39,7 @@ mate::WrappableBase* URLRequest::New(mate::Arguments* args) { auto browser_context = session->browser_context(); - //auto url_request_context_getter = browser_context->url_request_context_getter(); - // auto url_request_context = url_request_context_getter->GetURLRequestContext(); - //auto net_url_request = url_request_context->CreateRequest(GURL(url), - // net::RequestPriority::DEFAULT_PRIORITY, - // nullptr); - // net_url_request->set_method(method); - - // auto atom_url_request = new URLRequest(args->isolate(), args->GetThis(), net_url_request.release()); - auto api_url_request = new URLRequest(args->isolate(), args->GetThis()); auto weak_ptr = api_url_request->weak_ptr_factory_.GetWeakPtr(); auto atom_url_request = AtomURLRequest::create(browser_context, url, weak_ptr); @@ -67,20 +58,75 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { prototype->SetClassName(mate::StringToV8(isolate, "URLRequest")); mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) - .MakeDestroyable() - .SetMethod("start", &URLRequest::start); + // Request API + .MakeDestroyable() + .SetMethod("write", &URLRequest::Write) + .SetMethod("end", &URLRequest::End) + .SetMethod("abort", &URLRequest::Abort) + .SetMethod("setHeader", &URLRequest::SetHeader) + .SetMethod("getHeader", &URLRequest::GetHeader) + .SetMethod("removaHeader", &URLRequest::RemoveHeader) + // Response APi + .SetProperty("statusCode", &URLRequest::StatusCode) + .SetProperty("statusMessage", &URLRequest::StatusMessage) + .SetProperty("responseHeaders", &URLRequest::ResponseHeaders) + .SetProperty("responseHttpVersion", &URLRequest::ResponseHttpVersion); } -void URLRequest::start() { +void URLRequest::Write() { + atom_url_request_->Write(); +} + +void URLRequest::End() { pin(); - atom_url_request_->Start(); + atom_url_request_->End(); } -void URLRequest::stop() { - +void URLRequest::Abort() { + atom_url_request_->Abort(); } + +void URLRequest::SetHeader() { + atom_url_request_->SetHeader(); +} +void URLRequest::GetHeader() { + atom_url_request_->GetHeader(); +} +void URLRequest::RemoveHeader() { + atom_url_request_->RemoveHeader(); +} + + void URLRequest::OnResponseStarted() { - Emit("response-started"); + v8::Local _emitResponse; + + auto wrapper = GetWrapper(); + if (mate::Dictionary(isolate(), wrapper).Get("_emitResponse", &_emitResponse)) + _emitResponse->Call(wrapper, 0, nullptr); +} + +void URLRequest::OnResponseData() { + Emit("data"); +} + +void URLRequest::OnResponseEnd() { + Emit("end"); +} + +int URLRequest::StatusCode() { + return atom_url_request_->StatusCode(); +} + +void URLRequest::StatusMessage() { + return atom_url_request_->StatusMessage(); +} + +void URLRequest::ResponseHeaders() { + return atom_url_request_->ResponseHeaders(); +} + +void URLRequest::ResponseHttpVersion() { + return atom_url_request_->ResponseHttpVersion(); } void URLRequest::pin() { diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 474b13a748..172cc51e47 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -22,17 +22,31 @@ class URLRequest : public mate::EventEmitter { static void BuildPrototype(v8::Isolate* isolate, v8::Local prototype); - void start(); - void stop(); - void OnResponseStarted(); protected: URLRequest(v8::Isolate* isolate, v8::Local wrapper); ~URLRequest() override; +private: + void Write(); + void End(); + void Abort(); + void SetHeader(); + void GetHeader(); + void RemoveHeader(); + + friend class AtomURLRequest; + void OnResponseStarted(); + void OnResponseData(); + void OnResponseEnd(); + + int StatusCode(); + void StatusMessage(); + void ResponseHeaders(); + void ResponseHttpVersion(); + - private: void pin(); void unpin(); diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index 50aee48653..1770d01ca6 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -23,32 +23,71 @@ scoped_refptr AtomURLRequest::create( const std::string& url, base::WeakPtr delegate) { + DCHECK(browser_context); + DCHECK(!url.empty()); - auto url_request_context_getter = browser_context->url_request_context_getter(); - auto url_request_context = url_request_context_getter->GetURLRequestContext(); + auto request_context_getter = browser_context->url_request_context_getter(); - auto net_url_request = url_request_context->CreateRequest(GURL(url), - net::RequestPriority::DEFAULT_PRIORITY, - nullptr); - // net_url_request->set_method(method); + DCHECK(request_context_getter); + + auto context = request_context_getter->GetURLRequestContext(); + + DCHECK(context); scoped_refptr atom_url_request = new AtomURLRequest(delegate); - net_url_request->set_delegate(atom_url_request.get()); - - atom_url_request->url_request_ = std::move(net_url_request); + atom_url_request->url_request_ = context->CreateRequest(GURL(url), + net::RequestPriority::DEFAULT_PRIORITY, + atom_url_request.get()); return atom_url_request; } -void AtomURLRequest::Start() { +void AtomURLRequest::Write() { +} + +void AtomURLRequest::End() { // post to io thread content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, base::Bind(&AtomURLRequest::StartOnIOThread, this)); } +void AtomURLRequest::Abort() { +} + +void AtomURLRequest::SetHeader() { + +} + +void AtomURLRequest::GetHeader() { + +} + +void AtomURLRequest::RemoveHeader() { + +} + + + + + + +int AtomURLRequest::StatusCode() { + return url_request_->GetResponseCode(); +} + +void AtomURLRequest::StatusMessage() { +} +void AtomURLRequest::ResponseHeaders() { +} + +void AtomURLRequest::ResponseHttpVersion() { +} + + + void AtomURLRequest::StartOnIOThread() { url_request_->Start(); } diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index e581008eb4..d9a45885e6 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -25,9 +25,20 @@ public: const std::string& url, base::WeakPtr delegate); - void Start(); void set_method(const std::string& method); + void Write(); + void End(); + void Abort(); + void SetHeader(); + void GetHeader(); + void RemoveHeader(); + + int StatusCode(); + void StatusMessage(); + void ResponseHeaders(); + void ResponseHttpVersion(); + protected: // Overrides of net::URLRequest::Delegate virtual void OnResponseStarted(net::URLRequest* request) override; diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index c443a8ee9e..517c13bada 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -8,5 +8,47 @@ const {URLRequest} = net Object.setPrototypeOf(Net.prototype, EventEmitter.prototype) Object.setPrototypeOf(URLRequest.prototype, EventEmitter.prototype) +class URLResponse extends EventEmitter { + constructor(request) { + super(); + this.request = request; + } + + get statusCode() { + return this.request.statusCode; + } + + get statusMessage() { + return this.request.statusMessage; + } + + get headers() { + return this.request.responseHeaders; + } + + get httpVersion() { + return this.request.responseHttpVersion; + } + + + +} + +Net.prototype.request = function(options, callback) { + let request = new URLRequest(options) + + if (callback) { + request.once('response', callback) + } + + + return request +} + +URLRequest.prototype._emitResponse = function() { + this.response = new URLResponse(this); + this.emit('response', this.response); +} + module.exports = net \ No newline at end of file From 2d9d4af98dca29fafa0b800b5245d93ab69f3b3e Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 21 Sep 2016 09:23:00 +0200 Subject: [PATCH 004/148] Implementing URLRequest API, getting response body. --- atom/browser/api/atom_api_menu.cc | 3 +- atom/browser/api/atom_api_url_request.cc | 112 +++++++++++++++---- atom/browser/api/atom_api_url_request.h | 57 +++++++++- atom/browser/net/atom_url_request.cc | 130 +++++++++++++++++++---- atom/browser/net/atom_url_request.h | 22 +++- lib/browser/api/net.js | 65 ++++++++---- 6 files changed, 313 insertions(+), 76 deletions(-) diff --git a/atom/browser/api/atom_api_menu.cc b/atom/browser/api/atom_api_menu.cc index 0de2dffc77..627ce601f5 100644 --- a/atom/browser/api/atom_api_menu.cc +++ b/atom/browser/api/atom_api_menu.cc @@ -191,8 +191,7 @@ using atom::api::Menu; void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { v8::Isolate* isolate = context->GetIsolate(); - Menu::thehub - SetConstructor(isolate, base::Bind(&Menu::New)); + Menu::SetConstructor(isolate, base::Bind(&Menu::New)); mate::Dictionary dict(isolate, exports); dict.Set("Menu", Menu::GetConstructor(isolate)->GetFunction()); diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index f31c07cbba..5e71f243c4 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -7,12 +7,49 @@ #include "native_mate/dictionary.h" #include "atom/browser/net/atom_url_request.h" +#include "atom/common/node_includes.h" +namespace { +const char* const kResponse = "response"; +const char* const kData = "data"; +const char* const kEnd = "end"; + +} +namespace mate { + +template<> +struct Converter> { + static v8::Local ToV8(v8::Isolate* isolate, + scoped_refptr val) { + + mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); + if (val) { + size_t iter = 0; + std::string name; + std::string value; + while (val->EnumerateHeaderLines(&iter, &name, &value)) { + dict.Set(name, value); + } + } + return dict.GetHandle(); + } +}; + +template<> +struct Converter> { + static v8::Local ToV8( + v8::Isolate* isolate, + scoped_refptr buffer) { + return node::Buffer::Copy(isolate, buffer->data(), buffer->size()).ToLocalChecked(); + } +}; + +} namespace atom { namespace api { - + URLRequest::URLRequest(v8::Isolate* isolate, v8::Local wrapper) : weak_ptr_factory_(this) { @@ -69,8 +106,11 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, // Response APi .SetProperty("statusCode", &URLRequest::StatusCode) .SetProperty("statusMessage", &URLRequest::StatusMessage) - .SetProperty("responseHeaders", &URLRequest::ResponseHeaders) - .SetProperty("responseHttpVersion", &URLRequest::ResponseHttpVersion); + .SetProperty("rawResponseHeaders", &URLRequest::RawResponseHeaders) + .SetProperty("httpVersionMajor", &URLRequest::ResponseHttpVersionMajor) + .SetProperty("httpVersionMinor", &URLRequest::ResponseHttpVersionMinor); + + } void URLRequest::Write() { @@ -98,35 +138,71 @@ void URLRequest::RemoveHeader() { void URLRequest::OnResponseStarted() { - v8::Local _emitResponse; + //v8::Local _emitResponse; - auto wrapper = GetWrapper(); - if (mate::Dictionary(isolate(), wrapper).Get("_emitResponse", &_emitResponse)) - _emitResponse->Call(wrapper, 0, nullptr); + //auto wrapper = GetWrapper(); + //if (mate::Dictionary(isolate(), wrapper).Get("_emitResponse", &_emitResponse)) + // _emitResponse->Call(wrapper, 0, nullptr); + EmitRequestEvent("response"); } -void URLRequest::OnResponseData() { - Emit("data"); +void URLRequest::OnResponseData(scoped_refptr buffer) { + if (!buffer || !buffer->data() || !buffer->size()) { + return; + } + + EmitResponseEvent("data", buffer); + //v8::Local _emitData; + //auto data = mate::ConvertToV8(isolate(), buffer); + + //auto wrapper = GetWrapper(); + //if (mate::Dictionary(isolate(), wrapper).Get("_emitData", &_emitData)) + // _emitData->Call(wrapper, 1, &data); } -void URLRequest::OnResponseEnd() { - Emit("end"); +void URLRequest::OnResponseCompleted() { + + //v8::Local _emitEnd; + + //auto wrapper = GetWrapper(); + //if (mate::Dictionary(isolate(), wrapper).Get("_emitEnd", &_emitEnd)) + // _emitEnd->Call(wrapper, 0, nullptr); + + EmitResponseEvent("end"); } + int URLRequest::StatusCode() { - return atom_url_request_->StatusCode(); + if (auto response_headers = atom_url_request_->GetResponseHeaders()) { + return response_headers->response_code(); + } + return -1; } -void URLRequest::StatusMessage() { - return atom_url_request_->StatusMessage(); +std::string URLRequest::StatusMessage() { + std::string result; + if (auto response_headers = atom_url_request_->GetResponseHeaders()) { + result = response_headers->GetStatusText(); + } + return result; } -void URLRequest::ResponseHeaders() { - return atom_url_request_->ResponseHeaders(); +scoped_refptr URLRequest::RawResponseHeaders() { + return atom_url_request_->GetResponseHeaders(); } -void URLRequest::ResponseHttpVersion() { - return atom_url_request_->ResponseHttpVersion(); +uint32_t URLRequest::ResponseHttpVersionMajor() { + if (auto response_headers = atom_url_request_->GetResponseHeaders()) { + return response_headers->GetHttpVersion().major_value(); + } + return 0; +} + +uint32_t URLRequest::ResponseHttpVersionMinor() { + if (auto response_headers = atom_url_request_->GetResponseHeaders()) { + return response_headers->GetHttpVersion().minor_value(); + } + return 0; } void URLRequest::pin() { diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 172cc51e47..1ab4f1cc91 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -5,9 +5,12 @@ #ifndef ATOM_BROWSER_API_ATOM_API_URL_REQUEST_H_ #define ATOM_BROWSER_API_ATOM_API_URL_REQUEST_H_ +#include #include "atom/browser/api/trackable_object.h" #include "native_mate/handle.h" #include "net/url_request/url_request_context.h" +#include "net/http/http_response_headers.h" + namespace atom { @@ -38,13 +41,26 @@ private: friend class AtomURLRequest; void OnResponseStarted(); - void OnResponseData(); - void OnResponseEnd(); + void OnResponseData(scoped_refptr data); + void OnResponseCompleted(); int StatusCode(); - void StatusMessage(); - void ResponseHeaders(); - void ResponseHttpVersion(); + std::string StatusMessage(); + scoped_refptr RawResponseHeaders(); + uint32_t ResponseHttpVersionMajor(); + uint32_t ResponseHttpVersionMinor(); + + + template + std::array, sizeof...(ArgTypes)> + BuildArgsArray(ArgTypes... args); + + template + void EmitRequestEvent(ArgTypes... args); + + template + void EmitResponseEvent(ArgTypes... args); + void pin(); @@ -53,10 +69,41 @@ private: scoped_refptr atom_url_request_; v8::Global wrapper_; base::WeakPtrFactory weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(URLRequest); }; +template +std::array, sizeof...(ArgTypes)> +URLRequest::BuildArgsArray(ArgTypes... args) { + std::array, sizeof...(ArgTypes)> result + = { mate::ConvertToV8(isolate(), args)... }; + return result; +} + +template +void URLRequest::EmitRequestEvent(ArgTypes... args) { + auto arguments = BuildArgsArray(args...); + v8::Local _emitRequestEvent; + auto wrapper = GetWrapper(); + if (mate::Dictionary(isolate(), wrapper).Get("_emitRequestEvent", &_emitRequestEvent)) + _emitRequestEvent->Call(wrapper, arguments.size(), arguments.data()); +} + + +template +void URLRequest::EmitResponseEvent(ArgTypes... args) { + auto arguments = BuildArgsArray(args...); + v8::Local _emitResponseEvent; + auto wrapper = GetWrapper(); + if (mate::Dictionary(isolate(), wrapper).Get("_emitResponseEvent", &_emitResponseEvent)) + _emitResponseEvent->Call(wrapper, arguments.size(), arguments.data()); +} + + + + } // namepsace api } // namepsace atom diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index 1770d01ca6..bdabbfc9fa 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -8,11 +8,19 @@ #include "atom/browser/atom_browser_context.h" #include "base/callback.h" #include "content/public/browser/browser_thread.h" +#include "net/base/io_buffer.h" + +namespace { + +const int kBufferSize = 4096; + +} // namespace namespace atom { AtomURLRequest::AtomURLRequest(base::WeakPtr delegate) - : delegate_(delegate) { + : delegate_(delegate) + , buffer_( new net::IOBuffer(kBufferSize)) { } AtomURLRequest::~AtomURLRequest() { @@ -48,7 +56,7 @@ void AtomURLRequest::Write() { } void AtomURLRequest::End() { - // post to io thread + // Called on content::BrowserThread::UI content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, base::Bind(&AtomURLRequest::StartOnIOThread, this)); @@ -71,24 +79,15 @@ void AtomURLRequest::RemoveHeader() { - - - -int AtomURLRequest::StatusCode() { - return url_request_->GetResponseCode(); -} - -void AtomURLRequest::StatusMessage() { -} -void AtomURLRequest::ResponseHeaders() { -} - -void AtomURLRequest::ResponseHttpVersion() { +scoped_refptr AtomURLRequest::GetResponseHeaders() { + return url_request_->response_headers(); } void AtomURLRequest::StartOnIOThread() { + // Called on content::BrowserThread::IO + url_request_->Start(); } @@ -97,24 +96,109 @@ void AtomURLRequest::set_method(const std::string& method) { url_request_->set_method(method); } -void AtomURLRequest::OnResponseStarted(net::URLRequest* request) -{ - // post to main thread +void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { + // Called on content::BrowserThread::IO + + DCHECK_EQ(request, url_request_.get()); + + if (url_request_->status().is_success()) { + // Cache net::HttpResponseHeaders instance, a read-only objects + // so that headers and other http metainformation can be simultaneously + // read from UI thread while request data is simulataneously streaming + // on IO thread. + response_headers_ = url_request_->response_headers(); + } + content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegeteResponseStarted, this)); + base::Bind(&AtomURLRequest::InformDelegateResponseStarted, this)); + + ReadResponse(); } -void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) -{ - // post to main thread +void AtomURLRequest::ReadResponse() { + + // Called on content::BrowserThread::IO + + // Some servers may treat HEAD requests as GET requests. To free up the + // network connection as soon as possible, signal that the request has + // completed immediately, without trying to read any data back (all we care + // about is the response code and headers, which we already have). + int bytes_read = 0; + if (url_request_->status().is_success() /* TODO && (request_type_ != URLFetcher::HEAD)*/) { + if (!url_request_->Read(buffer_.get(), kBufferSize, &bytes_read)) + bytes_read = -1; + } + OnReadCompleted(url_request_.get(), bytes_read); } -void AtomURLRequest::InformDelegeteResponseStarted() { + +void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) { + // Called on content::BrowserThread::IO + + DCHECK_EQ(request, url_request_.get()); + + do { + if (!url_request_->status().is_success() || bytes_read <= 0) + break; + + + const auto result = CopyAndPostBuffer(bytes_read); + if (!result) { + // Failed to transfer data to UI thread. + return; + } + } while (url_request_->Read(buffer_.get(), kBufferSize, &bytes_read)); + + const auto status = url_request_->status(); + + if (!status.is_io_pending() /* TODO || request_type_ == URLFetcher::HEAD*/ ) { + + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateResponseCompleted, this)); + } + +} + + +bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) { + // Called on content::BrowserThread::IO. + + // data is only a wrapper for the async buffer_. + // Make a deep copy of payload and transfer ownership to the UI thread. + scoped_refptr buffer_copy(new net::IOBufferWithSize(bytes_read)); + memcpy(buffer_copy->data(), buffer_->data(), bytes_read); + + return content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateResponseData, this, buffer_copy)); +} + + +void AtomURLRequest::InformDelegateResponseStarted() { + // Called on content::BrowserThread::UI. + if (delegate_) { delegate_->OnResponseStarted(); } } +void AtomURLRequest::InformDelegateResponseData(scoped_refptr data) { + // Called on content::BrowserThread::IO. + + // Transfer ownership of the data buffer, data will be released + // by the delegate's OnResponseData. + if (delegate_) { + delegate_->OnResponseData(data); + } +} + +void AtomURLRequest::InformDelegateResponseCompleted() { + if (delegate_) { + delegate_->OnResponseCompleted(); + } +} + } // namespace atom \ No newline at end of file diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index d9a45885e6..1aeffd5560 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -9,6 +9,13 @@ #include "base/memory/ref_counted.h" #include "net/url_request/url_request.h" + +namespace net { +class IOBuffer; +class IOBufferWithSize; +class DrainableIOBuffer; +} + namespace atom { class AtomBrowserContext; @@ -34,10 +41,7 @@ public: void GetHeader(); void RemoveHeader(); - int StatusCode(); - void StatusMessage(); - void ResponseHeaders(); - void ResponseHttpVersion(); + scoped_refptr GetResponseHeaders(); protected: // Overrides of net::URLRequest::Delegate @@ -47,13 +51,21 @@ protected: private: friend class base::RefCountedThreadSafe; void StartOnIOThread(); - void InformDelegeteResponseStarted(); + + void ReadResponse(); + bool CopyAndPostBuffer(int bytes_read); + + void InformDelegateResponseStarted(); + void InformDelegateResponseData(scoped_refptr data); + void InformDelegateResponseCompleted(); AtomURLRequest(base::WeakPtr delegate); virtual ~AtomURLRequest(); base::WeakPtr delegate_; std::unique_ptr url_request_; + scoped_refptr buffer_; + scoped_refptr response_headers_; DISALLOW_COPY_AND_ASSIGN(AtomURLRequest); }; diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 517c13bada..96c448020b 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -9,46 +9,65 @@ Object.setPrototypeOf(Net.prototype, EventEmitter.prototype) Object.setPrototypeOf(URLRequest.prototype, EventEmitter.prototype) class URLResponse extends EventEmitter { - constructor(request) { - super(); - this.request = request; - } + constructor(request) { + super(); + this.request = request; + } - get statusCode() { - return this.request.statusCode; - } + get statusCode() { + return this.request.statusCode; + } - get statusMessage() { - return this.request.statusMessage; - } + get statusMessage() { + return this.request.statusMessage; + } - get headers() { - return this.request.responseHeaders; - } + get headers() { + return this.request.rawResponseHeaders; + } - get httpVersion() { - return this.request.responseHttpVersion; - } + get httpVersion() { + return `${this.httpVersionMajor}.${this.httpVersionMinor}`; + } + get httpVersionMajor() { + return this.request.httpVersionMajor; + } + get httpVersionMinor() { + return this.request.httpVersionMinor; + } + + get rawHeaders() { + return this.request.rawResponseHeaders; + } } Net.prototype.request = function(options, callback) { - let request = new URLRequest(options) + let request = new URLRequest(options) - if (callback) { - request.once('response', callback) - } + if (callback) { + request.once('response', callback) + } - return request + return request } -URLRequest.prototype._emitResponse = function() { +URLRequest.prototype._emitRequestEvent = function(name) { + if (name === 'response') { this.response = new URLResponse(this); - this.emit('response', this.response); + this.emit(name, this.response); + } else { + this.emit.apply(this, arguments); + } } +URLRequest.prototype._emitResponseEvent = function() { + this.response.emit.apply(this.response, arguments); +} + + module.exports = net \ No newline at end of file From 2b3b41d5f93f8899850bcf3ca9ab42152c72667e Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 21 Sep 2016 17:35:03 +0200 Subject: [PATCH 005/148] Implementing authentication callback. --- atom/browser/api/atom_api_url_request.cc | 98 +++++++-------- atom/browser/api/atom_api_url_request.h | 28 ++--- atom/browser/net/atom_url_request.cc | 153 ++++++++++++++++------- atom/browser/net/atom_url_request.h | 43 ++++--- lib/browser/api/net.js | 119 ++++++++++++++++++ 5 files changed, 312 insertions(+), 129 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 5e71f243c4..0b4939f2b9 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -8,6 +8,9 @@ #include "native_mate/dictionary.h" #include "atom/browser/net/atom_url_request.h" #include "atom/common/node_includes.h" +#include "atom/common/native_mate_converters/net_converter.h" +#include "atom/common/native_mate_converters/string16_converter.h" +#include "atom/common/native_mate_converters/callback.h" namespace { @@ -19,9 +22,9 @@ const char* const kEnd = "end"; namespace mate { template<> -struct Converter> { +struct Converter> { static v8::Local ToV8(v8::Isolate* isolate, - scoped_refptr val) { + scoped_refptr val) { mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); if (val) { @@ -37,10 +40,10 @@ struct Converter> { }; template<> -struct Converter> { +struct Converter> { static v8::Local ToV8( v8::Isolate* isolate, - scoped_refptr buffer) { + scoped_refptr buffer) { return node::Buffer::Copy(isolate, buffer->data(), buffer->size()).ToLocalChecked(); } }; @@ -79,11 +82,13 @@ mate::WrappableBase* URLRequest::New(mate::Arguments* args) { auto api_url_request = new URLRequest(args->isolate(), args->GetThis()); auto weak_ptr = api_url_request->weak_ptr_factory_.GetWeakPtr(); - auto atom_url_request = AtomURLRequest::create(browser_context, url, weak_ptr); - - atom_url_request->set_method(method); + auto atom_url_request = AtomURLRequest::Create( + browser_context, + method, + url, + weak_ptr); - api_url_request->atom_url_request_ = atom_url_request; + api_url_request->atom_request_ = atom_url_request; return api_url_request; @@ -97,12 +102,12 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) // Request API .MakeDestroyable() - .SetMethod("write", &URLRequest::Write) - .SetMethod("end", &URLRequest::End) + .SetMethod("_write", &URLRequest::Write) + .SetMethod("_end", &URLRequest::End) .SetMethod("abort", &URLRequest::Abort) - .SetMethod("setHeader", &URLRequest::SetHeader) - .SetMethod("getHeader", &URLRequest::GetHeader) - .SetMethod("removaHeader", &URLRequest::RemoveHeader) + .SetMethod("_setHeader", &URLRequest::SetHeader) + .SetMethod("_getHeader", &URLRequest::GetHeader) + .SetMethod("_removaHeader", &URLRequest::RemoveHeader) // Response APi .SetProperty("statusCode", &URLRequest::StatusCode) .SetProperty("statusMessage", &URLRequest::StatusMessage) @@ -114,92 +119,83 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, } void URLRequest::Write() { - atom_url_request_->Write(); + atom_request_->Write(); } void URLRequest::End() { pin(); - atom_url_request_->End(); + atom_request_->End(); } void URLRequest::Abort() { - atom_url_request_->Abort(); + atom_request_->Abort(); } -void URLRequest::SetHeader() { - atom_url_request_->SetHeader(); +void URLRequest::SetHeader(const std::string& name, const std::string& value) { + atom_request_->SetHeader(name, value); } -void URLRequest::GetHeader() { - atom_url_request_->GetHeader(); +std::string URLRequest::GetHeader(const std::string& name) { + return atom_request_->GetHeader(name); } -void URLRequest::RemoveHeader() { - atom_url_request_->RemoveHeader(); +void URLRequest::RemoveHeader(const std::string& name) { + atom_request_->RemoveHeader(name); } +void URLRequest::OnAuthenticationRequired( + scoped_refptr auth_info) { + EmitRequestEvent( + "login", + auth_info.get(), + base::Bind(&AtomURLRequest::PassLoginInformation, atom_request_)); +} + void URLRequest::OnResponseStarted() { - //v8::Local _emitResponse; - - //auto wrapper = GetWrapper(); - //if (mate::Dictionary(isolate(), wrapper).Get("_emitResponse", &_emitResponse)) - // _emitResponse->Call(wrapper, 0, nullptr); EmitRequestEvent("response"); } -void URLRequest::OnResponseData(scoped_refptr buffer) { +void URLRequest::OnResponseData( + scoped_refptr buffer) { if (!buffer || !buffer->data() || !buffer->size()) { return; } EmitResponseEvent("data", buffer); - //v8::Local _emitData; - //auto data = mate::ConvertToV8(isolate(), buffer); - - //auto wrapper = GetWrapper(); - //if (mate::Dictionary(isolate(), wrapper).Get("_emitData", &_emitData)) - // _emitData->Call(wrapper, 1, &data); } void URLRequest::OnResponseCompleted() { - - //v8::Local _emitEnd; - - //auto wrapper = GetWrapper(); - //if (mate::Dictionary(isolate(), wrapper).Get("_emitEnd", &_emitEnd)) - // _emitEnd->Call(wrapper, 0, nullptr); - EmitResponseEvent("end"); } -int URLRequest::StatusCode() { - if (auto response_headers = atom_url_request_->GetResponseHeaders()) { +int URLRequest::StatusCode() const { + if (auto response_headers = atom_request_->GetResponseHeaders()) { return response_headers->response_code(); } return -1; } -std::string URLRequest::StatusMessage() { +std::string URLRequest::StatusMessage() const { std::string result; - if (auto response_headers = atom_url_request_->GetResponseHeaders()) { + if (auto response_headers = atom_request_->GetResponseHeaders()) { result = response_headers->GetStatusText(); } return result; } -scoped_refptr URLRequest::RawResponseHeaders() { - return atom_url_request_->GetResponseHeaders(); +scoped_refptr URLRequest::RawResponseHeaders() const { + return atom_request_->GetResponseHeaders(); } -uint32_t URLRequest::ResponseHttpVersionMajor() { - if (auto response_headers = atom_url_request_->GetResponseHeaders()) { +uint32_t URLRequest::ResponseHttpVersionMajor() const { + if (auto response_headers = atom_request_->GetResponseHeaders()) { return response_headers->GetHttpVersion().major_value(); } return 0; } -uint32_t URLRequest::ResponseHttpVersionMinor() { - if (auto response_headers = atom_url_request_->GetResponseHeaders()) { +uint32_t URLRequest::ResponseHttpVersionMinor() const { + if (auto response_headers = atom_request_->GetResponseHeaders()) { return response_headers->GetHttpVersion().minor_value(); } return 0; diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 1ab4f1cc91..7fd5c6ee92 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -35,25 +35,27 @@ private: void Write(); void End(); void Abort(); - void SetHeader(); - void GetHeader(); - void RemoveHeader(); + void SetHeader(const std::string& name, const std::string& value); + std::string GetHeader(const std::string& name); + void RemoveHeader(const std::string& name); friend class AtomURLRequest; + void OnAuthenticationRequired( + scoped_refptr auth_info); void OnResponseStarted(); - void OnResponseData(scoped_refptr data); + void OnResponseData(scoped_refptr data); void OnResponseCompleted(); - int StatusCode(); - std::string StatusMessage(); - scoped_refptr RawResponseHeaders(); - uint32_t ResponseHttpVersionMajor(); - uint32_t ResponseHttpVersionMinor(); + int StatusCode() const; + std::string StatusMessage() const; + scoped_refptr RawResponseHeaders() const; + uint32_t ResponseHttpVersionMajor() const; + uint32_t ResponseHttpVersionMinor() const; template std::array, sizeof...(ArgTypes)> - BuildArgsArray(ArgTypes... args); + BuildArgsArray(ArgTypes... args) const; template void EmitRequestEvent(ArgTypes... args); @@ -61,12 +63,10 @@ private: template void EmitResponseEvent(ArgTypes... args); - - void pin(); void unpin(); - scoped_refptr atom_url_request_; + scoped_refptr atom_request_; v8::Global wrapper_; base::WeakPtrFactory weak_ptr_factory_; @@ -76,7 +76,7 @@ private: template std::array, sizeof...(ArgTypes)> -URLRequest::BuildArgsArray(ArgTypes... args) { +URLRequest::BuildArgsArray(ArgTypes... args) const { std::array, sizeof...(ArgTypes)> result = { mate::ConvertToV8(isolate(), args)... }; return result; diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index bdabbfc9fa..9c825888aa 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -10,6 +10,7 @@ #include "content/public/browser/browser_thread.h" #include "net/base/io_buffer.h" + namespace { const int kBufferSize = 4096; @@ -18,19 +19,20 @@ const int kBufferSize = 4096; namespace atom { -AtomURLRequest::AtomURLRequest(base::WeakPtr delegate) +AtomURLRequest::AtomURLRequest(base::WeakPtr delegate) : delegate_(delegate) - , buffer_( new net::IOBuffer(kBufferSize)) { + , buffer_(new net::IOBuffer(kBufferSize)) { } AtomURLRequest::~AtomURLRequest() { } -scoped_refptr AtomURLRequest::create( +scoped_refptr AtomURLRequest::Create( AtomBrowserContext* browser_context, + const std::string& method, const std::string& url, base::WeakPtr delegate) { - + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(browser_context); DCHECK(!url.empty()); @@ -44,69 +46,117 @@ scoped_refptr AtomURLRequest::create( scoped_refptr atom_url_request = new AtomURLRequest(delegate); - atom_url_request->url_request_ = context->CreateRequest(GURL(url), + atom_url_request->request_ = context->CreateRequest(GURL(url), net::RequestPriority::DEFAULT_PRIORITY, atom_url_request.get()); + atom_url_request->request_->set_method(method); return atom_url_request; } -void AtomURLRequest::Write() { +void AtomURLRequest::Write() const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } -void AtomURLRequest::End() { - // Called on content::BrowserThread::UI +void AtomURLRequest::End() const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&AtomURLRequest::StartOnIOThread, this)); + base::Bind(&AtomURLRequest::DoStart, this)); } -void AtomURLRequest::Abort() { +void AtomURLRequest::Abort() const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } -void AtomURLRequest::SetHeader() { - +void AtomURLRequest::SetHeader(const std::string& name, + const std::string& value) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + request_->SetExtraRequestHeaderByName(name, value, true); } -void AtomURLRequest::GetHeader() { - +std::string AtomURLRequest::GetHeader(const std::string& name) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + std::string result; + const auto& extra_headers = request_->extra_request_headers(); + if (!extra_headers.GetHeader(name, &result)) { + net::HttpRequestHeaders* request_headers = nullptr; + if (request_->GetFullRequestHeaders(request_headers) && request_headers) { + request_headers->GetHeader(name, &result); + } + } + return result; } -void AtomURLRequest::RemoveHeader() { - +void AtomURLRequest::RemoveHeader(const std::string& name) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + request_->RemoveRequestHeaderByName(name); } -scoped_refptr AtomURLRequest::GetResponseHeaders() { - return url_request_->response_headers(); +scoped_refptr +AtomURLRequest::GetResponseHeaders() const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + return request_->response_headers(); } - -void AtomURLRequest::StartOnIOThread() { - // Called on content::BrowserThread::IO - - url_request_->Start(); +void AtomURLRequest::PassLoginInformation(const base::string16& username, + const base::string16& password) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (username.empty() || password.empty()) { + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&AtomURLRequest::DoCancelAuth, this)); + } + else { + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&AtomURLRequest::DoSetAuth, this, username, password)); + } } -void AtomURLRequest::set_method(const std::string& method) { - url_request_->set_method(method); +void AtomURLRequest::DoStart() const { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + request_->Start(); +} + +void AtomURLRequest::DoSetAuth(const base::string16& username, + const base::string16& password) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + request_->SetAuth(net::AuthCredentials(username, password)); +} + +void AtomURLRequest::DoCancelAuth() const { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + request_->CancelAuth(); +} + +void AtomURLRequest::OnAuthRequired(net::URLRequest* request, + net::AuthChallengeInfo* auth_info) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateAuthenticationRequired, + this, + scoped_refptr(auth_info))); } void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { - // Called on content::BrowserThread::IO + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DCHECK_EQ(request, request_.get()); - DCHECK_EQ(request, url_request_.get()); - - if (url_request_->status().is_success()) { + if (request_->status().is_success()) { // Cache net::HttpResponseHeaders instance, a read-only objects // so that headers and other http metainformation can be simultaneously // read from UI thread while request data is simulataneously streaming // on IO thread. - response_headers_ = url_request_->response_headers(); + response_headers_ = request_->response_headers(); } content::BrowserThread::PostTask( @@ -117,29 +167,28 @@ void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { } void AtomURLRequest::ReadResponse() { - - // Called on content::BrowserThread::IO + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); // Some servers may treat HEAD requests as GET requests. To free up the // network connection as soon as possible, signal that the request has // completed immediately, without trying to read any data back (all we care // about is the response code and headers, which we already have). int bytes_read = 0; - if (url_request_->status().is_success() /* TODO && (request_type_ != URLFetcher::HEAD)*/) { - if (!url_request_->Read(buffer_.get(), kBufferSize, &bytes_read)) + if (request_->status().is_success() /* TODO && (request_type_ != URLFetcher::HEAD)*/) { + if (!request_->Read(buffer_.get(), kBufferSize, &bytes_read)) bytes_read = -1; } - OnReadCompleted(url_request_.get(), bytes_read); + OnReadCompleted(request_.get(), bytes_read); } void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) { - // Called on content::BrowserThread::IO + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - DCHECK_EQ(request, url_request_.get()); + DCHECK_EQ(request, request_.get()); do { - if (!url_request_->status().is_success() || bytes_read <= 0) + if (!request_->status().is_success() || bytes_read <= 0) break; @@ -148,9 +197,9 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) { // Failed to transfer data to UI thread. return; } - } while (url_request_->Read(buffer_.get(), kBufferSize, &bytes_read)); + } while (request_->Read(buffer_.get(), kBufferSize, &bytes_read)); - const auto status = url_request_->status(); + const auto status = request_->status(); if (!status.is_io_pending() /* TODO || request_type_ == URLFetcher::HEAD*/ ) { @@ -161,9 +210,8 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) { } - bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) { - // Called on content::BrowserThread::IO. + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); // data is only a wrapper for the async buffer_. // Make a deep copy of payload and transfer ownership to the UI thread. @@ -176,16 +224,25 @@ bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) { } -void AtomURLRequest::InformDelegateResponseStarted() { - // Called on content::BrowserThread::UI. +void AtomURLRequest::InformDelegateAuthenticationRequired( + scoped_refptr auth_info) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (delegate_) { + delegate_->OnAuthenticationRequired(auth_info); + } +} + +void AtomURLRequest::InformDelegateResponseStarted() const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (delegate_) { delegate_->OnResponseStarted(); } } -void AtomURLRequest::InformDelegateResponseData(scoped_refptr data) { - // Called on content::BrowserThread::IO. +void AtomURLRequest::InformDelegateResponseData( + scoped_refptr data) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Transfer ownership of the data buffer, data will be released // by the delegate's OnResponseData. @@ -194,7 +251,9 @@ void AtomURLRequest::InformDelegateResponseData(scoped_refptrOnResponseCompleted(); } diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index 1aeffd5560..be3c270ff9 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -27,43 +27,52 @@ namespace api { class AtomURLRequest : public base::RefCountedThreadSafe, public net::URLRequest::Delegate { public: - static scoped_refptr create( + static scoped_refptr Create( AtomBrowserContext* browser_context, + const std::string& method, const std::string& url, base::WeakPtr delegate); - void set_method(const std::string& method); - - void Write(); - void End(); - void Abort(); - void SetHeader(); - void GetHeader(); - void RemoveHeader(); - - scoped_refptr GetResponseHeaders(); + void Write() const; + void End() const; + void Abort() const; + void SetHeader(const std::string& name, const std::string& value) const; + std::string GetHeader(const std::string& name) const; + void RemoveHeader(const std::string& name) const; + void PassLoginInformation(const base::string16& username, + const base::string16& password) const; + scoped_refptr GetResponseHeaders() const; protected: // Overrides of net::URLRequest::Delegate + virtual void OnAuthRequired(net::URLRequest* request, + net::AuthChallengeInfo* auth_info) override; virtual void OnResponseStarted(net::URLRequest* request) override; - virtual void OnReadCompleted(net::URLRequest* request, int bytes_read) override; + virtual void OnReadCompleted(net::URLRequest* request, + int bytes_read) override; private: friend class base::RefCountedThreadSafe; - void StartOnIOThread(); + void DoStart() const; + void DoSetAuth(const base::string16& username, + const base::string16& password) const; + void DoCancelAuth() const; void ReadResponse(); bool CopyAndPostBuffer(int bytes_read); - void InformDelegateResponseStarted(); - void InformDelegateResponseData(scoped_refptr data); - void InformDelegateResponseCompleted(); + void InformDelegateAuthenticationRequired( + scoped_refptr auth_info) const; + void InformDelegateResponseStarted() const; + void InformDelegateResponseData( + scoped_refptr data) const; + void InformDelegateResponseCompleted() const; AtomURLRequest(base::WeakPtr delegate); virtual ~AtomURLRequest(); base::WeakPtr delegate_; - std::unique_ptr url_request_; + std::unique_ptr request_; scoped_refptr buffer_; scoped_refptr response_headers_; diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 96c448020b..a476cdf87a 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -55,6 +55,48 @@ Net.prototype.request = function(options, callback) { return request } +URLRequest.prototype._init = function() { + this._finished = false; + this._hasBody = true; + this._chunkedEncoding = false; + this._headersSent = false; +} + + +URLRequest.prototype.setHeader = function(name, value) { + if (typeof name !== 'string') + throw new TypeError('`name` should be a string in setHeader(name, value).'); + if (value === undefined) + throw new Error('`value` required in setHeader("' + name + '", value).'); + if (this._headersSent) + throw new Error('Can\'t set headers after they are sent.'); + + this._setHeader(name, value) +}; + + +URLRequest.prototype.getHeader = function(name) { + if (arguments.length < 1) { + throw new Error('`name` is required for getHeader(name).'); + } + + return this._getHeader(name); +}; + + +URLRequest.prototype.removeHeader = function(name) { + if (arguments.length < 1) { + throw new Error('`name` is required for removeHeader(name).'); + } + + if (this._headersSent) { + throw new Error('Can\'t remove headers after they are sent.'); + } + + this._removeHeader(name); +}; + + URLRequest.prototype._emitRequestEvent = function(name) { if (name === 'response') { this.response = new URLResponse(this); @@ -69,5 +111,82 @@ URLRequest.prototype._emitResponseEvent = function() { } +URLRequest.prototype.write = function(chunk, encoding, callback) { + + if (this.finished) { + var err = new Error('write after end'); + process.nextTick(writeAfterEndNT, this, err, callback); + + return true; + } + + /* TODO + if (!this._header) { + this._implicitHeader(); + } + */ + + if (!this._hasBody) { + //debug('This type of response MUST NOT have a body. ' + + // 'Ignoring write() calls.'); + return true; + } + + + if (typeof chunk !== 'string' && !(chunk instanceof Buffer)) { + throw new TypeError('First argument must be a string or Buffer'); + } + + + // If we get an empty string or buffer, then just do nothing, and + // signal the user to keep writing. + if (chunk.length === 0) return true; + + var len, ret; + if (this.chunkedEncoding) { + if (typeof chunk === 'string' && + encoding !== 'hex' && + encoding !== 'base64' && + encoding !== 'binary') { + len = Buffer.byteLength(chunk, encoding); + chunk = len.toString(16) + CRLF + chunk + CRLF; + ret = this._send(chunk, encoding, callback); + } else { + // buffer, or a non-toString-friendly encoding + if (typeof chunk === 'string') + len = Buffer.byteLength(chunk, encoding); + else + len = chunk.length; + + if (this.connection && !this.connection.corked) { + this.connection.cork(); + process.nextTick(connectionCorkNT, this.connection); + } + this._send(len.toString(16), 'binary', null); + this._send(crlf_buf, null, null); + this._send(chunk, encoding, null); + ret = this._send(crlf_buf, null, callback); + } + } else { + ret = this._send(chunk, encoding, callback); + } + + //debug('write ret = ' + ret); + return ret; +}; + + + +URLRequest.prototype.end = function() { + this._end(); +}; + + +function writeAfterEndNT(self, err, callback) { + self.emit('error', err); + if (callback) callback(err); +} + + module.exports = net \ No newline at end of file From f7525d7877ebbf4fc9c0b67f15716072d8cd7d0f Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Mon, 26 Sep 2016 14:03:49 +0200 Subject: [PATCH 006/148] Adding support for POST requests. --- atom/browser/api/atom_api_url_request.cc | 59 +++++++++-- atom/browser/api/atom_api_url_request.h | 7 +- atom/browser/net/atom_url_request.cc | 112 +++++++++++++++++--- atom/browser/net/atom_url_request.h | 20 ++-- lib/browser/api/net.js | 129 +++++++++++------------ 5 files changed, 230 insertions(+), 97 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 0b4939f2b9..5ded4cd52f 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -41,11 +41,45 @@ struct Converter> { template<> struct Converter> { + static v8::Local ToV8( v8::Isolate* isolate, scoped_refptr buffer) { return node::Buffer::Copy(isolate, buffer->data(), buffer->size()).ToLocalChecked(); } + + static bool FromV8(v8::Isolate* isolate, v8::Local val, + scoped_refptr* out) { + + auto size = node::Buffer::Length(val); + + if (size == 0) { + // Support conversoin from empty buffer. A use case is + // a GET request without body. + // Since zero-sized IOBuffer(s) are not supported, we set the + // out pointer to null. + *out = nullptr; + return true; + } + + auto data = node::Buffer::Data(val); + if (!data) { + // This is an error as size is positif but data is null. + return false; + } + + auto io_buffer = new net::IOBufferWithSize(size); + if (!io_buffer) { + // Assuming allocation failed. + return false; + } + + // We do a deep copy. We could have used Buffer's internal memory + // but that is much more complicated to be properly handled. + memcpy(io_buffer->data(), data, size); + *out = io_buffer; + return true; + } }; } @@ -102,8 +136,7 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) // Request API .MakeDestroyable() - .SetMethod("_write", &URLRequest::Write) - .SetMethod("_end", &URLRequest::End) + .SetMethod("_writeBuffer", &URLRequest::WriteBuffer) .SetMethod("abort", &URLRequest::Abort) .SetMethod("_setHeader", &URLRequest::SetHeader) .SetMethod("_getHeader", &URLRequest::GetHeader) @@ -118,21 +151,27 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, } -void URLRequest::Write() { - atom_request_->Write(); +bool URLRequest::WriteBuffer(scoped_refptr buffer, bool is_last) { + atom_request_->WriteBuffer(buffer, is_last); + return true; } -void URLRequest::End() { - pin(); - atom_request_->End(); -} void URLRequest::Abort() { atom_request_->Abort(); } -void URLRequest::SetHeader(const std::string& name, const std::string& value) { +bool URLRequest::SetHeader(const std::string& name, const std::string& value) { + if (!net::HttpUtil::IsValidHeaderName(name)) { + return false; + } + + if (!net::HttpUtil::IsValidHeaderValue(value)) { + return false; + } + atom_request_->SetHeader(name, value); + return true; } std::string URLRequest::GetHeader(const std::string& name) { return atom_request_->GetHeader(name); @@ -165,6 +204,8 @@ void URLRequest::OnResponseData( void URLRequest::OnResponseCompleted() { EmitResponseEvent("end"); + unpin(); + atom_request_ = nullptr; } diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 7fd5c6ee92..3831348f78 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -32,10 +32,9 @@ class URLRequest : public mate::EventEmitter { private: - void Write(); - void End(); + bool WriteBuffer(scoped_refptr buffer, bool is_last); void Abort(); - void SetHeader(const std::string& name, const std::string& value); + bool SetHeader(const std::string& name, const std::string& value); std::string GetHeader(const std::string& name); void RemoveHeader(const std::string& name); @@ -66,7 +65,7 @@ private: void pin(); void unpin(); - scoped_refptr atom_request_; + scoped_refptr atom_request_; v8::Global wrapper_; base::WeakPtrFactory weak_ptr_factory_; diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index 9c825888aa..09d787a51f 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -9,6 +9,8 @@ #include "base/callback.h" #include "content/public/browser/browser_thread.h" #include "net/base/io_buffer.h" +#include "net/base/elements_upload_data_stream.h" +#include "net/base/upload_bytes_element_reader.h" namespace { @@ -19,9 +21,37 @@ const int kBufferSize = 4096; namespace atom { +namespace internal { + + +class UploadOwnedIOBufferElementReader : public net::UploadBytesElementReader { +public: + explicit UploadOwnedIOBufferElementReader( + scoped_refptr buffer) + : net::UploadBytesElementReader(buffer->data(), buffer->size()) + , buffer_(buffer) { + } + ~UploadOwnedIOBufferElementReader() override { + } + + + static UploadOwnedIOBufferElementReader* CreateWithBuffer( + scoped_refptr buffer) { + return new UploadOwnedIOBufferElementReader(std::move(buffer)); + } + +private: + scoped_refptr buffer_; + + DISALLOW_COPY_AND_ASSIGN(UploadOwnedIOBufferElementReader); +}; + +} + AtomURLRequest::AtomURLRequest(base::WeakPtr delegate) : delegate_(delegate) - , buffer_(new net::IOBuffer(kBufferSize)) { + , response_read_buffer_(new net::IOBuffer(kBufferSize)) + , is_chunked_upload_(is_chunked_upload_) { } AtomURLRequest::~AtomURLRequest() { @@ -55,17 +85,25 @@ scoped_refptr AtomURLRequest::Create( } -void AtomURLRequest::Write() const { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); -} -void AtomURLRequest::End() const { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); +void AtomURLRequest::WriteBuffer(scoped_refptr buffer, + bool is_last) { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&AtomURLRequest::DoStart, this)); + base::Bind(&AtomURLRequest::DoWriteBuffer, this, buffer, is_last)); } +void AtomURLRequest::SetChunkedUpload() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + // The method can be called only before switching to multi-threaded mode, + // i.e. before the first call to write. + // So it is safe to change the object in the UI thread. + is_chunked_upload_ = true; +} + + void AtomURLRequest::Abort() const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } @@ -119,10 +157,58 @@ void AtomURLRequest::PassLoginInformation(const base::string16& username, } -void AtomURLRequest::DoStart() const { +void AtomURLRequest::DoWriteBuffer(scoped_refptr buffer, + bool is_last) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - request_->Start(); + if (is_chunked_upload_) { + + // Chunked encoding case. + + bool first_call = false; + if (!chunked_stream_writer_) { + std::unique_ptr chunked_stream( + new net::ChunkedUploadDataStream(0)); + chunked_stream_writer_ = chunked_stream->CreateWriter(); + request_->set_upload(std::move(chunked_stream)); + first_call = true; + } + + if (buffer) { + // Non-empty buffer. + auto write_result = chunked_stream_writer_->AppendData( + buffer->data(), + buffer->size(), + is_last); + } + else if (is_last) { + // Empty buffer and last chunck, i.e. request.end(). + auto write_result = chunked_stream_writer_->AppendData( + nullptr, + 0, + true); + } + + if (first_call) { + request_->Start(); + } + } + else { + + if (buffer) { + // Handling potential empty buffers. + std::unique_ptr element_reader(internal::UploadOwnedIOBufferElementReader + ::CreateWithBuffer(std::move(buffer))); + upload_element_readers_.push_back(std::move(element_reader)); + } + + if (is_last) { + std::unique_ptr elements_upload_data_stream( + new net::ElementsUploadDataStream(std::move(upload_element_readers_), 0)); + request_->set_upload(std::move(elements_upload_data_stream)); + request_->Start(); + } + } } void AtomURLRequest::DoSetAuth(const base::string16& username, @@ -175,7 +261,7 @@ void AtomURLRequest::ReadResponse() { // about is the response code and headers, which we already have). int bytes_read = 0; if (request_->status().is_success() /* TODO && (request_type_ != URLFetcher::HEAD)*/) { - if (!request_->Read(buffer_.get(), kBufferSize, &bytes_read)) + if (!request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)) bytes_read = -1; } OnReadCompleted(request_.get(), bytes_read); @@ -197,7 +283,7 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) { // Failed to transfer data to UI thread. return; } - } while (request_->Read(buffer_.get(), kBufferSize, &bytes_read)); + } while (request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)); const auto status = request_->status(); @@ -213,10 +299,10 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) { bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - // data is only a wrapper for the async buffer_. + // data is only a wrapper for the async response_read_buffer_. // Make a deep copy of payload and transfer ownership to the UI thread. scoped_refptr buffer_copy(new net::IOBufferWithSize(bytes_read)); - memcpy(buffer_copy->data(), buffer_->data(), bytes_read); + memcpy(buffer_copy->data(), response_read_buffer_->data(), bytes_read); return content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index be3c270ff9..3a923a002e 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -8,20 +8,21 @@ #include "base/memory/ref_counted.h" #include "net/url_request/url_request.h" +#include "net/base/chunked_upload_data_stream.h" namespace net { class IOBuffer; class IOBufferWithSize; class DrainableIOBuffer; -} +}; namespace atom { class AtomBrowserContext; namespace api { - class URLRequest; +class URLRequest; } class AtomURLRequest : public base::RefCountedThreadSafe, @@ -33,8 +34,8 @@ public: const std::string& url, base::WeakPtr delegate); - void Write() const; - void End() const; + void WriteBuffer(scoped_refptr buffer, bool is_last); + void SetChunkedUpload(); void Abort() const; void SetHeader(const std::string& name, const std::string& value) const; std::string GetHeader(const std::string& name) const; @@ -53,7 +54,7 @@ protected: private: friend class base::RefCountedThreadSafe; - void DoStart() const; + void DoWriteBuffer(scoped_refptr buffer, bool is_last); void DoSetAuth(const base::string16& username, const base::string16& password) const; void DoCancelAuth() const; @@ -73,7 +74,14 @@ private: base::WeakPtr delegate_; std::unique_ptr request_; - scoped_refptr buffer_; + + bool is_chunked_upload_; + std::unique_ptr chunked_stream_; + std::unique_ptr chunked_stream_writer_; + + std::vector>upload_element_readers_; + + scoped_refptr response_read_buffer_; scoped_refptr response_headers_; DISALLOW_COPY_AND_ASSIGN(AtomURLRequest); diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index a476cdf87a..d1d8cb7e7c 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -56,10 +56,16 @@ Net.prototype.request = function(options, callback) { } URLRequest.prototype._init = function() { - this._finished = false; - this._hasBody = true; + // Flag to prevent writings after end. + this._finished = false; + + // Set when the request uses chuned encoding. Can be switched + // to true only once and never set back to false. this._chunkedEncoding = false; - this._headersSent = false; + + // Flag to prevent request's headers modifications after + // headers flush. + this._headersSent = false; } @@ -111,80 +117,73 @@ URLRequest.prototype._emitResponseEvent = function() { } -URLRequest.prototype.write = function(chunk, encoding, callback) { - - if (this.finished) { - var err = new Error('write after end'); - process.nextTick(writeAfterEndNT, this, err, callback); - - return true; - } - - /* TODO - if (!this._header) { - this._implicitHeader(); - } - */ - - if (!this._hasBody) { - //debug('This type of response MUST NOT have a body. ' + - // 'Ignoring write() calls.'); - return true; - } +URLRequest.prototype._write = function(chunk, encoding, callback, is_last) { - - if (typeof chunk !== 'string' && !(chunk instanceof Buffer)) { - throw new TypeError('First argument must be a string or Buffer'); + let chunk_is_string = typeof chunk === 'string'; + let chunk_is_buffer = chunk instanceof Buffer; + if (!chunk_is_string && !chunk_is_buffer) { + throw new TypeError('First argument must be a string or Buffer.'); } - - // If we get an empty string or buffer, then just do nothing, and - // signal the user to keep writing. - if (chunk.length === 0) return true; - - var len, ret; - if (this.chunkedEncoding) { - if (typeof chunk === 'string' && - encoding !== 'hex' && - encoding !== 'base64' && - encoding !== 'binary') { - len = Buffer.byteLength(chunk, encoding); - chunk = len.toString(16) + CRLF + chunk + CRLF; - ret = this._send(chunk, encoding, callback); - } else { - // buffer, or a non-toString-friendly encoding - if (typeof chunk === 'string') - len = Buffer.byteLength(chunk, encoding); - else - len = chunk.length; - - if (this.connection && !this.connection.corked) { - this.connection.cork(); - process.nextTick(connectionCorkNT, this.connection); - } - this._send(len.toString(16), 'binary', null); - this._send(crlf_buf, null, null); - this._send(chunk, encoding, null); - ret = this._send(crlf_buf, null, callback); - } - } else { - ret = this._send(chunk, encoding, callback); + if (chunk_is_string) { + // We convert all strings into binary buffers. + chunk = Buffer.from(chunk, encoding); } - //debug('write ret = ' + ret); - return ret; + // Headers are assumed to be sent on first call to _writeBuffer, + // i.e. after the first call to write or end. + let result = this._writeBuffer(chunk, is_last); + + // Since writing to the network is asynchronous, we conservatively + // assume that request headers are written after delivering the first + // buffer to the network IO thread. + this._headersSent = true; + + // The write callback is fired asynchronously to mimic Node.js. + if (callback) { + process.nextTick(callback); + } + + return result; +} + +URLRequest.prototype.write = function(data, encoding, callback) { + + if (this._finished) { + let error = new Error('Write after end.'); + process.nextTick(writeAfterEndNT, this, error, callback); + return true; + } + + return this._write(data, encoding, callback, false); }; +URLRequest.prototype.end = function(data, encoding, callback) { + if (this._finished) { + return false; + } + + this._finished = true; -URLRequest.prototype.end = function() { - this._end(); + if (typeof data === 'function') { + callback = data; + encoding = null; + data = null; + } else if (typeof encoding === 'function') { + callback = encoding; + encoding = null; + } + + data = data || ''; + + return this._write(data, encoding, callback, true); }; -function writeAfterEndNT(self, err, callback) { - self.emit('error', err); - if (callback) callback(err); +function writeAfterEndNT(self, error, callback) { + self.emit('error', error); + if (callback) callback(error); } From fcaf9cb0312ac28fe0c8d32d66db4e9750da2db2 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Mon, 26 Sep 2016 14:59:53 +0200 Subject: [PATCH 007/148] Some code cleaning. --- atom/browser/api/atom_api_url_request.cc | 53 ++++++++++--------- atom/browser/api/atom_api_url_request.h | 9 ++-- atom/browser/net/atom_url_request.cc | 65 ++++++++++++++---------- atom/browser/net/atom_url_request.h | 6 ++- lib/browser/api/net.js | 12 ++--- 5 files changed, 85 insertions(+), 60 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 5ded4cd52f..623487fa67 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -23,8 +23,9 @@ namespace mate { template<> struct Converter> { - static v8::Local ToV8(v8::Isolate* isolate, - scoped_refptr val) { + static v8::Local ToV8( + v8::Isolate* isolate, + scoped_refptr val) { mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); if (val) { @@ -41,15 +42,18 @@ struct Converter> { template<> struct Converter> { - static v8::Local ToV8( - v8::Isolate* isolate, - scoped_refptr buffer) { - return node::Buffer::Copy(isolate, buffer->data(), buffer->size()).ToLocalChecked(); + v8::Isolate* isolate, + scoped_refptr buffer) { + return node::Buffer::Copy(isolate, + buffer->data(), + buffer->size()).ToLocalChecked(); } - static bool FromV8(v8::Isolate* isolate, v8::Local val, - scoped_refptr* out) { + static bool FromV8( + v8::Isolate* isolate, + v8::Local val, + scoped_refptr* out) { auto size = node::Buffer::Length(val); @@ -87,10 +91,9 @@ namespace atom { namespace api { -URLRequest::URLRequest(v8::Isolate* isolate, - v8::Local wrapper) +URLRequest::URLRequest(v8::Isolate* isolate, v8::Local wrapper) : weak_ptr_factory_(this) { - InitWith(isolate, wrapper); + InitWith(isolate, wrapper); } URLRequest::~URLRequest() { @@ -142,18 +145,20 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, .SetMethod("_getHeader", &URLRequest::GetHeader) .SetMethod("_removaHeader", &URLRequest::RemoveHeader) // Response APi - .SetProperty("statusCode", &URLRequest::StatusCode) - .SetProperty("statusMessage", &URLRequest::StatusMessage) - .SetProperty("rawResponseHeaders", &URLRequest::RawResponseHeaders) - .SetProperty("httpVersionMajor", &URLRequest::ResponseHttpVersionMajor) - .SetProperty("httpVersionMinor", &URLRequest::ResponseHttpVersionMinor); + .SetProperty("_statusCode", &URLRequest::StatusCode) + .SetProperty("_statusMessage", &URLRequest::StatusMessage) + .SetProperty("_rawResponseHeaders", &URLRequest::RawResponseHeaders) + .SetProperty("_httpVersionMajor", &URLRequest::ResponseHttpVersionMajor) + .SetProperty("_httpVersionMinor", &URLRequest::ResponseHttpVersionMinor); } -bool URLRequest::WriteBuffer(scoped_refptr buffer, bool is_last) { - atom_request_->WriteBuffer(buffer, is_last); - return true; +bool URLRequest::WriteBuffer( + scoped_refptr buffer, + bool is_last) { + return atom_request_->WriteBuffer(buffer, is_last); + } @@ -161,7 +166,8 @@ void URLRequest::Abort() { atom_request_->Abort(); } -bool URLRequest::SetHeader(const std::string& name, const std::string& value) { +bool URLRequest::SetHeader(const std::string& name, + const std::string& value) { if (!net::HttpUtil::IsValidHeaderName(name)) { return false; } @@ -181,7 +187,7 @@ void URLRequest::RemoveHeader(const std::string& name) { } void URLRequest::OnAuthenticationRequired( - scoped_refptr auth_info) { + scoped_refptr auth_info) { EmitRequestEvent( "login", auth_info.get(), @@ -194,7 +200,7 @@ void URLRequest::OnResponseStarted() { } void URLRequest::OnResponseData( - scoped_refptr buffer) { + scoped_refptr buffer) { if (!buffer || !buffer->data() || !buffer->size()) { return; } @@ -224,7 +230,8 @@ std::string URLRequest::StatusMessage() const { return result; } -scoped_refptr URLRequest::RawResponseHeaders() const { +scoped_refptr +URLRequest::RawResponseHeaders() const { return atom_request_->GetResponseHeaders(); } diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 3831348f78..55bc516c4d 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -32,7 +32,8 @@ class URLRequest : public mate::EventEmitter { private: - bool WriteBuffer(scoped_refptr buffer, bool is_last); + bool WriteBuffer(scoped_refptr buffer, + bool is_last); void Abort(); bool SetHeader(const std::string& name, const std::string& value); std::string GetHeader(const std::string& name); @@ -86,7 +87,8 @@ void URLRequest::EmitRequestEvent(ArgTypes... args) { auto arguments = BuildArgsArray(args...); v8::Local _emitRequestEvent; auto wrapper = GetWrapper(); - if (mate::Dictionary(isolate(), wrapper).Get("_emitRequestEvent", &_emitRequestEvent)) + if (mate::Dictionary(isolate(), wrapper) + .Get("_emitRequestEvent", &_emitRequestEvent)) _emitRequestEvent->Call(wrapper, arguments.size(), arguments.data()); } @@ -96,7 +98,8 @@ void URLRequest::EmitResponseEvent(ArgTypes... args) { auto arguments = BuildArgsArray(args...); v8::Local _emitResponseEvent; auto wrapper = GetWrapper(); - if (mate::Dictionary(isolate(), wrapper).Get("_emitResponseEvent", &_emitResponseEvent)) + if (mate::Dictionary(isolate(), wrapper) + .Get("_emitResponseEvent", &_emitResponseEvent)) _emitResponseEvent->Call(wrapper, arguments.size(), arguments.data()); } diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index 09d787a51f..6afc0cbb04 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -14,9 +14,7 @@ namespace { - const int kBufferSize = 4096; - } // namespace namespace atom { @@ -31,6 +29,7 @@ public: : net::UploadBytesElementReader(buffer->data(), buffer->size()) , buffer_(buffer) { } + ~UploadOwnedIOBufferElementReader() override { } @@ -58,10 +57,10 @@ AtomURLRequest::~AtomURLRequest() { } scoped_refptr AtomURLRequest::Create( - AtomBrowserContext* browser_context, - const std::string& method, - const std::string& url, - base::WeakPtr delegate) { + AtomBrowserContext* browser_context, + const std::string& method, + const std::string& url, + base::WeakPtr delegate) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(browser_context); DCHECK(!url.empty()); @@ -74,7 +73,8 @@ scoped_refptr AtomURLRequest::Create( DCHECK(context); - scoped_refptr atom_url_request = new AtomURLRequest(delegate); + scoped_refptr atom_url_request = + new AtomURLRequest(delegate); atom_url_request->request_ = context->CreateRequest(GURL(url), net::RequestPriority::DEFAULT_PRIORITY, @@ -86,12 +86,13 @@ scoped_refptr AtomURLRequest::Create( } -void AtomURLRequest::WriteBuffer(scoped_refptr buffer, - bool is_last) { +bool AtomURLRequest::WriteBuffer( + scoped_refptr buffer, + bool is_last) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::Bind(&AtomURLRequest::DoWriteBuffer, this, buffer, is_last)); + return content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&AtomURLRequest::DoWriteBuffer, this, buffer, is_last)); } void AtomURLRequest::SetChunkedUpload() { @@ -157,8 +158,9 @@ void AtomURLRequest::PassLoginInformation(const base::string16& username, } -void AtomURLRequest::DoWriteBuffer(scoped_refptr buffer, - bool is_last) { +void AtomURLRequest::DoWriteBuffer( + scoped_refptr buffer, + bool is_last) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (is_chunked_upload_) { @@ -197,15 +199,19 @@ void AtomURLRequest::DoWriteBuffer(scoped_refptr bu if (buffer) { // Handling potential empty buffers. - std::unique_ptr element_reader(internal::UploadOwnedIOBufferElementReader - ::CreateWithBuffer(std::move(buffer))); - upload_element_readers_.push_back(std::move(element_reader)); + using internal::UploadOwnedIOBufferElementReader; + auto element_reader = UploadOwnedIOBufferElementReader::CreateWithBuffer( + std::move(buffer)); + upload_element_readers_.push_back( + std::unique_ptr(element_reader)); } if (is_last) { - std::unique_ptr elements_upload_data_stream( - new net::ElementsUploadDataStream(std::move(upload_element_readers_), 0)); - request_->set_upload(std::move(elements_upload_data_stream)); + auto elements_upload_data_stream = new net::ElementsUploadDataStream( + std::move(upload_element_readers_), + 0); + request_->set_upload( + std::unique_ptr(elements_upload_data_stream)); request_->Start(); } } @@ -260,7 +266,8 @@ void AtomURLRequest::ReadResponse() { // completed immediately, without trying to read any data back (all we care // about is the response code and headers, which we already have). int bytes_read = 0; - if (request_->status().is_success() /* TODO && (request_type_ != URLFetcher::HEAD)*/) { + if (request_->status().is_success() + /* TODO && (request_type_ != URLFetcher::HEAD)*/) { if (!request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)) bytes_read = -1; } @@ -268,7 +275,8 @@ void AtomURLRequest::ReadResponse() { } -void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) { +void AtomURLRequest::OnReadCompleted(net::URLRequest* request, + int bytes_read) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_EQ(request, request_.get()); @@ -283,11 +291,14 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) { // Failed to transfer data to UI thread. return; } - } while (request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)); + } while (request_->Read(response_read_buffer_.get(), + kBufferSize, + &bytes_read)); const auto status = request_->status(); - if (!status.is_io_pending() /* TODO || request_type_ == URLFetcher::HEAD*/ ) { + if (!status.is_io_pending() + /* TODO || request_type_ == URLFetcher::HEAD*/ ) { content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, @@ -301,12 +312,14 @@ bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) { // data is only a wrapper for the async response_read_buffer_. // Make a deep copy of payload and transfer ownership to the UI thread. - scoped_refptr buffer_copy(new net::IOBufferWithSize(bytes_read)); + auto buffer_copy = new net::IOBufferWithSize(bytes_read); memcpy(buffer_copy->data(), response_read_buffer_->data(), bytes_read); return content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseData, this, buffer_copy)); + base::Bind(&AtomURLRequest::InformDelegateResponseData, + this, + buffer_copy)); } diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index 3a923a002e..38f60c8d3b 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -34,7 +34,8 @@ public: const std::string& url, base::WeakPtr delegate); - void WriteBuffer(scoped_refptr buffer, bool is_last); + bool WriteBuffer(scoped_refptr buffer, + bool is_last); void SetChunkedUpload(); void Abort() const; void SetHeader(const std::string& name, const std::string& value) const; @@ -54,7 +55,8 @@ protected: private: friend class base::RefCountedThreadSafe; - void DoWriteBuffer(scoped_refptr buffer, bool is_last); + void DoWriteBuffer(scoped_refptr buffer, + bool is_last); void DoSetAuth(const base::string16& username, const base::string16& password) const; void DoCancelAuth() const; diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index d1d8cb7e7c..7392c7687c 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -15,15 +15,15 @@ class URLResponse extends EventEmitter { } get statusCode() { - return this.request.statusCode; + return this.request._statusCode; } get statusMessage() { - return this.request.statusMessage; + return this.request._statusMessage; } get headers() { - return this.request.rawResponseHeaders; + return this.request._rawResponseHeaders; } get httpVersion() { @@ -31,15 +31,15 @@ class URLResponse extends EventEmitter { } get httpVersionMajor() { - return this.request.httpVersionMajor; + return this.request._httpVersionMajor; } get httpVersionMinor() { - return this.request.httpVersionMinor; + return this.request._httpVersionMinor; } get rawHeaders() { - return this.request.rawResponseHeaders; + return this.request._rawResponseHeaders; } } From 9498a5738a7e94739c0806dbb0b99c653e832dd4 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 27 Sep 2016 10:21:11 +0200 Subject: [PATCH 008/148] Refactoring net module, adding a ClientRequest and IncomingMessage classes. --- atom/browser/api/atom_api_url_request.cc | 38 ++- atom/browser/api/atom_api_url_request.h | 6 +- atom/browser/net/atom_url_request.cc | 20 +- atom/browser/net/atom_url_request.h | 7 +- lib/browser/api/net.js | 292 +++++++++++++---------- 5 files changed, 191 insertions(+), 172 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 623487fa67..8bd8074f96 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -115,8 +115,6 @@ mate::WrappableBase* URLRequest::New(mate::Arguments* args) { auto session = Session::FromPartition(args->isolate(), session_name); auto browser_context = session->browser_context(); - - auto api_url_request = new URLRequest(args->isolate(), args->GetThis()); auto weak_ptr = api_url_request->weak_ptr_factory_.GetWeakPtr(); auto atom_url_request = AtomURLRequest::Create( @@ -126,12 +124,10 @@ mate::WrappableBase* URLRequest::New(mate::Arguments* args) { weak_ptr); api_url_request->atom_request_ = atom_url_request; - return api_url_request; } - // static void URLRequest::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { @@ -139,17 +135,17 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) // Request API .MakeDestroyable() - .SetMethod("_writeBuffer", &URLRequest::WriteBuffer) + .SetMethod("writeBuffer", &URLRequest::WriteBuffer) .SetMethod("abort", &URLRequest::Abort) - .SetMethod("_setHeader", &URLRequest::SetHeader) - .SetMethod("_getHeader", &URLRequest::GetHeader) - .SetMethod("_removaHeader", &URLRequest::RemoveHeader) + .SetMethod("setExtraHeader", &URLRequest::SetExtraHeader) + .SetMethod("removeExtraHeader", &URLRequest::RemoveExtraHeader) + .SetMethod("setChunkedUpload", &URLRequest::SetChunkedUpload) // Response APi - .SetProperty("_statusCode", &URLRequest::StatusCode) - .SetProperty("_statusMessage", &URLRequest::StatusMessage) - .SetProperty("_rawResponseHeaders", &URLRequest::RawResponseHeaders) - .SetProperty("_httpVersionMajor", &URLRequest::ResponseHttpVersionMajor) - .SetProperty("_httpVersionMinor", &URLRequest::ResponseHttpVersionMinor); + .SetProperty("statusCode", &URLRequest::StatusCode) + .SetProperty("statusMessage", &URLRequest::StatusMessage) + .SetProperty("rawResponseHeaders", &URLRequest::RawResponseHeaders) + .SetProperty("httpVersionMajor", &URLRequest::ResponseHttpVersionMajor) + .SetProperty("httpVersionMinor", &URLRequest::ResponseHttpVersionMinor); } @@ -166,7 +162,7 @@ void URLRequest::Abort() { atom_request_->Abort(); } -bool URLRequest::SetHeader(const std::string& name, +bool URLRequest::SetExtraHeader(const std::string& name, const std::string& value) { if (!net::HttpUtil::IsValidHeaderName(name)) { return false; @@ -176,14 +172,16 @@ bool URLRequest::SetHeader(const std::string& name, return false; } - atom_request_->SetHeader(name, value); + atom_request_->SetExtraHeader(name, value); return true; } -std::string URLRequest::GetHeader(const std::string& name) { - return atom_request_->GetHeader(name); + +void URLRequest::RemoveExtraHeader(const std::string& name) { + atom_request_->RemoveExtraHeader(name); } -void URLRequest::RemoveHeader(const std::string& name) { - atom_request_->RemoveHeader(name); + +void URLRequest::SetChunkedUpload(bool is_chunked_upload) { + atom_request_->SetChunkedUpload(is_chunked_upload); } void URLRequest::OnAuthenticationRequired( @@ -196,7 +194,7 @@ void URLRequest::OnAuthenticationRequired( void URLRequest::OnResponseStarted() { - EmitRequestEvent("response"); + Emit("response"); } void URLRequest::OnResponseData( diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 55bc516c4d..3437397884 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -35,9 +35,9 @@ private: bool WriteBuffer(scoped_refptr buffer, bool is_last); void Abort(); - bool SetHeader(const std::string& name, const std::string& value); - std::string GetHeader(const std::string& name); - void RemoveHeader(const std::string& name); + bool SetExtraHeader(const std::string& name, const std::string& value); + void RemoveExtraHeader(const std::string& name); + void SetChunkedUpload(bool is_chunked_upload); friend class AtomURLRequest; void OnAuthenticationRequired( diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index 6afc0cbb04..f9707f3dae 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -95,13 +95,13 @@ bool AtomURLRequest::WriteBuffer( base::Bind(&AtomURLRequest::DoWriteBuffer, this, buffer, is_last)); } -void AtomURLRequest::SetChunkedUpload() { +void AtomURLRequest::SetChunkedUpload(bool is_chunked_upload) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // The method can be called only before switching to multi-threaded mode, // i.e. before the first call to write. // So it is safe to change the object in the UI thread. - is_chunked_upload_ = true; + is_chunked_upload_ = is_chunked_upload; } @@ -109,26 +109,14 @@ void AtomURLRequest::Abort() const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); } -void AtomURLRequest::SetHeader(const std::string& name, +void AtomURLRequest::SetExtraHeader(const std::string& name, const std::string& value) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); request_->SetExtraRequestHeaderByName(name, value, true); } -std::string AtomURLRequest::GetHeader(const std::string& name) const { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - std::string result; - const auto& extra_headers = request_->extra_request_headers(); - if (!extra_headers.GetHeader(name, &result)) { - net::HttpRequestHeaders* request_headers = nullptr; - if (request_->GetFullRequestHeaders(request_headers) && request_headers) { - request_headers->GetHeader(name, &result); - } - } - return result; -} -void AtomURLRequest::RemoveHeader(const std::string& name) const { +void AtomURLRequest::RemoveExtraHeader(const std::string& name) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); request_->RemoveRequestHeaderByName(name); } diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index 38f60c8d3b..a3288bfab6 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -36,11 +36,10 @@ public: bool WriteBuffer(scoped_refptr buffer, bool is_last); - void SetChunkedUpload(); + void SetChunkedUpload(bool is_chunked_upload); void Abort() const; - void SetHeader(const std::string& name, const std::string& value) const; - std::string GetHeader(const std::string& name) const; - void RemoveHeader(const std::string& name) const; + void SetExtraHeader(const std::string& name, const std::string& value) const; + void RemoveExtraHeader(const std::string& name) const; void PassLoginInformation(const base::string16& username, const base::string16& password) const; scoped_refptr GetResponseHeaders() const; diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 7392c7687c..3594d0b2a3 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -8,22 +8,22 @@ const {URLRequest} = net Object.setPrototypeOf(Net.prototype, EventEmitter.prototype) Object.setPrototypeOf(URLRequest.prototype, EventEmitter.prototype) -class URLResponse extends EventEmitter { - constructor(request) { +class IncomingMessage extends EventEmitter { + constructor(url_request) { super(); - this.request = request; + this._url_request = url_request; } get statusCode() { - return this.request._statusCode; + return this._url_request.statusCode; } get statusMessage() { - return this.request._statusMessage; + return this._url_request.statusMessage; } get headers() { - return this.request._rawResponseHeaders; + return this._url_request.rawResponseHeaders; } get httpVersion() { @@ -31,161 +31,195 @@ class URLResponse extends EventEmitter { } get httpVersionMajor() { - return this.request._httpVersionMajor; + return this._url_request.httpVersionMajor; } get httpVersionMinor() { - return this.request._httpVersionMinor; + return this._url_request.httpVersionMinor; } get rawHeaders() { - return this.request._rawResponseHeaders; + return this._url_request.rawResponseHeaders; } } -Net.prototype.request = function(options, callback) { - let request = new URLRequest(options) - - if (callback) { - request.once('response', callback) - } - - - return request -} - -URLRequest.prototype._init = function() { - // Flag to prevent writings after end. - this._finished = false; - - // Set when the request uses chuned encoding. Can be switched - // to true only once and never set back to false. - this._chunkedEncoding = false; - - // Flag to prevent request's headers modifications after - // headers flush. - this._headersSent = false; -} - - -URLRequest.prototype.setHeader = function(name, value) { - if (typeof name !== 'string') - throw new TypeError('`name` should be a string in setHeader(name, value).'); - if (value === undefined) - throw new Error('`value` required in setHeader("' + name + '", value).'); - if (this._headersSent) - throw new Error('Can\'t set headers after they are sent.'); - - this._setHeader(name, value) -}; - - -URLRequest.prototype.getHeader = function(name) { - if (arguments.length < 1) { - throw new Error('`name` is required for getHeader(name).'); - } - - return this._getHeader(name); -}; - - -URLRequest.prototype.removeHeader = function(name) { - if (arguments.length < 1) { - throw new Error('`name` is required for removeHeader(name).'); - } - - if (this._headersSent) { - throw new Error('Can\'t remove headers after they are sent.'); - } - - this._removeHeader(name); -}; - - -URLRequest.prototype._emitRequestEvent = function(name) { - if (name === 'response') { - this.response = new URLResponse(this); - this.emit(name, this.response); - } else { - this.emit.apply(this, arguments); - } +URLRequest.prototype._emitRequestEvent = function() { + this._request.emit.apply(this._request, arguments); } URLRequest.prototype._emitResponseEvent = function() { - this.response.emit.apply(this.response, arguments); + this._response.emit.apply(this._response, arguments); } +class ClientRequest extends EventEmitter { -URLRequest.prototype._write = function(chunk, encoding, callback, is_last) { + constructor(options, callback) { + super(); + + // Flag to prevent writings after end. + this._finished = false; + + // Set when the request uses chuned encoding. Can be switched + // to true only once and never set back to false. + this._chunkedEncoding = false; + + // Flag to prevent request's headers modifications after + // headers flush. + this._headersSent = false; + + // This is a copy of the extra headers structure held by the native + // net::URLRequest. The main reason is to keep the getHeader API synchronous + // after the request starts. + this._extra_headers = {}; + + let url = options.url; + let method = options.method; + let session = options.session; + + let url_request = new URLRequest({ + url: url, + method: method, + session: session + }); + + this._url_request = url_request; + url_request._request = this; + + url_request.on('response', ()=> { + let response = new IncomingMessage(url_request); + url_request._response = response; + this.emit('response', response); + }); + + if (callback) { + this.once('response', callback) + } + } + + + setHeader(name, value) { + if (typeof name !== 'string') + throw new TypeError('`name` should be a string in setHeader(name, value).'); + if (value === undefined) + throw new Error('`value` required in setHeader("' + name + '", value).'); + if (this._headersSent) + throw new Error('Can\'t set headers after they are sent.'); + + let key = name.toLowerCase(); + this._extra_headers[key] = value; + this._url_request.setExtraHeader(name, value) + } + + + getHeader(name) { + if (arguments.length < 1) { + throw new Error('`name` is required for getHeader(name).'); + } + + if (!this._extra_headers) { + return; + } + + var key = name.toLowerCase(); + return this._extra_headers[key]; + } + + + removeHeader(name) { + if (arguments.length < 1) { + throw new Error('`name` is required for removeHeader(name).'); + } + + if (this._headersSent) { + throw new Error('Can\'t remove headers after they are sent.'); + } + + var key = name.toLowerCase(); + delete this._extra_headers[key]; + this._url_request.removeExtraHeader(name); + } + + + _write(chunk, encoding, callback, is_last) { - let chunk_is_string = typeof chunk === 'string'; - let chunk_is_buffer = chunk instanceof Buffer; - if (!chunk_is_string && !chunk_is_buffer) { - throw new TypeError('First argument must be a string or Buffer.'); + let chunk_is_string = typeof chunk === 'string'; + let chunk_is_buffer = chunk instanceof Buffer; + if (!chunk_is_string && !chunk_is_buffer) { + throw new TypeError('First argument must be a string or Buffer.'); + } + + if (chunk_is_string) { + // We convert all strings into binary buffers. + chunk = Buffer.from(chunk, encoding); + } + + // Headers are assumed to be sent on first call to _writeBuffer, + // i.e. after the first call to write or end. + let result = this._url_request.writeBuffer(chunk, is_last); + + // Since writing to the network is asynchronous, we conservatively + // assume that request headers are written after delivering the first + // buffer to the network IO thread. + if (!this._headersSent) { + this._url_request.setChunkedUpload(this._chunkedEncoding); + this._headersSent = true; + } + + // The write callback is fired asynchronously to mimic Node.js. + if (callback) { + process.nextTick(callback); + } + + return result; } - if (chunk_is_string) { - // We convert all strings into binary buffers. - chunk = Buffer.from(chunk, encoding); + write(data, encoding, callback) { + + if (this._finished) { + let error = new Error('Write after end.'); + process.nextTick(writeAfterEndNT, this, error, callback); + return true; + } + + return this._write(data, encoding, callback, false); } - // Headers are assumed to be sent on first call to _writeBuffer, - // i.e. after the first call to write or end. - let result = this._writeBuffer(chunk, is_last); - // Since writing to the network is asynchronous, we conservatively - // assume that request headers are written after delivering the first - // buffer to the network IO thread. - this._headersSent = true; + end(data, encoding, callback) { + if (this._finished) { + return false; + } + + this._finished = true; - // The write callback is fired asynchronously to mimic Node.js. - if (callback) { - process.nextTick(callback); + if (typeof data === 'function') { + callback = data; + encoding = null; + data = null; + } else if (typeof encoding === 'function') { + callback = encoding; + encoding = null; + } + + data = data || ''; + + return this._write(data, encoding, callback, true); } - return result; } -URLRequest.prototype.write = function(data, encoding, callback) { - - if (this._finished) { - let error = new Error('Write after end.'); - process.nextTick(writeAfterEndNT, this, error, callback); - return true; - } - - return this._write(data, encoding, callback, false); -}; - - -URLRequest.prototype.end = function(data, encoding, callback) { - if (this._finished) { - return false; - } - - this._finished = true; - - if (typeof data === 'function') { - callback = data; - encoding = null; - data = null; - } else if (typeof encoding === 'function') { - callback = encoding; - encoding = null; - } - - data = data || ''; - - return this._write(data, encoding, callback, true); -}; - - function writeAfterEndNT(self, error, callback) { self.emit('error', error); if (callback) callback(error); } +Net.prototype.request = function(options, callback) { + return new ClientRequest(options, callback); +} + +net.ClientRequest = ClientRequest; + module.exports = net \ No newline at end of file From cbbc4376cad4c67139c30ec8ed1c14ed541ae192 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 27 Sep 2016 12:33:51 +0200 Subject: [PATCH 009/148] Adding support for upload chunked encoding. --- atom/browser/api/atom_api_url_request.cc | 10 +-- atom/browser/api/atom_api_url_request.h | 2 +- atom/browser/net/atom_url_request.cc | 2 +- atom/browser/net/atom_url_request.h | 2 +- lib/browser/api/net.js | 103 +++++++++++++++++++---- 5 files changed, 95 insertions(+), 24 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 8bd8074f96..ec14cf5904 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -105,10 +105,10 @@ mate::WrappableBase* URLRequest::New(mate::Arguments* args) { v8::Local options; args->GetNext(&options); mate::Dictionary dict(args->isolate(), options); - std::string url; - dict.Get("url", &url); std::string method; dict.Get("method", &method); + std::string url; + dict.Get("url", &url); std::string session_name; dict.Get("session", &session_name); @@ -135,7 +135,7 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) // Request API .MakeDestroyable() - .SetMethod("writeBuffer", &URLRequest::WriteBuffer) + .SetMethod("writeBuffer", &URLRequest::Write) .SetMethod("abort", &URLRequest::Abort) .SetMethod("setExtraHeader", &URLRequest::SetExtraHeader) .SetMethod("removeExtraHeader", &URLRequest::RemoveExtraHeader) @@ -150,10 +150,10 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, } -bool URLRequest::WriteBuffer( +bool URLRequest::Write( scoped_refptr buffer, bool is_last) { - return atom_request_->WriteBuffer(buffer, is_last); + return atom_request_->Write(buffer, is_last); } diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 3437397884..a34810d3d8 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -32,7 +32,7 @@ class URLRequest : public mate::EventEmitter { private: - bool WriteBuffer(scoped_refptr buffer, + bool Write(scoped_refptr buffer, bool is_last); void Abort(); bool SetExtraHeader(const std::string& name, const std::string& value); diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index f9707f3dae..f6549b9d3b 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -86,7 +86,7 @@ scoped_refptr AtomURLRequest::Create( } -bool AtomURLRequest::WriteBuffer( +bool AtomURLRequest::Write( scoped_refptr buffer, bool is_last) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index a3288bfab6..5902ba6ffa 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -34,7 +34,7 @@ public: const std::string& url, base::WeakPtr delegate); - bool WriteBuffer(scoped_refptr buffer, + bool Write(scoped_refptr buffer, bool is_last); void SetChunkedUpload(bool is_chunked_upload); void Abort() const; diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 3594d0b2a3..3679c925f2 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -1,6 +1,7 @@ 'use strict' const {EventEmitter} = require('events') +const util = require('util') const binding = process.atomBinding('net') const {net, Net} = binding const {URLRequest} = net @@ -8,6 +9,10 @@ const {URLRequest} = net Object.setPrototypeOf(Net.prototype, EventEmitter.prototype) Object.setPrototypeOf(URLRequest.prototype, EventEmitter.prototype) +let kSupportedProtocols = new Set(); +kSupportedProtocols.add('http:'); +kSupportedProtocols.add('https:'); + class IncomingMessage extends EventEmitter { constructor(url_request) { super(); @@ -57,6 +62,74 @@ class ClientRequest extends EventEmitter { constructor(options, callback) { super(); + if (typeof options === 'string') { + options = url.parse(options); + } else { + options = util._extend({}, options); + } + + const method = (options.method || 'GET').toUpperCase(); + let url_str = options.url; + + if (!url_str) { + let url_obj = {}; + + const protocol = options.protocol || 'http'; + if (!kSupportedProtocols.has(protocol)) { + throw new Error('Protocol "' + protocol + '" not supported. '); + } + url_obj.protocol = protocol; + + + if (options.host) { + url_obj.host = options.host; + } else { + + if (options.hostname) { + url_obj.hostname = options.hostname; + } else { + url_obj.hostname = 'localhost'; + } + + if (options.port) { + url_obj.port = options.port; + } + } + + const path = options.path || '/'; + if (options.path && / /.test(options.path)) { + // The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/ + // with an additional rule for ignoring percentage-escaped characters + // but that's a) hard to capture in a regular expression that performs + // well, and b) possibly too restrictive for real-world usage. That's + // why it only scans for spaces because those are guaranteed to create + // an invalid request. + throw new TypeError('Request path contains unescaped characters.'); + } + url_obj.path = path; + + url_str = url.format(url_obj); + } + + const session_name = options.session || ''; + let url_request = new URLRequest({ + method: method, + url: url_str, + session: session_name + }); + + // Set back and forward links. + this._url_request = url_request; + url_request._request = this; + + if (options.headers) { + let keys = Object.keys(options.headers); + for (let i = 0, l = keys.length; i < l; i++) { + let key = keys[i]; + this.setHeader(key, options.headers[key]); + } + } + // Flag to prevent writings after end. this._finished = false; @@ -73,19 +146,6 @@ class ClientRequest extends EventEmitter { // after the request starts. this._extra_headers = {}; - let url = options.url; - let method = options.method; - let session = options.session; - - let url_request = new URLRequest({ - url: url, - method: method, - session: session - }); - - this._url_request = url_request; - url_request._request = this; - url_request.on('response', ()=> { let response = new IncomingMessage(url_request); url_request._response = response; @@ -97,6 +157,17 @@ class ClientRequest extends EventEmitter { } } + get chunkedEncoding() { + return this._chunkedEncoding; + } + + set chunkedEncoding(value) { + if (this._headersSent) { + throw new Error('Can\'t set the transfer encoding, headers have been sent.'); + } + this._chunkedEncoding = value; + } + setHeader(name, value) { if (typeof name !== 'string') @@ -121,7 +192,7 @@ class ClientRequest extends EventEmitter { return; } - var key = name.toLowerCase(); + let key = name.toLowerCase(); return this._extra_headers[key]; } @@ -135,7 +206,7 @@ class ClientRequest extends EventEmitter { throw new Error('Can\'t remove headers after they are sent.'); } - var key = name.toLowerCase(); + let key = name.toLowerCase(); delete this._extra_headers[key]; this._url_request.removeExtraHeader(name); } @@ -162,7 +233,7 @@ class ClientRequest extends EventEmitter { // assume that request headers are written after delivering the first // buffer to the network IO thread. if (!this._headersSent) { - this._url_request.setChunkedUpload(this._chunkedEncoding); + this._url_request.setChunkedUpload(this.chunkedEncoding); this._headersSent = true; } From 08947682b07eb14dc5caa0344e0976087297b5f8 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 28 Sep 2016 15:07:54 +0200 Subject: [PATCH 010/148] Implementing abort workflow, emitting error events. --- atom/browser/api/atom_api_url_request.cc | 6 +- atom/browser/api/atom_api_url_request.h | 1 + atom/browser/net/atom_url_request.cc | 84 ++++++++++++++---------- atom/browser/net/atom_url_request.h | 2 + lib/browser/api/net.js | 37 ++++++++--- 5 files changed, 84 insertions(+), 46 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index ec14cf5904..a98bd58e74 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -135,7 +135,7 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) // Request API .MakeDestroyable() - .SetMethod("writeBuffer", &URLRequest::Write) + .SetMethod("write", &URLRequest::Write) .SetMethod("abort", &URLRequest::Abort) .SetMethod("setExtraHeader", &URLRequest::SetExtraHeader) .SetMethod("removeExtraHeader", &URLRequest::RemoveExtraHeader) @@ -212,6 +212,10 @@ void URLRequest::OnResponseCompleted() { atom_request_ = nullptr; } +void URLRequest::OnError(const std::string& error) { + auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error)); + EmitRequestEvent("error", error_object); +} int URLRequest::StatusCode() const { if (auto response_headers = atom_request_->GetResponseHeaders()) { diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index a34810d3d8..9fb0724302 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -45,6 +45,7 @@ private: void OnResponseStarted(); void OnResponseData(scoped_refptr data); void OnResponseCompleted(); + void OnError(const std::string& error); int StatusCode() const; std::string StatusMessage() const; diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index f6549b9d3b..d7f5096951 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -107,6 +107,10 @@ void AtomURLRequest::SetChunkedUpload(bool is_chunked_upload) { void AtomURLRequest::Abort() const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + content::BrowserThread::PostTask( + content::BrowserThread::IO, + FROM_HERE, + base::Bind(&AtomURLRequest::DoAbort, this)); } void AtomURLRequest::SetExtraHeader(const std::string& name, @@ -133,16 +137,14 @@ AtomURLRequest::GetResponseHeaders() const { void AtomURLRequest::PassLoginInformation(const base::string16& username, const base::string16& password) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (username.empty() || password.empty()) { + if (username.empty() || password.empty()) content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, base::Bind(&AtomURLRequest::DoCancelAuth, this)); - } - else { + else content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, base::Bind(&AtomURLRequest::DoSetAuth, this, username, password)); - } } @@ -164,24 +166,21 @@ void AtomURLRequest::DoWriteBuffer( first_call = true; } - if (buffer) { + if (buffer) // Non-empty buffer. auto write_result = chunked_stream_writer_->AppendData( buffer->data(), buffer->size(), is_last); - } - else if (is_last) { + else if (is_last) // Empty buffer and last chunck, i.e. request.end(). auto write_result = chunked_stream_writer_->AppendData( nullptr, 0, true); - } - if (first_call) { + if (first_call) request_->Start(); - } } else { @@ -205,6 +204,11 @@ void AtomURLRequest::DoWriteBuffer( } } +void AtomURLRequest::DoAbort() const { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + request_->Cancel(); +} + void AtomURLRequest::DoSetAuth(const base::string16& username, const base::string16& password) const { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); @@ -231,19 +235,25 @@ void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_EQ(request, request_.get()); - if (request_->status().is_success()) { + const auto& status = request_->status(); + if (status.is_success()) { // Cache net::HttpResponseHeaders instance, a read-only objects // so that headers and other http metainformation can be simultaneously // read from UI thread while request data is simulataneously streaming // on IO thread. response_headers_ = request_->response_headers(); + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateResponseStarted, this)); + + ReadResponse(); + } + else { + auto error = net::ErrorToString(status.ToNetError()); + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateErrorOccured, this, std::move(error))); } - - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseStarted, this)); - - ReadResponse(); } void AtomURLRequest::ReadResponse() { @@ -255,10 +265,9 @@ void AtomURLRequest::ReadResponse() { // about is the response code and headers, which we already have). int bytes_read = 0; if (request_->status().is_success() - /* TODO && (request_type_ != URLFetcher::HEAD)*/) { + /* TODO && (request_type_ != URLFetcher::HEAD)*/) if (!request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)) bytes_read = -1; - } OnReadCompleted(request_.get(), bytes_read); } @@ -269,29 +278,31 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, DCHECK_EQ(request, request_.get()); + const auto status = request_->status(); do { - if (!request_->status().is_success() || bytes_read <= 0) + if (!status.is_success() || bytes_read <= 0) { + auto error = net::ErrorToString(status.ToNetError()); + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateErrorOccured, this, std::move(error))); break; - + } const auto result = CopyAndPostBuffer(bytes_read); - if (!result) { + if (!result) // Failed to transfer data to UI thread. return; - } } while (request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)); - const auto status = request_->status(); if (!status.is_io_pending() - /* TODO || request_type_ == URLFetcher::HEAD*/ ) { + /* TODO || request_type_ == URLFetcher::HEAD*/ ) content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, base::Bind(&AtomURLRequest::InformDelegateResponseCompleted, this)); - } } @@ -314,17 +325,14 @@ bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) { void AtomURLRequest::InformDelegateAuthenticationRequired( scoped_refptr auth_info) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (delegate_) { + if (delegate_) delegate_->OnAuthenticationRequired(auth_info); - } } void AtomURLRequest::InformDelegateResponseStarted() const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - if (delegate_) { + if (delegate_) delegate_->OnResponseStarted(); - } } void AtomURLRequest::InformDelegateResponseData( @@ -333,17 +341,23 @@ void AtomURLRequest::InformDelegateResponseData( // Transfer ownership of the data buffer, data will be released // by the delegate's OnResponseData. - if (delegate_) { + if (delegate_) delegate_->OnResponseData(data); - } } void AtomURLRequest::InformDelegateResponseCompleted() const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (delegate_) { + if (delegate_) delegate_->OnResponseCompleted(); - } +} + +void AtomURLRequest::InformDelegateErrorOccured( + const std::string& error) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + if (delegate_) + delegate_->OnError(error); } diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index 5902ba6ffa..7de6e1a40a 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -56,6 +56,7 @@ private: friend class base::RefCountedThreadSafe; void DoWriteBuffer(scoped_refptr buffer, bool is_last); + void DoAbort() const; void DoSetAuth(const base::string16& username, const base::string16& password) const; void DoCancelAuth() const; @@ -69,6 +70,7 @@ private: void InformDelegateResponseData( scoped_refptr data) const; void InformDelegateResponseCompleted() const; + void InformDelegateErrorOccured(const std::string& error) const; AtomURLRequest(base::WeakPtr delegate); virtual ~AtomURLRequest(); diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 3679c925f2..398c30c07f 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -130,6 +130,12 @@ class ClientRequest extends EventEmitter { } } + // Flag to prevent request's headers modifications after + // headers flush. + this._started = false; + + this._aborted = false; + // Flag to prevent writings after end. this._finished = false; @@ -137,10 +143,6 @@ class ClientRequest extends EventEmitter { // to true only once and never set back to false. this._chunkedEncoding = false; - // Flag to prevent request's headers modifications after - // headers flush. - this._headersSent = false; - // This is a copy of the extra headers structure held by the native // net::URLRequest. The main reason is to keep the getHeader API synchronous // after the request starts. @@ -162,7 +164,7 @@ class ClientRequest extends EventEmitter { } set chunkedEncoding(value) { - if (this._headersSent) { + if (this._started) { throw new Error('Can\'t set the transfer encoding, headers have been sent.'); } this._chunkedEncoding = value; @@ -174,7 +176,7 @@ class ClientRequest extends EventEmitter { throw new TypeError('`name` should be a string in setHeader(name, value).'); if (value === undefined) throw new Error('`value` required in setHeader("' + name + '", value).'); - if (this._headersSent) + if (this._started) throw new Error('Can\'t set headers after they are sent.'); let key = name.toLowerCase(); @@ -202,7 +204,7 @@ class ClientRequest extends EventEmitter { throw new Error('`name` is required for removeHeader(name).'); } - if (this._headersSent) { + if (this._started) { throw new Error('Can\'t remove headers after they are sent.'); } @@ -227,14 +229,14 @@ class ClientRequest extends EventEmitter { // Headers are assumed to be sent on first call to _writeBuffer, // i.e. after the first call to write or end. - let result = this._url_request.writeBuffer(chunk, is_last); + let result = this._url_request.write(chunk, is_last); // Since writing to the network is asynchronous, we conservatively // assume that request headers are written after delivering the first // buffer to the network IO thread. - if (!this._headersSent) { + if (!this._started) { this._url_request.setChunkedUpload(this.chunkedEncoding); - this._headersSent = true; + this._started = true; } // The write callback is fired asynchronously to mimic Node.js. @@ -278,6 +280,21 @@ class ClientRequest extends EventEmitter { return this._write(data, encoding, callback, true); } + abort() { + if (!this._started) { + // Does nothing if stream + return; + } + + if (!this._aborted) { + this._url_request.abort(); + this._aborted = true; + process.nextTick( ()=>{ + this.emit('abort'); + } ); + } + } + } function writeAfterEndNT(self, error, callback) { From 05884358827a7645fe65d55722affa4ee64dda0d Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 29 Sep 2016 11:31:08 +0200 Subject: [PATCH 011/148] Fixing cpplint issues. --- atom/browser/api/atom_api_net.cc | 6 +-- atom/browser/api/atom_api_net.h | 12 ++--- atom/browser/api/atom_api_url_request.cc | 64 +++++++++--------------- atom/browser/api/atom_api_url_request.h | 21 ++++---- atom/browser/net/atom_url_request.cc | 51 +++++++++---------- atom/browser/net/atom_url_request.h | 29 +++++------ 6 files changed, 83 insertions(+), 100 deletions(-) diff --git a/atom/browser/api/atom_api_net.cc b/atom/browser/api/atom_api_net.cc index 1559cee4ca..2464393fcd 100644 --- a/atom/browser/api/atom_api_net.cc +++ b/atom/browser/api/atom_api_net.cc @@ -4,8 +4,8 @@ #include "atom/browser/api/atom_api_net.h" #include "atom/browser/api/atom_api_url_request.h" -#include "native_mate/dictionary.h" #include "atom/common/node_includes.h" +#include "native_mate/dictionary.h" namespace atom { @@ -50,7 +50,6 @@ using atom::api::URLRequest; void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { - v8::Isolate* isolate = context->GetIsolate(); URLRequest::SetConstructor(isolate, base::Bind(URLRequest::New)); @@ -58,9 +57,8 @@ void Initialize(v8::Local exports, v8::Local unused, mate::Dictionary dict(isolate, exports); dict.Set("net", Net::Create(isolate)); dict.Set("Net", Net::GetConstructor(isolate)->GetFunction()); - } } // namespace -NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_net, Initialize) \ No newline at end of file +NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_net, Initialize) diff --git a/atom/browser/api/atom_api_net.h b/atom/browser/api/atom_api_net.h index dd97bb9653..640a6445eb 100644 --- a/atom/browser/api/atom_api_net.h +++ b/atom/browser/api/atom_api_net.h @@ -12,20 +12,18 @@ namespace atom { namespace api { class Net : public mate::EventEmitter { - -public: + public: static v8::Local Create(v8::Isolate* isolate); static void BuildPrototype(v8::Isolate* isolate, v8::Local prototype); v8::Local URLRequest(v8::Isolate* isolate); -protected: - Net(v8::Isolate* isolate); + protected: + explicit Net(v8::Isolate* isolate); ~Net() override; -private: - + private: DISALLOW_COPY_AND_ASSIGN(Net); }; @@ -34,4 +32,4 @@ private: } // namespace atom -#endif // ATOM_BROWSER_API_ATOM_API_NET_H_ \ No newline at end of file +#endif // ATOM_BROWSER_API_ATOM_API_NET_H_ diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index a98bd58e74..ad2d66f5fe 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -2,31 +2,24 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#include "atom/browser/api/atom_api_url_request.h" +#include #include "atom/browser/api/atom_api_session.h" - -#include "native_mate/dictionary.h" +#include "atom/browser/api/atom_api_url_request.h" #include "atom/browser/net/atom_url_request.h" -#include "atom/common/node_includes.h" +#include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/net_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" -#include "atom/common/native_mate_converters/callback.h" +#include "atom/common/node_includes.h" +#include "native_mate/dictionary.h" -namespace { -const char* const kResponse = "response"; -const char* const kData = "data"; -const char* const kEnd = "end"; - -} namespace mate { template<> struct Converter> { static v8::Local ToV8( - v8::Isolate* isolate, - scoped_refptr val) { - + v8::Isolate* isolate, + scoped_refptr val) { mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); if (val) { size_t iter = 0; @@ -34,7 +27,7 @@ struct Converter> { std::string value; while (val->EnumerateHeaderLines(&iter, &name, &value)) { dict.Set(name, value); - } + } } return dict.GetHandle(); } @@ -43,29 +36,27 @@ struct Converter> { template<> struct Converter> { static v8::Local ToV8( - v8::Isolate* isolate, - scoped_refptr buffer) { + v8::Isolate* isolate, + scoped_refptr buffer) { return node::Buffer::Copy(isolate, - buffer->data(), - buffer->size()).ToLocalChecked(); + buffer->data(), + buffer->size()).ToLocalChecked(); } static bool FromV8( - v8::Isolate* isolate, - v8::Local val, - scoped_refptr* out) { - + v8::Isolate* isolate, + v8::Local val, + scoped_refptr* out) { auto size = node::Buffer::Length(val); - + if (size == 0) { - // Support conversoin from empty buffer. A use case is - // a GET request without body. + // Support conversoin from empty buffer. A use case is + // a GET request without body. // Since zero-sized IOBuffer(s) are not supported, we set the // out pointer to null. *out = nullptr; return true; } - auto data = node::Buffer::Data(val); if (!data) { // This is an error as size is positif but data is null. @@ -86,9 +77,9 @@ struct Converter> { } }; -} -namespace atom { +} // namespace mate +namespace atom { namespace api { URLRequest::URLRequest(v8::Isolate* isolate, v8::Local wrapper) @@ -101,7 +92,6 @@ URLRequest::~URLRequest() { // static mate::WrappableBase* URLRequest::New(mate::Arguments* args) { - v8::Local options; args->GetNext(&options); mate::Dictionary dict(args->isolate(), options); @@ -122,7 +112,7 @@ mate::WrappableBase* URLRequest::New(mate::Arguments* args) { method, url, weak_ptr); - + api_url_request->atom_request_ = atom_url_request; return api_url_request; @@ -146,15 +136,12 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, .SetProperty("rawResponseHeaders", &URLRequest::RawResponseHeaders) .SetProperty("httpVersionMajor", &URLRequest::ResponseHttpVersionMajor) .SetProperty("httpVersionMinor", &URLRequest::ResponseHttpVersionMinor); - - } bool URLRequest::Write( scoped_refptr buffer, bool is_last) { return atom_request_->Write(buffer, is_last); - } @@ -191,7 +178,7 @@ void URLRequest::OnAuthenticationRequired( auth_info.get(), base::Bind(&AtomURLRequest::PassLoginInformation, atom_request_)); } - + void URLRequest::OnResponseStarted() { Emit("response"); @@ -202,7 +189,6 @@ void URLRequest::OnResponseData( if (!buffer || !buffer->data() || !buffer->size()) { return; } - EmitResponseEvent("data", buffer); } @@ -234,7 +220,7 @@ std::string URLRequest::StatusMessage() const { scoped_refptr URLRequest::RawResponseHeaders() const { - return atom_request_->GetResponseHeaders(); + return atom_request_->GetResponseHeaders(); } uint32_t URLRequest::ResponseHttpVersionMajor() const { @@ -261,6 +247,6 @@ void URLRequest::unpin() { wrapper_.Reset(); } -} // namespace mate +} // namespace api -} // namepsace mate \ No newline at end of file +} // namespace atom diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 9fb0724302..89702b0d40 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -6,10 +6,11 @@ #define ATOM_BROWSER_API_ATOM_API_URL_REQUEST_H_ #include +#include #include "atom/browser/api/trackable_object.h" #include "native_mate/handle.h" -#include "net/url_request/url_request_context.h" #include "net/http/http_response_headers.h" +#include "net/url_request/url_request_context.h" namespace atom { @@ -22,18 +23,19 @@ class URLRequest : public mate::EventEmitter { public: static mate::WrappableBase* New(mate::Arguments* args); - static void BuildPrototype(v8::Isolate* isolate, + static void BuildPrototype( + v8::Isolate* isolate, v8::Local prototype); protected: - URLRequest(v8::Isolate* isolate, + explicit URLRequest(v8::Isolate* isolate, v8::Local wrapper); ~URLRequest() override; -private: + private: bool Write(scoped_refptr buffer, - bool is_last); + bool is_last); void Abort(); bool SetExtraHeader(const std::string& name, const std::string& value); void RemoveExtraHeader(const std::string& name); @@ -55,7 +57,7 @@ private: template - std::array, sizeof...(ArgTypes)> + std::array, sizeof...(ArgTypes)> BuildArgsArray(ArgTypes... args) const; template @@ -70,7 +72,6 @@ private: scoped_refptr atom_request_; v8::Global wrapper_; base::WeakPtrFactory weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(URLRequest); }; @@ -107,8 +108,8 @@ void URLRequest::EmitResponseEvent(ArgTypes... args) { -} // namepsace api +} // namespace api -} // namepsace atom +} // namespace atom -#endif // ATOM_BROWSER_API_ATOM_API_URL_REQUEST_H_ \ No newline at end of file +#endif // ATOM_BROWSER_API_ATOM_API_URL_REQUEST_H_ diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index d7f5096951..6b07a2e3ef 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -3,19 +3,21 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#include "atom/browser/net/atom_url_request.h" +#include #include "atom/browser/api/atom_api_url_request.h" #include "atom/browser/atom_browser_context.h" +#include "atom/browser/net/atom_url_request.h" #include "base/callback.h" #include "content/public/browser/browser_thread.h" -#include "net/base/io_buffer.h" #include "net/base/elements_upload_data_stream.h" +#include "net/base/io_buffer.h" #include "net/base/upload_bytes_element_reader.h" + namespace { const int kBufferSize = 4096; -} // namespace +} // namespace namespace atom { @@ -23,7 +25,7 @@ namespace internal { class UploadOwnedIOBufferElementReader : public net::UploadBytesElementReader { -public: + public: explicit UploadOwnedIOBufferElementReader( scoped_refptr buffer) : net::UploadBytesElementReader(buffer->data(), buffer->size()) @@ -39,18 +41,18 @@ public: return new UploadOwnedIOBufferElementReader(std::move(buffer)); } -private: + private: scoped_refptr buffer_; DISALLOW_COPY_AND_ASSIGN(UploadOwnedIOBufferElementReader); }; -} +} // namespace internal AtomURLRequest::AtomURLRequest(base::WeakPtr delegate) : delegate_(delegate) , response_read_buffer_(new net::IOBuffer(kBufferSize)) - , is_chunked_upload_(is_chunked_upload_) { + , is_chunked_upload_(false) { } AtomURLRequest::~AtomURLRequest() { @@ -73,7 +75,7 @@ scoped_refptr AtomURLRequest::Create( DCHECK(context); - scoped_refptr atom_url_request = + scoped_refptr atom_url_request = new AtomURLRequest(delegate); atom_url_request->request_ = context->CreateRequest(GURL(url), @@ -82,14 +84,13 @@ scoped_refptr AtomURLRequest::Create( atom_url_request->request_->set_method(method); return atom_url_request; - } bool AtomURLRequest::Write( scoped_refptr buffer, bool is_last) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, base::Bind(&AtomURLRequest::DoWriteBuffer, this, buffer, is_last)); @@ -154,7 +155,6 @@ void AtomURLRequest::DoWriteBuffer( DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (is_chunked_upload_) { - // Chunked encoding case. bool first_call = false; @@ -181,9 +181,7 @@ void AtomURLRequest::DoWriteBuffer( if (first_call) request_->Start(); - } - else { - + } else { if (buffer) { // Handling potential empty buffers. using internal::UploadOwnedIOBufferElementReader; @@ -223,10 +221,10 @@ void AtomURLRequest::DoCancelAuth() const { void AtomURLRequest::OnAuthRequired(net::URLRequest* request, net::AuthChallengeInfo* auth_info) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - + content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateAuthenticationRequired, + base::Bind(&AtomURLRequest::InformDelegateAuthenticationRequired, this, scoped_refptr(auth_info))); } @@ -247,12 +245,13 @@ void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { base::Bind(&AtomURLRequest::InformDelegateResponseStarted, this)); ReadResponse(); - } - else { + } else { auto error = net::ErrorToString(status.ToNetError()); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateErrorOccured, this, std::move(error))); + base::Bind(&AtomURLRequest::InformDelegateErrorOccured, + this, + std::move(error))); } } @@ -264,10 +263,10 @@ void AtomURLRequest::ReadResponse() { // completed immediately, without trying to read any data back (all we care // about is the response code and headers, which we already have). int bytes_read = 0; - if (request_->status().is_success() + if (request_->status().is_success() /* TODO && (request_type_ != URLFetcher::HEAD)*/) if (!request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)) - bytes_read = -1; + bytes_read = -1; OnReadCompleted(request_.get(), bytes_read); } @@ -284,7 +283,9 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, auto error = net::ErrorToString(status.ToNetError()); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateErrorOccured, this, std::move(error))); + base::Bind(&AtomURLRequest::InformDelegateErrorOccured, + this, + std::move(error))); break; } @@ -295,15 +296,13 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, } while (request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)); - - if (!status.is_io_pending() + if (!status.is_io_pending() /* TODO || request_type_ == URLFetcher::HEAD*/ ) content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, base::Bind(&AtomURLRequest::InformDelegateResponseCompleted, this)); - } bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) { @@ -361,4 +360,4 @@ void AtomURLRequest::InformDelegateErrorOccured( } -} // namespace atom \ No newline at end of file +} // namespace atom diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index 7de6e1a40a..dd6e3d11e0 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -6,9 +6,11 @@ #ifndef ATOM_BROWSER_NET_ATOM_URL_REQUEST_H_ #define ATOM_BROWSER_NET_ATOM_URL_REQUEST_H_ +#include +#include #include "base/memory/ref_counted.h" -#include "net/url_request/url_request.h" #include "net/base/chunked_upload_data_stream.h" +#include "net/url_request/url_request.h" namespace net { @@ -27,7 +29,7 @@ class URLRequest; class AtomURLRequest : public base::RefCountedThreadSafe, public net::URLRequest::Delegate { -public: + public: static scoped_refptr Create( AtomBrowserContext* browser_context, const std::string& method, @@ -44,15 +46,15 @@ public: const base::string16& password) const; scoped_refptr GetResponseHeaders() const; -protected: + protected: // Overrides of net::URLRequest::Delegate - virtual void OnAuthRequired(net::URLRequest* request, + void OnAuthRequired(net::URLRequest* request, net::AuthChallengeInfo* auth_info) override; - virtual void OnResponseStarted(net::URLRequest* request) override; - virtual void OnReadCompleted(net::URLRequest* request, + void OnResponseStarted(net::URLRequest* request) override; + void OnReadCompleted(net::URLRequest* request, int bytes_read) override; -private: + private: friend class base::RefCountedThreadSafe; void DoWriteBuffer(scoped_refptr buffer, bool is_last); @@ -72,7 +74,7 @@ private: void InformDelegateResponseCompleted() const; void InformDelegateErrorOccured(const std::string& error) const; - AtomURLRequest(base::WeakPtr delegate); + explicit AtomURLRequest(base::WeakPtr delegate); virtual ~AtomURLRequest(); base::WeakPtr delegate_; @@ -81,15 +83,14 @@ private: bool is_chunked_upload_; std::unique_ptr chunked_stream_; std::unique_ptr chunked_stream_writer_; - - std::vector>upload_element_readers_; - + std::vector> + upload_element_readers_; scoped_refptr response_read_buffer_; scoped_refptr response_headers_; - DISALLOW_COPY_AND_ASSIGN(AtomURLRequest); - }; + DISALLOW_COPY_AND_ASSIGN(AtomURLRequest); +}; } // namespace atom -#endif // ATOM_BROWSER_NET_ATOM_URL_REQUEST_H_ \ No newline at end of file +#endif // ATOM_BROWSER_NET_ATOM_URL_REQUEST_H_ From 42adb2afd4a4d9e99e2b12ba4a1f4ede0ee8cc12 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 29 Sep 2016 15:24:28 +0200 Subject: [PATCH 012/148] Fixing lint-js issues. --- lib/browser/api/exports/electron.js | 8 +- lib/browser/api/net.js | 281 ++++++++++++++-------------- 2 files changed, 140 insertions(+), 149 deletions(-) diff --git a/lib/browser/api/exports/electron.js b/lib/browser/api/exports/electron.js index 09d5b0e47a..9a486b575d 100644 --- a/lib/browser/api/exports/electron.js +++ b/lib/browser/api/exports/electron.js @@ -108,10 +108,10 @@ Object.defineProperties(exports, { } }, net: { - enumerable: true, - get: function () { - return require('../net') - } + enumerable: true, + get: function () { + return require('../net') + } }, // The internal modules, invisible unless you know their names. diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 398c30c07f..1471ae4f1d 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -1,5 +1,6 @@ 'use strict' +const url = require('url') const {EventEmitter} = require('events') const util = require('util') const binding = process.atomBinding('net') @@ -9,94 +10,91 @@ const {URLRequest} = net Object.setPrototypeOf(Net.prototype, EventEmitter.prototype) Object.setPrototypeOf(URLRequest.prototype, EventEmitter.prototype) -let kSupportedProtocols = new Set(); -kSupportedProtocols.add('http:'); -kSupportedProtocols.add('https:'); +let kSupportedProtocols = new Set() +kSupportedProtocols.add('http:') +kSupportedProtocols.add('https:') class IncomingMessage extends EventEmitter { - constructor(url_request) { - super(); - this._url_request = url_request; + constructor (urlRequest) { + super() + this._url_request = urlRequest } - get statusCode() { - return this._url_request.statusCode; + get statusCode () { + return this._url_request.statusCode } - get statusMessage() { - return this._url_request.statusMessage; + get statusMessage () { + return this._url_request.statusMessage } - get headers() { - return this._url_request.rawResponseHeaders; + get headers () { + return this._url_request.rawResponseHeaders } - get httpVersion() { - return `${this.httpVersionMajor}.${this.httpVersionMinor}`; + get httpVersion () { + return `${this.httpVersionMajor}.${this.httpVersionMinor}` } - get httpVersionMajor() { - return this._url_request.httpVersionMajor; + get httpVersionMajor () { + return this._url_request.httpVersionMajor } - get httpVersionMinor() { - return this._url_request.httpVersionMinor; + get httpVersionMinor () { + return this._url_request.httpVersionMinor } - get rawHeaders() { - return this._url_request.rawResponseHeaders; + get rawHeaders () { + return this._url_request.rawResponseHeaders } } -URLRequest.prototype._emitRequestEvent = function() { - this._request.emit.apply(this._request, arguments); +URLRequest.prototype._emitRequestEvent = function () { + this._request.emit.apply(this._request, arguments) } -URLRequest.prototype._emitResponseEvent = function() { - this._response.emit.apply(this._response, arguments); +URLRequest.prototype._emitResponseEvent = function () { + this._response.emit.apply(this._response, arguments) } class ClientRequest extends EventEmitter { - constructor(options, callback) { - super(); + constructor (options, callback) { + super() if (typeof options === 'string') { - options = url.parse(options); + options = url.parse(options) } else { - options = util._extend({}, options); + options = util._extend({}, options) } - const method = (options.method || 'GET').toUpperCase(); - let url_str = options.url; + const method = (options.method || 'GET').toUpperCase() + let urlStr = options.url - if (!url_str) { - let url_obj = {}; - - const protocol = options.protocol || 'http'; + if (!urlStr) { + let urlObj = {} + const protocol = options.protocol || 'http' if (!kSupportedProtocols.has(protocol)) { - throw new Error('Protocol "' + protocol + '" not supported. '); + throw new Error('Protocol "' + protocol + '" not supported. ') } - url_obj.protocol = protocol; - + urlObj.protocol = protocol if (options.host) { - url_obj.host = options.host; + urlObj.host = options.host } else { - if (options.hostname) { - url_obj.hostname = options.hostname; + urlObj.hostname = options.hostname } else { - url_obj.hostname = 'localhost'; + urlObj.hostname = 'localhost' } if (options.port) { - url_obj.port = options.port; + urlObj.port = options.port } } - const path = options.path || '/'; + const path = options.path || '/' if (options.path && / /.test(options.path)) { // The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/ // with an additional rule for ignoring percentage-escaped characters @@ -104,210 +102,203 @@ class ClientRequest extends EventEmitter { // well, and b) possibly too restrictive for real-world usage. That's // why it only scans for spaces because those are guaranteed to create // an invalid request. - throw new TypeError('Request path contains unescaped characters.'); + throw new TypeError('Request path contains unescaped characters.') } - url_obj.path = path; - - url_str = url.format(url_obj); + urlObj.path = path + urlStr = url.format(urlObj) } - const session_name = options.session || ''; - let url_request = new URLRequest({ + const sessionName = options.session || '' + let urlRequest = new URLRequest({ method: method, - url: url_str, - session: session_name - }); + url: urlStr, + session: sessionName + }) // Set back and forward links. - this._url_request = url_request; - url_request._request = this; + this._url_request = urlRequest + urlRequest._request = this if (options.headers) { - let keys = Object.keys(options.headers); + const keys = Object.keys(options.headers) for (let i = 0, l = keys.length; i < l; i++) { - let key = keys[i]; - this.setHeader(key, options.headers[key]); + const key = keys[i] + this.setHeader(key, options.headers[key]) } } - // Flag to prevent request's headers modifications after + // Flag to prevent request's headers modifications after // headers flush. - this._started = false; + this._started = false - this._aborted = false; + this._aborted = false // Flag to prevent writings after end. - this._finished = false; + this._finished = false // Set when the request uses chuned encoding. Can be switched // to true only once and never set back to false. - this._chunkedEncoding = false; + this._chunkedEncoding = false // This is a copy of the extra headers structure held by the native // net::URLRequest. The main reason is to keep the getHeader API synchronous // after the request starts. - this._extra_headers = {}; + this._extra_headers = {} - url_request.on('response', ()=> { - let response = new IncomingMessage(url_request); - url_request._response = response; - this.emit('response', response); - }); + urlRequest.on('response', () => { + const response = new IncomingMessage(urlRequest) + urlRequest._response = response + this.emit('response', response) + }) if (callback) { this.once('response', callback) } } - get chunkedEncoding() { - return this._chunkedEncoding; + get chunkedEncoding () { + return this._chunkedEncoding } - set chunkedEncoding(value) { + set chunkedEncoding (value) { if (this._started) { - throw new Error('Can\'t set the transfer encoding, headers have been sent.'); + throw new Error('Can\'t set the transfer encoding, headers have been sent.') } - this._chunkedEncoding = value; + this._chunkedEncoding = value } + setHeader (name, value) { + if (typeof name !== 'string') { + throw new TypeError('`name` should be a string in setHeader(name, value).') + } + if (value === undefined) { + throw new Error('`value` required in setHeader("' + name + '", value).') + } + if (this._started) { + throw new Error('Can\'t set headers after they are sent.') + } - setHeader(name, value) { - if (typeof name !== 'string') - throw new TypeError('`name` should be a string in setHeader(name, value).'); - if (value === undefined) - throw new Error('`value` required in setHeader("' + name + '", value).'); - if (this._started) - throw new Error('Can\'t set headers after they are sent.'); - - let key = name.toLowerCase(); - this._extra_headers[key] = value; + const key = name.toLowerCase() + this._extra_headers[key] = value this._url_request.setExtraHeader(name, value) } - - getHeader(name) { + getHeader (name) { if (arguments.length < 1) { - throw new Error('`name` is required for getHeader(name).'); + throw new Error('`name` is required for getHeader(name).') } if (!this._extra_headers) { - return; + return } - let key = name.toLowerCase(); - return this._extra_headers[key]; + const key = name.toLowerCase() + return this._extra_headers[key] } - - removeHeader(name) { + removeHeader (name) { if (arguments.length < 1) { - throw new Error('`name` is required for removeHeader(name).'); + throw new Error('`name` is required for removeHeader(name).') } if (this._started) { - throw new Error('Can\'t remove headers after they are sent.'); + throw new Error('Can\'t remove headers after they are sent.') } - let key = name.toLowerCase(); - delete this._extra_headers[key]; - this._url_request.removeExtraHeader(name); + const key = name.toLowerCase() + delete this._extra_headers[key] + this._url_request.removeExtraHeader(name) } - - _write(chunk, encoding, callback, is_last) { - - let chunk_is_string = typeof chunk === 'string'; - let chunk_is_buffer = chunk instanceof Buffer; - if (!chunk_is_string && !chunk_is_buffer) { - throw new TypeError('First argument must be a string or Buffer.'); + _write (chunk, encoding, callback, isLast) { + let chunkIsString = typeof chunk === 'string' + let chunkIsBuffer = chunk instanceof Buffer + if (!chunkIsString && !chunkIsBuffer) { + throw new TypeError('First argument must be a string or Buffer.') } - if (chunk_is_string) { + if (chunkIsString) { // We convert all strings into binary buffers. - chunk = Buffer.from(chunk, encoding); + chunk = Buffer.from(chunk, encoding) } // Headers are assumed to be sent on first call to _writeBuffer, // i.e. after the first call to write or end. - let result = this._url_request.write(chunk, is_last); + let result = this._url_request.write(chunk, isLast) - // Since writing to the network is asynchronous, we conservatively + // Since writing to the network is asynchronous, we conservatively // assume that request headers are written after delivering the first // buffer to the network IO thread. if (!this._started) { - this._url_request.setChunkedUpload(this.chunkedEncoding); - this._started = true; + this._url_request.setChunkedUpload(this.chunkedEncoding) + this._started = true } // The write callback is fired asynchronously to mimic Node.js. if (callback) { - process.nextTick(callback); + process.nextTick(callback) } - return result; + return result } - write(data, encoding, callback) { - + write (data, encoding, callback) { if (this._finished) { - let error = new Error('Write after end.'); - process.nextTick(writeAfterEndNT, this, error, callback); - return true; + let error = new Error('Write after end.') + process.nextTick(writeAfterEndNT, this, error, callback) + return true } - return this._write(data, encoding, callback, false); + return this._write(data, encoding, callback, false) } - - end(data, encoding, callback) { + end (data, encoding, callback) { if (this._finished) { - return false; + return false } - - this._finished = true; + + this._finished = true if (typeof data === 'function') { - callback = data; - encoding = null; - data = null; + callback = data + encoding = null + data = null } else if (typeof encoding === 'function') { - callback = encoding; - encoding = null; + callback = encoding + encoding = null } - data = data || ''; + data = data || '' - return this._write(data, encoding, callback, true); + return this._write(data, encoding, callback, true) } - abort() { + abort () { if (!this._started) { - // Does nothing if stream - return; + // Does nothing if stream + return } if (!this._aborted) { - this._url_request.abort(); - this._aborted = true; - process.nextTick( ()=>{ - this.emit('abort'); - } ); + this._url_request.abort() + this._aborted = true + process.nextTick(() => { + this.emit('abort') + }) } } } -function writeAfterEndNT(self, error, callback) { - self.emit('error', error); - if (callback) callback(error); +function writeAfterEndNT (self, error, callback) { + self.emit('error', error) + if (callback) callback(error) } - -Net.prototype.request = function(options, callback) { - return new ClientRequest(options, callback); +Net.prototype.request = function (options, callback) { + return new ClientRequest(options, callback) } -net.ClientRequest = ClientRequest; +net.ClientRequest = ClientRequest module.exports = net - \ No newline at end of file From bde30b90e871cba8414e416528e30caa0edadfbd Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Fri, 30 Sep 2016 14:17:29 +0200 Subject: [PATCH 013/148] Adding some implementation comments. Enforcing Chromium coding conventions. --- atom/browser/api/atom_api_url_request.cc | 5 +- atom/browser/api/atom_api_url_request.h | 97 ++++++++++++++++++++---- atom/browser/net/atom_url_request.cc | 12 ++- atom/browser/net/atom_url_request.h | 27 +++---- 4 files changed, 101 insertions(+), 40 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index ad2d66f5fe..016edbe0c7 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -13,6 +13,7 @@ #include "native_mate/dictionary.h" + namespace mate { template<> @@ -83,8 +84,8 @@ namespace atom { namespace api { URLRequest::URLRequest(v8::Isolate* isolate, v8::Local wrapper) - : weak_ptr_factory_(this) { - InitWith(isolate, wrapper); + : weak_ptr_factory_(this) { + InitWith(isolate, wrapper); } URLRequest::~URLRequest() { diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 89702b0d40..20eb66d3f0 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -7,18 +7,88 @@ #include #include +#include "atom/browser/api/event_emitter.h" #include "atom/browser/api/trackable_object.h" +#include "base/memory/weak_ptr.h" #include "native_mate/handle.h" +#include "native_mate/wrappable_base.h" +#include "net/base/auth.h" +#include "net/base/io_buffer.h" #include "net/http/http_response_headers.h" #include "net/url_request/url_request_context.h" - namespace atom { class AtomURLRequest; namespace api { +// +// The URLRequest class implements the V8 binding between the JavaScript API +// and Chromium native net library. It is responsible for handling HTTP/HTTPS +// requests. +// +// The current class provides only the binding layer. Two other JavaScript +// classes (ClientRequest and IncomingMessage) in the net module provide the +// final API, including some state management and arguments validation. +// +// URLRequest's methods fall into two main categories: command and event methods. +// They are always executed on the Browser's UI thread. +// Command methods are called directly from JavaScript code via the API defined +// in BuildPrototype. A command method is generally implemented by forwarding +// the call to a corresponding method on AtomURLRequest which does the +// synchronization on the Browser IO thread. The latter then calls into Chromium +// net library. On the other hand, net library events originate on the IO +// thread in AtomURLRequest and are synchronized back on the UI thread, then +// forwarded to a corresponding event method in URLRequest and then to +// JavaScript via the EmitRequestEvent/EmitResponseEvent helpers. +// +// URLRequest lifetime management: we followed the Wrapper/Wrappable pattern +// defined in native_mate. However, we augment that pattern with a pin/unpin +// mechanism. The main reason is that we want the JS API to provide a similar +// lifetime guarantees as the XMLHttpRequest. +// https://xhr.spec.whatwg.org/#garbage-collection +// +// The primary motivation is to not garbage collect a URLInstance as long as the +// object is emitting network events. For instance, in the following JS code +// +// (function() { +// let request = new URLRequest(...); +// request.on('response', (response)=>{ +// response.on('data', (data) = > { +// console.log(data.toString()); +// }); +// }); +// })(); +// +// we still want data to be logged even if the response/request objects are no +// more referenced in JavaScript. +// +// Binding by simply following the native_mate Wrapper/Wrappable pattern will +// delete the URLRequest object when the corresponding JS object is collected. +// The v8 handle is a private member in WrappableBase and it is always weak, +// there is no way to make it strong without changing native_mate. +// The solution we implement consists of maintaining some kind of state that +// prevents collection of JS wrappers as long as the request is emitting network +// events. At initialization, the object is unpinned. When the request starts, +// it is pinned. When no more events would be emitted, the object is unpinned +// and lifetime is again managed by the standard native mate Wrapper/Wrappable +// pattern. +// +// pin/unpin: are implemented by constructing/reseting a V8 strong persistent +// handle. +// +// The URLRequest/AtmURLRequest interaction could have been implemented in a +// single class. However, it implies that the resulting class lifetime will be +// managed by two conflicting mechanisms: JavaScript garbage collection and +// Chromium reference counting. Reasoning about lifetime issues become much +// more complex. +// +// We chose to split the implementation into two classes linked via a strong/weak +// pointers. A URLRequest instance is deleted if it is unpinned and the +// corresponding JS wrapper object is garbage collected. On the other hand, +// an AtmURLRequest instance lifetime is totally governed by reference counting. +// class URLRequest : public mate::EventEmitter { public: static mate::WrappableBase* New(mate::Arguments* args); @@ -27,12 +97,19 @@ class URLRequest : public mate::EventEmitter { v8::Isolate* isolate, v8::Local prototype); + // Methods for reporting events into JavaScript. + void OnAuthenticationRequired( + scoped_refptr auth_info); + void OnResponseStarted(); + void OnResponseData(scoped_refptr data); + void OnResponseCompleted(); + void OnError(const std::string& error); + protected: explicit URLRequest(v8::Isolate* isolate, v8::Local wrapper); ~URLRequest() override; - private: bool Write(scoped_refptr buffer, bool is_last); @@ -41,21 +118,12 @@ class URLRequest : public mate::EventEmitter { void RemoveExtraHeader(const std::string& name); void SetChunkedUpload(bool is_chunked_upload); - friend class AtomURLRequest; - void OnAuthenticationRequired( - scoped_refptr auth_info); - void OnResponseStarted(); - void OnResponseData(scoped_refptr data); - void OnResponseCompleted(); - void OnError(const std::string& error); - int StatusCode() const; std::string StatusMessage() const; scoped_refptr RawResponseHeaders() const; uint32_t ResponseHttpVersionMajor() const; uint32_t ResponseHttpVersionMinor() const; - template std::array, sizeof...(ArgTypes)> BuildArgsArray(ArgTypes... args) const; @@ -70,7 +138,10 @@ class URLRequest : public mate::EventEmitter { void unpin(); scoped_refptr atom_request_; + + // Used to implement pin/unpin. v8::Global wrapper_; + base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(URLRequest); @@ -94,7 +165,6 @@ void URLRequest::EmitRequestEvent(ArgTypes... args) { _emitRequestEvent->Call(wrapper, arguments.size(), arguments.data()); } - template void URLRequest::EmitResponseEvent(ArgTypes... args) { auto arguments = BuildArgsArray(args...); @@ -105,9 +175,6 @@ void URLRequest::EmitResponseEvent(ArgTypes... args) { _emitResponseEvent->Call(wrapper, arguments.size(), arguments.data()); } - - - } // namespace api } // namespace atom diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index 6b07a2e3ef..6a20dc4768 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -50,9 +50,9 @@ class UploadOwnedIOBufferElementReader : public net::UploadBytesElementReader { } // namespace internal AtomURLRequest::AtomURLRequest(base::WeakPtr delegate) - : delegate_(delegate) - , response_read_buffer_(new net::IOBuffer(kBufferSize)) - , is_chunked_upload_(false) { + : delegate_(delegate), + response_read_buffer_(new net::IOBuffer(kBufferSize)), + is_chunked_upload_(false) { } AtomURLRequest::~AtomURLRequest() { @@ -263,8 +263,7 @@ void AtomURLRequest::ReadResponse() { // completed immediately, without trying to read any data back (all we care // about is the response code and headers, which we already have). int bytes_read = 0; - if (request_->status().is_success() - /* TODO && (request_type_ != URLFetcher::HEAD)*/) + if (request_->status().is_success()) if (!request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)) bytes_read = -1; OnReadCompleted(request_.get(), bytes_read); @@ -297,8 +296,7 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, kBufferSize, &bytes_read)); - if (!status.is_io_pending() - /* TODO || request_type_ == URLFetcher::HEAD*/ ) + if (!status.is_io_pending()) content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index dd6e3d11e0..f065bc5249 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -8,25 +8,19 @@ #include #include +#include "atom/browser/api/atom_api_url_request.h" +#include "atom/browser/atom_browser_context.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "net/base/auth.h" #include "net/base/chunked_upload_data_stream.h" +#include "net/base/io_buffer.h" +#include "net/base/upload_element_reader.h" +#include "net/http/http_response_headers.h" #include "net/url_request/url_request.h" - -namespace net { -class IOBuffer; -class IOBufferWithSize; -class DrainableIOBuffer; -}; - namespace atom { -class AtomBrowserContext; - -namespace api { -class URLRequest; -} - class AtomURLRequest : public base::RefCountedThreadSafe, public net::URLRequest::Delegate { public: @@ -56,6 +50,10 @@ class AtomURLRequest : public base::RefCountedThreadSafe, private: friend class base::RefCountedThreadSafe; + + explicit AtomURLRequest(base::WeakPtr delegate); + ~AtomURLRequest()override; + void DoWriteBuffer(scoped_refptr buffer, bool is_last); void DoAbort() const; @@ -74,9 +72,6 @@ class AtomURLRequest : public base::RefCountedThreadSafe, void InformDelegateResponseCompleted() const; void InformDelegateErrorOccured(const std::string& error) const; - explicit AtomURLRequest(base::WeakPtr delegate); - virtual ~AtomURLRequest(); - base::WeakPtr delegate_; std::unique_ptr request_; From ec1fc5a17ba09d03a7fcfb261e11824798126b3c Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 4 Oct 2016 17:12:17 +0200 Subject: [PATCH 014/148] Implementing error, close, finish, abort events management. --- atom/browser/api/atom_api_net.cc | 9 +- atom/browser/api/atom_api_net.h | 1 + atom/browser/api/atom_api_url_request.cc | 219 +++++++++++++++++++++-- atom/browser/api/atom_api_url_request.h | 116 +++++++++--- atom/browser/net/atom_url_request.cc | 92 ++++++---- atom/browser/net/atom_url_request.h | 12 +- lib/browser/api/net.js | 59 +++--- 7 files changed, 391 insertions(+), 117 deletions(-) diff --git a/atom/browser/api/atom_api_net.cc b/atom/browser/api/atom_api_net.cc index 2464393fcd..5d23f04886 100644 --- a/atom/browser/api/atom_api_net.cc +++ b/atom/browser/api/atom_api_net.cc @@ -29,7 +29,9 @@ void Net::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { prototype->SetClassName(mate::StringToV8(isolate, "Net")); mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) - .SetProperty("URLRequest", &Net::URLRequest); + .SetProperty("URLRequest", &Net::URLRequest) + .SetMethod("RequestGarbageCollectionForTesting", + &Net::RequestGarbageCollectionForTesting); } v8::Local Net::URLRequest(v8::Isolate* isolate) { @@ -37,6 +39,11 @@ v8::Local Net::URLRequest(v8::Isolate* isolate) { } +void Net::RequestGarbageCollectionForTesting() { + isolate()->RequestGarbageCollectionForTesting( + v8::Isolate::GarbageCollectionType::kFullGarbageCollection); +} + } // namespace api diff --git a/atom/browser/api/atom_api_net.h b/atom/browser/api/atom_api_net.h index 640a6445eb..04b882d259 100644 --- a/atom/browser/api/atom_api_net.h +++ b/atom/browser/api/atom_api_net.h @@ -24,6 +24,7 @@ class Net : public mate::EventEmitter { ~Net() override; private: + void RequestGarbageCollectionForTesting(); DISALLOW_COPY_AND_ASSIGN(Net); }; diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 016edbe0c7..29736a5d06 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -83,6 +83,84 @@ struct Converter> { namespace atom { namespace api { + +template +URLRequest::StateBase::StateBase(Flags initialState) + : state_(initialState) { +} + +template +void URLRequest::StateBase::SetFlag(Flags flag) { + state_ = static_cast(static_cast(state_) & + static_cast(flag)); +} + +template +bool URLRequest::StateBase::operator==(Flags flag) const { + return state_ == flag; +} + +template +bool URLRequest::StateBase::IsFlagSet(Flags flag) const { + return static_cast(state_) & static_cast(flag); +} + +URLRequest::RequestState::RequestState() + : StateBase(RequestStateFlags::kNotStarted) { +} + +bool URLRequest::RequestState::NotStarted() const { + return *this == RequestStateFlags::kNotStarted; +} + +bool URLRequest::RequestState::Started() const { + return IsFlagSet(RequestStateFlags::kStarted); +} + +bool URLRequest::RequestState::Finished() const { + return IsFlagSet(RequestStateFlags::kFinished); +} + +bool URLRequest::RequestState::Canceled() const { + return IsFlagSet(RequestStateFlags::kCanceled); +} + +bool URLRequest::RequestState::Failed() const { + return IsFlagSet(RequestStateFlags::kFailed); +} + +bool URLRequest::RequestState::Closed() const { + return IsFlagSet(RequestStateFlags::kClosed); +} + +URLRequest::ResponseState::ResponseState() + : StateBase(ResponseStateFlags::kNotStarted) { +} + +bool URLRequest::ResponseState::NotStarted() const { + return *this == ResponseStateFlags::kNotStarted; +} + +bool URLRequest::ResponseState::Started() const { + return IsFlagSet(ResponseStateFlags::kStarted); +} + +bool URLRequest::ResponseState::Ended() const { + return IsFlagSet(ResponseStateFlags::kEnded); +} + +bool URLRequest::ResponseState::Canceled() const { + return IsFlagSet(ResponseStateFlags::kCanceled); +} + +bool URLRequest::ResponseState::Failed() const { + return IsFlagSet(ResponseStateFlags::kFailed); +} + +bool URLRequest::ResponseState::Closed() const { + return IsFlagSet(ResponseStateFlags::kClosed); +} + URLRequest::URLRequest(v8::Isolate* isolate, v8::Local wrapper) : weak_ptr_factory_(this) { InitWith(isolate, wrapper); @@ -127,10 +205,12 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, // Request API .MakeDestroyable() .SetMethod("write", &URLRequest::Write) - .SetMethod("abort", &URLRequest::Abort) + .SetMethod("cancel", &URLRequest::Cancel) .SetMethod("setExtraHeader", &URLRequest::SetExtraHeader) .SetMethod("removeExtraHeader", &URLRequest::RemoveExtraHeader) .SetMethod("setChunkedUpload", &URLRequest::SetChunkedUpload) + .SetProperty("notStarted", &URLRequest::NotStarted) + .SetProperty("finished", &URLRequest::Finished) // Response APi .SetProperty("statusCode", &URLRequest::StatusCode) .SetProperty("statusMessage", &URLRequest::StatusMessage) @@ -139,19 +219,81 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, .SetProperty("httpVersionMinor", &URLRequest::ResponseHttpVersionMinor); } +bool URLRequest::NotStarted() const { + return request_state_.NotStarted(); +} + +bool URLRequest::Finished() const { + return request_state_.Finished(); +} + +bool URLRequest::Canceled() const { + return request_state_.Canceled(); +} + bool URLRequest::Write( scoped_refptr buffer, bool is_last) { - return atom_request_->Write(buffer, is_last); + if (request_state_.Canceled() || + request_state_.Failed() || + request_state_.Finished() || + request_state_.Closed()) { + return false; + } + + if (request_state_.NotStarted()) { + request_state_.SetFlag(RequestStateFlags::kStarted); + // Pin on first write. + pin(); + } + + if (is_last) { + request_state_.SetFlag(RequestStateFlags::kFinished); + EmitRequestEvent(true, "finish"); + } + + DCHECK(atom_request_); + if (atom_request_) { + return atom_request_->Write(buffer, is_last); + } + return false; } -void URLRequest::Abort() { - atom_request_->Abort(); +void URLRequest::Cancel() { + if (request_state_.Canceled()) { + // Cancel only once. + return; + } + + // Mark as canceled. + request_state_.SetFlag(RequestStateFlags::kCanceled); + + if (request_state_.Started()) { + // Really cancel if it was started. + atom_request_->Cancel(); + } + + if (!request_state_.Closed()) { + EmitRequestEvent(true, "abort"); + } + + + response_state_.SetFlag(ResponseStateFlags::kCanceled); + if (response_state_.Started() && !response_state_.Closed()) { + EmitResponseEvent(true, "aborted"); + } + Close(); } bool URLRequest::SetExtraHeader(const std::string& name, const std::string& value) { + // State must be equal to not started. + if (!request_state_.NotStarted()) { + // Cannot change headers after send. + return false; + } + if (!net::HttpUtil::IsValidHeaderName(name)) { return false; } @@ -165,45 +307,84 @@ bool URLRequest::SetExtraHeader(const std::string& name, } void URLRequest::RemoveExtraHeader(const std::string& name) { + // State must be equal to not started. + if (!request_state_.NotStarted()) { + // Cannot change headers after send. + return; + } atom_request_->RemoveExtraHeader(name); } void URLRequest::SetChunkedUpload(bool is_chunked_upload) { + // State must be equal to not started. + if (!request_state_.NotStarted()) { + // Cannot change headers after send. + return; + } atom_request_->SetChunkedUpload(is_chunked_upload); } void URLRequest::OnAuthenticationRequired( scoped_refptr auth_info) { EmitRequestEvent( + false, "login", auth_info.get(), base::Bind(&AtomURLRequest::PassLoginInformation, atom_request_)); } - void URLRequest::OnResponseStarted() { + if (request_state_.Canceled() || + request_state_.Failed() || + request_state_.Closed()) { + // Don't emit any event after request cancel. + return; + } + response_state_.SetFlag(ResponseStateFlags::kStarted); Emit("response"); } void URLRequest::OnResponseData( scoped_refptr buffer) { + if (request_state_.Canceled()) { + // Don't emit any event after request cancel. + return; + } if (!buffer || !buffer->data() || !buffer->size()) { return; } - EmitResponseEvent("data", buffer); + if (!response_state_.Closed()) { + EmitResponseEvent(false, "data", buffer); + } } void URLRequest::OnResponseCompleted() { - EmitResponseEvent("end"); - unpin(); - atom_request_ = nullptr; + response_state_.SetFlag(ResponseStateFlags::kEnded); + if (request_state_.Canceled()) { + // Don't emit any event after request cancel. + return; + } + if (!response_state_.Closed()) { + EmitResponseEvent(false, "end"); + } + Close(); } -void URLRequest::OnError(const std::string& error) { +void URLRequest::OnRequestError(const std::string& error) { + request_state_.SetFlag(RequestStateFlags::kFailed); auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error)); - EmitRequestEvent("error", error_object); + EmitRequestEvent(false, "error", error_object); + Close(); } +void URLRequest::OnResponseError(const std::string& error) { + response_state_.SetFlag(ResponseStateFlags::kFailed); + auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error)); + EmitResponseEvent(false, "error", error_object); + Close(); +} + + int URLRequest::StatusCode() const { if (auto response_headers = atom_request_->GetResponseHeaders()) { return response_headers->response_code(); @@ -238,6 +419,22 @@ uint32_t URLRequest::ResponseHttpVersionMinor() const { return 0; } +void URLRequest::Close() { + if (!response_state_.Closed()) { + response_state_.SetFlag(ResponseStateFlags::kClosed); + if (response_state_.Started()) { + // Emit a close event if we really have a response object. + EmitResponseEvent(true, "close"); + } + } + if (!request_state_.Closed()) { + request_state_.SetFlag(RequestStateFlags::kClosed); + EmitRequestEvent(true, "close"); + } + unpin(); + atom_request_ = nullptr; +} + void URLRequest::pin() { if (wrapper_.IsEmpty()) { wrapper_.Reset(isolate(), GetWrapper()); diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 20eb66d3f0..e5baed4f05 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -25,28 +25,28 @@ namespace api { // // The URLRequest class implements the V8 binding between the JavaScript API -// and Chromium native net library. It is responsible for handling HTTP/HTTPS +// and Chromium native net library. It is responsible for handling HTTP/HTTPS // requests. // -// The current class provides only the binding layer. Two other JavaScript -// classes (ClientRequest and IncomingMessage) in the net module provide the +// The current class provides only the binding layer. Two other JavaScript +// classes (ClientRequest and IncomingMessage) in the net module provide the // final API, including some state management and arguments validation. // -// URLRequest's methods fall into two main categories: command and event methods. -// They are always executed on the Browser's UI thread. +// URLRequest's methods fall into two main categories: command and event +// methods. They are always executed on the Browser's UI thread. // Command methods are called directly from JavaScript code via the API defined -// in BuildPrototype. A command method is generally implemented by forwarding -// the call to a corresponding method on AtomURLRequest which does the -// synchronization on the Browser IO thread. The latter then calls into Chromium -// net library. On the other hand, net library events originate on the IO +// in BuildPrototype. A command method is generally implemented by forwarding +// the call to a corresponding method on AtomURLRequest which does the +// synchronization on the Browser IO thread. The latter then calls into Chromium +// net library. On the other hand, net library events originate on the IO // thread in AtomURLRequest and are synchronized back on the UI thread, then -// forwarded to a corresponding event method in URLRequest and then to +// forwarded to a corresponding event method in URLRequest and then to // JavaScript via the EmitRequestEvent/EmitResponseEvent helpers. // -// URLRequest lifetime management: we followed the Wrapper/Wrappable pattern +// URLRequest lifetime management: we followed the Wrapper/Wrappable pattern // defined in native_mate. However, we augment that pattern with a pin/unpin // mechanism. The main reason is that we want the JS API to provide a similar -// lifetime guarantees as the XMLHttpRequest. +// lifetime guarantees as the XMLHttpRequest. // https://xhr.spec.whatwg.org/#garbage-collection // // The primary motivation is to not garbage collect a URLInstance as long as the @@ -61,32 +61,32 @@ namespace api { // }); // })(); // -// we still want data to be logged even if the response/request objects are no +// we still want data to be logged even if the response/request objects are n // more referenced in JavaScript. // // Binding by simply following the native_mate Wrapper/Wrappable pattern will // delete the URLRequest object when the corresponding JS object is collected. -// The v8 handle is a private member in WrappableBase and it is always weak, +// The v8 handle is a private member in WrappableBase and it is always weak, // there is no way to make it strong without changing native_mate. -// The solution we implement consists of maintaining some kind of state that +// The solution we implement consists of maintaining some kind of state that // prevents collection of JS wrappers as long as the request is emitting network -// events. At initialization, the object is unpinned. When the request starts, -// it is pinned. When no more events would be emitted, the object is unpinned -// and lifetime is again managed by the standard native mate Wrapper/Wrappable +// events. At initialization, the object is unpinned. When the request starts, +// it is pinned. When no more events would be emitted, the object is unpinned +// and lifetime is again managed by the standard native mate Wrapper/Wrappable // pattern. // -// pin/unpin: are implemented by constructing/reseting a V8 strong persistent +// pin/unpin: are implemented by constructing/reseting a V8 strong persistent // handle. // -// The URLRequest/AtmURLRequest interaction could have been implemented in a +// The URLRequest/AtmURLRequest interaction could have been implemented in a // single class. However, it implies that the resulting class lifetime will be -// managed by two conflicting mechanisms: JavaScript garbage collection and -// Chromium reference counting. Reasoning about lifetime issues become much +// managed by two conflicting mechanisms: JavaScript garbage collection and +// Chromium reference counting. Reasoning about lifetime issues become much // more complex. // -// We chose to split the implementation into two classes linked via a strong/weak -// pointers. A URLRequest instance is deleted if it is unpinned and the -// corresponding JS wrapper object is garbage collected. On the other hand, +// We chose to split the implementation into two classes linked via a +// strong/weak pointers. A URLRequest instance is deleted if it is unpinned and +// the corresponding JS wrapper object is garbage collected. On the other hand, // an AtmURLRequest instance lifetime is totally governed by reference counting. // class URLRequest : public mate::EventEmitter { @@ -103,7 +103,8 @@ class URLRequest : public mate::EventEmitter { void OnResponseStarted(); void OnResponseData(scoped_refptr data); void OnResponseCompleted(); - void OnError(const std::string& error); + void OnRequestError(const std::string& error); + void OnResponseError(const std::string& error); protected: explicit URLRequest(v8::Isolate* isolate, @@ -111,13 +112,70 @@ class URLRequest : public mate::EventEmitter { ~URLRequest() override; private: + template + class StateBase { + public: + void SetFlag(Flags flag); + protected: + explicit StateBase(Flags initialState); + bool operator==(Flags flag) const; + bool IsFlagSet(Flags flag) const; + private: + Flags state_; + }; + + enum class RequestStateFlags { + kNotStarted = 0x0, + kStarted = 0x1, + kFinished = 0x2, + kCanceled = 0x4, + kFailed = 0x8, + kClosed = 0x10 + }; + + class RequestState : public StateBase { + public: + RequestState(); + bool NotStarted() const; + bool Started() const; + bool Finished() const; + bool Canceled() const; + bool Failed() const; + bool Closed() const; + }; + + enum class ResponseStateFlags { + kNotStarted = 0x0, + kStarted = 0x1, + kEnded = 0x2, + kCanceled = 0x4, + kFailed = 0x8, + kClosed = 0x10 + }; + + class ResponseState : public StateBase { + public: + ResponseState(); + bool NotStarted() const; + bool Started() const; + bool Ended() const; + bool Canceled() const; + bool Failed() const; + bool Closed() const; + }; + + bool NotStarted() const; + bool Finished() const; + bool Canceled() const; + bool Failed() const; bool Write(scoped_refptr buffer, bool is_last); - void Abort(); + void Cancel(); bool SetExtraHeader(const std::string& name, const std::string& value); void RemoveExtraHeader(const std::string& name); void SetChunkedUpload(bool is_chunked_upload); + bool CanReadHeaders() const; int StatusCode() const; std::string StatusMessage() const; scoped_refptr RawResponseHeaders() const; @@ -134,16 +192,20 @@ class URLRequest : public mate::EventEmitter { template void EmitResponseEvent(ArgTypes... args); + void Close(); void pin(); void unpin(); scoped_refptr atom_request_; + RequestState request_state_; + ResponseState response_state_; // Used to implement pin/unpin. v8::Global wrapper_; base::WeakPtrFactory weak_ptr_factory_; + DISALLOW_COPY_AND_ASSIGN(URLRequest); }; diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index 6a20dc4768..f985915018 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -106,12 +106,12 @@ void AtomURLRequest::SetChunkedUpload(bool is_chunked_upload) { } -void AtomURLRequest::Abort() const { +void AtomURLRequest::Cancel() const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&AtomURLRequest::DoAbort, this)); + base::Bind(&AtomURLRequest::DoCancel, this)); } void AtomURLRequest::SetExtraHeader(const std::string& name, @@ -202,7 +202,7 @@ void AtomURLRequest::DoWriteBuffer( } } -void AtomURLRequest::DoAbort() const { +void AtomURLRequest::DoCancel() const { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); request_->Cancel(); } @@ -235,38 +235,32 @@ void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { const auto& status = request_->status(); if (status.is_success()) { - // Cache net::HttpResponseHeaders instance, a read-only objects - // so that headers and other http metainformation can be simultaneously - // read from UI thread while request data is simulataneously streaming - // on IO thread. - response_headers_ = request_->response_headers(); + // Success or pending trigger a Read. content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, base::Bind(&AtomURLRequest::InformDelegateResponseStarted, this)); ReadResponse(); - } else { + } else if (status.status() == net::URLRequestStatus::Status::FAILED) { + // Report error on Start. + DoCancel(); auto error = net::ErrorToString(status.ToNetError()); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateErrorOccured, + base::Bind(&AtomURLRequest::InformDelegateRequestErrorOccured, this, std::move(error))); } + // We don't report an error is the request is canceled. } void AtomURLRequest::ReadResponse() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - // Some servers may treat HEAD requests as GET requests. To free up the - // network connection as soon as possible, signal that the request has - // completed immediately, without trying to read any data back (all we care - // about is the response code and headers, which we already have). - int bytes_read = 0; - if (request_->status().is_success()) - if (!request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)) - bytes_read = -1; - OnReadCompleted(request_.get(), bytes_read); + int bytes_read = -1; + if (request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)) { + OnReadCompleted(request_.get(), bytes_read); + } } @@ -277,36 +271,53 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, DCHECK_EQ(request, request_.get()); const auto status = request_->status(); + + bool response_error = false; + bool data_ended = false; + bool data_transfer_error = false; do { - if (!status.is_success() || bytes_read <= 0) { - auto error = net::ErrorToString(status.ToNetError()); - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateErrorOccured, - this, - std::move(error))); + if (!status.is_success()) { + response_error = true; + break; + } + if (bytes_read == 0) { + data_ended = true; + break; + } + if (bytes_read < 0 || !CopyAndPostBuffer(bytes_read)) { + data_transfer_error = true; break; } - - const auto result = CopyAndPostBuffer(bytes_read); - if (!result) - // Failed to transfer data to UI thread. - return; } while (request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)); - - if (!status.is_io_pending()) - + if (response_error) { + DoCancel(); + auto error = net::ErrorToString(status.ToNetError()); + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured, + this, + std::move(error))); + } else if (data_ended) { content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, base::Bind(&AtomURLRequest::InformDelegateResponseCompleted, this)); + } else if (data_transfer_error) { + // We abort the request on corrupted data transfer. + DoCancel(); + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured, + this, + "Failed to transfer data from IO to UI thread.")); + } } bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - // data is only a wrapper for the async response_read_buffer_. + // data is only a wrapper for the asynchronous response_read_buffer_. // Make a deep copy of payload and transfer ownership to the UI thread. auto buffer_copy = new net::IOBufferWithSize(bytes_read); memcpy(buffer_copy->data(), response_read_buffer_->data(), bytes_read); @@ -349,13 +360,20 @@ void AtomURLRequest::InformDelegateResponseCompleted() const { delegate_->OnResponseCompleted(); } -void AtomURLRequest::InformDelegateErrorOccured( +void AtomURLRequest::InformDelegateRequestErrorOccured( const std::string& error) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (delegate_) - delegate_->OnError(error); + delegate_->OnRequestError(error); } +void AtomURLRequest::InformDelegateResponseErrorOccured( + const std::string& error) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + + if (delegate_) + delegate_->OnResponseError(error); +} } // namespace atom diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index f065bc5249..f0708c0ac2 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -33,7 +33,7 @@ class AtomURLRequest : public base::RefCountedThreadSafe, bool Write(scoped_refptr buffer, bool is_last); void SetChunkedUpload(bool is_chunked_upload); - void Abort() const; + void Cancel() const; void SetExtraHeader(const std::string& name, const std::string& value) const; void RemoveExtraHeader(const std::string& name) const; void PassLoginInformation(const base::string16& username, @@ -51,12 +51,12 @@ class AtomURLRequest : public base::RefCountedThreadSafe, private: friend class base::RefCountedThreadSafe; - explicit AtomURLRequest(base::WeakPtr delegate); - ~AtomURLRequest()override; + explicit AtomURLRequest(base::WeakPtr delegate); + ~AtomURLRequest()override; void DoWriteBuffer(scoped_refptr buffer, bool is_last); - void DoAbort() const; + void DoCancel() const; void DoSetAuth(const base::string16& username, const base::string16& password) const; void DoCancelAuth() const; @@ -70,7 +70,8 @@ class AtomURLRequest : public base::RefCountedThreadSafe, void InformDelegateResponseData( scoped_refptr data) const; void InformDelegateResponseCompleted() const; - void InformDelegateErrorOccured(const std::string& error) const; + void InformDelegateRequestErrorOccured(const std::string& error) const; + void InformDelegateResponseErrorOccured(const std::string& error) const; base::WeakPtr delegate_; std::unique_ptr request_; @@ -81,7 +82,6 @@ class AtomURLRequest : public base::RefCountedThreadSafe, std::vector> upload_element_readers_; scoped_refptr response_read_buffer_; - scoped_refptr response_headers_; DISALLOW_COPY_AND_ASSIGN(AtomURLRequest); }; diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 1471ae4f1d..5f2c7345d4 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -50,12 +50,24 @@ class IncomingMessage extends EventEmitter { } -URLRequest.prototype._emitRequestEvent = function () { - this._request.emit.apply(this._request, arguments) +URLRequest.prototype._emitRequestEvent = function (async, ...rest) { + if (async) { + process.nextTick(() => { + this._request.emit.apply(this._request, rest) + }) + } else { + this._request.emit.apply(this._request, rest) + } } -URLRequest.prototype._emitResponseEvent = function () { - this._response.emit.apply(this._response, arguments) +URLRequest.prototype._emitResponseEvent = function (async, ...rest) { + if (async) { + process.nextTick(() => { + this._request.emit.apply(this._request, rest) + }) + } else { + this._response.emit.apply(this._response, rest) + } } class ClientRequest extends EventEmitter { @@ -127,16 +139,7 @@ class ClientRequest extends EventEmitter { } } - // Flag to prevent request's headers modifications after - // headers flush. - this._started = false - - this._aborted = false - - // Flag to prevent writings after end. - this._finished = false - - // Set when the request uses chuned encoding. Can be switched + // Set when the request uses chunked encoding. Can be switched // to true only once and never set back to false. this._chunkedEncoding = false @@ -161,7 +164,7 @@ class ClientRequest extends EventEmitter { } set chunkedEncoding (value) { - if (this._started) { + if (!this._url_request.notStarted) { throw new Error('Can\'t set the transfer encoding, headers have been sent.') } this._chunkedEncoding = value @@ -174,7 +177,7 @@ class ClientRequest extends EventEmitter { if (value === undefined) { throw new Error('`value` required in setHeader("' + name + '", value).') } - if (this._started) { + if (!this._url_request.notStarted) { throw new Error('Can\'t set headers after they are sent.') } @@ -201,7 +204,7 @@ class ClientRequest extends EventEmitter { throw new Error('`name` is required for removeHeader(name).') } - if (this._started) { + if (!this._url_request.notStarted) { throw new Error('Can\'t remove headers after they are sent.') } @@ -229,9 +232,8 @@ class ClientRequest extends EventEmitter { // Since writing to the network is asynchronous, we conservatively // assume that request headers are written after delivering the first // buffer to the network IO thread. - if (!this._started) { + if (!this._url_request.notStarted) { this._url_request.setChunkedUpload(this.chunkedEncoding) - this._started = true } // The write callback is fired asynchronously to mimic Node.js. @@ -243,7 +245,7 @@ class ClientRequest extends EventEmitter { } write (data, encoding, callback) { - if (this._finished) { + if (this._url_request.finished) { let error = new Error('Write after end.') process.nextTick(writeAfterEndNT, this, error, callback) return true @@ -253,12 +255,10 @@ class ClientRequest extends EventEmitter { } end (data, encoding, callback) { - if (this._finished) { + if (this._url_request.finished) { return false } - this._finished = true - if (typeof data === 'function') { callback = data encoding = null @@ -274,18 +274,7 @@ class ClientRequest extends EventEmitter { } abort () { - if (!this._started) { - // Does nothing if stream - return - } - - if (!this._aborted) { - this._url_request.abort() - this._aborted = true - process.nextTick(() => { - this.emit('abort') - }) - } + this._url_request.cancel() } } From e472d1176124c7dd8775762fda49352e3b7ad4c9 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 4 Oct 2016 17:33:34 +0200 Subject: [PATCH 015/148] Caching response headers so that AtomURLRequest can be freed after the close event. --- atom/browser/api/atom_api_url_request.cc | 26 +++++++++++++----------- atom/browser/api/atom_api_url_request.h | 5 +++-- atom/browser/net/atom_url_request.cc | 22 ++++++++------------ atom/browser/net/atom_url_request.h | 4 ++-- 4 files changed, 28 insertions(+), 29 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 29736a5d06..14a1d8a379 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -51,7 +51,7 @@ struct Converter> { auto size = node::Buffer::Length(val); if (size == 0) { - // Support conversoin from empty buffer. A use case is + // Support conversion from empty buffer. A use case is // a GET request without body. // Since zero-sized IOBuffer(s) are not supported, we set the // out pointer to null. @@ -60,7 +60,7 @@ struct Converter> { } auto data = node::Buffer::Data(val); if (!data) { - // This is an error as size is positif but data is null. + // This is an error as size is positive but data is null. return false; } @@ -333,13 +333,15 @@ void URLRequest::OnAuthenticationRequired( base::Bind(&AtomURLRequest::PassLoginInformation, atom_request_)); } -void URLRequest::OnResponseStarted() { +void URLRequest::OnResponseStarted( + scoped_refptr response_headers) { if (request_state_.Canceled() || request_state_.Failed() || request_state_.Closed()) { // Don't emit any event after request cancel. return; } + response_headers_ = response_headers; response_state_.SetFlag(ResponseStateFlags::kStarted); Emit("response"); } @@ -386,35 +388,35 @@ void URLRequest::OnResponseError(const std::string& error) { int URLRequest::StatusCode() const { - if (auto response_headers = atom_request_->GetResponseHeaders()) { - return response_headers->response_code(); + if (response_headers_) { + return response_headers_->response_code(); } return -1; } std::string URLRequest::StatusMessage() const { std::string result; - if (auto response_headers = atom_request_->GetResponseHeaders()) { - result = response_headers->GetStatusText(); + if (response_headers_) { + result = response_headers_->GetStatusText(); } return result; } scoped_refptr URLRequest::RawResponseHeaders() const { - return atom_request_->GetResponseHeaders(); + return response_headers_; } uint32_t URLRequest::ResponseHttpVersionMajor() const { - if (auto response_headers = atom_request_->GetResponseHeaders()) { - return response_headers->GetHttpVersion().major_value(); + if (response_headers_) { + return response_headers_->GetHttpVersion().major_value(); } return 0; } uint32_t URLRequest::ResponseHttpVersionMinor() const { - if (auto response_headers = atom_request_->GetResponseHeaders()) { - return response_headers->GetHttpVersion().minor_value(); + if (response_headers_) { + return response_headers_->GetHttpVersion().minor_value(); } return 0; } diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index e5baed4f05..4f688e4545 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -100,7 +100,8 @@ class URLRequest : public mate::EventEmitter { // Methods for reporting events into JavaScript. void OnAuthenticationRequired( scoped_refptr auth_info); - void OnResponseStarted(); + void OnResponseStarted( + scoped_refptr response_headers); void OnResponseData(scoped_refptr data); void OnResponseCompleted(); void OnRequestError(const std::string& error); @@ -202,7 +203,7 @@ class URLRequest : public mate::EventEmitter { // Used to implement pin/unpin. v8::Global wrapper_; - + scoped_refptr response_headers_; base::WeakPtrFactory weak_ptr_factory_; diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index f985915018..d795b0b518 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -126,15 +126,6 @@ void AtomURLRequest::RemoveExtraHeader(const std::string& name) const { request_->RemoveRequestHeaderByName(name); } - - -scoped_refptr -AtomURLRequest::GetResponseHeaders() const { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - return request_->response_headers(); -} - - void AtomURLRequest::PassLoginInformation(const base::string16& username, const base::string16& password) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -173,7 +164,7 @@ void AtomURLRequest::DoWriteBuffer( buffer->size(), is_last); else if (is_last) - // Empty buffer and last chunck, i.e. request.end(). + // Empty buffer and last chunk, i.e. request.end(). auto write_result = chunked_stream_writer_->AppendData( nullptr, 0, @@ -233,12 +224,16 @@ void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_EQ(request, request_.get()); + scoped_refptr response_headers = + request->response_headers(); const auto& status = request_->status(); if (status.is_success()) { // Success or pending trigger a Read. content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseStarted, this)); + base::Bind(&AtomURLRequest::InformDelegateResponseStarted, + this, + response_headers)); ReadResponse(); } else if (status.status() == net::URLRequestStatus::Status::FAILED) { @@ -337,10 +332,11 @@ void AtomURLRequest::InformDelegateAuthenticationRequired( delegate_->OnAuthenticationRequired(auth_info); } -void AtomURLRequest::InformDelegateResponseStarted() const { +void AtomURLRequest::InformDelegateResponseStarted( + scoped_refptr response_headers) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (delegate_) - delegate_->OnResponseStarted(); + delegate_->OnResponseStarted(response_headers); } void AtomURLRequest::InformDelegateResponseData( diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index f0708c0ac2..6a867aac08 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -38,7 +38,6 @@ class AtomURLRequest : public base::RefCountedThreadSafe, void RemoveExtraHeader(const std::string& name) const; void PassLoginInformation(const base::string16& username, const base::string16& password) const; - scoped_refptr GetResponseHeaders() const; protected: // Overrides of net::URLRequest::Delegate @@ -66,7 +65,8 @@ class AtomURLRequest : public base::RefCountedThreadSafe, void InformDelegateAuthenticationRequired( scoped_refptr auth_info) const; - void InformDelegateResponseStarted() const; + void InformDelegateResponseStarted( + scoped_refptr) const; void InformDelegateResponseData( scoped_refptr data) const; void InformDelegateResponseCompleted() const; From a655cca0a1f9f5a542a72d2c74de1f3ecddbf672 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 4 Oct 2016 17:54:34 +0200 Subject: [PATCH 016/148] Request/Response state simplification. Removing redundant state flags. --- atom/browser/api/atom_api_url_request.cc | 55 ++++++++++-------------- atom/browser/api/atom_api_url_request.h | 4 +- 2 files changed, 24 insertions(+), 35 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 14a1d8a379..8e16c02bb5 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -149,18 +149,11 @@ bool URLRequest::ResponseState::Ended() const { return IsFlagSet(ResponseStateFlags::kEnded); } -bool URLRequest::ResponseState::Canceled() const { - return IsFlagSet(ResponseStateFlags::kCanceled); -} bool URLRequest::ResponseState::Failed() const { return IsFlagSet(ResponseStateFlags::kFailed); } -bool URLRequest::ResponseState::Closed() const { - return IsFlagSet(ResponseStateFlags::kClosed); -} - URLRequest::URLRequest(v8::Isolate* isolate, v8::Local wrapper) : weak_ptr_factory_(this) { InitWith(isolate, wrapper); @@ -261,7 +254,8 @@ bool URLRequest::Write( void URLRequest::Cancel() { - if (request_state_.Canceled()) { + if (request_state_.Canceled() || + request_state_.Closed()) { // Cancel only once. return; } @@ -269,18 +263,14 @@ void URLRequest::Cancel() { // Mark as canceled. request_state_.SetFlag(RequestStateFlags::kCanceled); - if (request_state_.Started()) { + DCHECK(atom_request_); + if (atom_request_ && request_state_.Started()) { // Really cancel if it was started. atom_request_->Cancel(); } + EmitRequestEvent(true, "abort"); - if (!request_state_.Closed()) { - EmitRequestEvent(true, "abort"); - } - - - response_state_.SetFlag(ResponseStateFlags::kCanceled); - if (response_state_.Started() && !response_state_.Closed()) { + if (response_state_.Started() && !response_state_.Ended()) { EmitResponseEvent(true, "aborted"); } Close(); @@ -348,27 +338,31 @@ void URLRequest::OnResponseStarted( void URLRequest::OnResponseData( scoped_refptr buffer) { - if (request_state_.Canceled()) { - // Don't emit any event after request cancel. + if (request_state_.Canceled() || + request_state_.Closed() || + request_state_.Failed() || + response_state_.Failed()) { + // In case we received an unexpected event from Chromium net, + // don't emit any data event after request cancel/error/close. return; } if (!buffer || !buffer->data() || !buffer->size()) { return; } - if (!response_state_.Closed()) { - EmitResponseEvent(false, "data", buffer); - } + EmitResponseEvent(false, "data", buffer); } void URLRequest::OnResponseCompleted() { - response_state_.SetFlag(ResponseStateFlags::kEnded); - if (request_state_.Canceled()) { - // Don't emit any event after request cancel. + if (request_state_.Canceled() || + request_state_.Closed() || + request_state_.Failed() || + response_state_.Failed()) { + // In case we received an unexpected event from Chromium net, + // don't emit any data event after request cancel/error/close. return; } - if (!response_state_.Closed()) { - EmitResponseEvent(false, "end"); - } + response_state_.SetFlag(ResponseStateFlags::kEnded); + EmitResponseEvent(false, "end"); Close(); } @@ -422,15 +416,12 @@ uint32_t URLRequest::ResponseHttpVersionMinor() const { } void URLRequest::Close() { - if (!response_state_.Closed()) { - response_state_.SetFlag(ResponseStateFlags::kClosed); + if (!request_state_.Closed()) { + request_state_.SetFlag(RequestStateFlags::kClosed); if (response_state_.Started()) { // Emit a close event if we really have a response object. EmitResponseEvent(true, "close"); } - } - if (!request_state_.Closed()) { - request_state_.SetFlag(RequestStateFlags::kClosed); EmitRequestEvent(true, "close"); } unpin(); diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 4f688e4545..672a6693ee 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -149,9 +149,7 @@ class URLRequest : public mate::EventEmitter { kNotStarted = 0x0, kStarted = 0x1, kEnded = 0x2, - kCanceled = 0x4, - kFailed = 0x8, - kClosed = 0x10 + kFailed = 0x4 }; class ResponseState : public StateBase { From 8c5751e9f7f666b64e42e76d0ef35d592ce2447e Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 4 Oct 2016 18:09:36 +0200 Subject: [PATCH 017/148] Adding systematic checks on the atom_request_ pointer as it may be reset to null. --- atom/browser/api/atom_api_url_request.cc | 33 +++++++++++++++++++----- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 8e16c02bb5..c1c95e27e5 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -278,7 +278,7 @@ void URLRequest::Cancel() { bool URLRequest::SetExtraHeader(const std::string& name, const std::string& value) { - // State must be equal to not started. + // Request state must be in the initial non started state. if (!request_state_.NotStarted()) { // Cannot change headers after send. return false; @@ -292,7 +292,10 @@ bool URLRequest::SetExtraHeader(const std::string& name, return false; } - atom_request_->SetExtraHeader(name, value); + DCHECK(atom_request_); + if (atom_request_) { + atom_request_->SetExtraHeader(name, value); + } return true; } @@ -302,7 +305,10 @@ void URLRequest::RemoveExtraHeader(const std::string& name) { // Cannot change headers after send. return; } - atom_request_->RemoveExtraHeader(name); + DCHECK(atom_request_); + if (atom_request_) { + atom_request_->RemoveExtraHeader(name); + } } void URLRequest::SetChunkedUpload(bool is_chunked_upload) { @@ -311,11 +317,24 @@ void URLRequest::SetChunkedUpload(bool is_chunked_upload) { // Cannot change headers after send. return; } - atom_request_->SetChunkedUpload(is_chunked_upload); + DCHECK(atom_request_); + if (atom_request_) { + atom_request_->SetChunkedUpload(is_chunked_upload); + } } void URLRequest::OnAuthenticationRequired( - scoped_refptr auth_info) { + scoped_refptr auth_info) { + if (request_state_.Canceled() || + request_state_.Closed()) { + return; + } + + DCHECK(atom_request_); + if (!atom_request_) { + return; + } + EmitRequestEvent( false, "login", @@ -367,15 +386,15 @@ void URLRequest::OnResponseCompleted() { } void URLRequest::OnRequestError(const std::string& error) { - request_state_.SetFlag(RequestStateFlags::kFailed); auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error)); + request_state_.SetFlag(RequestStateFlags::kFailed); EmitRequestEvent(false, "error", error_object); Close(); } void URLRequest::OnResponseError(const std::string& error) { - response_state_.SetFlag(ResponseStateFlags::kFailed); auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error)); + response_state_.SetFlag(ResponseStateFlags::kFailed); EmitResponseEvent(false, "error", error_object); Close(); } From dcffb51e5e5e4002e4d440192f5dd1535f4ae162 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 5 Oct 2016 15:06:35 +0200 Subject: [PATCH 018/148] Adding net module spec file skeleton. --- spec/api-net-spec.js | 137 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 spec/api-net-spec.js diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js new file mode 100644 index 0000000000..442e045ac9 --- /dev/null +++ b/spec/api-net-spec.js @@ -0,0 +1,137 @@ +const assert = require('assert') +const {net} = require('electron'); + +describe('net module', function() { + describe('HTTP basics', function() { + it ('should be able to fetch google.com', function(done) { + let response_event_emitted = false; + let data_event_emitted = false; + let end_event_emitted = false; + let finish_event_emitted = false; + const urlRequest = net.request({ + method: 'GET', + url: 'https://www.google.com' + }) + urlRequest.on('response', function(response) { + response_event_emitted = true; + const statusCode = response.statusCode + assert(typeof statusCode === 'number') + assert.equal(statusCode, 200) + const statusMessage = response.statusMessage + const rawHeaders = response.rawHeaders + assert(typeof rawHeaders === 'string') + assert(rawHeaders.length > 0) + const httpVersion = response.httpVersion; + assert(typeof httpVersion === 'string') + assert(httpVersion.length > 0) + const httpVersionMajor = response.httpVersionMajor; + assert(typeof httpVersionMajor === 'number') + assert(httpVersionMajor >= 1) + const httpVersionMinor = response.httpVersionMinor; + assert(typeof rawHeaders === 'number') + assert(httpVersionMinor >= 0) + let body = ''; + response.on('data', function(buffer) { + data_event_emitted = true; + body += buffer.toString() + assert(typeof body === 'string') + assert(body.length > 0) + }); + response.on('end', function() { + end_event_emitted = true; + }) + }); + urlRequest.on('finish', function() { + finish_event_emitted = true; + }) + urlRequest.on('error', function(error) { + assert.ifError(error); + }) + urlRequest.on('close', function() { + asset(response_event_emitted) + assert(data_event_emitted) + assert(end_event_emitted) + assert(finish_event_emitted) + done() + }) + urlRequest.end(); + }) + + it ('should be able to post data', function(done) { + let response_event_emitted = false; + let data_event_emitted = false; + let end_event_emitted = false; + let finish_event_emitted = false; + let urlRequest = net.request({ + method: 'POST', + url: 'http://httpbin.org/post' + }); + urlRequest.on('response', function(response) { + response_event_emitted = true; + const statusCode = response.statusCode + assert(typeof statusCode === 'number') + assert.equal(statusCode, 200) + const statusMessage = response.statusMessage + const rawHeaders = response.rawHeaders + assert(typeof rawHeaders === 'string') + assert(rawHeaders.length > 0) + const httpVersion = response.httpVersion; + assert(typeof httpVersion === 'string') + assert(httpVersion.length > 0) + const httpVersionMajor = response.httpVersionMajor; + assert(typeof httpVersionMajor === 'number') + assert(httpVersionMajor >= 1) + const httpVersionMinor = response.httpVersionMinor; + assert(typeof rawHeaders === 'number') + assert(httpVersionMinor >= 0) + let body = ''; + response.on('data', function(buffer) { + data_event_emitted = true; + body += buffer.toString() + assert(typeof body === 'string') + assert(body.length > 0) + }); + response.on('end', function() { + end_event_emitted = true; + }) + }); + urlRequest.on('finish', function() { + finish_event_emitted = true; + }) + urlRequest.on('error', function(error) { + assert.ifError(error); + }) + urlRequest.on('close', function() { + asset(response_event_emitted) + assert(data_event_emitted) + assert(end_event_emitted) + assert(finish_event_emitted) + done() + }) + for (let i = 0; i < 100; ++i) { + urlRequest.write('Hello World!'); + } + urlRequest.end(); + }) + }) + describe('ClientRequest API', function() { + it ('should be able to set a custom HTTP header', function() { + assert(false) + }) + it ('should be able to abort an HTTP request', function() { + assert(false) + }) + it ('should be able to pipe into a request', function() { + + }) + it ('should be able to create a request with options', function() { + + }) + it ('should be able to specify a custom session', function() { + }) + it ('should support chunked encoding', function() { + + }) + + }) +}) \ No newline at end of file From 42bae9d71d1f69d0a8d4e794a8f08d1984854982 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 6 Oct 2016 14:14:05 +0200 Subject: [PATCH 019/148] Making the HTTP response a full-fledged Readable stream. --- atom/browser/api/atom_api_url_request.cc | 4 ++-- lib/browser/api/net.js | 29 +++++++++++++++++++++++- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index c1c95e27e5..e3d0f59929 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -368,7 +368,7 @@ void URLRequest::OnResponseData( if (!buffer || !buffer->data() || !buffer->size()) { return; } - EmitResponseEvent(false, "data", buffer); + Emit("data", buffer); } void URLRequest::OnResponseCompleted() { @@ -381,7 +381,7 @@ void URLRequest::OnResponseCompleted() { return; } response_state_.SetFlag(ResponseStateFlags::kEnded); - EmitResponseEvent(false, "end"); + Emit("end"); Close(); } diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 5f2c7345d4..d00946be83 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -3,6 +3,7 @@ const url = require('url') const {EventEmitter} = require('events') const util = require('util') +const Readable = require('stream').Readable const binding = process.atomBinding('net') const {net, Net} = binding const {URLRequest} = net @@ -14,10 +15,20 @@ let kSupportedProtocols = new Set() kSupportedProtocols.add('http:') kSupportedProtocols.add('https:') -class IncomingMessage extends EventEmitter { +class IncomingMessage extends Readable { constructor (urlRequest) { super() this._url_request = urlRequest + this._shouldPush = false; + this._data = []; + this._url_request.on('data', (event, chunk) => { + this._storeInternalData(chunk) + this._pushInternalData() + }) + this._url_request.on('end', () => { + this._storeInternalData(null) + this._pushInternalData() + }) } get statusCode () { @@ -48,6 +59,22 @@ class IncomingMessage extends EventEmitter { return this._url_request.rawResponseHeaders } + _storeInternalData(chunk) { + this._data.push(chunk) + } + + _pushInternalData() { + while (this._shouldPush && this._data.length > 0) { + const chunk = this._data.shift() + this._shouldPush = this.push(chunk) + } + } + + _read() { + this._shouldPush = true + this._pushInternalData() + } + } URLRequest.prototype._emitRequestEvent = function (async, ...rest) { From b57ffbf1ab2ba9e29c9a2cb9a46af71f4df3ca1e Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 6 Oct 2016 14:32:20 +0200 Subject: [PATCH 020/148] Temporary fix for the post data test. --- spec/api-net-spec.js | 53 ++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index 442e045ac9..2cf92327da 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -1,9 +1,11 @@ const assert = require('assert') -const {net} = require('electron'); +const {remote} = require('electron') +const {net} = remote -describe('net module', function() { +describe.only('net module', function() { describe('HTTP basics', function() { it ('should be able to fetch google.com', function(done) { + this.timeout(30000); let response_event_emitted = false; let data_event_emitted = false; let end_event_emitted = false; @@ -19,8 +21,7 @@ describe('net module', function() { assert.equal(statusCode, 200) const statusMessage = response.statusMessage const rawHeaders = response.rawHeaders - assert(typeof rawHeaders === 'string') - assert(rawHeaders.length > 0) + assert(typeof rawHeaders === 'object') const httpVersion = response.httpVersion; assert(typeof httpVersion === 'string') assert(httpVersion.length > 0) @@ -28,7 +29,7 @@ describe('net module', function() { assert(typeof httpVersionMajor === 'number') assert(httpVersionMajor >= 1) const httpVersionMinor = response.httpVersionMinor; - assert(typeof rawHeaders === 'number') + assert(typeof httpVersionMinor === 'number') assert(httpVersionMinor >= 0) let body = ''; response.on('data', function(buffer) { @@ -48,7 +49,7 @@ describe('net module', function() { assert.ifError(error); }) urlRequest.on('close', function() { - asset(response_event_emitted) + assert(response_event_emitted) assert(data_event_emitted) assert(end_event_emitted) assert(finish_event_emitted) @@ -58,11 +59,12 @@ describe('net module', function() { }) it ('should be able to post data', function(done) { + this.timeout(20000); let response_event_emitted = false; let data_event_emitted = false; let end_event_emitted = false; let finish_event_emitted = false; - let urlRequest = net.request({ + const urlRequest = net.request({ method: 'POST', url: 'http://httpbin.org/post' }); @@ -73,8 +75,7 @@ describe('net module', function() { assert.equal(statusCode, 200) const statusMessage = response.statusMessage const rawHeaders = response.rawHeaders - assert(typeof rawHeaders === 'string') - assert(rawHeaders.length > 0) + assert(typeof rawHeaders === 'object') const httpVersion = response.httpVersion; assert(typeof httpVersion === 'string') assert(httpVersion.length > 0) @@ -82,18 +83,24 @@ describe('net module', function() { assert(typeof httpVersionMajor === 'number') assert(httpVersionMajor >= 1) const httpVersionMinor = response.httpVersionMinor; - assert(typeof rawHeaders === 'number') + assert(typeof httpVersionMinor === 'number') assert(httpVersionMinor >= 0) let body = ''; + response.on('end', function() { + end_event_emitted = true; + assert(response_event_emitted) + assert(data_event_emitted) + assert(end_event_emitted) + assert(finish_event_emitted) + done() + }) response.on('data', function(buffer) { data_event_emitted = true; body += buffer.toString() assert(typeof body === 'string') assert(body.length > 0) }); - response.on('end', function() { - end_event_emitted = true; - }) + }); urlRequest.on('finish', function() { finish_event_emitted = true; @@ -102,11 +109,7 @@ describe('net module', function() { assert.ifError(error); }) urlRequest.on('close', function() { - asset(response_event_emitted) - assert(data_event_emitted) - assert(end_event_emitted) - assert(finish_event_emitted) - done() + }) for (let i = 0; i < 100; ++i) { urlRequest.write('Hello World!'); @@ -122,16 +125,22 @@ describe('net module', function() { assert(false) }) it ('should be able to pipe into a request', function() { - + assert(false) + }) + it ('should be able to pipe from a response', function() { + assert(false) }) it ('should be able to create a request with options', function() { - + assert(false) }) it ('should be able to specify a custom session', function() { + assert(false) }) it ('should support chunked encoding', function() { - + assert(false) + }) + it ('should not emit any event after close', function() { + assert(false) }) - }) }) \ No newline at end of file From 046f48db51e4631db2d1798ff20eac6a17d4259f Mon Sep 17 00:00:00 2001 From: Ali Ibrahim Date: Thu, 6 Oct 2016 17:28:21 +0200 Subject: [PATCH 021/148] Fixing build on Linux --- atom/browser/api/atom_api_url_request.h | 1 + 1 file changed, 1 insertion(+) diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 672a6693ee..c10b542856 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -10,6 +10,7 @@ #include "atom/browser/api/event_emitter.h" #include "atom/browser/api/trackable_object.h" #include "base/memory/weak_ptr.h" +#include "native_mate/dictionary.h" #include "native_mate/handle.h" #include "native_mate/wrappable_base.h" #include "net/base/auth.h" From 9b94dfcbdc4af4b6b69e1133ad01919d0a7c9e5d Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Fri, 7 Oct 2016 11:07:49 +0200 Subject: [PATCH 022/148] Adding basic http tests, fixing issues in ClientRequest constructor. --- lib/browser/api/net.js | 23 +++-- spec/api-net-spec.js | 221 ++++++++++++++++++++++++++++++++++------- 2 files changed, 202 insertions(+), 42 deletions(-) diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index d00946be83..9c9c57c202 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -59,6 +59,14 @@ class IncomingMessage extends Readable { return this._url_request.rawResponseHeaders } + get rawTrailers() { + throw (new Error('HTTP trailers are not supported.')) + } + + get trailers() { + throw (new Error('HTTP trailers are not supported.')) + } + _storeInternalData(chunk) { this._data.push(chunk) } @@ -113,7 +121,7 @@ class ClientRequest extends EventEmitter { if (!urlStr) { let urlObj = {} - const protocol = options.protocol || 'http' + const protocol = options.protocol || 'http:' if (!kSupportedProtocols.has(protocol)) { throw new Error('Protocol "' + protocol + '" not supported. ') } @@ -133,7 +141,6 @@ class ClientRequest extends EventEmitter { } } - const path = options.path || '/' if (options.path && / /.test(options.path)) { // The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/ // with an additional rule for ignoring percentage-escaped characters @@ -143,7 +150,9 @@ class ClientRequest extends EventEmitter { // an invalid request. throw new TypeError('Request path contains unescaped characters.') } - urlObj.path = path + urlObj.pathname = options.pathname || '/' + urlObj.search = options.search + urlObj.hash = options.hash urlStr = url.format(urlObj) } @@ -252,10 +261,6 @@ class ClientRequest extends EventEmitter { chunk = Buffer.from(chunk, encoding) } - // Headers are assumed to be sent on first call to _writeBuffer, - // i.e. after the first call to write or end. - let result = this._url_request.write(chunk, isLast) - // Since writing to the network is asynchronous, we conservatively // assume that request headers are written after delivering the first // buffer to the network IO thread. @@ -263,6 +268,10 @@ class ClientRequest extends EventEmitter { this._url_request.setChunkedUpload(this.chunkedEncoding) } + // Headers are assumed to be sent on first call to _writeBuffer, + // i.e. after the first call to write or end. + let result = this._url_request.write(chunk, isLast) + // The write callback is fired asynchronously to mimic Node.js. if (callback) { process.nextTick(callback) diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index 2cf92327da..20bced19be 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -1,19 +1,166 @@ const assert = require('assert') const {remote} = require('electron') +const http = require('http') +const url = require('url') const {net} = remote describe.only('net module', function() { + this.timeout(0) describe('HTTP basics', function() { - it ('should be able to fetch google.com', function(done) { + + let server + beforeEach(function (done) { + server = http.createServer() + server.listen(0, '127.0.0.1', function () { + server.url = 'http://127.0.0.1:' + server.address().port + done() + }) + }) + + afterEach(function () { + server.close(function() { + }) + server = null + }) + + it('should be able to issue a basic GET request', function(done) { + const request_url = '/request_url' + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + assert.equal(request.method, 'GET') + response.end(); + break; + default: + response.statusCode = 501 + response.statusMessage = 'Not Implemented' + response.end() + } + }) + const urlRequest = net.request(`${server.url}${request_url}`) + urlRequest.on('response', function(response) { + assert.equal(response.statusCode, 200) + response.on('end', function() { + done() + }) + response.on('data', function(chunk) { + + }) + }) + urlRequest.end(); + }) + + it('should be able to issue a basic POST request', function(done) { + const request_url = '/request_url' + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + assert.equal(request.method, 'POST') + response.end(); + break; + default: + response.statusCode = 501 + response.statusMessage = 'Not Implemented' + response.end() + } + }) + const urlRequest = net.request({ + method: 'POST', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + assert.equal(response.statusCode, 200) + response.on('end', function() { + done() + }) + response.on('data', function(chunk) { + + }) + }) + urlRequest.end(); + }) + + it('should fetch correct data in a GET request', function(done) { + const request_url = '/request_url' + const body_data = "Hello World!" + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + assert.equal(request.method, 'GET') + response.write(body_data) + response.end(); + break; + default: + response.statusCode = 501 + response.statusMessage = 'Not Implemented' + response.end() + } + }) + const urlRequest = net.request(`${server.url}${request_url}`) + urlRequest.on('response', function(response) { + let expected_body_data = ''; + assert.equal(response.statusCode, 200) + response.on('end', function() { + assert.equal(expected_body_data, body_data) + done() + }) + response.on('data', function(chunk) { + expected_body_data += chunk.toString(); + }) + }) + urlRequest.end(); + }) + + it('should post the correct data in a POST request', function(done) { + const request_url = '/request_url' + const body_data = "Hello World!" + server.on('request', function(request, response) { + let posted_body_data = '' + switch (request.url) { + case request_url: + assert.equal(request.method, 'POST') + request.on('data', function(chunk) { + posted_body_data += chunk.toString() + }) + request.on('end', function() { + assert.equal(posted_body_data, body_data) + response.end(); + }) + break; + default: + response.statusCode = 501 + response.statusMessage = 'Not Implemented' + response.end() + } + }) + const urlRequest = net.request({ + method: 'POST', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + assert.equal(response.statusCode, 200) + response.on('end', function() { + done() + }) + response.on('data', function(chunk) { + }) + }) + urlRequest.write(body_data) + urlRequest.end(); + }) + + }) + describe('ClientRequest API', function() { + it ('should emit ClientRequest events in a GET request', function(done) { this.timeout(30000); let response_event_emitted = false; let data_event_emitted = false; let end_event_emitted = false; let finish_event_emitted = false; const urlRequest = net.request({ - method: 'GET', - url: 'https://www.google.com' - }) + method: 'GET', + url: 'https://www.google.com' + }) urlRequest.on('response', function(response) { response_event_emitted = true; const statusCode = response.statusCode @@ -37,37 +184,37 @@ describe.only('net module', function() { body += buffer.toString() assert(typeof body === 'string') assert(body.length > 0) - }); + }); response.on('end', function() { end_event_emitted = true; - }) - }); + }) + }); urlRequest.on('finish', function() { finish_event_emitted = true; - }) + }) urlRequest.on('error', function(error) { assert.ifError(error); - }) + }) urlRequest.on('close', function() { assert(response_event_emitted) assert(data_event_emitted) assert(end_event_emitted) assert(finish_event_emitted) done() - }) + }) urlRequest.end(); - }) + }) - it ('should be able to post data', function(done) { + it ('should emit ClientRequest events in a POST request', function(done) { this.timeout(20000); let response_event_emitted = false; let data_event_emitted = false; let end_event_emitted = false; let finish_event_emitted = false; const urlRequest = net.request({ - method: 'POST', - url: 'http://httpbin.org/post' - }); + method: 'POST', + url: 'http://httpbin.org/post' + }); urlRequest.on('response', function(response) { response_event_emitted = true; const statusCode = response.statusCode @@ -93,54 +240,58 @@ describe.only('net module', function() { assert(end_event_emitted) assert(finish_event_emitted) done() - }) + }) response.on('data', function(buffer) { data_event_emitted = true; body += buffer.toString() assert(typeof body === 'string') assert(body.length > 0) - }); + }); - }); + }); urlRequest.on('finish', function() { finish_event_emitted = true; - }) + }) urlRequest.on('error', function(error) { assert.ifError(error); - }) + }) urlRequest.on('close', function() { - }) + }) for (let i = 0; i < 100; ++i) { urlRequest.write('Hello World!'); - } + } urlRequest.end(); - }) }) - describe('ClientRequest API', function() { + it ('should be able to set a custom HTTP header', function() { assert(false) - }) + }) it ('should be able to abort an HTTP request', function() { assert(false) - }) + }) it ('should be able to pipe into a request', function() { assert(false) - }) - it ('should be able to pipe from a response', function() { - assert(false) - }) + }) it ('should be able to create a request with options', function() { assert(false) - }) + }) it ('should be able to specify a custom session', function() { assert(false) - }) + }) it ('should support chunked encoding', function() { assert(false) - }) + }) + }) + describe('IncomingMessage API', function() { + it('should provide a Node.js-similar API', function() { + assert(false) + }) it ('should not emit any event after close', function() { assert(false) - }) }) -}) \ No newline at end of file + it ('should be able to pipe from a response', function() { + assert(false) + }) + }) + }) \ No newline at end of file From 4eb9fc1bb6581616b6192fe526418b6bcb10b358 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Fri, 7 Oct 2016 16:34:36 +0200 Subject: [PATCH 023/148] Adding chunked uploading test. --- lib/browser/api/net.js | 2 +- spec/api-net-spec.js | 366 +++++++++++++++++++++++++++-------------- 2 files changed, 248 insertions(+), 120 deletions(-) diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 9c9c57c202..6761abed19 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -264,7 +264,7 @@ class ClientRequest extends EventEmitter { // Since writing to the network is asynchronous, we conservatively // assume that request headers are written after delivering the first // buffer to the network IO thread. - if (!this._url_request.notStarted) { + if (this._url_request.notStarted) { this._url_request.setChunkedUpload(this.chunkedEncoding) } diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index 20bced19be..75bcb0f42f 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -4,7 +4,27 @@ const http = require('http') const url = require('url') const {net} = remote -describe.only('net module', function() { +function randomBuffer(size, start, end) { + start = start || 0 + end = end || 255 + let range = 1 + end - start + const buffer = Buffer.allocUnsafe(size) + for (let i = 0; i < size; ++i) { + buffer[i] = start + Math.floor(Math.random()*range) + } + return buffer; +} + +function randomString(length) { + let buffer = randomBuffer(length, '0'.charCodeAt(0), 'z'.charCodeAt(0)) + return buffer.toString(); +} + +const kOneKiloByte = 1024 +const kOneMegaByte = kOneKiloByte * kOneKiloByte + + +describe('net module', function() { this.timeout(0) describe('HTTP basics', function() { @@ -40,12 +60,13 @@ describe.only('net module', function() { const urlRequest = net.request(`${server.url}${request_url}`) urlRequest.on('response', function(response) { assert.equal(response.statusCode, 200) + response.pause() + response.on('data', function(chunk) { + }) response.on('end', function() { done() }) - response.on('data', function(chunk) { - - }) + response.resume() }) urlRequest.end(); }) @@ -70,12 +91,13 @@ describe.only('net module', function() { }) urlRequest.on('response', function(response) { assert.equal(response.statusCode, 200) + response.pause() + response.on('data', function(chunk) { + }) response.on('end', function() { done() }) - response.on('data', function(chunk) { - - }) + response.resume() }) urlRequest.end(); }) @@ -100,13 +122,15 @@ describe.only('net module', function() { urlRequest.on('response', function(response) { let expected_body_data = ''; assert.equal(response.statusCode, 200) + response.pause() + response.on('data', function(chunk) { + expected_body_data += chunk.toString(); + }) response.on('end', function() { assert.equal(expected_body_data, body_data) done() }) - response.on('data', function(chunk) { - expected_body_data += chunk.toString(); - }) + response.resume() }) urlRequest.end(); }) @@ -139,130 +163,237 @@ describe.only('net module', function() { }) urlRequest.on('response', function(response) { assert.equal(response.statusCode, 200) + response.pause() + response.on('data', function(chunk) { + }) response.on('end', function() { done() }) - response.on('data', function(chunk) { - }) + response.resume() }) urlRequest.write(body_data) urlRequest.end(); }) - }) - describe('ClientRequest API', function() { - it ('should emit ClientRequest events in a GET request', function(done) { - this.timeout(30000); - let response_event_emitted = false; - let data_event_emitted = false; - let end_event_emitted = false; - let finish_event_emitted = false; - const urlRequest = net.request({ - method: 'GET', - url: 'https://www.google.com' - }) - urlRequest.on('response', function(response) { - response_event_emitted = true; - const statusCode = response.statusCode - assert(typeof statusCode === 'number') - assert.equal(statusCode, 200) - const statusMessage = response.statusMessage - const rawHeaders = response.rawHeaders - assert(typeof rawHeaders === 'object') - const httpVersion = response.httpVersion; - assert(typeof httpVersion === 'string') - assert(httpVersion.length > 0) - const httpVersionMajor = response.httpVersionMajor; - assert(typeof httpVersionMajor === 'number') - assert(httpVersionMajor >= 1) - const httpVersionMinor = response.httpVersionMinor; - assert(typeof httpVersionMinor === 'number') - assert(httpVersionMinor >= 0) - let body = ''; - response.on('data', function(buffer) { - data_event_emitted = true; - body += buffer.toString() - assert(typeof body === 'string') - assert(body.length > 0) - }); - response.on('end', function() { - end_event_emitted = true; - }) - }); - urlRequest.on('finish', function() { - finish_event_emitted = true; - }) - urlRequest.on('error', function(error) { - assert.ifError(error); - }) - urlRequest.on('close', function() { - assert(response_event_emitted) - assert(data_event_emitted) - assert(end_event_emitted) - assert(finish_event_emitted) - done() - }) - urlRequest.end(); - }) + it.only('should support chunked encoding', function(done) { + const request_url = '/request_url' + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + response.statusCode = 200 + response.statusMessage = 'OK' + response.chunkedEncoding = true + assert.equal(request.method, 'POST') + assert.equal(request.headers['transfer-encoding'], 'chunked') + assert(!request.headers['content-length']) + request.on('data', function(chunk) { + response.write(chunk) + }) + request.on('end', function(chunk) { + response.end(chunk); + }) + break; + default: + response.statusCode = 501 + response.statusMessage = 'Not Implemented' + response.end() + } + }) + const urlRequest = net.request({ + method: 'POST', + url: `${server.url}${request_url}` + }) - it ('should emit ClientRequest events in a POST request', function(done) { - this.timeout(20000); - let response_event_emitted = false; - let data_event_emitted = false; - let end_event_emitted = false; - let finish_event_emitted = false; - const urlRequest = net.request({ - method: 'POST', - url: 'http://httpbin.org/post' - }); + let chunk_index = 0 + let chunk_count = 100 + let sent_chunks = []; + let received_chunks = []; urlRequest.on('response', function(response) { - response_event_emitted = true; - const statusCode = response.statusCode - assert(typeof statusCode === 'number') - assert.equal(statusCode, 200) - const statusMessage = response.statusMessage - const rawHeaders = response.rawHeaders - assert(typeof rawHeaders === 'object') - const httpVersion = response.httpVersion; - assert(typeof httpVersion === 'string') - assert(httpVersion.length > 0) - const httpVersionMajor = response.httpVersionMajor; - assert(typeof httpVersionMajor === 'number') - assert(httpVersionMajor >= 1) - const httpVersionMinor = response.httpVersionMinor; - assert(typeof httpVersionMinor === 'number') - assert(httpVersionMinor >= 0) - let body = ''; + assert.equal(response.statusCode, 200) + response.pause() + response.on('data', function(chunk) { + received_chunks.push(chunk) + }) response.on('end', function() { - end_event_emitted = true; - assert(response_event_emitted) - assert(data_event_emitted) - assert(end_event_emitted) - assert(finish_event_emitted) + let sent_data = Buffer.concat(sent_chunks) + let received_data = Buffer.concat(received_chunks) + assert.equal(sent_data.toString(), received_data.toString()) + assert.equal(chunk_index, chunk_count) done() + }) + response.resume() + }) + urlRequest.chunkedEncoding = true + while (chunk_index < chunk_count) { + ++chunk_index + let chunk = randomBuffer(kOneKiloByte) + sent_chunks.push(chunk) + assert(urlRequest.write(chunk)) + } + urlRequest.end(); + }) }) - response.on('data', function(buffer) { - data_event_emitted = true; - body += buffer.toString() - assert(typeof body === 'string') - assert(body.length > 0) - }); - }); + describe('ClientRequest API', function() { + + let server + beforeEach(function (done) { + server = http.createServer() + server.listen(0, '127.0.0.1', function () { + server.url = 'http://127.0.0.1:' + server.address().port + done() + }) + }) + + afterEach(function () { + server.close(function() { + }) + server = null + }) + + it ('response object should implement the IncomingMessage API', function(done) { + const request_url = '/request_url' + const custom_header_name = 'Some-Custom-Header-Name' + const custom_header_value = 'Some-Customer-Header-Value' + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + response.statusCode = 200 + response.statusMessage = 'OK' + response.setHeader(custom_header_name, custom_header_value) + response.end(); + break; + default: + response.statusCode = 501 + response.statusMessage = 'Not Implemented' + response.end() + } + }) + let response_event_emitted = false; + let data_event_emitted = false; + let end_event_emitted = false; + let finish_event_emitted = false; + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + response_event_emitted = true; + const statusCode = response.statusCode + assert(typeof statusCode === 'number') + assert.equal(statusCode, 200) + const statusMessage = response.statusMessage + assert(typeof statusMessage === 'string') + assert.equal(statusMessage, 'OK') + const rawHeaders = response.rawHeaders + assert(typeof rawHeaders === 'object') + assert(rawHeaders[custom_header_name] === + custom_header_value) + const httpVersion = response.httpVersion; + assert(typeof httpVersion === 'string') + assert(httpVersion.length > 0) + const httpVersionMajor = response.httpVersionMajor; + assert(typeof httpVersionMajor === 'number') + assert(httpVersionMajor >= 1) + const httpVersionMinor = response.httpVersionMinor; + assert(typeof httpVersionMinor === 'number') + assert(httpVersionMinor >= 0) + response.pause() + response.on('data', function(chunk) { + }); + response.on('end', function() { + done() + }) + response.resume() + }) + urlRequest.end(); + }) + + + + it('request/response objects should emit expected events', function(done) { + + const request_url = '/request_url' + let body_data = randomString(kOneMegaByte) + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + response.statusCode = 200 + response.statusMessage = 'OK' + response.write(body_data) + response.end(); + break; + default: + response.statusCode = 501 + response.statusMessage = 'Not Implemented' + response.end() + } + }) + + let request_response_event_emitted = false + let request_finish_event_emitted = false + let request_close_event_emitted = false + let response_data_event_emitted = false + let response_end_event_emitted = false + let response_close_event_emitted = false + + function maybeDone(done) { + if (!request_close_event_emitted || !response_end_event_emitted) { + return + } + + assert(request_response_event_emitted) + assert(request_finish_event_emitted) + assert(request_close_event_emitted) + assert(response_data_event_emitted) + assert(response_end_event_emitted) + done() + } + + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + request_response_event_emitted = true; + const statusCode = response.statusCode + assert.equal(statusCode, 200) + let buffers = []; + response.pause(); + response.on('data', function(chunk) { + buffers.push(chunk) + response_data_event_emitted = true + }) + response.on('end', function() { + let received_body_data = Buffer.concat(buffers); + assert(received_body_data.toString() === body_data) + response_end_event_emitted = true + maybeDone(done) + }) + response.resume(); + response.on('error', function(error) { + assert.ifError(error); + }) + response.on('aborted', function() { + assert(false) + }) + }) urlRequest.on('finish', function() { - finish_event_emitted = true; - }) + request_finish_event_emitted = true + }) urlRequest.on('error', function(error) { assert.ifError(error); - }) + }) + urlRequest.on('abort', function() { + assert(false); + }) urlRequest.on('close', function() { - - }) - for (let i = 0; i < 100; ++i) { - urlRequest.write('Hello World!'); - } + request_close_event_emitted = true + maybeDone(done) + }) urlRequest.end(); - }) + }) + it ('should be able to set a custom HTTP header', function() { assert(false) @@ -278,10 +409,7 @@ describe.only('net module', function() { }) it ('should be able to specify a custom session', function() { assert(false) - }) - it ('should support chunked encoding', function() { - assert(false) - }) + }) }) describe('IncomingMessage API', function() { it('should provide a Node.js-similar API', function() { From b731ca50bc49842a741e9c6c51f2d400ec368afd Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Mon, 10 Oct 2016 10:11:22 +0200 Subject: [PATCH 024/148] Adding HTTP request headers manipulation tests. --- atom/browser/api/atom_api_url_request.cc | 2 +- spec/api-net-spec.js | 198 +++++++++++++++++++++-- 2 files changed, 187 insertions(+), 13 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index e3d0f59929..bc11ecad52 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -91,7 +91,7 @@ URLRequest::StateBase::StateBase(Flags initialState) template void URLRequest::StateBase::SetFlag(Flags flag) { - state_ = static_cast(static_cast(state_) & + state_ = static_cast(static_cast(state_) | static_cast(flag)); } diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index 75bcb0f42f..8cba404a89 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -24,7 +24,7 @@ const kOneKiloByte = 1024 const kOneMegaByte = kOneKiloByte * kOneKiloByte -describe('net module', function() { +describe.only('net module', function() { this.timeout(0) describe('HTTP basics', function() { @@ -175,7 +175,7 @@ describe('net module', function() { urlRequest.end(); }) - it.only('should support chunked encoding', function(done) { + it('should support chunked encoding', function(done) { const request_url = '/request_url' server.on('request', function(request, response) { switch (request.url) { @@ -394,19 +394,193 @@ describe('net module', function() { urlRequest.end(); }) + it('should be able to set a custom HTTP request header before first write', function(done) { + const request_url = '/request_url' + const custom_header_name = 'Some-Custom-Header-Name' + const custom_header_value = 'Some-Customer-Header-Value' + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + assert.equal(request.headers[custom_header_name.toLowerCase()], + custom_header_value) + response.statusCode = 200 + response.statusMessage = 'OK' + response.end(); + break; + default: + response.statusCode = 501 + response.statusMessage = 'Not Implemented' + response.end() + } + }) + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + const statusCode = response.statusCode + assert.equal(statusCode, 200) + response.pause() + response.on('data', function(chunk) { + }); + response.on('end', function() { + done() + }) + response.resume() + }) + urlRequest.setHeader(custom_header_name, custom_header_value) + assert.equal(urlRequest.getHeader(custom_header_name), + custom_header_value) + assert.equal(urlRequest.getHeader(custom_header_name.toLowerCase()), + custom_header_value) + urlRequest.write(''); + assert.equal(urlRequest.getHeader(custom_header_name), + custom_header_value) + assert.equal(urlRequest.getHeader(custom_header_name.toLowerCase()), + custom_header_value) + urlRequest.end(); + }) + + it('should not be able to set a custom HTTP request header after first write', function(done) { + const request_url = '/request_url' + const custom_header_name = 'Some-Custom-Header-Name' + const custom_header_value = 'Some-Customer-Header-Value' + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + assert(!request.headers[custom_header_name.toLowerCase()]) + response.statusCode = 200 + response.statusMessage = 'OK' + response.end(); + break; + default: + response.statusCode = 501 + response.statusMessage = 'Not Implemented' + response.end() + } + }) + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + const statusCode = response.statusCode + assert.equal(statusCode, 200) + response.pause() + response.on('data', function(chunk) { + }); + response.on('end', function() { + done() + }) + response.resume() + }) + urlRequest.write(''); + assert.throws( () => { + urlRequest.setHeader(custom_header_name, custom_header_value) + }) + assert(!urlRequest.getHeader(custom_header_name)) + urlRequest.end(); + }) + + it('should be able to remove a custom HTTP request header before first write', function(done) { + const request_url = '/request_url' + const custom_header_name = 'Some-Custom-Header-Name' + const custom_header_value = 'Some-Customer-Header-Value' + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + assert(!request.headers[custom_header_name.toLowerCase()]) + response.statusCode = 200 + response.statusMessage = 'OK' + response.end(); + break; + default: + response.statusCode = 501 + response.statusMessage = 'Not Implemented' + response.end() + } + }) + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + const statusCode = response.statusCode + assert.equal(statusCode, 200) + response.pause() + response.on('data', function(chunk) { + }); + response.on('end', function() { + done() + }) + response.resume() + }) + urlRequest.setHeader(custom_header_name, custom_header_value) + assert.equal(urlRequest.getHeader(custom_header_name), + custom_header_value) + urlRequest.removeHeader(custom_header_name) + assert(!urlRequest.getHeader(custom_header_name)) + urlRequest.write(''); + urlRequest.end(); + }) + + it('should not be able to remove a custom HTTP request header after first write', function(done) { + const request_url = '/request_url' + const custom_header_name = 'Some-Custom-Header-Name' + const custom_header_value = 'Some-Customer-Header-Value' + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + assert.equal(request.headers[custom_header_name.toLowerCase()], + custom_header_value) + response.statusCode = 200 + response.statusMessage = 'OK' + response.end(); + break; + default: + response.statusCode = 501 + response.statusMessage = 'Not Implemented' + response.end() + } + }) + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + const statusCode = response.statusCode + assert.equal(statusCode, 200) + response.pause() + response.on('data', function(chunk) { + }); + response.on('end', function() { + done() + }) + response.resume() + }) + urlRequest.setHeader(custom_header_name, custom_header_value) + assert.equal(urlRequest.getHeader(custom_header_name), + custom_header_value) + urlRequest.write(''); + assert.throws(function() { + urlRequest.removeHeader(custom_header_name) + }) + assert.equal(urlRequest.getHeader(custom_header_name), + custom_header_value) + urlRequest.end(); + }) + + - it ('should be able to set a custom HTTP header', function() { - assert(false) - }) it ('should be able to abort an HTTP request', function() { assert(false) - }) + }) it ('should be able to pipe into a request', function() { assert(false) - }) + }) it ('should be able to create a request with options', function() { assert(false) - }) + }) it ('should be able to specify a custom session', function() { assert(false) }) @@ -414,12 +588,12 @@ describe('net module', function() { describe('IncomingMessage API', function() { it('should provide a Node.js-similar API', function() { assert(false) - }) + }) it ('should not emit any event after close', function() { assert(false) - }) + }) it ('should be able to pipe from a response', function() { assert(false) + }) }) - }) - }) \ No newline at end of file +}) \ No newline at end of file From a5c508d2d715c4f269d79603f566d3ed0dfc032d Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Mon, 10 Oct 2016 16:21:12 +0200 Subject: [PATCH 025/148] Adding abort, webRequest interception and creation tests. --- lib/browser/api/net.js | 22 ++- spec/api-net-spec.js | 416 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 387 insertions(+), 51 deletions(-) diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 6761abed19..36af3b08af 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -98,7 +98,7 @@ URLRequest.prototype._emitRequestEvent = function (async, ...rest) { URLRequest.prototype._emitResponseEvent = function (async, ...rest) { if (async) { process.nextTick(() => { - this._request.emit.apply(this._request, rest) + this._request.emit.apply(this._response, rest) }) } else { this._response.emit.apply(this._response, rest) @@ -141,6 +141,7 @@ class ClientRequest extends EventEmitter { } } + if (options.path && / /.test(options.path)) { // The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/ // with an additional rule for ignoring percentage-escaped characters @@ -149,10 +150,11 @@ class ClientRequest extends EventEmitter { // why it only scans for spaces because those are guaranteed to create // an invalid request. throw new TypeError('Request path contains unescaped characters.') - } - urlObj.pathname = options.pathname || '/' - urlObj.search = options.search - urlObj.hash = options.hash + } + let pathObj = url.parse(options.path || '/') + urlObj.pathname = pathObj.pathname + urlObj.search = pathObj.search + urlObj.hash = pathObj.hash urlStr = url.format(urlObj) } @@ -167,6 +169,11 @@ class ClientRequest extends EventEmitter { this._url_request = urlRequest urlRequest._request = this + // This is a copy of the extra headers structure held by the native + // net::URLRequest. The main reason is to keep the getHeader API synchronous + // after the request starts. + this._extra_headers = {} + if (options.headers) { const keys = Object.keys(options.headers) for (let i = 0, l = keys.length; i < l; i++) { @@ -179,11 +186,6 @@ class ClientRequest extends EventEmitter { // to true only once and never set back to false. this._chunkedEncoding = false - // This is a copy of the extra headers structure held by the native - // net::URLRequest. The main reason is to keep the getHeader API synchronous - // after the request starts. - this._extra_headers = {} - urlRequest.on('response', () => { const response = new IncomingMessage(urlRequest) urlRequest._response = response diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index 8cba404a89..9fe3623d78 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -3,6 +3,7 @@ const {remote} = require('electron') const http = require('http') const url = require('url') const {net} = remote +const {session} = remote function randomBuffer(size, start, end) { start = start || 0 @@ -24,7 +25,7 @@ const kOneKiloByte = 1024 const kOneMegaByte = kOneKiloByte * kOneKiloByte -describe.only('net module', function() { +describe('net module', function() { this.timeout(0) describe('HTTP basics', function() { @@ -52,9 +53,7 @@ describe.only('net module', function() { response.end(); break; default: - response.statusCode = 501 - response.statusMessage = 'Not Implemented' - response.end() + assert(false) } }) const urlRequest = net.request(`${server.url}${request_url}`) @@ -80,9 +79,7 @@ describe.only('net module', function() { response.end(); break; default: - response.statusCode = 501 - response.statusMessage = 'Not Implemented' - response.end() + assert(false) } }) const urlRequest = net.request({ @@ -113,9 +110,7 @@ describe.only('net module', function() { response.end(); break; default: - response.statusCode = 501 - response.statusMessage = 'Not Implemented' - response.end() + assert(false) } }) const urlRequest = net.request(`${server.url}${request_url}`) @@ -152,9 +147,7 @@ describe.only('net module', function() { }) break; default: - response.statusCode = 501 - response.statusMessage = 'Not Implemented' - response.end() + assert(false) } }) const urlRequest = net.request({ @@ -194,9 +187,7 @@ describe.only('net module', function() { }) break; default: - response.statusCode = 501 - response.statusMessage = 'Not Implemented' - response.end() + assert(false) } }) const urlRequest = net.request({ @@ -264,9 +255,7 @@ describe.only('net module', function() { response.end(); break; default: - response.statusCode = 501 - response.statusMessage = 'Not Implemented' - response.end() + assert(false) } }) let response_event_emitted = false; @@ -324,9 +313,7 @@ describe.only('net module', function() { response.end(); break; default: - response.statusCode = 501 - response.statusMessage = 'Not Implemented' - response.end() + assert(false) } }) @@ -408,9 +395,7 @@ describe.only('net module', function() { response.end(); break; default: - response.statusCode = 501 - response.statusMessage = 'Not Implemented' - response.end() + assert(false) } }) const urlRequest = net.request({ @@ -454,9 +439,7 @@ describe.only('net module', function() { response.end(); break; default: - response.statusCode = 501 - response.statusMessage = 'Not Implemented' - response.end() + assert(false) } }) const urlRequest = net.request({ @@ -495,9 +478,7 @@ describe.only('net module', function() { response.end(); break; default: - response.statusCode = 501 - response.statusMessage = 'Not Implemented' - response.end() + assert(false) } }) const urlRequest = net.request({ @@ -538,9 +519,7 @@ describe.only('net module', function() { response.end(); break; default: - response.statusCode = 501 - response.statusMessage = 'Not Implemented' - response.end() + assert(false) } }) const urlRequest = net.request({ @@ -570,20 +549,375 @@ describe.only('net module', function() { urlRequest.end(); }) + it('should be able to abort an HTTP request before first write', function() { + const request_url = '/request_url' + server.on('request', function(request, response) { + assert(false) + }) + + let request_abort_event_emitted = false + let request_close_event_emitted = false + + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + assert(false) + }) + urlRequest.on('finish', function() { + assert(false); + }) + urlRequest.on('error', function(error) { + assert(false); + }) + urlRequest.on('abort', function() { + request_abort_event_emitted = true + }) + urlRequest.on('close', function() { + request_close_event_emitted = true + assert(request_abort_event_emitted) + assert(request_close_event_emitted) + done(); + }) + urlRequest.abort() + assert(!urlRequest.write('')) + urlRequest.end(); + }) + + + it('it should be able to abort an HTTP request before request end', function(done) { + const request_url = '/request_url' + let request_received_by_server = false + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + request_received_by_server = true; + cancelRequest(); + break; + default: + assert(false) + } + }) + + let request_abort_event_emitted = false + let request_close_event_emitted = false + + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + assert(false) + }) + urlRequest.on('finish', function() { + assert(false) + }) + urlRequest.on('error', function(error) { + assert(false); + }) + urlRequest.on('abort', function() { + request_abort_event_emitted = true + }) + urlRequest.on('close', function() { + request_close_event_emitted = true + assert(request_received_by_server) + assert(request_abort_event_emitted) + assert(request_close_event_emitted) + done() + }) + + urlRequest.chunkedEncoding = true + urlRequest.write(randomString(kOneKiloByte)) + function cancelRequest() { + urlRequest.abort() + } + }) + + it('it should be able to abort an HTTP request after request end and before response', function(done) { + const request_url = '/request_url' + let request_received_by_server = false + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + request_received_by_server = true; + cancelRequest(); + process.nextTick( () => { + response.statusCode = 200 + response.statusMessage = 'OK' + response.end(); + }) + break; + default: + assert(false) + } + }) + + let request_abort_event_emitted = false + let request_finish_event_emitted = false + let request_close_event_emitted = false + + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + assert(false) + }) + urlRequest.on('finish', function() { + request_finish_event_emitted = true + }) + urlRequest.on('error', function(error) { + assert(false); + }) + urlRequest.on('abort', function() { + request_abort_event_emitted = true + }) + urlRequest.on('close', function() { + request_close_event_emitted = true + assert(request_finish_event_emitted) + assert(request_received_by_server) + assert(request_abort_event_emitted) + assert(request_close_event_emitted) + done() + }) + + urlRequest.end(randomString(kOneKiloByte)) + function cancelRequest() { + urlRequest.abort() + } + }) + + it('it should be able to abort an HTTP request after response start', function(done) { + const request_url = '/request_url' + let request_received_by_server = false + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + request_received_by_server = true; + response.statusCode = 200 + response.statusMessage = 'OK' + response.write(randomString(kOneKiloByte)) + break; + default: + assert(false) + } + }) + + let request_finish_event_emitted = false + let request_response_event_emitted = false + let request_abort_event_emitted = false + let request_close_event_emitted = false + let response_aborted_event_emitted = false - it ('should be able to abort an HTTP request', function() { + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + request_response_event_emitted = true + const statusCode = response.statusCode + assert.equal(statusCode, 200) + response.pause(); + response.on('data', function(chunk) { + }) + response.on('end', function() { + assert(false) + }) + response.resume(); + response.on('error', function(error) { + assert(false) + }) + response.on('aborted', function() { + response_aborted_event_emitted = true + }) + urlRequest.abort() + }) + urlRequest.on('finish', function() { + request_finish_event_emitted = true + }) + urlRequest.on('error', function(error) { + assert(false); + }) + urlRequest.on('abort', function() { + request_abort_event_emitted = true + }) + urlRequest.on('close', function() { + request_close_event_emitted = true + assert(request_finish_event_emitted, 'request should emit "finish" event') + assert(request_received_by_server, 'request should be received by the server') + assert(request_response_event_emitted, '"response" event should be emitted') + assert(request_abort_event_emitted, 'request should emit "abort" event') + assert(response_aborted_event_emitted, 'response should emit "aborted" event') + assert(request_close_event_emitted, 'request should emit "close" event') + done() + }) + urlRequest.end(randomString(kOneKiloByte)) + }) + + it('Requests should be intercepted by webRequest module', function(done) { + + const request_url = '/request_url' + const redirect_url = '/redirect_url' + let request_is_redirected = false; + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + assert(false) + break + case redirect_url: + request_is_redirected = true + response.end(); + break + default: + assert(false) + } + }) + + let request_is_intercepted = false + session.defaultSession.webRequest.onBeforeRequest( + function(details, callback){ + if (details.url === `${server.url}${request_url}`) { + request_is_intercepted = true + callback({ + redirectURL: `${server.url}${redirect_url}` + }) + } else { + callback( { + cancel: false + }) + } + }); + + const urlRequest = net.request(`${server.url}${request_url}`) + + urlRequest.on('response', function(response) { + assert.equal(response.statusCode, 200) + response.pause() + response.on('data', function(chunk) { + }) + response.on('end', function() { + assert(request_is_redirected, 'The server should receive a request to the forward URL') + assert(request_is_intercepted, 'The request should be intercepted by the webRequest module') + done() + }) + response.resume() + }) + urlRequest.end(); + }) + + it('should to able to create and intercept a request on a custom session', function(done) { + const request_url = '/request_url' + const redirect_url = '/redirect_url' + const custom_session_name = 'custom-session' + let request_is_redirected = false; + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + assert(false) + break + case redirect_url: + request_is_redirected = true + response.end(); + break + default: + assert(false) + } + }) + + session.defaultSession.webRequest.onBeforeRequest( + function(details, callback) { + assert(false, 'Request should not be intercepted by the default session') + }); + + let custom_session = session.fromPartition(custom_session_name, { + cache: false + }) + let request_is_intercepted = false + custom_session.webRequest.onBeforeRequest( + function(details, callback){ + if (details.url === `${server.url}${request_url}`) { + request_is_intercepted = true + callback({ + redirectURL: `${server.url}${redirect_url}` + }) + } else { + callback( { + cancel: false + }) + } + }); + + const urlRequest = net.request({ + url: `${server.url}${request_url}`, + session: custom_session_name + }) + urlRequest.on('response', function(response) { + assert.equal(response.statusCode, 200) + response.pause() + response.on('data', function(chunk) { + }) + response.on('end', function() { + assert(request_is_redirected, 'The server should receive a request to the forward URL') + assert(request_is_intercepted, 'The request should be intercepted by the webRequest module') + done() + }) + response.resume() + }) + urlRequest.end(); + }) + + it.only ('should be able to create a request with options', function() { + const request_url = '/' + const custom_header_name = 'Some-Custom-Header-Name' + const custom_header_value = 'Some-Customer-Header-Value' + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + assert.equal(request.method, 'GET') + assert.equal(request.headers[custom_header_name.toLowerCase()], + custom_header_value) + response.end(); + break; + default: + assert(false) + } + }) + + const server_url = url.parse(server.url) + let options = { + port: server_url.port, + headers: {} + } + options.headers[custom_header_name] = custom_header_value + const urlRequest = net.request(options) + urlRequest.on('response', function(response) { + assert.equal(response.statusCode, 200) + response.pause() + response.on('data', function(chunk) { + }) + response.on('end', function() { + done() + }) + response.resume() + }) + urlRequest.end(); + }) + + it('abort request should be emitted at most once', function() { assert(false) }) + + it('headers cannot be manipulated after abort', function() { + assert(false) + }) + it ('should be able to pipe into a request', function() { assert(false) }) - it ('should be able to create a request with options', function() { - assert(false) - }) - it ('should be able to specify a custom session', function() { - assert(false) - }) + + }) describe('IncomingMessage API', function() { it('should provide a Node.js-similar API', function() { From bd5e622bec4befd89f2235456a0f5c879f31a489 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 11 Oct 2016 15:25:26 +0200 Subject: [PATCH 026/148] Adding request/response piping tests. --- spec/api-net-spec.js | 299 ++++++++++++++++++++++++++++++++----------- 1 file changed, 227 insertions(+), 72 deletions(-) diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index 9fe3623d78..c5bf32505e 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -242,64 +242,6 @@ describe('net module', function() { server = null }) - it ('response object should implement the IncomingMessage API', function(done) { - const request_url = '/request_url' - const custom_header_name = 'Some-Custom-Header-Name' - const custom_header_value = 'Some-Customer-Header-Value' - server.on('request', function(request, response) { - switch (request.url) { - case request_url: - response.statusCode = 200 - response.statusMessage = 'OK' - response.setHeader(custom_header_name, custom_header_value) - response.end(); - break; - default: - assert(false) - } - }) - let response_event_emitted = false; - let data_event_emitted = false; - let end_event_emitted = false; - let finish_event_emitted = false; - const urlRequest = net.request({ - method: 'GET', - url: `${server.url}${request_url}` - }) - urlRequest.on('response', function(response) { - response_event_emitted = true; - const statusCode = response.statusCode - assert(typeof statusCode === 'number') - assert.equal(statusCode, 200) - const statusMessage = response.statusMessage - assert(typeof statusMessage === 'string') - assert.equal(statusMessage, 'OK') - const rawHeaders = response.rawHeaders - assert(typeof rawHeaders === 'object') - assert(rawHeaders[custom_header_name] === - custom_header_value) - const httpVersion = response.httpVersion; - assert(typeof httpVersion === 'string') - assert(httpVersion.length > 0) - const httpVersionMajor = response.httpVersionMajor; - assert(typeof httpVersionMajor === 'number') - assert(httpVersionMajor >= 1) - const httpVersionMinor = response.httpVersionMinor; - assert(typeof httpVersionMinor === 'number') - assert(httpVersionMinor >= 0) - response.pause() - response.on('data', function(chunk) { - }); - response.on('end', function() { - done() - }) - response.resume() - }) - urlRequest.end(); - }) - - - it('request/response objects should emit expected events', function(done) { const request_url = '/request_url' @@ -756,6 +698,60 @@ describe('net module', function() { urlRequest.end(randomString(kOneKiloByte)) }) + it('abort event should be emitted at most once', function(done) { + const request_url = '/request_url' + let request_received_by_server = false + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + request_received_by_server = true; + cancelRequest(); + break; + default: + assert(false) + } + }) + + let request_finish_event_emitted = false + let request_abort_event_count = 0 + let request_close_event_emitted = false + + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + assert(false) + }) + urlRequest.on('finish', function() { + request_finish_event_emitted = true + }) + urlRequest.on('error', function(error) { + assert(false); + }) + urlRequest.on('abort', function() { + ++request_abort_event_count + urlRequest.abort() + }) + urlRequest.on('close', function() { + request_close_event_emitted = true + // Let all pending async events to be emitted + setTimeout(function() { + assert(request_finish_event_emitted) + assert(request_received_by_server) + assert.equal(request_abort_event_count, 1) + assert(request_close_event_emitted) + done() + }, 500) + }) + + urlRequest.end(randomString(kOneKiloByte)) + function cancelRequest() { + urlRequest.abort() + urlRequest.abort() + } + }) + it('Requests should be intercepted by webRequest module', function(done) { const request_url = '/request_url' @@ -868,7 +864,7 @@ describe('net module', function() { urlRequest.end(); }) - it.only ('should be able to create a request with options', function() { + it('should be able to create a request with options', function() { const request_url = '/' const custom_header_name = 'Some-Custom-Header-Name' const custom_header_value = 'Some-Customer-Header-Value' @@ -905,29 +901,188 @@ describe('net module', function() { urlRequest.end(); }) - it('abort request should be emitted at most once', function() { - assert(false) - }) + it('should be able to pipe a readable stream into a net request', function(done) { + const node_request_url = '/node_request_url' + const net_request_url = '/net_request_url' + const body_data = randomString(kOneMegaByte) + let net_request_received = false + let net_request_ended = false + server.on('request', function(request, response) { + switch (request.url) { + case node_request_url: + response.write(body_data) + response.end(); + break; + case net_request_url: + net_request_received = true + let received_body_data = '' + request.on('data', function(chunk) { + received_body_data += chunk.toString() + }) + request.on('end', function(chunk) { + net_request_ended = true + if (chunk) { + received_body_data += chunk.toString() + } + assert.equal(received_body_data, body_data) + response.end() + }) + break; + default: + assert(false) + } + }) + + let nodeRequest = http.request(`${server.url}${node_request_url}`); + nodeRequest.on('response', function(nodeResponse) { + const netRequest = net.request(`${server.url}${net_request_url}`) + netRequest.on('response', function(netResponse) { + + assert.equal(netResponse.statusCode, 200) + netResponse.pause() + netResponse.on('data', function(chunk) { + }) + netResponse.on('end', function() { + assert(net_request_received) + assert(net_request_ended) + done() + }) + netResponse.resume() + }) + nodeResponse.pipe(netRequest) + }) + nodeRequest.end() + }) it('headers cannot be manipulated after abort', function() { assert(false) }) - - it ('should be able to pipe into a request', function() { - assert(false) - }) - - }) describe('IncomingMessage API', function() { - it('should provide a Node.js-similar API', function() { - assert(false) + + let server + beforeEach(function (done) { + server = http.createServer() + server.listen(0, '127.0.0.1', function () { + server.url = 'http://127.0.0.1:' + server.address().port + done() + }) }) + + afterEach(function () { + server.close(function() { + }) + server = null + }) + + it ('response object should implement the IncomingMessage API', function(done) { + const request_url = '/request_url' + const custom_header_name = 'Some-Custom-Header-Name' + const custom_header_value = 'Some-Customer-Header-Value' + server.on('request', function(request, response) { + switch (request.url) { + case request_url: + response.statusCode = 200 + response.statusMessage = 'OK' + response.setHeader(custom_header_name, custom_header_value) + response.end(); + break; + default: + assert(false) + } + }) + let response_event_emitted = false; + let data_event_emitted = false; + let end_event_emitted = false; + let finish_event_emitted = false; + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${request_url}` + }) + urlRequest.on('response', function(response) { + response_event_emitted = true; + const statusCode = response.statusCode + assert(typeof statusCode === 'number') + assert.equal(statusCode, 200) + const statusMessage = response.statusMessage + assert(typeof statusMessage === 'string') + assert.equal(statusMessage, 'OK') + const rawHeaders = response.rawHeaders + assert(typeof rawHeaders === 'object') + assert(rawHeaders[custom_header_name] === + custom_header_value) + const httpVersion = response.httpVersion; + assert(typeof httpVersion === 'string') + assert(httpVersion.length > 0) + const httpVersionMajor = response.httpVersionMajor; + assert(typeof httpVersionMajor === 'number') + assert(httpVersionMajor >= 1) + const httpVersionMinor = response.httpVersionMinor; + assert(typeof httpVersionMinor === 'number') + assert(httpVersionMinor >= 0) + response.pause() + response.on('data', function(chunk) { + }); + response.on('end', function() { + done() + }) + response.resume() + }) + urlRequest.end(); + }) + it ('should not emit any event after close', function() { assert(false) }) - it ('should be able to pipe from a response', function() { - assert(false) + + it.only('should be able to net response into a writable stream', function() { + const node_request_url = '/node_request_url' + const net_request_url = '/net_request_url' + const body_data = randomString(kOneMegaByte) + let node_request_received = false + let node_request_ended = false + server.on('request', function(request, response) { + switch (request.url) { + case net_request_url: + response.write(body_data) + response.end(); + break; + case node_request_url: + node_request_received = true + let received_body_data = '' + request.on('data', function(chunk) { + received_body_data += chunk.toString() + }) + request.on('end', function(chunk) { + node_request_ended = true + if (chunk) { + received_body_data += chunk.toString() + } + assert.equal(received_body_data, body_data) + response.end() + }) + break; + default: + assert(false) + } + }) + const netRequest = net.request(`${server.url}${net_request_url}`) + netRequest.on('response', function(netResponse) { + assert.equal(netResponse.statusCode, 200) + let nodeRequest = http.request(`${server.url}${node_request_url}`); + nodeRequest.on('response', function(nodeResponse) { + nodeResponse.on('data', function(chunk) { + + }) + nodeResponse.on('end', function(chunk) { + assert(node_request_received) + assert(node_request_ended) + done() + }) + }) + netResponse.pipe(nodeRequest) + }) + netRequest.end() }) }) }) \ No newline at end of file From d21def7b8db62b1996305de658b0aa1c713a0099 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 11 Oct 2016 19:16:23 +0200 Subject: [PATCH 027/148] Fixing various issues in tests. --- spec/api-net-spec.js | 45 ++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index c5bf32505e..c0fa0f4b95 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -240,6 +240,7 @@ describe('net module', function() { server.close(function() { }) server = null + session.defaultSession.webRequest.onBeforeRequest(null) }) it('request/response objects should emit expected events', function(done) { @@ -491,7 +492,7 @@ describe('net module', function() { urlRequest.end(); }) - it('should be able to abort an HTTP request before first write', function() { + it('should be able to abort an HTTP request before first write', function(done) { const request_url = '/request_url' server.on('request', function(request, response) { assert(false) @@ -864,7 +865,7 @@ describe('net module', function() { urlRequest.end(); }) - it('should be able to create a request with options', function() { + it('should be able to create a request with options', function(done) { const request_url = '/' const custom_header_name = 'Some-Custom-Header-Name' const custom_header_value = 'Some-Customer-Header-Value' @@ -874,6 +875,8 @@ describe('net module', function() { assert.equal(request.method, 'GET') assert.equal(request.headers[custom_header_name.toLowerCase()], custom_header_value) + response.statusCode = 200 + response.statusMessage = 'OK' response.end(); break; default: @@ -881,9 +884,10 @@ describe('net module', function() { } }) - const server_url = url.parse(server.url) + const serverUrl = url.parse(server.url) let options = { - port: server_url.port, + port: serverUrl.port, + hostname: '127.0.0.1', headers: {} } options.headers[custom_header_name] = custom_header_value @@ -954,13 +958,14 @@ describe('net module', function() { }) nodeRequest.end() }) - it('headers cannot be manipulated after abort', function() { + + it.skip('should emit error event on server socket close', function(done) { assert(false) }) }) describe('IncomingMessage API', function() { - let server + let server beforeEach(function (done) { server = http.createServer() server.listen(0, '127.0.0.1', function () { @@ -970,8 +975,7 @@ describe('net module', function() { }) afterEach(function () { - server.close(function() { - }) + server.close() server = null }) @@ -1031,11 +1035,7 @@ describe('net module', function() { urlRequest.end(); }) - it ('should not emit any event after close', function() { - assert(false) - }) - - it.only('should be able to net response into a writable stream', function() { + it.skip('should be able to pipe a net response into a writable stream', function(done) { const node_request_url = '/node_request_url' const net_request_url = '/net_request_url' const body_data = randomString(kOneMegaByte) @@ -1044,6 +1044,8 @@ describe('net module', function() { server.on('request', function(request, response) { switch (request.url) { case net_request_url: + response.statusCode = 200 + response.statusMessage = 'OK' response.write(body_data) response.end(); break; @@ -1066,13 +1068,20 @@ describe('net module', function() { assert(false) } }) - const netRequest = net.request(`${server.url}${net_request_url}`) + + netRequest = net.request(`${server.url}${net_request_url}`); netRequest.on('response', function(netResponse) { assert.equal(netResponse.statusCode, 200) - let nodeRequest = http.request(`${server.url}${node_request_url}`); + const serverUrl = url.parse(server.url) + const nodeOptions = { + method: 'POST', + path: node_request_url, + port: serverUrl.port + } + let nodeRequest = http.request(nodeOptions); + nodeRequest.on('response', function(nodeResponse) { nodeResponse.on('data', function(chunk) { - }) nodeResponse.on('end', function(chunk) { assert(node_request_received) @@ -1084,5 +1093,9 @@ describe('net module', function() { }) netRequest.end() }) + + it.skip('should not emit any event after close', function() { + assert(false) + }) }) }) \ No newline at end of file From ae1c33b863d0509017a5a7e4e533f34aed62ec45 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 12 Oct 2016 12:29:25 +0200 Subject: [PATCH 028/148] fixing linter issues. --- atom/browser/api/atom_api_url_request.cc | 2 +- lib/browser/api/net.js | 27 +- spec/api-net-spec.js | 1100 +++++++++++----------- 3 files changed, 556 insertions(+), 573 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index bc11ecad52..1bcf44eeb6 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -334,7 +334,7 @@ void URLRequest::OnAuthenticationRequired( if (!atom_request_) { return; } - + EmitRequestEvent( false, "login", diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 36af3b08af..02a3f3a164 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -19,8 +19,8 @@ class IncomingMessage extends Readable { constructor (urlRequest) { super() this._url_request = urlRequest - this._shouldPush = false; - this._data = []; + this._shouldPush = false + this._data = [] this._url_request.on('data', (event, chunk) => { this._storeInternalData(chunk) this._pushInternalData() @@ -59,26 +59,26 @@ class IncomingMessage extends Readable { return this._url_request.rawResponseHeaders } - get rawTrailers() { - throw (new Error('HTTP trailers are not supported.')) + get rawTrailers () { + throw new Error('HTTP trailers are not supported.') } - get trailers() { - throw (new Error('HTTP trailers are not supported.')) + get trailers () { + throw new Error('HTTP trailers are not supported.') } - _storeInternalData(chunk) { + _storeInternalData (chunk) { this._data.push(chunk) } - _pushInternalData() { + _pushInternalData () { while (this._shouldPush && this._data.length > 0) { - const chunk = this._data.shift() - this._shouldPush = this.push(chunk) + const chunk = this._data.shift() + this._shouldPush = this.push(chunk) } } - _read() { + _read () { this._shouldPush = true this._pushInternalData() } @@ -141,7 +141,6 @@ class ClientRequest extends EventEmitter { } } - if (options.path && / /.test(options.path)) { // The actual regex is more like /[^A-Za-z0-9\-._~!$&'()*+,;=/:@]/ // with an additional rule for ignoring percentage-escaped characters @@ -150,9 +149,9 @@ class ClientRequest extends EventEmitter { // why it only scans for spaces because those are guaranteed to create // an invalid request. throw new TypeError('Request path contains unescaped characters.') - } + } let pathObj = url.parse(options.path || '/') - urlObj.pathname = pathObj.pathname + urlObj.pathname = pathObj.pathname urlObj.search = pathObj.search urlObj.hash = pathObj.hash urlStr = url.format(urlObj) diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index c0fa0f4b95..bb7f866c59 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -5,30 +5,28 @@ const url = require('url') const {net} = remote const {session} = remote -function randomBuffer(size, start, end) { +function randomBuffer (size, start, end) { start = start || 0 end = end || 255 let range = 1 + end - start const buffer = Buffer.allocUnsafe(size) for (let i = 0; i < size; ++i) { - buffer[i] = start + Math.floor(Math.random()*range) + buffer[i] = start + Math.floor(Math.random() * range) } - return buffer; + return buffer } -function randomString(length) { +function randomString (length) { let buffer = randomBuffer(length, '0'.charCodeAt(0), 'z'.charCodeAt(0)) - return buffer.toString(); + return buffer.toString() } const kOneKiloByte = 1024 const kOneMegaByte = kOneKiloByte * kOneKiloByte - -describe('net module', function() { +describe('net module', function () { this.timeout(0) - describe('HTTP basics', function() { - + describe('HTTP basics', function () { let server beforeEach(function (done) { server = http.createServer() @@ -39,194 +37,193 @@ describe('net module', function() { }) afterEach(function () { - server.close(function() { + server.close(function () { }) server = null }) - it('should be able to issue a basic GET request', function(done) { - const request_url = '/request_url' - server.on('request', function(request, response) { + it('should be able to issue a basic GET request', function (done) { + const requestUrl = '/requestUrl' + server.on('request', function (request, response) { switch (request.url) { - case request_url: + case requestUrl: assert.equal(request.method, 'GET') - response.end(); - break; + response.end() + break default: assert(false) } }) - const urlRequest = net.request(`${server.url}${request_url}`) - urlRequest.on('response', function(response) { + const urlRequest = net.request(`${server.url}${requestUrl}`) + urlRequest.on('response', function (response) { assert.equal(response.statusCode, 200) response.pause() - response.on('data', function(chunk) { + response.on('data', function (chunk) { }) - response.on('end', function() { + response.on('end', function () { done() }) response.resume() }) - urlRequest.end(); + urlRequest.end() }) - it('should be able to issue a basic POST request', function(done) { - const request_url = '/request_url' - server.on('request', function(request, response) { + it('should be able to issue a basic POST request', function (done) { + const requestUrl = '/requestUrl' + server.on('request', function (request, response) { switch (request.url) { - case request_url: + case requestUrl: assert.equal(request.method, 'POST') - response.end(); - break; + response.end() + break default: assert(false) } }) const urlRequest = net.request({ method: 'POST', - url: `${server.url}${request_url}` + url: `${server.url}${requestUrl}` }) - urlRequest.on('response', function(response) { + urlRequest.on('response', function (response) { assert.equal(response.statusCode, 200) response.pause() - response.on('data', function(chunk) { + response.on('data', function (chunk) { }) - response.on('end', function() { + response.on('end', function () { done() }) response.resume() }) - urlRequest.end(); + urlRequest.end() }) - it('should fetch correct data in a GET request', function(done) { - const request_url = '/request_url' - const body_data = "Hello World!" - server.on('request', function(request, response) { + it('should fetch correct data in a GET request', function (done) { + const requestUrl = '/requestUrl' + const bodyData = 'Hello World!' + server.on('request', function (request, response) { switch (request.url) { - case request_url: + case requestUrl: assert.equal(request.method, 'GET') - response.write(body_data) - response.end(); - break; + response.write(bodyData) + response.end() + break default: assert(false) } }) - const urlRequest = net.request(`${server.url}${request_url}`) - urlRequest.on('response', function(response) { - let expected_body_data = ''; + const urlRequest = net.request(`${server.url}${requestUrl}`) + urlRequest.on('response', function (response) { + let expectedBodyData = '' assert.equal(response.statusCode, 200) response.pause() - response.on('data', function(chunk) { - expected_body_data += chunk.toString(); + response.on('data', function (chunk) { + expectedBodyData += chunk.toString() }) - response.on('end', function() { - assert.equal(expected_body_data, body_data) + response.on('end', function () { + assert.equal(expectedBodyData, bodyData) done() }) response.resume() }) - urlRequest.end(); + urlRequest.end() }) - it('should post the correct data in a POST request', function(done) { - const request_url = '/request_url' - const body_data = "Hello World!" - server.on('request', function(request, response) { - let posted_body_data = '' + it('should post the correct data in a POST request', function (done) { + const requestUrl = '/requestUrl' + const bodyData = 'Hello World!' + server.on('request', function (request, response) { + let postedBodyData = '' switch (request.url) { - case request_url: + case requestUrl: assert.equal(request.method, 'POST') - request.on('data', function(chunk) { - posted_body_data += chunk.toString() + request.on('data', function (chunk) { + postedBodyData += chunk.toString() }) - request.on('end', function() { - assert.equal(posted_body_data, body_data) - response.end(); + request.on('end', function () { + assert.equal(postedBodyData, bodyData) + response.end() }) - break; + break default: assert(false) } }) const urlRequest = net.request({ method: 'POST', - url: `${server.url}${request_url}` + url: `${server.url}${requestUrl}` }) - urlRequest.on('response', function(response) { + urlRequest.on('response', function (response) { assert.equal(response.statusCode, 200) response.pause() - response.on('data', function(chunk) { + response.on('data', function (chunk) { }) - response.on('end', function() { + response.on('end', function () { done() }) response.resume() }) - urlRequest.write(body_data) - urlRequest.end(); + urlRequest.write(bodyData) + urlRequest.end() }) - it('should support chunked encoding', function(done) { - const request_url = '/request_url' - server.on('request', function(request, response) { + it('should support chunked encoding', function (done) { + const requestUrl = '/requestUrl' + server.on('request', function (request, response) { switch (request.url) { - case request_url: + case requestUrl: response.statusCode = 200 response.statusMessage = 'OK' response.chunkedEncoding = true assert.equal(request.method, 'POST') assert.equal(request.headers['transfer-encoding'], 'chunked') assert(!request.headers['content-length']) - request.on('data', function(chunk) { + request.on('data', function (chunk) { response.write(chunk) }) - request.on('end', function(chunk) { - response.end(chunk); + request.on('end', function (chunk) { + response.end(chunk) }) - break; + break default: assert(false) } }) const urlRequest = net.request({ method: 'POST', - url: `${server.url}${request_url}` + url: `${server.url}${requestUrl}` }) - let chunk_index = 0 - let chunk_count = 100 - let sent_chunks = []; - let received_chunks = []; - urlRequest.on('response', function(response) { + let chunkIndex = 0 + let chunkCount = 100 + let sentChunks = [] + let receivedChunks = [] + urlRequest.on('response', function (response) { assert.equal(response.statusCode, 200) response.pause() - response.on('data', function(chunk) { - received_chunks.push(chunk) + response.on('data', function (chunk) { + receivedChunks.push(chunk) }) - response.on('end', function() { - let sent_data = Buffer.concat(sent_chunks) - let received_data = Buffer.concat(received_chunks) - assert.equal(sent_data.toString(), received_data.toString()) - assert.equal(chunk_index, chunk_count) + response.on('end', function () { + let sentData = Buffer.concat(sentChunks) + let receivedData = Buffer.concat(receivedChunks) + assert.equal(sentData.toString(), receivedData.toString()) + assert.equal(chunkIndex, chunkCount) done() }) response.resume() }) urlRequest.chunkedEncoding = true - while (chunk_index < chunk_count) { - ++chunk_index + while (chunkIndex < chunkCount) { + ++chunkIndex let chunk = randomBuffer(kOneKiloByte) - sent_chunks.push(chunk) + sentChunks.push(chunk) assert(urlRequest.write(chunk)) } - urlRequest.end(); + urlRequest.end() }) }) - describe('ClientRequest API', function() { - + describe('ClientRequest API', function () { let server beforeEach(function (done) { server = http.createServer() @@ -237,586 +234,581 @@ describe('net module', function() { }) afterEach(function () { - server.close(function() { + server.close(function () { }) server = null session.defaultSession.webRequest.onBeforeRequest(null) }) - it('request/response objects should emit expected events', function(done) { - - const request_url = '/request_url' - let body_data = randomString(kOneMegaByte) - server.on('request', function(request, response) { + it('request/response objects should emit expected events', function (done) { + const requestUrl = '/requestUrl' + let bodyData = randomString(kOneMegaByte) + server.on('request', function (request, response) { switch (request.url) { - case request_url: + case requestUrl: response.statusCode = 200 response.statusMessage = 'OK' - response.write(body_data) - response.end(); - break; + response.write(bodyData) + response.end() + break default: assert(false) } }) - let request_response_event_emitted = false - let request_finish_event_emitted = false - let request_close_event_emitted = false - let response_data_event_emitted = false - let response_end_event_emitted = false - let response_close_event_emitted = false + let requestResponseEventEmitted = false + let requestFinishEventEmitted = false + let requestCloseEventEmitted = false + let responseDataEventEmitted = false + let responseEndEventEmitted = false - function maybeDone(done) { - if (!request_close_event_emitted || !response_end_event_emitted) { + function maybeDone (done) { + if (!requestCloseEventEmitted || !responseEndEventEmitted) { return } - assert(request_response_event_emitted) - assert(request_finish_event_emitted) - assert(request_close_event_emitted) - assert(response_data_event_emitted) - assert(response_end_event_emitted) + assert(requestResponseEventEmitted) + assert(requestFinishEventEmitted) + assert(requestCloseEventEmitted) + assert(responseDataEventEmitted) + assert(responseEndEventEmitted) done() } - const urlRequest = net.request({ + const urlRequest = net.request({ method: 'GET', - url: `${server.url}${request_url}` + url: `${server.url}${requestUrl}` }) - urlRequest.on('response', function(response) { - request_response_event_emitted = true; + urlRequest.on('response', function (response) { + requestResponseEventEmitted = true const statusCode = response.statusCode assert.equal(statusCode, 200) - let buffers = []; - response.pause(); - response.on('data', function(chunk) { + let buffers = [] + response.pause() + response.on('data', function (chunk) { buffers.push(chunk) - response_data_event_emitted = true + responseDataEventEmitted = true }) - response.on('end', function() { - let received_body_data = Buffer.concat(buffers); - assert(received_body_data.toString() === body_data) - response_end_event_emitted = true + response.on('end', function () { + let receivedBodyData = Buffer.concat(buffers) + assert(receivedBodyData.toString() === bodyData) + responseEndEventEmitted = true maybeDone(done) }) - response.resume(); - response.on('error', function(error) { - assert.ifError(error); + response.resume() + response.on('error', function (error) { + assert.ifError(error) }) - response.on('aborted', function() { + response.on('aborted', function () { assert(false) }) }) - urlRequest.on('finish', function() { - request_finish_event_emitted = true + urlRequest.on('finish', function () { + requestFinishEventEmitted = true }) - urlRequest.on('error', function(error) { - assert.ifError(error); + urlRequest.on('error', function (error) { + assert.ifError(error) }) - urlRequest.on('abort', function() { - assert(false); + urlRequest.on('abort', function () { + assert(false) }) - urlRequest.on('close', function() { - request_close_event_emitted = true + urlRequest.on('close', function () { + requestCloseEventEmitted = true maybeDone(done) }) - urlRequest.end(); + urlRequest.end() }) - it('should be able to set a custom HTTP request header before first write', function(done) { - const request_url = '/request_url' - const custom_header_name = 'Some-Custom-Header-Name' - const custom_header_value = 'Some-Customer-Header-Value' - server.on('request', function(request, response) { + it('should be able to set a custom HTTP request header before first write', function (done) { + const requestUrl = '/requestUrl' + const customHeaderName = 'Some-Custom-Header-Name' + const customHeaderValue = 'Some-Customer-Header-Value' + server.on('request', function (request, response) { switch (request.url) { - case request_url: - assert.equal(request.headers[custom_header_name.toLowerCase()], - custom_header_value) + case requestUrl: + assert.equal(request.headers[customHeaderName.toLowerCase()], + customHeaderValue) response.statusCode = 200 response.statusMessage = 'OK' - response.end(); - break; + response.end() + break default: assert(false) } }) - const urlRequest = net.request({ + const urlRequest = net.request({ method: 'GET', - url: `${server.url}${request_url}` + url: `${server.url}${requestUrl}` }) - urlRequest.on('response', function(response) { + urlRequest.on('response', function (response) { const statusCode = response.statusCode assert.equal(statusCode, 200) response.pause() - response.on('data', function(chunk) { - }); - response.on('end', function() { + response.on('data', function (chunk) { + }) + response.on('end', function () { done() }) response.resume() }) - urlRequest.setHeader(custom_header_name, custom_header_value) - assert.equal(urlRequest.getHeader(custom_header_name), - custom_header_value) - assert.equal(urlRequest.getHeader(custom_header_name.toLowerCase()), - custom_header_value) - urlRequest.write(''); - assert.equal(urlRequest.getHeader(custom_header_name), - custom_header_value) - assert.equal(urlRequest.getHeader(custom_header_name.toLowerCase()), - custom_header_value) - urlRequest.end(); + urlRequest.setHeader(customHeaderName, customHeaderValue) + assert.equal(urlRequest.getHeader(customHeaderName), + customHeaderValue) + assert.equal(urlRequest.getHeader(customHeaderName.toLowerCase()), + customHeaderValue) + urlRequest.write('') + assert.equal(urlRequest.getHeader(customHeaderName), + customHeaderValue) + assert.equal(urlRequest.getHeader(customHeaderName.toLowerCase()), + customHeaderValue) + urlRequest.end() }) - it('should not be able to set a custom HTTP request header after first write', function(done) { - const request_url = '/request_url' - const custom_header_name = 'Some-Custom-Header-Name' - const custom_header_value = 'Some-Customer-Header-Value' - server.on('request', function(request, response) { + it('should not be able to set a custom HTTP request header after first write', function (done) { + const requestUrl = '/requestUrl' + const customHeaderName = 'Some-Custom-Header-Name' + const customHeaderValue = 'Some-Customer-Header-Value' + server.on('request', function (request, response) { switch (request.url) { - case request_url: - assert(!request.headers[custom_header_name.toLowerCase()]) + case requestUrl: + assert(!request.headers[customHeaderName.toLowerCase()]) response.statusCode = 200 response.statusMessage = 'OK' - response.end(); - break; + response.end() + break default: assert(false) } }) - const urlRequest = net.request({ + const urlRequest = net.request({ method: 'GET', - url: `${server.url}${request_url}` + url: `${server.url}${requestUrl}` }) - urlRequest.on('response', function(response) { + urlRequest.on('response', function (response) { const statusCode = response.statusCode assert.equal(statusCode, 200) response.pause() - response.on('data', function(chunk) { - }); - response.on('end', function() { + response.on('data', function (chunk) { + }) + response.on('end', function () { done() }) response.resume() }) - urlRequest.write(''); - assert.throws( () => { - urlRequest.setHeader(custom_header_name, custom_header_value) + urlRequest.write('') + assert.throws(() => { + urlRequest.setHeader(customHeaderName, customHeaderValue) }) - assert(!urlRequest.getHeader(custom_header_name)) - urlRequest.end(); + assert(!urlRequest.getHeader(customHeaderName)) + urlRequest.end() }) - it('should be able to remove a custom HTTP request header before first write', function(done) { - const request_url = '/request_url' - const custom_header_name = 'Some-Custom-Header-Name' - const custom_header_value = 'Some-Customer-Header-Value' - server.on('request', function(request, response) { + it('should be able to remove a custom HTTP request header before first write', function (done) { + const requestUrl = '/requestUrl' + const customHeaderName = 'Some-Custom-Header-Name' + const customHeaderValue = 'Some-Customer-Header-Value' + server.on('request', function (request, response) { switch (request.url) { - case request_url: - assert(!request.headers[custom_header_name.toLowerCase()]) + case requestUrl: + assert(!request.headers[customHeaderName.toLowerCase()]) response.statusCode = 200 response.statusMessage = 'OK' - response.end(); - break; - default: - assert(false) - } - }) - const urlRequest = net.request({ - method: 'GET', - url: `${server.url}${request_url}` - }) - urlRequest.on('response', function(response) { - const statusCode = response.statusCode - assert.equal(statusCode, 200) - response.pause() - response.on('data', function(chunk) { - }); - response.on('end', function() { - done() - }) - response.resume() - }) - urlRequest.setHeader(custom_header_name, custom_header_value) - assert.equal(urlRequest.getHeader(custom_header_name), - custom_header_value) - urlRequest.removeHeader(custom_header_name) - assert(!urlRequest.getHeader(custom_header_name)) - urlRequest.write(''); - urlRequest.end(); - }) - - it('should not be able to remove a custom HTTP request header after first write', function(done) { - const request_url = '/request_url' - const custom_header_name = 'Some-Custom-Header-Name' - const custom_header_value = 'Some-Customer-Header-Value' - server.on('request', function(request, response) { - switch (request.url) { - case request_url: - assert.equal(request.headers[custom_header_name.toLowerCase()], - custom_header_value) - response.statusCode = 200 - response.statusMessage = 'OK' - response.end(); - break; + response.end() + break default: assert(false) } }) - const urlRequest = net.request({ + const urlRequest = net.request({ method: 'GET', - url: `${server.url}${request_url}` + url: `${server.url}${requestUrl}` }) - urlRequest.on('response', function(response) { + urlRequest.on('response', function (response) { const statusCode = response.statusCode assert.equal(statusCode, 200) response.pause() - response.on('data', function(chunk) { - }); - response.on('end', function() { + response.on('data', function (chunk) { + }) + response.on('end', function () { done() }) response.resume() }) - urlRequest.setHeader(custom_header_name, custom_header_value) - assert.equal(urlRequest.getHeader(custom_header_name), - custom_header_value) - urlRequest.write(''); - assert.throws(function() { - urlRequest.removeHeader(custom_header_name) - }) - assert.equal(urlRequest.getHeader(custom_header_name), - custom_header_value) - urlRequest.end(); + urlRequest.setHeader(customHeaderName, customHeaderValue) + assert.equal(urlRequest.getHeader(customHeaderName), + customHeaderValue) + urlRequest.removeHeader(customHeaderName) + assert(!urlRequest.getHeader(customHeaderName)) + urlRequest.write('') + urlRequest.end() }) - it('should be able to abort an HTTP request before first write', function(done) { - const request_url = '/request_url' - server.on('request', function(request, response) { + it('should not be able to remove a custom HTTP request header after first write', function (done) { + const requestUrl = '/requestUrl' + const customHeaderName = 'Some-Custom-Header-Name' + const customHeaderValue = 'Some-Customer-Header-Value' + server.on('request', function (request, response) { + switch (request.url) { + case requestUrl: + assert.equal(request.headers[customHeaderName.toLowerCase()], + customHeaderValue) + response.statusCode = 200 + response.statusMessage = 'OK' + response.end() + break + default: + assert(false) + } + }) + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${requestUrl}` + }) + urlRequest.on('response', function (response) { + const statusCode = response.statusCode + assert.equal(statusCode, 200) + response.pause() + response.on('data', function (chunk) { + }) + response.on('end', function () { + done() + }) + response.resume() + }) + urlRequest.setHeader(customHeaderName, customHeaderValue) + assert.equal(urlRequest.getHeader(customHeaderName), + customHeaderValue) + urlRequest.write('') + assert.throws(function () { + urlRequest.removeHeader(customHeaderName) + }) + assert.equal(urlRequest.getHeader(customHeaderName), + customHeaderValue) + urlRequest.end() + }) + + it('should be able to abort an HTTP request before first write', function (done) { + const requestUrl = '/requestUrl' + server.on('request', function (request, response) { assert(false) }) - let request_abort_event_emitted = false - let request_close_event_emitted = false + let requestAbortEventEmitted = false + let requestCloseEventEmitted = false - const urlRequest = net.request({ + const urlRequest = net.request({ method: 'GET', - url: `${server.url}${request_url}` + url: `${server.url}${requestUrl}` }) - urlRequest.on('response', function(response) { + urlRequest.on('response', function (response) { assert(false) }) - urlRequest.on('finish', function() { - assert(false); + urlRequest.on('finish', function () { + assert(false) }) - urlRequest.on('error', function(error) { - assert(false); + urlRequest.on('error', function () { + assert(false) }) - urlRequest.on('abort', function() { - request_abort_event_emitted = true + urlRequest.on('abort', function () { + requestAbortEventEmitted = true }) - urlRequest.on('close', function() { - request_close_event_emitted = true - assert(request_abort_event_emitted) - assert(request_close_event_emitted) - done(); + urlRequest.on('close', function () { + requestCloseEventEmitted = true + assert(requestAbortEventEmitted) + assert(requestCloseEventEmitted) + done() }) urlRequest.abort() assert(!urlRequest.write('')) - urlRequest.end(); + urlRequest.end() }) - - it('it should be able to abort an HTTP request before request end', function(done) { - const request_url = '/request_url' - let request_received_by_server = false - server.on('request', function(request, response) { + it('it should be able to abort an HTTP request before request end', function (done) { + const requestUrl = '/requestUrl' + let requestReceivedByServer = false + server.on('request', function (request, response) { switch (request.url) { - case request_url: - request_received_by_server = true; - cancelRequest(); - break; + case requestUrl: + requestReceivedByServer = true + cancelRequest() + break default: assert(false) } }) - let request_abort_event_emitted = false - let request_close_event_emitted = false + let requestAbortEventEmitted = false + let requestCloseEventEmitted = false - const urlRequest = net.request({ + const urlRequest = net.request({ method: 'GET', - url: `${server.url}${request_url}` + url: `${server.url}${requestUrl}` }) - urlRequest.on('response', function(response) { + urlRequest.on('response', function (response) { assert(false) }) - urlRequest.on('finish', function() { + urlRequest.on('finish', function () { assert(false) }) - urlRequest.on('error', function(error) { - assert(false); + urlRequest.on('error', function () { + assert(false) }) - urlRequest.on('abort', function() { - request_abort_event_emitted = true + urlRequest.on('abort', function () { + requestAbortEventEmitted = true }) - urlRequest.on('close', function() { - request_close_event_emitted = true - assert(request_received_by_server) - assert(request_abort_event_emitted) - assert(request_close_event_emitted) + urlRequest.on('close', function () { + requestCloseEventEmitted = true + assert(requestReceivedByServer) + assert(requestAbortEventEmitted) + assert(requestCloseEventEmitted) done() }) urlRequest.chunkedEncoding = true urlRequest.write(randomString(kOneKiloByte)) - function cancelRequest() { + function cancelRequest () { urlRequest.abort() } }) - it('it should be able to abort an HTTP request after request end and before response', function(done) { - const request_url = '/request_url' - let request_received_by_server = false - server.on('request', function(request, response) { + it('it should be able to abort an HTTP request after request end and before response', function (done) { + const requestUrl = '/requestUrl' + let requestReceivedByServer = false + server.on('request', function (request, response) { switch (request.url) { - case request_url: - request_received_by_server = true; - cancelRequest(); - process.nextTick( () => { + case requestUrl: + requestReceivedByServer = true + cancelRequest() + process.nextTick(() => { response.statusCode = 200 response.statusMessage = 'OK' - response.end(); + response.end() }) - break; + break default: assert(false) } }) - let request_abort_event_emitted = false - let request_finish_event_emitted = false - let request_close_event_emitted = false + let requestAbortEventEmitted = false + let requestFinishEventEmitted = false + let requestCloseEventEmitted = false - const urlRequest = net.request({ + const urlRequest = net.request({ method: 'GET', - url: `${server.url}${request_url}` + url: `${server.url}${requestUrl}` }) - urlRequest.on('response', function(response) { + urlRequest.on('response', function (response) { assert(false) }) - urlRequest.on('finish', function() { - request_finish_event_emitted = true + urlRequest.on('finish', function () { + requestFinishEventEmitted = true }) - urlRequest.on('error', function(error) { - assert(false); + urlRequest.on('error', function () { + assert(false) }) - urlRequest.on('abort', function() { - request_abort_event_emitted = true + urlRequest.on('abort', function () { + requestAbortEventEmitted = true }) - urlRequest.on('close', function() { - request_close_event_emitted = true - assert(request_finish_event_emitted) - assert(request_received_by_server) - assert(request_abort_event_emitted) - assert(request_close_event_emitted) + urlRequest.on('close', function () { + requestCloseEventEmitted = true + assert(requestFinishEventEmitted) + assert(requestReceivedByServer) + assert(requestAbortEventEmitted) + assert(requestCloseEventEmitted) done() }) urlRequest.end(randomString(kOneKiloByte)) - function cancelRequest() { + function cancelRequest () { urlRequest.abort() } }) - it('it should be able to abort an HTTP request after response start', function(done) { - const request_url = '/request_url' - let request_received_by_server = false - server.on('request', function(request, response) { + it('it should be able to abort an HTTP request after response start', function (done) { + const requestUrl = '/requestUrl' + let requestReceivedByServer = false + server.on('request', function (request, response) { switch (request.url) { - case request_url: - request_received_by_server = true; - response.statusCode = 200 - response.statusMessage = 'OK' - response.write(randomString(kOneKiloByte)) - break; + case requestUrl: + requestReceivedByServer = true + response.statusCode = 200 + response.statusMessage = 'OK' + response.write(randomString(kOneKiloByte)) + break default: assert(false) } }) - let request_finish_event_emitted = false - let request_response_event_emitted = false - let request_abort_event_emitted = false - let request_close_event_emitted = false - let response_aborted_event_emitted = false + let requestFinishEventEmitted = false + let requestResponseEventEmitted = false + let requestAbortEventEmitted = false + let requestCloseEventEmitted = false + let responseAbortedEventEmitted = false - - const urlRequest = net.request({ + const urlRequest = net.request({ method: 'GET', - url: `${server.url}${request_url}` + url: `${server.url}${requestUrl}` }) - urlRequest.on('response', function(response) { - request_response_event_emitted = true + urlRequest.on('response', function (response) { + requestResponseEventEmitted = true const statusCode = response.statusCode assert.equal(statusCode, 200) - response.pause(); - response.on('data', function(chunk) { + response.pause() + response.on('data', function (chunk) { }) - response.on('end', function() { + response.on('end', function () { assert(false) }) - response.resume(); - response.on('error', function(error) { + response.resume() + response.on('error', function () { assert(false) }) - response.on('aborted', function() { - response_aborted_event_emitted = true + response.on('aborted', function () { + responseAbortedEventEmitted = true }) urlRequest.abort() }) - urlRequest.on('finish', function() { - request_finish_event_emitted = true + urlRequest.on('finish', function () { + requestFinishEventEmitted = true }) - urlRequest.on('error', function(error) { - assert(false); + urlRequest.on('error', function () { + assert(false) }) - urlRequest.on('abort', function() { - request_abort_event_emitted = true + urlRequest.on('abort', function () { + requestAbortEventEmitted = true }) - urlRequest.on('close', function() { - request_close_event_emitted = true - assert(request_finish_event_emitted, 'request should emit "finish" event') - assert(request_received_by_server, 'request should be received by the server') - assert(request_response_event_emitted, '"response" event should be emitted') - assert(request_abort_event_emitted, 'request should emit "abort" event') - assert(response_aborted_event_emitted, 'response should emit "aborted" event') - assert(request_close_event_emitted, 'request should emit "close" event') + urlRequest.on('close', function () { + requestCloseEventEmitted = true + assert(requestFinishEventEmitted, 'request should emit "finish" event') + assert(requestReceivedByServer, 'request should be received by the server') + assert(requestResponseEventEmitted, '"response" event should be emitted') + assert(requestAbortEventEmitted, 'request should emit "abort" event') + assert(responseAbortedEventEmitted, 'response should emit "aborted" event') + assert(requestCloseEventEmitted, 'request should emit "close" event') done() }) urlRequest.end(randomString(kOneKiloByte)) }) - it('abort event should be emitted at most once', function(done) { - const request_url = '/request_url' - let request_received_by_server = false - server.on('request', function(request, response) { + it('abort event should be emitted at most once', function (done) { + const requestUrl = '/requestUrl' + let requestReceivedByServer = false + server.on('request', function (request, response) { switch (request.url) { - case request_url: - request_received_by_server = true; - cancelRequest(); - break; + case requestUrl: + requestReceivedByServer = true + cancelRequest() + break default: assert(false) } }) - let request_finish_event_emitted = false - let request_abort_event_count = 0 - let request_close_event_emitted = false + let requestFinishEventEmitted = false + let requestAbortEventCount = 0 + let requestCloseEventEmitted = false - const urlRequest = net.request({ + const urlRequest = net.request({ method: 'GET', - url: `${server.url}${request_url}` + url: `${server.url}${requestUrl}` }) - urlRequest.on('response', function(response) { + urlRequest.on('response', function (response) { assert(false) }) - urlRequest.on('finish', function() { - request_finish_event_emitted = true + urlRequest.on('finish', function () { + requestFinishEventEmitted = true }) - urlRequest.on('error', function(error) { - assert(false); + urlRequest.on('error', function () { + assert(false) }) - urlRequest.on('abort', function() { - ++request_abort_event_count + urlRequest.on('abort', function () { + ++requestAbortEventCount urlRequest.abort() }) - urlRequest.on('close', function() { - request_close_event_emitted = true + urlRequest.on('close', function () { + requestCloseEventEmitted = true // Let all pending async events to be emitted - setTimeout(function() { - assert(request_finish_event_emitted) - assert(request_received_by_server) - assert.equal(request_abort_event_count, 1) - assert(request_close_event_emitted) + setTimeout(function () { + assert(requestFinishEventEmitted) + assert(requestReceivedByServer) + assert.equal(requestAbortEventCount, 1) + assert(requestCloseEventEmitted) done() }, 500) }) urlRequest.end(randomString(kOneKiloByte)) - function cancelRequest() { + function cancelRequest () { urlRequest.abort() urlRequest.abort() } }) - it('Requests should be intercepted by webRequest module', function(done) { - - const request_url = '/request_url' - const redirect_url = '/redirect_url' - let request_is_redirected = false; - server.on('request', function(request, response) { + it('Requests should be intercepted by webRequest module', function (done) { + const requestUrl = '/requestUrl' + const redirectUrl = '/redirectUrl' + let requestIsRedirected = false + server.on('request', function (request, response) { switch (request.url) { - case request_url: + case requestUrl: assert(false) break - case redirect_url: - request_is_redirected = true - response.end(); + case redirectUrl: + requestIsRedirected = true + response.end() break default: assert(false) } }) - let request_is_intercepted = false + let requestIsIntercepted = false session.defaultSession.webRequest.onBeforeRequest( - function(details, callback){ - if (details.url === `${server.url}${request_url}`) { - request_is_intercepted = true + function (details, callback) { + if (details.url === `${server.url}${requestUrl}`) { + requestIsIntercepted = true callback({ - redirectURL: `${server.url}${redirect_url}` + redirectURL: `${server.url}${redirectUrl}` }) } else { - callback( { + callback({ cancel: false }) } - }); + }) - const urlRequest = net.request(`${server.url}${request_url}`) + const urlRequest = net.request(`${server.url}${requestUrl}`) - urlRequest.on('response', function(response) { + urlRequest.on('response', function (response) { assert.equal(response.statusCode, 200) response.pause() - response.on('data', function(chunk) { + response.on('data', function (chunk) { }) - response.on('end', function() { - assert(request_is_redirected, 'The server should receive a request to the forward URL') - assert(request_is_intercepted, 'The request should be intercepted by the webRequest module') + response.on('end', function () { + assert(requestIsRedirected, 'The server should receive a request to the forward URL') + assert(requestIsIntercepted, 'The request should be intercepted by the webRequest module') done() }) response.resume() }) - urlRequest.end(); + urlRequest.end() }) - it('should to able to create and intercept a request on a custom session', function(done) { - const request_url = '/request_url' - const redirect_url = '/redirect_url' - const custom_session_name = 'custom-session' - let request_is_redirected = false; - server.on('request', function(request, response) { + it('should to able to create and intercept a request on a custom session', function (done) { + const requestUrl = '/requestUrl' + const redirectUrl = '/redirectUrl' + const customSessionName = 'custom-session' + let requestIsRedirected = false + server.on('request', function (request, response) { switch (request.url) { - case request_url: + case requestUrl: assert(false) break - case redirect_url: - request_is_redirected = true - response.end(); + case redirectUrl: + requestIsRedirected = true + response.end() break default: assert(false) @@ -824,61 +816,61 @@ describe('net module', function() { }) session.defaultSession.webRequest.onBeforeRequest( - function(details, callback) { + function (details, callback) { assert(false, 'Request should not be intercepted by the default session') - }); + }) - let custom_session = session.fromPartition(custom_session_name, { + let customSession = session.fromPartition(customSessionName, { cache: false }) - let request_is_intercepted = false - custom_session.webRequest.onBeforeRequest( - function(details, callback){ - if (details.url === `${server.url}${request_url}`) { - request_is_intercepted = true + let requestIsIntercepted = false + customSession.webRequest.onBeforeRequest( + function (details, callback) { + if (details.url === `${server.url}${requestUrl}`) { + requestIsIntercepted = true callback({ - redirectURL: `${server.url}${redirect_url}` + redirectURL: `${server.url}${redirectUrl}` }) } else { - callback( { + callback({ cancel: false }) } - }); + }) const urlRequest = net.request({ - url: `${server.url}${request_url}`, - session: custom_session_name + url: `${server.url}${requestUrl}`, + session: customSessionName }) - urlRequest.on('response', function(response) { + urlRequest.on('response', function (response) { assert.equal(response.statusCode, 200) response.pause() - response.on('data', function(chunk) { + response.on('data', function (chunk) { }) - response.on('end', function() { - assert(request_is_redirected, 'The server should receive a request to the forward URL') - assert(request_is_intercepted, 'The request should be intercepted by the webRequest module') + response.on('end', function () { + assert(requestIsRedirected, 'The server should receive a request to the forward URL') + assert(requestIsIntercepted, 'The request should be intercepted by the webRequest module') done() }) response.resume() }) - urlRequest.end(); + urlRequest.end() }) - it('should be able to create a request with options', function(done) { - const request_url = '/' - const custom_header_name = 'Some-Custom-Header-Name' - const custom_header_value = 'Some-Customer-Header-Value' - server.on('request', function(request, response) { + it('should be able to create a request with options', function (done) { + const requestUrl = '/' + const customHeaderName = 'Some-Custom-Header-Name' + const customHeaderValue = 'Some-Customer-Header-Value' + server.on('request', function (request, response) { switch (request.url) { - case request_url: + case requestUrl: assert.equal(request.method, 'GET') - assert.equal(request.headers[custom_header_name.toLowerCase()], - custom_header_value) + assert.equal(request.headers[customHeaderName.toLowerCase()], + customHeaderValue) response.statusCode = 200 response.statusMessage = 'OK' - response.end(); - break; + response.end() + break default: assert(false) } @@ -890,66 +882,64 @@ describe('net module', function() { hostname: '127.0.0.1', headers: {} } - options.headers[custom_header_name] = custom_header_value + options.headers[customHeaderName] = customHeaderValue const urlRequest = net.request(options) - urlRequest.on('response', function(response) { + urlRequest.on('response', function (response) { assert.equal(response.statusCode, 200) response.pause() - response.on('data', function(chunk) { + response.on('data', function (chunk) { }) - response.on('end', function() { + response.on('end', function () { done() }) response.resume() }) - urlRequest.end(); + urlRequest.end() }) - - it('should be able to pipe a readable stream into a net request', function(done) { - const node_request_url = '/node_request_url' - const net_request_url = '/net_request_url' - const body_data = randomString(kOneMegaByte) - let net_request_received = false - let net_request_ended = false - server.on('request', function(request, response) { + it('should be able to pipe a readable stream into a net request', function (done) { + const nodeRequestUrl = '/nodeRequestUrl' + const netRequestUrl = '/netRequestUrl' + const bodyData = randomString(kOneMegaByte) + let netRequestReceived = false + let netRequestEnded = false + server.on('request', function (request, response) { switch (request.url) { - case node_request_url: - response.write(body_data) - response.end(); - break; - case net_request_url: - net_request_received = true - let received_body_data = '' - request.on('data', function(chunk) { - received_body_data += chunk.toString() + case nodeRequestUrl: + response.write(bodyData) + response.end() + break + case netRequestUrl: + netRequestReceived = true + let receivedBodyData = '' + request.on('data', function (chunk) { + receivedBodyData += chunk.toString() }) - request.on('end', function(chunk) { - net_request_ended = true + request.on('end', function (chunk) { + netRequestEnded = true if (chunk) { - received_body_data += chunk.toString() + receivedBodyData += chunk.toString() } - assert.equal(received_body_data, body_data) + assert.equal(receivedBodyData, bodyData) response.end() }) - break; + break default: assert(false) } }) - let nodeRequest = http.request(`${server.url}${node_request_url}`); - nodeRequest.on('response', function(nodeResponse) { - const netRequest = net.request(`${server.url}${net_request_url}`) - netRequest.on('response', function(netResponse) { - + let nodeRequest = http.request(`${server.url}${nodeRequestUrl}`) + nodeRequest.on('response', function (nodeResponse) { + const netRequest = net.request(`${server.url}${netRequestUrl}`) + netRequest.on('response', function (netResponse) { assert.equal(netResponse.statusCode, 200) netResponse.pause() - netResponse.on('data', function(chunk) { + netResponse.on('data', function (chunk) { }) - netResponse.on('end', function() { - assert(net_request_received) - assert(net_request_ended) + netResponse.on('end', function () { + assert(netRequestReceived) + assert(netRequestEnded) done() }) netResponse.resume() @@ -959,12 +949,11 @@ describe('net module', function() { nodeRequest.end() }) - it.skip('should emit error event on server socket close', function(done) { + it.skip('should emit error event on server socket close', function (done) { assert(false) }) }) - describe('IncomingMessage API', function() { - + describe('IncomingMessage API', function () { let server beforeEach(function (done) { server = http.createServer() @@ -979,32 +968,27 @@ describe('net module', function() { server = null }) - it ('response object should implement the IncomingMessage API', function(done) { - const request_url = '/request_url' - const custom_header_name = 'Some-Custom-Header-Name' - const custom_header_value = 'Some-Customer-Header-Value' - server.on('request', function(request, response) { + it('response object should implement the IncomingMessage API', function (done) { + const requestUrl = '/requestUrl' + const customHeaderName = 'Some-Custom-Header-Name' + const customHeaderValue = 'Some-Customer-Header-Value' + server.on('request', function (request, response) { switch (request.url) { - case request_url: + case requestUrl: response.statusCode = 200 response.statusMessage = 'OK' - response.setHeader(custom_header_name, custom_header_value) - response.end(); - break; + response.setHeader(customHeaderName, customHeaderValue) + response.end() + break default: assert(false) } }) - let response_event_emitted = false; - let data_event_emitted = false; - let end_event_emitted = false; - let finish_event_emitted = false; - const urlRequest = net.request({ + const urlRequest = net.request({ method: 'GET', - url: `${server.url}${request_url}` + url: `${server.url}${requestUrl}` }) - urlRequest.on('response', function(response) { - response_event_emitted = true; + urlRequest.on('response', function (response) { const statusCode = response.statusCode assert(typeof statusCode === 'number') assert.equal(statusCode, 200) @@ -1013,79 +997,79 @@ describe('net module', function() { assert.equal(statusMessage, 'OK') const rawHeaders = response.rawHeaders assert(typeof rawHeaders === 'object') - assert(rawHeaders[custom_header_name] === - custom_header_value) - const httpVersion = response.httpVersion; + assert(rawHeaders[customHeaderName] === + customHeaderValue) + const httpVersion = response.httpVersion assert(typeof httpVersion === 'string') assert(httpVersion.length > 0) - const httpVersionMajor = response.httpVersionMajor; + const httpVersionMajor = response.httpVersionMajor assert(typeof httpVersionMajor === 'number') assert(httpVersionMajor >= 1) - const httpVersionMinor = response.httpVersionMinor; + const httpVersionMinor = response.httpVersionMinor assert(typeof httpVersionMinor === 'number') assert(httpVersionMinor >= 0) response.pause() - response.on('data', function(chunk) { - }); - response.on('end', function() { + response.on('data', function (chunk) { + }) + response.on('end', function () { done() }) response.resume() }) - urlRequest.end(); + urlRequest.end() }) - it.skip('should be able to pipe a net response into a writable stream', function(done) { - const node_request_url = '/node_request_url' - const net_request_url = '/net_request_url' - const body_data = randomString(kOneMegaByte) - let node_request_received = false - let node_request_ended = false - server.on('request', function(request, response) { + it.skip('should be able to pipe a net response into a writable stream', function (done) { + const nodeRequestUrl = '/nodeRequestUrl' + const netRequestUrl = '/netRequestUrl' + const bodyData = randomString(kOneMegaByte) + let nodeRequestReceived = false + let nodeRequestEnded = false + server.on('request', function (request, response) { switch (request.url) { - case net_request_url: + case netRequestUrl: response.statusCode = 200 response.statusMessage = 'OK' - response.write(body_data) - response.end(); - break; - case node_request_url: - node_request_received = true - let received_body_data = '' - request.on('data', function(chunk) { - received_body_data += chunk.toString() + response.write(bodyData) + response.end() + break + case nodeRequestUrl: + nodeRequestReceived = true + let receivedBodyData = '' + request.on('data', function (chunk) { + receivedBodyData += chunk.toString() }) - request.on('end', function(chunk) { - node_request_ended = true + request.on('end', function (chunk) { + nodeRequestEnded = true if (chunk) { - received_body_data += chunk.toString() + receivedBodyData += chunk.toString() } - assert.equal(received_body_data, body_data) + assert.equal(receivedBodyData, bodyData) response.end() }) - break; + break default: assert(false) } }) - - netRequest = net.request(`${server.url}${net_request_url}`); - netRequest.on('response', function(netResponse) { + + const netRequest = net.request(`${server.url}${netRequestUrl}`) + netRequest.on('response', function (netResponse) { assert.equal(netResponse.statusCode, 200) const serverUrl = url.parse(server.url) const nodeOptions = { method: 'POST', - path: node_request_url, + path: nodeRequestUrl, port: serverUrl.port } - let nodeRequest = http.request(nodeOptions); + let nodeRequest = http.request(nodeOptions) - nodeRequest.on('response', function(nodeResponse) { - nodeResponse.on('data', function(chunk) { + nodeRequest.on('response', function (nodeResponse) { + nodeResponse.on('data', function (chunk) { }) - nodeResponse.on('end', function(chunk) { - assert(node_request_received) - assert(node_request_ended) + nodeResponse.on('end', function (chunk) { + assert(nodeRequestReceived) + assert(nodeRequestEnded) done() }) }) @@ -1094,8 +1078,8 @@ describe('net module', function() { netRequest.end() }) - it.skip('should not emit any event after close', function() { + it.skip('should not emit any event after close', function () { assert(false) }) }) -}) \ No newline at end of file +}) From 16069cd477a0f36fd6d4ad906e35856d81465478 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 12 Oct 2016 17:13:06 +0200 Subject: [PATCH 029/148] Commenting some test code. --- atom/browser/api/atom_api_net.cc | 2 +- spec/api-net-spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/atom_api_net.cc b/atom/browser/api/atom_api_net.cc index 5d23f04886..73b4364aa2 100644 --- a/atom/browser/api/atom_api_net.cc +++ b/atom/browser/api/atom_api_net.cc @@ -30,7 +30,7 @@ void Net::BuildPrototype(v8::Isolate* isolate, prototype->SetClassName(mate::StringToV8(isolate, "Net")); mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) .SetProperty("URLRequest", &Net::URLRequest) - .SetMethod("RequestGarbageCollectionForTesting", + .SetMethod("_RequestGarbageCollectionForTesting", &Net::RequestGarbageCollectionForTesting); } diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index bb7f866c59..94788adefa 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -25,7 +25,7 @@ const kOneKiloByte = 1024 const kOneMegaByte = kOneKiloByte * kOneKiloByte describe('net module', function () { - this.timeout(0) + // this.timeout(0) describe('HTTP basics', function () { let server beforeEach(function (done) { From b290415bbd04bf10e188178d130a0247159010ee Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 12 Oct 2016 19:41:13 +0200 Subject: [PATCH 030/148] Fixing build on Mac OS --- atom/browser/api/atom_api_url_request.h | 2 +- atom/browser/net/atom_url_request.cc | 10 ++++------ 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index c10b542856..71e6a81ca2 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -213,7 +213,7 @@ template std::array, sizeof...(ArgTypes)> URLRequest::BuildArgsArray(ArgTypes... args) const { std::array, sizeof...(ArgTypes)> result - = { mate::ConvertToV8(isolate(), args)... }; + = { { mate::ConvertToV8(isolate(), args)... } }; return result; } diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index d795b0b518..c5d5b9b42d 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -51,8 +51,8 @@ class UploadOwnedIOBufferElementReader : public net::UploadBytesElementReader { AtomURLRequest::AtomURLRequest(base::WeakPtr delegate) : delegate_(delegate), - response_read_buffer_(new net::IOBuffer(kBufferSize)), - is_chunked_upload_(false) { + is_chunked_upload_(false), + response_read_buffer_(new net::IOBuffer(kBufferSize)) { } AtomURLRequest::~AtomURLRequest() { @@ -159,14 +159,12 @@ void AtomURLRequest::DoWriteBuffer( if (buffer) // Non-empty buffer. - auto write_result = chunked_stream_writer_->AppendData( - buffer->data(), + chunked_stream_writer_->AppendData(buffer->data(), buffer->size(), is_last); else if (is_last) // Empty buffer and last chunk, i.e. request.end(). - auto write_result = chunked_stream_writer_->AppendData( - nullptr, + chunked_stream_writer_->AppendData(nullptr, 0, true); From 78343a62b838f90f4a4500657cec7b7c06a53fa7 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Thu, 13 Oct 2016 14:38:06 +1100 Subject: [PATCH 031/148] Cleanup docs and standardize structs --- docs/api/app.md | 9 +-------- docs/api/session.md | 18 ++---------------- docs/api/structures/bluetooth-device.md | 4 ++++ docs/api/structures/cookie.md | 14 ++++++++++++++ docs/api/web-contents.md | 8 +++----- 5 files changed, 24 insertions(+), 29 deletions(-) create mode 100644 docs/api/structures/bluetooth-device.md create mode 100644 docs/api/structures/cookie.md diff --git a/docs/api/app.md b/docs/api/app.md index 2abd9ce7c4..befe4a1ade 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -184,14 +184,7 @@ Returns: * `webContents` [WebContents](web-contents.md) * `url` URL * `error` String - The error code -* `certificate` Object - * `data` String - PEM encoded data - * `issuerName` String - Issuer's Common Name - * `subjectName` String - Subject's Common Name - * `serialNumber` String - Hex value represented string - * `validStart` Integer - Start date of the certificate being valid in seconds - * `validExpiry` Integer - End date of the certificate being valid in seconds - * `fingerprint` String - Fingerprint of the certificate +* `certificate` [Certificate](structures/certificate.md) * `callback` Function Emitted when failed to verify the `certificate` for `url`, to trust the diff --git a/docs/api/session.md b/docs/api/session.md index 4883f915ff..d07d03b745 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -402,7 +402,7 @@ The following events are available on instances of `Cookies`: #### Event: 'changed' * `event` Event -* `cookie` Object - The cookie that was changed +* `cookie` [Cookie](structures/cookie.md) - The cookie that was changed * `cause` String - The cause of the change with one of the following values: * `explicit` - The cookie was changed directly by a consumer's action. * `overwrite` - The cookie was automatically removed due to an insert @@ -436,21 +436,7 @@ The following methods are available on instances of `Cookies`: Sends a request to get all cookies matching `details`, `callback` will be called with `callback(error, cookies)` on complete. -`cookies` is an Array of `cookie` objects. - -* `cookie` Object - * `name` String - The name of the cookie. - * `value` String - The value of the cookie. - * `domain` String - The domain of the cookie. - * `hostOnly` String - Whether the cookie is a host-only cookie. - * `path` String - The path of the cookie. - * `secure` Boolean - Whether the cookie is marked as secure. - * `httpOnly` Boolean - Whether the cookie is marked as HTTP only. - * `session` Boolean - Whether the cookie is a session cookie or a persistent - cookie with an expiration date. - * `expirationDate` Double (optional) - The expiration date of the cookie as - the number of seconds since the UNIX epoch. Not provided for session - cookies. +`cookies` is an Array of [`cookie`](structures/cookie.md) objects. #### `cookies.set(details, callback)` diff --git a/docs/api/structures/bluetooth-device.md b/docs/api/structures/bluetooth-device.md new file mode 100644 index 0000000000..422fd21a11 --- /dev/null +++ b/docs/api/structures/bluetooth-device.md @@ -0,0 +1,4 @@ +# Bluetooth Device Object + +* `deviceName` String +* `deviceId` String diff --git a/docs/api/structures/cookie.md b/docs/api/structures/cookie.md new file mode 100644 index 0000000000..7fdaa03d90 --- /dev/null +++ b/docs/api/structures/cookie.md @@ -0,0 +1,14 @@ +# Certificate Object + +* `name` String - The name of the cookie. +* `value` String - The value of the cookie. +* `domain` String - The domain of the cookie. +* `hostOnly` String - Whether the cookie is a host-only cookie. +* `path` String - The path of the cookie. +* `secure` Boolean - Whether the cookie is marked as secure. +* `httpOnly` Boolean - Whether the cookie is marked as HTTP only. +* `session` Boolean - Whether the cookie is a session cookie or a persistent + cookie with an expiration date. +* `expirationDate` Double (optional) - The expiration date of the cookie as + the number of seconds since the UNIX epoch. Not provided for session + cookies. diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 106934ab0b..b38104440e 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -147,7 +147,7 @@ Returns: `new-window`, `save-to-disk` and `other`. * `options` Object - The options which will be used for creating the new `BrowserWindow`. -* `additionalFeatures` Array - The non-standard features (features not handled +* `additionalFeatures` String[] - The non-standard features (features not handled by Chromium or Electron) given to `window.open()`. Emitted when the page requests to open a new window for a `url`. It could be @@ -428,9 +428,7 @@ Emitted when there is a new context menu that needs to be handled. Returns: * `event` Event -* `devices` [Objects] - * `deviceName` String - * `deviceId` String +* `devices` [BluetoothDevice[]](structures/bluetooth-device.md) * `callback` Function * `deviceId` String @@ -1069,7 +1067,7 @@ End subscribing for frame presentation events. #### `contents.startDrag(item)` -* `item` object +* `item` Object * `file` String * `icon` [NativeImage](native-image.md) From 20323e7032c74c5f84083d9ed09814a67e049904 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Thu, 13 Oct 2016 17:30:57 +1100 Subject: [PATCH 032/148] Specifiy function param types in docs --- docs/api/app.md | 6 + docs/api/browser-window.md | 1 + docs/api/content-tracing.md | 5 + docs/api/desktop-capturer.md | 21 +-- docs/api/dialog.md | 3 + docs/api/menu-item.md | 3 + docs/api/protocol.md | 107 ++++++++--- docs/api/session.md | 172 +++++++++--------- .../api/structures/desktop-capturer-source.md | 14 ++ docs/api/structures/upload-data.md | 6 + docs/api/system-preferences.md | 4 + docs/api/web-contents.md | 15 +- docs/api/web-view-tag.md | 2 +- 13 files changed, 226 insertions(+), 133 deletions(-) create mode 100644 docs/api/structures/desktop-capturer-source.md create mode 100644 docs/api/structures/upload-data.md diff --git a/docs/api/app.md b/docs/api/app.md index 3acac8737f..216a9f2ef9 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -193,6 +193,7 @@ Returns: * `validExpiry` Integer - End date of the certificate being valid in seconds * `fingerprint` String - Fingerprint of the certificate * `callback` Function + * `isTrusted` Boolean - Whether to consider the certificate as trusted Emitted when failed to verify the `certificate` for `url`, to trust the certificate you should prevent the default behavior with @@ -221,6 +222,7 @@ Returns: * `url` URL * `certificateList` [Certificate[]](structures/certificate.md) * `callback` Function + * `certificate` [Certificate](structures/certificate.md) Emitted when a client certificate is requested. @@ -255,6 +257,8 @@ Returns: * `port` Integer * `realm` String * `callback` Function + * `username` String + * `password` String Emitted when `webContents` wants to do basic auth. @@ -696,6 +700,8 @@ app.setJumpList([ ### `app.makeSingleInstance(callback)` * `callback` Function + * `argv` String[] - An array of the second instance's command line arguments + * `workingDirectory` String - The second instance's working directory This method makes your application a Single Instance Application - instead of allowing multiple instances of your app to run, this will ensure that only a diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index b42f397a49..7bec8987b1 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -950,6 +950,7 @@ Whether `Boolean` - Whether the window's document has been edited. * `rect` [Rectangle](structures/rectangle.md) (optional) - The bounds to capture * `callback` Function + * `image` [NativeImage](native-image.md) Same as `webContents.capturePage([rect, ]callback)`. diff --git a/docs/api/content-tracing.md b/docs/api/content-tracing.md index 8cfc7670c6..13a6fb6065 100644 --- a/docs/api/content-tracing.md +++ b/docs/api/content-tracing.md @@ -33,6 +33,7 @@ The `contentTracing` module has the following methods: ### `contentTracing.getCategories(callback)` * `callback` Function + * `categories` String[] Get a set of category groups. The category groups can change as new code paths are reached. @@ -86,6 +87,7 @@ before options parsed from `traceOptions` are applied on it. * `resultFilePath` String * `callback` Function + * `resultFilePath` String Stop recording on all processes. @@ -130,6 +132,7 @@ Once all child processes have acknowledged the `stopMonitoring` request the * `resultFilePath` String * `callback` Function + * `resultFilePath` Get the current monitoring traced data. @@ -146,6 +149,8 @@ request the `callback` will be called with a file that contains the traced data. ### `contentTracing.getTraceBufferUsage(callback)` * `callback` Function + * `value` Number + * `percentage` Number Get the maximum usage across processes of trace buffer as a percentage of the full state. When the TraceBufferUsage value is determined the `callback` is diff --git a/docs/api/desktop-capturer.md b/docs/api/desktop-capturer.md index 255340aa64..56872100d5 100644 --- a/docs/api/desktop-capturer.md +++ b/docs/api/desktop-capturer.md @@ -61,25 +61,14 @@ The `desktopCapturer` module has the following methods: * `thumbnailSize` Object (optional) - The suggested size that the media source thumbnail should be scaled to, defaults to `{width: 150, height: 150}`. * `callback` Function + * `error` Error + * `sources` [DesktopCapturerSource[]](structures/desktop-capturer-source.md) Starts gathering information about all available desktop media sources, and calls `callback(error, sources)` when finished. -`sources` is an array of `Source` objects, each `Source` represents a -screen or an individual window that can be captured, and has the following -properties: - -* `id` String - The identifier of a window or screen that can be used as a - `chromeMediaSourceId` constraint when calling - [`navigator.webkitGetUserMedia`]. The format of the identifier will be - `window:XX` or `screen:XX`, where `XX` is a random generated number. -* `name` String - A screen source will be named either `Entire Screen` or - `Screen `, while the name of a window source will match the window - title. -* `thumbnail` [NativeImage](native-image.md) - A thumbnail image. **Note:** - There is no guarantee that the size of the thumbnail is the same as the - `thumnbailSize` specified in the `options` passed to - `desktopCapturer.getSources`. The actual size depends on the scale of the - screen or window. +`sources` is an array of [`DesktopCapturerSource`](structures/desktop-capturer-source.md) +objects, each `Source` represents a screen or an individual window that can be +captured. [`navigator.webkitGetUserMedia`]: https://developer.mozilla.org/en/docs/Web/API/Navigator/getUserMedia diff --git a/docs/api/dialog.md b/docs/api/dialog.md index 70f8a643f8..1bc971164c 100644 --- a/docs/api/dialog.md +++ b/docs/api/dialog.md @@ -34,6 +34,7 @@ The `dialog` module has the following methods: contain `openFile`, `openDirectory`, `multiSelections`, `createDirectory` and `showHiddenFiles`. * `callback` Function (optional) + * `filePaths` String[] - An array of file paths chosen by the user On success this method returns an array of file paths chosen by the user, otherwise it returns `undefined`. @@ -74,6 +75,7 @@ shown. left empty the default label will be used. * `filters` String[] * `callback` Function (optional) + * `filename` String On success this method returns the path of the file chosen by the user, otherwise it returns `undefined`. @@ -110,6 +112,7 @@ will be passed via `callback(filename)` the style of modern Windows apps. If you don't like this behavior, you can set `noLink` to `true`. * `callback` Function + * `response` Number - The index of the button that was clicked Shows a message box, it will block the process until the message box is closed. It returns the index of the clicked button. diff --git a/docs/api/menu-item.md b/docs/api/menu-item.md index d9b78b4df3..5adcdd75ad 100644 --- a/docs/api/menu-item.md +++ b/docs/api/menu-item.md @@ -13,6 +13,9 @@ Create a new `MenuItem` with the following method: * `options` Object * `click` Function - Will be called with `click(menuItem, browserWindow, event)` when the menu item is clicked. + * `menuItem` MenuItem + * `browserWindow` BrowserWindow + * `event` Event * `role` String - Define the action of the menu item, when specified the `click` property will be ignored. * `type` String - Can be `normal`, `separator`, `submenu`, `checkbox` or diff --git a/docs/api/protocol.md b/docs/api/protocol.md index 538db54113..f689b38e3d 100644 --- a/docs/api/protocol.md +++ b/docs/api/protocol.md @@ -76,7 +76,15 @@ module gets emitted. * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `filePath` String (optional) * `completion` Function (optional) + * `error` Error Registers a protocol of `scheme` that will send the file as a response. The `handler` will be called with `handler(request, callback)` when a `request` is @@ -84,21 +92,6 @@ going to be created with `scheme`. `completion` will be called with `completion(null)` when `scheme` is successfully registered or `completion(error)` when failed. -* `request` Object - * `url` String - * `referrer` String - * `method` String - * `uploadData` Array (optional) -* `callback` Function - -The `uploadData` is an array of `data` objects: - -* `data` Object - * `bytes` Buffer - Content being sent. - * `file` String - Path of file being uploaded. - * `blobUUID` String - UUID of blob data. Use [ses.getBlobData](session.md#sesgetblobdataidentifier-callback) method - to retrieve the data. - To handle the `request`, the `callback` should be called with either the file's path or an object that has a `path` property, e.g. `callback(filePath)` or `callback({path: filePath})`. @@ -117,7 +110,15 @@ treated as a standard scheme. * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `buffer` Buffer (optional) * `completion` Function (optional) + * `error` Error Registers a protocol of `scheme` that will send a `Buffer` as a response. @@ -141,7 +142,15 @@ protocol.registerBufferProtocol('atom', (request, callback) => { * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `data` String (optional) * `completion` Function (optional) + * `error` Error Registers a protocol of `scheme` that will send a `String` as a response. @@ -153,7 +162,21 @@ should be called with either a `String` or an object that has the `data`, * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `redirectRequest` Object + * `url` String + * `method` String + * `session` Object (optional) + * `uploadData` Object (optional) + * `contentType` String - MIME type of the content. + * `data` String - Content to be sent. * `completion` Function (optional) + * `error` Error Registers a protocol of `scheme` that will send an HTTP request as a response. @@ -161,25 +184,16 @@ The usage is the same with `registerFileProtocol`, except that the `callback` should be called with a `redirectRequest` object that has the `url`, `method`, `referrer`, `uploadData` and `session` properties. -* `redirectRequest` Object - * `url` String - * `method` String - * `session` Object (optional) - * `uploadData` Object (optional) - By default the HTTP request will reuse the current session. If you want the request to have a different session you should set `session` to `null`. For POST requests the `uploadData` object must be provided. -* `uploadData` object - * `contentType` String - MIME type of the content. - * `data` String - Content to be sent. - ### `protocol.unregisterProtocol(scheme[, completion])` * `scheme` String * `completion` Function (optional) + * `error` Error Unregisters the custom protocol of `scheme`. @@ -187,6 +201,7 @@ Unregisters the custom protocol of `scheme`. * `scheme` String * `callback` Function + * `error` Error The `callback` will be called with a boolean that indicates whether there is already a handler for `scheme`. @@ -195,7 +210,15 @@ already a handler for `scheme`. * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `filePath` String * `completion` Function (optional) + * `error` Error Intercepts `scheme` protocol and uses `handler` as the protocol's new handler which sends a file as a response. @@ -204,7 +227,15 @@ which sends a file as a response. * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `data` String (optional) * `completion` Function (optional) + * `error` Error Intercepts `scheme` protocol and uses `handler` as the protocol's new handler which sends a `String` as a response. @@ -213,7 +244,15 @@ which sends a `String` as a response. * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `buffer` Buffer (optional) * `completion` Function (optional) + * `error` Error Intercepts `scheme` protocol and uses `handler` as the protocol's new handler which sends a `Buffer` as a response. @@ -222,7 +261,21 @@ which sends a `Buffer` as a response. * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `redirectRequest` Object + * `url` String + * `method` String + * `session` Object (optional) + * `uploadData` Object (optional) + * `contentType` String - MIME type of the content. + * `data` String - Content to be sent. * `completion` Function (optional) + * `error` Error Intercepts `scheme` protocol and uses `handler` as the protocol's new handler which sends a new HTTP request as a response. @@ -230,7 +283,9 @@ which sends a new HTTP request as a response. ### `protocol.uninterceptProtocol(scheme[, completion])` * `scheme` String -* `completion` Function +* `completion` Function (optional) + * `error` Error + Remove the interceptor installed for `scheme` and restore its original handler. diff --git a/docs/api/session.md b/docs/api/session.md index 4883f915ff..1c1030ac42 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -200,6 +200,7 @@ The `proxyBypassRules` is a comma separated list of rules described below: * `url` URL * `callback` Function + * `proxy` Object Resolves the proxy information for `url`. The `callback` will be called with `callback(proxy)` when the request is performed. @@ -245,6 +246,10 @@ the original network configuration. #### `ses.setCertificateVerifyProc(proc)` * `proc` Function + * `hostname` String + * `certificate` [Certificate](structures/certificate.md) + * `callback` Function + * `isTrusted` Boolean - Determines if the certificate should be trusted Sets the certificate verify proc for `session`, the `proc` will be called with `proc(hostname, certificate, callback)` whenever a server certificate @@ -269,7 +274,8 @@ win.webContents.session.setCertificateVerifyProc((hostname, cert, callback) => { * `webContents` Object - [WebContents](web-contents.md) requesting the permission. * `permission` String - Enum of 'media', 'geolocation', 'notifications', 'midiSysex', 'pointerLock', 'fullscreen', 'openExternal'. - * `callback` Function - Allow or deny the permission. + * `callback` Function + * `permissionGranted` Boolean - Allow or deny the permission Sets the handler which can be used to respond to permission requests for the `session`. Calling `callback(true)` will allow the permission and `callback(false)` will reject it. @@ -432,6 +438,8 @@ The following methods are available on instances of `Cookies`: * `secure` Boolean (optional) - Filters cookies by their Secure property. * `session` Boolean (optional) - Filters out session or persistent cookies. * `callback` Function + * `error` Error + * `cookies` Cookies[] Sends a request to get all cookies matching `details`, `callback` will be called with `callback(error, cookies)` on complete. @@ -468,6 +476,7 @@ with `callback(error, cookies)` on complete. seconds since the UNIX epoch. If omitted then the cookie becomes a session cookie and will not be retained between sessions. * `callback` Function + * `error` Error Sets a cookie with `details`, `callback` will be called with `callback(error)` on complete. @@ -524,34 +533,26 @@ The following methods are available on instances of `WebRequest`: * `filter` Object * `listener` Function + * `details` Object + * `id` Integer + * `url` String + * `method` String + * `resourceType` String + * `timestamp` Double + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `response` Object + * `cancel` Boolean (optional) + * `redirectURL` String (optional) - The original request is prevented from + being sent or completed and is instead redirected to the given URL. The `listener` will be called with `listener(details, callback)` when a request is about to occur. -* `details` Object - * `id` Integer - * `url` String - * `method` String - * `resourceType` String - * `timestamp` Double - * `uploadData` Array (optional) -* `callback` Function - -The `uploadData` is an array of `data` objects: - -* `data` Object - * `bytes` Buffer - Content being sent. - * `file` String - Path of file being uploaded. - * `blobUUID` String - UUID of blob data. Use [ses.getBlobData](session.md#sesgetblobdataidentifier-callback) method - to retrieve the data. +The `uploadData` is an array of `UploadData` objects: The `callback` has to be called with an `response` object: -* `response` Object - * `cancel` Boolean (optional) - * `redirectURL` String (optional) - The original request is prevented from - being sent or completed, and is instead redirected to the given URL. - #### `webRequest.onBeforeSendHeaders([filter, ]listener)` * `filter` Object @@ -569,31 +570,29 @@ TCP connection is made to the server, but before any http data is sent. * `timestamp` Double * `requestHeaders` Object * `callback` Function + * `response` Object + * `cancel` Boolean (optional) + * `requestHeaders` Object (optional) - When provided, request will be made + with these headers. The `callback` has to be called with an `response` object: -* `response` Object - * `cancel` Boolean (optional) - * `requestHeaders` Object (optional) - When provided, request will be made - with these headers. - #### `webRequest.onSendHeaders([filter, ]listener)` * `filter` Object * `listener` Function + * `details` Object + * `id` Integer + * `url` String + * `method` String + * `resourceType` String + * `timestamp` Double + * `requestHeaders` Object The `listener` will be called with `listener(details)` just before a request is going to be sent to the server, modifications of previous `onBeforeSendHeaders` response are visible by the time this listener is fired. -* `details` Object - * `id` Integer - * `url` String - * `method` String - * `resourceType` String - * `timestamp` Double - * `requestHeaders` Object - #### `webRequest.onHeadersReceived([filter, ]listener)` * `filter` Object @@ -612,90 +611,85 @@ response headers of a request have been received. * `statusCode` Integer * `responseHeaders` Object * `callback` Function + * `response` Object + * `cancel` Boolean + * `responseHeaders` Object (optional) - When provided, the server is assumed + to have responded with these headers. + * `statusLine` String (optional) - Should be provided when overriding + `responseHeaders` to change header status otherwise original response + header's status will be used. -The `callback` has to be called with an `response` object: - -* `response` Object - * `cancel` Boolean - * `responseHeaders` Object (optional) - When provided, the server is assumed - to have responded with these headers. - * `statusLine` String (optional) - Should be provided when overriding - `responseHeaders` to change header status otherwise original response - header's status will be used. +The `callback` has to be called with an `response` object. #### `webRequest.onResponseStarted([filter, ]listener)` * `filter` Object * `listener` Function + * `details` Object + * `id` Integer + * `url` String + * `method` String + * `resourceType` String + * `timestamp` Double + * `responseHeaders` Object + * `fromCache` Boolean - Indicates whether the response was fetched from disk + cache. + * `statusCode` Integer + * `statusLine` String The `listener` will be called with `listener(details)` when first byte of the response body is received. For HTTP requests, this means that the status line and response headers are available. -* `details` Object - * `id` Integer - * `url` String - * `method` String - * `resourceType` String - * `timestamp` Double - * `responseHeaders` Object - * `fromCache` Boolean - Indicates whether the response was fetched from disk - cache. - * `statusCode` Integer - * `statusLine` String - #### `webRequest.onBeforeRedirect([filter, ]listener)` * `filter` Object * `listener` Function + * `details` Object + * `id` String + * `url` String + * `method` String + * `resourceType` String + * `timestamp` Double + * `redirectURL` String + * `statusCode` Integer + * `ip` String (optional) - The server IP address that the request was + actually sent to. + * `fromCache` Boolean + * `responseHeaders` Object The `listener` will be called with `listener(details)` when a server initiated redirect is about to occur. -* `details` Object - * `id` String - * `url` String - * `method` String - * `resourceType` String - * `timestamp` Double - * `redirectURL` String - * `statusCode` Integer - * `ip` String (optional) - The server IP address that the request was - actually sent to. - * `fromCache` Boolean - * `responseHeaders` Object - #### `webRequest.onCompleted([filter, ]listener)` * `filter` Object * `listener` Function + * `details` Object + * `id` Integer + * `url` String + * `method` String + * `resourceType` String + * `timestamp` Double + * `responseHeaders` Object + * `fromCache` Boolean + * `statusCode` Integer + * `statusLine` String The `listener` will be called with `listener(details)` when a request is completed. -* `details` Object - * `id` Integer - * `url` String - * `method` String - * `resourceType` String - * `timestamp` Double - * `responseHeaders` Object - * `fromCache` Boolean - * `statusCode` Integer - * `statusLine` String - #### `webRequest.onErrorOccurred([filter, ]listener)` * `filter` Object * `listener` Function + * `details` Object + * `id` Integer + * `url` String + * `method` String + * `resourceType` String + * `timestamp` Double + * `fromCache` Boolean + * `error` String - The error description. The `listener` will be called with `listener(details)` when an error occurs. - -* `details` Object - * `id` Integer - * `url` String - * `method` String - * `resourceType` String - * `timestamp` Double - * `fromCache` Boolean - * `error` String - The error description. diff --git a/docs/api/structures/desktop-capturer-source.md b/docs/api/structures/desktop-capturer-source.md new file mode 100644 index 0000000000..494856bcc9 --- /dev/null +++ b/docs/api/structures/desktop-capturer-source.md @@ -0,0 +1,14 @@ +# Desktop Capturer Source Object + +* `id` String - The identifier of a window or screen that can be used as a + `chromeMediaSourceId` constraint when calling + [`navigator.webkitGetUserMedia`]. The format of the identifier will be + `window:XX` or `screen:XX`, where `XX` is a random generated number. +* `name` String - A screen source will be named either `Entire Screen` or + `Screen `, while the name of a window source will match the window + title. +* `thumbnail` [NativeImage](../native-image.md) - A thumbnail image. **Note:** + There is no guarantee that the size of the thumbnail is the same as the + `thumnbailSize` specified in the `options` passed to + `desktopCapturer.getSources`. The actual size depends on the scale of the + screen or window. diff --git a/docs/api/structures/upload-data.md b/docs/api/structures/upload-data.md new file mode 100644 index 0000000000..f39b563b95 --- /dev/null +++ b/docs/api/structures/upload-data.md @@ -0,0 +1,6 @@ +# ThumbarButton Object + +* `bytes` Buffer - Content being sent. +* `file` String - Path of file being uploaded. +* `blobUUID` String - UUID of blob data. Use [ses.getBlobData](../session.md#sesgetblobdataidentifier-callback) method + to retrieve the data. diff --git a/docs/api/system-preferences.md b/docs/api/system-preferences.md index 75b4f7ae2b..90fef8fec3 100644 --- a/docs/api/system-preferences.md +++ b/docs/api/system-preferences.md @@ -63,6 +63,8 @@ that contains the user information dictionary sent along with the notification. * `event` String * `callback` Function + * `event` String + * `userInfo` Object Subscribes to native notifications of macOS, `callback` will be called with `callback(event, userInfo)` when the corresponding `event` happens. The @@ -90,6 +92,8 @@ Removes the subscriber with `id`. * `event` String * `callback` Function + * `event` String + * `userInfo` Object Same as `subscribeNotification`, but uses `NSNotificationCenter` for local defaults. This is necessary for events such as `NSUserDefaultsDidChangeNotification` diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 106934ab0b..eaf058ef7f 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -249,6 +249,7 @@ Returns: * `error` String - The error code * `certificate` [Certificate](structures/certificate.md) * `callback` Function + * `isTrusted` Boolean - Indicates whether the certificate can be considered trusted Emitted when failed to verify the `certificate` for `url`. @@ -263,6 +264,7 @@ Returns: * `url` URL * `certificateList` Certificate[] * `callback` Function + * `certificate` [Certificate](structures/certificate.md) - Must be a certificate from the given list Emitted when a client certificate is requested. @@ -285,6 +287,8 @@ Returns: * `port` Integer * `realm` String * `callback` Function + * `username` String + * `password` String Emitted when `webContents` wants to do basic auth. @@ -622,7 +626,7 @@ Injects CSS into the current web page. * `code` String * `userGesture` Boolean (optional) * `callback` Function (optional) - Called after script has been executed. - * `result` + * `result` Any Evaluates `code` in page. @@ -650,6 +654,7 @@ zoom percent divided by 100, so 300% = 3.0. #### `contents.getZoomFactor(callback)` * `callback` Function + * `zoomFactor` Number Sends a request to get current zoom factor, the `callback` will be called with `callback(zoomFactor)`. @@ -665,6 +670,7 @@ limits of 300% and 50% of original size, respectively. #### `contents.getZoomLevel(callback)` * `callback` Function + * `zoomLevel` Number Sends a request to get current zoom level, the `callback` will be called with `callback(zoomLevel)`. @@ -782,6 +788,7 @@ console.log(requestId) * `rect` [Rectangle](structures/rectangle.md) (optional) - The area of the page to be captured * `callback` Function + * `image` [NativeImage](native-image.md) Captures a snapshot of the page within `rect`. Upon completion `callback` will be called with `callback(image)`. The `image` is an instance of @@ -791,6 +798,7 @@ be called with `callback(image)`. The `image` is an instance of #### `contents.hasServiceWorker(callback)` * `callback` Function + * `hasWorker` Boolean Checks if any ServiceWorker is registered and returns a boolean as response to `callback`. @@ -798,6 +806,7 @@ response to `callback`. #### `contents.unregisterServiceWorker(callback)` * `callback` Function + * `success` Boolean Unregisters any ServiceWorker if present and returns a boolean as response to `callback` when the JS promise is fulfilled or false @@ -830,6 +839,8 @@ Use `page-break-before: always; ` CSS style to force to print to a new page. * `printSelectionOnly` Boolean - Whether to print selection only. * `landscape` Boolean - `true` for landscape, `false` for portrait. * `callback` Function + * `error` Error + * `data` Buffer Prints window's web page as PDF with Chromium's preview printing custom settings. @@ -1047,6 +1058,8 @@ For the `mouseWheel` event, the `event` object also have following properties: * `onlyDirty` Boolean (optional) - Defaults to `false` * `callback` Function + * `frameBuffer` Buffer + * `dirtyRect` [Rectangle](structures/rectangle.md) Begin subscribing for presentation events and captured frames, the `callback` will be called with `callback(frameBuffer, dirtyRect)` when there is a diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index 512300c9f6..595e32353e 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -347,7 +347,7 @@ Injects CSS into the guest page. * `code` String * `userGesture` Boolean - Default `false`. * `callback` Function (optional) - Called after script has been executed. - * `result` + * `result` Any Evaluates `code` in page. If `userGesture` is set, it will create the user gesture context in the page. HTML APIs like `requestFullScreen`, which require From 5cf03e68d421a746d50153b95ae11a92fa34f090 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Thu, 13 Oct 2016 17:33:12 +1100 Subject: [PATCH 033/148] Fix missing type --- docs/api/content-tracing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/content-tracing.md b/docs/api/content-tracing.md index 13a6fb6065..73c48e05d9 100644 --- a/docs/api/content-tracing.md +++ b/docs/api/content-tracing.md @@ -132,7 +132,7 @@ Once all child processes have acknowledged the `stopMonitoring` request the * `resultFilePath` String * `callback` Function - * `resultFilePath` + * `resultFilePath` String Get the current monitoring traced data. From 6f5b0a28c57222987dffe27f8865a4b51c485f88 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 13 Oct 2016 17:14:23 +0200 Subject: [PATCH 034/148] Fixing code review issues: function call formatting, renaming JS member variables, refactoring response headers conversion. --- atom/browser/api/atom_api_net.cc | 2 +- atom/browser/api/atom_api_url_request.cc | 61 +++---- atom/browser/api/atom_api_web_contents.cc | 33 +--- atom/browser/net/atom_url_request.cc | 151 +++++++++++------- atom/browser/net/atom_url_request.h | 6 + .../native_mate_converters/net_converter.cc | 27 ++++ .../native_mate_converters/net_converter.h | 7 + lib/browser/api/net.js | 82 +++++----- spec/api-net-spec.js | 88 +++++++++- 9 files changed, 272 insertions(+), 185 deletions(-) diff --git a/atom/browser/api/atom_api_net.cc b/atom/browser/api/atom_api_net.cc index 73b4364aa2..2ce7aa3816 100644 --- a/atom/browser/api/atom_api_net.cc +++ b/atom/browser/api/atom_api_net.cc @@ -41,7 +41,7 @@ v8::Local Net::URLRequest(v8::Isolate* isolate) { void Net::RequestGarbageCollectionForTesting() { isolate()->RequestGarbageCollectionForTesting( - v8::Isolate::GarbageCollectionType::kFullGarbageCollection); + v8::Isolate::GarbageCollectionType::kFullGarbageCollection); } diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 1bcf44eeb6..5c47293411 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -16,38 +16,20 @@ namespace mate { -template<> -struct Converter> { - static v8::Local ToV8( - v8::Isolate* isolate, - scoped_refptr val) { - mate::Dictionary dict = mate::Dictionary::CreateEmpty(isolate); - if (val) { - size_t iter = 0; - std::string name; - std::string value; - while (val->EnumerateHeaderLines(&iter, &name, &value)) { - dict.Set(name, value); - } - } - return dict.GetHandle(); - } -}; - template<> struct Converter> { static v8::Local ToV8( - v8::Isolate* isolate, - scoped_refptr buffer) { + v8::Isolate* isolate, + scoped_refptr buffer) { return node::Buffer::Copy(isolate, - buffer->data(), - buffer->size()).ToLocalChecked(); + buffer->data(), + buffer->size()).ToLocalChecked(); } static bool FromV8( - v8::Isolate* isolate, - v8::Local val, - scoped_refptr* out) { + v8::Isolate* isolate, + v8::Local val, + scoped_refptr* out) { auto size = node::Buffer::Length(val); if (size == 0) { @@ -179,11 +161,8 @@ mate::WrappableBase* URLRequest::New(mate::Arguments* args) { auto browser_context = session->browser_context(); auto api_url_request = new URLRequest(args->isolate(), args->GetThis()); auto weak_ptr = api_url_request->weak_ptr_factory_.GetWeakPtr(); - auto atom_url_request = AtomURLRequest::Create( - browser_context, - method, - url, - weak_ptr); + auto atom_url_request = AtomURLRequest::Create(browser_context, method, url, + weak_ptr); api_url_request->atom_request_ = atom_url_request; @@ -228,9 +207,9 @@ bool URLRequest::Write( scoped_refptr buffer, bool is_last) { if (request_state_.Canceled() || - request_state_.Failed() || - request_state_.Finished() || - request_state_.Closed()) { + request_state_.Failed() || + request_state_.Finished() || + request_state_.Closed()) { return false; } @@ -326,7 +305,7 @@ void URLRequest::SetChunkedUpload(bool is_chunked_upload) { void URLRequest::OnAuthenticationRequired( scoped_refptr auth_info) { if (request_state_.Canceled() || - request_state_.Closed()) { + request_state_.Closed()) { return; } @@ -336,10 +315,10 @@ void URLRequest::OnAuthenticationRequired( } EmitRequestEvent( - false, - "login", - auth_info.get(), - base::Bind(&AtomURLRequest::PassLoginInformation, atom_request_)); + false, + "login", + auth_info.get(), + base::Bind(&AtomURLRequest::PassLoginInformation, atom_request_)); } void URLRequest::OnResponseStarted( @@ -373,9 +352,9 @@ void URLRequest::OnResponseData( void URLRequest::OnResponseCompleted() { if (request_state_.Canceled() || - request_state_.Closed() || - request_state_.Failed() || - response_state_.Failed()) { + request_state_.Closed() || + request_state_.Failed() || + response_state_.Failed()) { // In case we received an unexpected event from Chromium net, // don't emit any data event after request cancel/error/close. return; diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 124a0d3358..bd7de5a22a 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -35,10 +35,10 @@ #include "atom/common/native_mate_converters/gfx_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/image_converter.h" +#include "atom/common/native_mate_converters/net_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" #include "atom/common/native_mate_converters/value_converter.h" #include "atom/common/options_switches.h" -#include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "brightray/browser/inspectable_web_contents.h" #include "brightray/browser/inspectable_web_contents_view.h" @@ -66,7 +66,6 @@ #include "content/public/common/context_menu_params.h" #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" -#include "net/http/http_response_headers.h" #include "net/url_request/url_request_context.h" #include "third_party/WebKit/public/web/WebFindOptions.h" #include "third_party/WebKit/public/web/WebInputEvent.h" @@ -141,32 +140,6 @@ struct Converter { } }; -template<> -struct Converter { - static v8::Local ToV8(v8::Isolate* isolate, - net::HttpResponseHeaders* headers) { - base::DictionaryValue response_headers; - if (headers) { - size_t iter = 0; - std::string key; - std::string value; - while (headers->EnumerateHeaderLines(&iter, &key, &value)) { - key = base::ToLowerASCII(key); - if (response_headers.HasKey(key)) { - base::ListValue* values = nullptr; - if (response_headers.GetList(key, &values)) - values->AppendString(value); - } else { - std::unique_ptr values(new base::ListValue()); - values->AppendString(value); - response_headers.Set(key, std::move(values)); - } - } - } - return ConvertToV8(isolate, response_headers); - } -}; - template<> struct Converter { static bool FromV8(v8::Isolate* isolate, v8::Local val, @@ -691,7 +664,7 @@ void WebContents::DidGetResourceResponseStart( details.http_response_code, details.method, details.referrer, - details.headers.get(), + details.headers, ResourceTypeToString(details.resource_type)); } @@ -705,7 +678,7 @@ void WebContents::DidGetRedirectForResourceRequest( details.http_response_code, details.method, details.referrer, - details.headers.get()); + details.headers); } void WebContents::DidFinishNavigation( diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index c5d5b9b42d..7a3a0b1423 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -64,29 +64,42 @@ scoped_refptr AtomURLRequest::Create( const std::string& url, base::WeakPtr delegate) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + DCHECK(browser_context); DCHECK(!url.empty()); + if (!browser_context || url.empty()) { + return nullptr; + } auto request_context_getter = browser_context->url_request_context_getter(); + scoped_refptr atom_url_request(new AtomURLRequest(delegate)); + if (content::BrowserThread::PostTask( + content::BrowserThread::IO, + FROM_HERE, + base::Bind(&AtomURLRequest::DoInitialize, atom_url_request, + request_context_getter, method, url))) { + return atom_url_request; + } + return nullptr; +} +void AtomURLRequest::DoInitialize( + scoped_refptr request_context_getter, + const std::string& method, + const std::string& url) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(request_context_getter); auto context = request_context_getter->GetURLRequestContext(); DCHECK(context); + request_ = context->CreateRequest(GURL(url), + net::RequestPriority::DEFAULT_PRIORITY, + this); - scoped_refptr atom_url_request = - new AtomURLRequest(delegate); - - atom_url_request->request_ = context->CreateRequest(GURL(url), - net::RequestPriority::DEFAULT_PRIORITY, - atom_url_request.get()); - - atom_url_request->request_->set_method(method); - return atom_url_request; + request_->set_method(method); } - bool AtomURLRequest::Write( scoped_refptr buffer, bool is_last) { @@ -105,41 +118,45 @@ void AtomURLRequest::SetChunkedUpload(bool is_chunked_upload) { is_chunked_upload_ = is_chunked_upload; } - void AtomURLRequest::Cancel() const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::BrowserThread::PostTask( - content::BrowserThread::IO, - FROM_HERE, - base::Bind(&AtomURLRequest::DoCancel, this)); + content::BrowserThread::IO, + FROM_HERE, + base::Bind(&AtomURLRequest::DoCancel, this)); } void AtomURLRequest::SetExtraHeader(const std::string& name, const std::string& value) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - request_->SetExtraRequestHeaderByName(name, value, true); + content::BrowserThread::PostTask( + content::BrowserThread::IO, + FROM_HERE, + base::Bind(&AtomURLRequest::DoSetExtraHeader, this, name, value)); } - void AtomURLRequest::RemoveExtraHeader(const std::string& name) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - request_->RemoveRequestHeaderByName(name); + content::BrowserThread::PostTask( + content::BrowserThread::IO, + FROM_HERE, + base::Bind(&AtomURLRequest::DoRemoveExtraHeader, this, name)); } void AtomURLRequest::PassLoginInformation(const base::string16& username, const base::string16& password) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - if (username.empty() || password.empty()) + if (username.empty() || password.empty()) { content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::Bind(&AtomURLRequest::DoCancelAuth, this)); - else + content::BrowserThread::IO, FROM_HERE, + base::Bind(&AtomURLRequest::DoCancelAuth, this)); + } else { content::BrowserThread::PostTask( - content::BrowserThread::IO, FROM_HERE, - base::Bind(&AtomURLRequest::DoSetAuth, this, username, password)); + content::BrowserThread::IO, FROM_HERE, + base::Bind(&AtomURLRequest::DoSetAuth, this, username, password)); + } } - void AtomURLRequest::DoWriteBuffer( scoped_refptr buffer, bool is_last) { @@ -151,7 +168,7 @@ void AtomURLRequest::DoWriteBuffer( bool first_call = false; if (!chunked_stream_writer_) { std::unique_ptr chunked_stream( - new net::ChunkedUploadDataStream(0)); + new net::ChunkedUploadDataStream(0)); chunked_stream_writer_ = chunked_stream->CreateWriter(); request_->set_upload(std::move(chunked_stream)); first_call = true; @@ -160,32 +177,32 @@ void AtomURLRequest::DoWriteBuffer( if (buffer) // Non-empty buffer. chunked_stream_writer_->AppendData(buffer->data(), - buffer->size(), - is_last); + buffer->size(), + is_last); else if (is_last) // Empty buffer and last chunk, i.e. request.end(). chunked_stream_writer_->AppendData(nullptr, - 0, - true); + 0, + true); - if (first_call) + if (first_call) { request_->Start(); + } } else { if (buffer) { // Handling potential empty buffers. using internal::UploadOwnedIOBufferElementReader; auto element_reader = UploadOwnedIOBufferElementReader::CreateWithBuffer( - std::move(buffer)); + std::move(buffer)); upload_element_readers_.push_back( - std::unique_ptr(element_reader)); + std::unique_ptr(element_reader)); } if (is_last) { - auto elements_upload_data_stream = new net::ElementsUploadDataStream( - std::move(upload_element_readers_), - 0); + auto elements_upload_data_stream = new net::ElementsUploadDataStream( + std::move(upload_element_readers_), 0); request_->set_upload( - std::unique_ptr(elements_upload_data_stream)); + std::unique_ptr(elements_upload_data_stream)); request_->Start(); } } @@ -196,6 +213,16 @@ void AtomURLRequest::DoCancel() const { request_->Cancel(); } +void AtomURLRequest::DoSetExtraHeader(const std::string& name, + const std::string& value) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + request_->SetExtraRequestHeaderByName(name, value, true); +} +void AtomURLRequest::DoRemoveExtraHeader(const std::string& name) const { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + request_->RemoveRequestHeaderByName(name); +} + void AtomURLRequest::DoSetAuth(const base::string16& username, const base::string16& password) const { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); @@ -212,10 +239,10 @@ void AtomURLRequest::OnAuthRequired(net::URLRequest* request, DCHECK_CURRENTLY_ON(content::BrowserThread::IO); content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateAuthenticationRequired, - this, - scoped_refptr(auth_info))); + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateAuthenticationRequired, + this, + scoped_refptr(auth_info))); } void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { @@ -228,10 +255,10 @@ void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { if (status.is_success()) { // Success or pending trigger a Read. content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseStarted, - this, - response_headers)); + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateResponseStarted, + this, + response_headers)); ReadResponse(); } else if (status.status() == net::URLRequestStatus::Status::FAILED) { @@ -239,10 +266,10 @@ void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { DoCancel(); auto error = net::ErrorToString(status.ToNetError()); content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateRequestErrorOccured, - this, - std::move(error))); + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateRequestErrorOccured, + this, + std::move(error))); } // We don't report an error is the request is canceled. } @@ -288,22 +315,22 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, DoCancel(); auto error = net::ErrorToString(status.ToNetError()); content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured, - this, - std::move(error))); + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured, + this, + std::move(error))); } else if (data_ended) { content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseCompleted, this)); + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateResponseCompleted, this)); } else if (data_transfer_error) { // We abort the request on corrupted data transfer. DoCancel(); content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured, - this, - "Failed to transfer data from IO to UI thread.")); + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured, + this, + "Failed to transfer data from IO to UI thread.")); } } @@ -316,10 +343,10 @@ bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) { memcpy(buffer_copy->data(), response_read_buffer_->data(), bytes_read); return content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseData, - this, - buffer_copy)); + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateResponseData, + this, + buffer_copy)); } diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index 6a867aac08..c00616d198 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -53,9 +53,15 @@ class AtomURLRequest : public base::RefCountedThreadSafe, explicit AtomURLRequest(base::WeakPtr delegate); ~AtomURLRequest()override; + void DoInitialize(scoped_refptr, + const std::string& method, + const std::string& url); void DoWriteBuffer(scoped_refptr buffer, bool is_last); void DoCancel() const; + void DoSetExtraHeader(const std::string& name, + const std::string& value) const; + void DoRemoveExtraHeader(const std::string& name) const; void DoSetAuth(const base::string16& username, const base::string16& password) const; void DoCancelAuth() const; diff --git a/atom/common/native_mate_converters/net_converter.cc b/atom/common/native_mate_converters/net_converter.cc index d74356e956..de6a7bae98 100644 --- a/atom/common/native_mate_converters/net_converter.cc +++ b/atom/common/native_mate_converters/net_converter.cc @@ -10,6 +10,7 @@ #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/native_mate_converters/value_converter.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" #include "base/values.h" #include "native_mate/dictionary.h" #include "net/base/upload_bytes_element_reader.h" @@ -58,6 +59,32 @@ v8::Local Converter>::ToV8( return dict.GetHandle(); } +// static +v8::Local +Converter>::ToV8( + v8::Isolate* isolate, + scoped_refptr headers) { + base::DictionaryValue response_headers; + if (headers) { + size_t iter = 0; + std::string key; + std::string value; + while (headers->EnumerateHeaderLines(&iter, &key, &value)) { + key = base::ToLowerASCII(key); + if (response_headers.HasKey(key)) { + base::ListValue* values = nullptr; + if (response_headers.GetList(key, &values)) + values->AppendString(value); + } else { + std::unique_ptr values(new base::ListValue()); + values->AppendString(value); + response_headers.Set(key, std::move(values)); + } + } + } + return ConvertToV8(isolate, response_headers); +} + } // namespace mate namespace atom { diff --git a/atom/common/native_mate_converters/net_converter.h b/atom/common/native_mate_converters/net_converter.h index 37e4280695..de31f870b6 100644 --- a/atom/common/native_mate_converters/net_converter.h +++ b/atom/common/native_mate_converters/net_converter.h @@ -17,6 +17,7 @@ namespace net { class AuthChallengeInfo; class URLRequest; class X509Certificate; +class HttpResponseHeaders; } namespace mate { @@ -33,6 +34,12 @@ struct Converter> { const scoped_refptr& val); }; +template<> +struct Converter> { + static v8::Local ToV8(v8::Isolate* isolate, + scoped_refptr headers); +}; + } // namespace mate namespace atom { diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 02a3f3a164..74d6c05063 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -18,29 +18,29 @@ kSupportedProtocols.add('https:') class IncomingMessage extends Readable { constructor (urlRequest) { super() - this._url_request = urlRequest - this._shouldPush = false - this._data = [] - this._url_request.on('data', (event, chunk) => { + this.urlRequest = urlRequest + this.shouldPush = false + this.data = [] + this.urlRequest.on('data', (event, chunk) => { this._storeInternalData(chunk) this._pushInternalData() }) - this._url_request.on('end', () => { + this.urlRequest.on('end', () => { this._storeInternalData(null) this._pushInternalData() }) } get statusCode () { - return this._url_request.statusCode + return this.urlRequest.statusCode } get statusMessage () { - return this._url_request.statusMessage + return this.urlRequest.statusMessage } get headers () { - return this._url_request.rawResponseHeaders + return this.urlRequest.rawResponseHeaders } get httpVersion () { @@ -48,15 +48,11 @@ class IncomingMessage extends Readable { } get httpVersionMajor () { - return this._url_request.httpVersionMajor + return this.urlRequest.httpVersionMajor } get httpVersionMinor () { - return this._url_request.httpVersionMinor - } - - get rawHeaders () { - return this._url_request.rawResponseHeaders + return this.urlRequest.httpVersionMinor } get rawTrailers () { @@ -68,18 +64,18 @@ class IncomingMessage extends Readable { } _storeInternalData (chunk) { - this._data.push(chunk) + this.data.push(chunk) } _pushInternalData () { - while (this._shouldPush && this._data.length > 0) { - const chunk = this._data.shift() - this._shouldPush = this.push(chunk) + while (this.shouldPush && this.data.length > 0) { + const chunk = this.data.shift() + this.shouldPush = this.push(chunk) } } _read () { - this._shouldPush = true + this.shouldPush = true this._pushInternalData() } @@ -88,17 +84,17 @@ class IncomingMessage extends Readable { URLRequest.prototype._emitRequestEvent = function (async, ...rest) { if (async) { process.nextTick(() => { - this._request.emit.apply(this._request, rest) + this.clientRequest.emit.apply(this.clientRequest, rest) }) } else { - this._request.emit.apply(this._request, rest) + this.clientRequest.emit.apply(this.clientRequest, rest) } } URLRequest.prototype._emitResponseEvent = function (async, ...rest) { if (async) { process.nextTick(() => { - this._request.emit.apply(this._response, rest) + this.clientRequest.emit.apply(this._response, rest) }) } else { this._response.emit.apply(this._response, rest) @@ -165,13 +161,13 @@ class ClientRequest extends EventEmitter { }) // Set back and forward links. - this._url_request = urlRequest - urlRequest._request = this + this.urlRequest = urlRequest + urlRequest.clientRequest = this // This is a copy of the extra headers structure held by the native // net::URLRequest. The main reason is to keep the getHeader API synchronous // after the request starts. - this._extra_headers = {} + this.extraHeaders = {} if (options.headers) { const keys = Object.keys(options.headers) @@ -183,7 +179,7 @@ class ClientRequest extends EventEmitter { // Set when the request uses chunked encoding. Can be switched // to true only once and never set back to false. - this._chunkedEncoding = false + this.chunkedEncodingEnabled = false urlRequest.on('response', () => { const response = new IncomingMessage(urlRequest) @@ -197,14 +193,14 @@ class ClientRequest extends EventEmitter { } get chunkedEncoding () { - return this._chunkedEncoding + return this.chunkedEncodingEnabled } set chunkedEncoding (value) { - if (!this._url_request.notStarted) { + if (!this.urlRequest.notStarted) { throw new Error('Can\'t set the transfer encoding, headers have been sent.') } - this._chunkedEncoding = value + this.chunkedEncodingEnabled = value } setHeader (name, value) { @@ -214,13 +210,13 @@ class ClientRequest extends EventEmitter { if (value === undefined) { throw new Error('`value` required in setHeader("' + name + '", value).') } - if (!this._url_request.notStarted) { + if (!this.urlRequest.notStarted) { throw new Error('Can\'t set headers after they are sent.') } const key = name.toLowerCase() - this._extra_headers[key] = value - this._url_request.setExtraHeader(name, value) + this.extraHeaders[key] = value + this.urlRequest.setExtraHeader(name, value) } getHeader (name) { @@ -228,12 +224,12 @@ class ClientRequest extends EventEmitter { throw new Error('`name` is required for getHeader(name).') } - if (!this._extra_headers) { + if (!this.extraHeaders) { return } const key = name.toLowerCase() - return this._extra_headers[key] + return this.extraHeaders[key] } removeHeader (name) { @@ -241,13 +237,13 @@ class ClientRequest extends EventEmitter { throw new Error('`name` is required for removeHeader(name).') } - if (!this._url_request.notStarted) { + if (!this.urlRequest.notStarted) { throw new Error('Can\'t remove headers after they are sent.') } const key = name.toLowerCase() - delete this._extra_headers[key] - this._url_request.removeExtraHeader(name) + delete this.extraHeaders[key] + this.urlRequest.removeExtraHeader(name) } _write (chunk, encoding, callback, isLast) { @@ -265,13 +261,13 @@ class ClientRequest extends EventEmitter { // Since writing to the network is asynchronous, we conservatively // assume that request headers are written after delivering the first // buffer to the network IO thread. - if (this._url_request.notStarted) { - this._url_request.setChunkedUpload(this.chunkedEncoding) + if (this.urlRequest.notStarted) { + this.urlRequest.setChunkedUpload(this.chunkedEncoding) } // Headers are assumed to be sent on first call to _writeBuffer, // i.e. after the first call to write or end. - let result = this._url_request.write(chunk, isLast) + let result = this.urlRequest.write(chunk, isLast) // The write callback is fired asynchronously to mimic Node.js. if (callback) { @@ -282,7 +278,7 @@ class ClientRequest extends EventEmitter { } write (data, encoding, callback) { - if (this._url_request.finished) { + if (this.urlRequest.finished) { let error = new Error('Write after end.') process.nextTick(writeAfterEndNT, this, error, callback) return true @@ -292,7 +288,7 @@ class ClientRequest extends EventEmitter { } end (data, encoding, callback) { - if (this._url_request.finished) { + if (this.urlRequest.finished) { return false } @@ -311,7 +307,7 @@ class ClientRequest extends EventEmitter { } abort () { - this._url_request.cancel() + this.urlRequest.cancel() } } diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index 94788adefa..e1970494a8 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -949,8 +949,28 @@ describe('net module', function () { nodeRequest.end() }) - it.skip('should emit error event on server socket close', function (done) { - assert(false) + it('should emit error event on server socket close', function (done) { + const requestUrl = '/requestUrl' + server.on('request', function (request, response) { + switch (request.url) { + case requestUrl: + request.socket.destroy() + break + default: + assert(false) + } + }) + let requestErrorEventEmitted = false + const urlRequest = net.request(`${server.url}${requestUrl}`) + urlRequest.on('error', function (error) { + assert(error) + requestErrorEventEmitted = true + }) + urlRequest.on('close', function () { + assert(requestErrorEventEmitted) + done() + }) + urlRequest.end() }) }) describe('IncomingMessage API', function () { @@ -995,10 +1015,10 @@ describe('net module', function () { const statusMessage = response.statusMessage assert(typeof statusMessage === 'string') assert.equal(statusMessage, 'OK') - const rawHeaders = response.rawHeaders - assert(typeof rawHeaders === 'object') - assert(rawHeaders[customHeaderName] === - customHeaderValue) + const headers = response.headers + assert(typeof headers === 'object') + assert.deepEqual(headers[customHeaderName.toLowerCase()], + [customHeaderValue]) const httpVersion = response.httpVersion assert(typeof httpVersion === 'string') assert(httpVersion.length > 0) @@ -1078,8 +1098,60 @@ describe('net module', function () { netRequest.end() }) - it.skip('should not emit any event after close', function () { - assert(false) + it('should not emit any event after close', function (done) { + const requestUrl = '/requestUrl' + let bodyData = randomString(kOneKiloByte) + server.on('request', function (request, response) { + switch (request.url) { + case requestUrl: + response.statusCode = 200 + response.statusMessage = 'OK' + response.write(bodyData) + response.end() + break + default: + assert(false) + } + }) + let requestCloseEventEmitted = false + const urlRequest = net.request({ + method: 'GET', + url: `${server.url}${requestUrl}` + }) + urlRequest.on('response', function (response) { + assert(!requestCloseEventEmitted) + const statusCode = response.statusCode + assert.equal(statusCode, 200) + response.pause() + response.on('data', function () { + }) + response.on('end', function () { + }) + response.resume() + response.on('error', function () { + assert(!requestCloseEventEmitted) + }) + response.on('aborted', function () { + assert(!requestCloseEventEmitted) + }) + }) + urlRequest.on('finish', function () { + assert(!requestCloseEventEmitted) + }) + urlRequest.on('error', function () { + assert(!requestCloseEventEmitted) + }) + urlRequest.on('abort', function () { + assert(!requestCloseEventEmitted) + }) + urlRequest.on('close', function () { + requestCloseEventEmitted = true + // Wait so that all async events get scheduled. + setTimeout(function () { + done() + }, 100) + }) + urlRequest.end() }) }) }) From de29f2dde5ed6bfe75a13ee304beaf3cc1b8d763 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 13 Oct 2016 17:51:19 +0200 Subject: [PATCH 035/148] Fixing build: removing constness on net::HttpResponseHeaders as otherwise we would need a change in libchromiumcontent. --- atom/browser/api/atom_api_url_request.cc | 4 ++-- atom/browser/api/atom_api_url_request.h | 6 +++--- atom/browser/net/atom_url_request.cc | 4 ++-- atom/browser/net/atom_url_request.h | 2 +- atom/common/native_mate_converters/net_converter.cc | 4 ++-- atom/common/native_mate_converters/net_converter.h | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 5c47293411..c4df35dda3 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -322,7 +322,7 @@ void URLRequest::OnAuthenticationRequired( } void URLRequest::OnResponseStarted( - scoped_refptr response_headers) { + scoped_refptr response_headers) { if (request_state_.Canceled() || request_state_.Failed() || request_state_.Closed()) { @@ -394,7 +394,7 @@ std::string URLRequest::StatusMessage() const { return result; } -scoped_refptr +scoped_refptr URLRequest::RawResponseHeaders() const { return response_headers_; } diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 71e6a81ca2..1dcb901391 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -102,7 +102,7 @@ class URLRequest : public mate::EventEmitter { void OnAuthenticationRequired( scoped_refptr auth_info); void OnResponseStarted( - scoped_refptr response_headers); + scoped_refptr response_headers); void OnResponseData(scoped_refptr data); void OnResponseCompleted(); void OnRequestError(const std::string& error); @@ -178,7 +178,7 @@ class URLRequest : public mate::EventEmitter { bool CanReadHeaders() const; int StatusCode() const; std::string StatusMessage() const; - scoped_refptr RawResponseHeaders() const; + scoped_refptr RawResponseHeaders() const; uint32_t ResponseHttpVersionMajor() const; uint32_t ResponseHttpVersionMinor() const; @@ -202,7 +202,7 @@ class URLRequest : public mate::EventEmitter { // Used to implement pin/unpin. v8::Global wrapper_; - scoped_refptr response_headers_; + scoped_refptr response_headers_; base::WeakPtrFactory weak_ptr_factory_; diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index 7a3a0b1423..bbe835e926 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -249,7 +249,7 @@ void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_EQ(request, request_.get()); - scoped_refptr response_headers = + scoped_refptr response_headers = request->response_headers(); const auto& status = request_->status(); if (status.is_success()) { @@ -358,7 +358,7 @@ void AtomURLRequest::InformDelegateAuthenticationRequired( } void AtomURLRequest::InformDelegateResponseStarted( - scoped_refptr response_headers) const { + scoped_refptr response_headers) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (delegate_) delegate_->OnResponseStarted(response_headers); diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index c00616d198..b16258e5e8 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -72,7 +72,7 @@ class AtomURLRequest : public base::RefCountedThreadSafe, void InformDelegateAuthenticationRequired( scoped_refptr auth_info) const; void InformDelegateResponseStarted( - scoped_refptr) const; + scoped_refptr) const; void InformDelegateResponseData( scoped_refptr data) const; void InformDelegateResponseCompleted() const; diff --git a/atom/common/native_mate_converters/net_converter.cc b/atom/common/native_mate_converters/net_converter.cc index de6a7bae98..89120c94ab 100644 --- a/atom/common/native_mate_converters/net_converter.cc +++ b/atom/common/native_mate_converters/net_converter.cc @@ -61,9 +61,9 @@ v8::Local Converter>::ToV8( // static v8::Local -Converter>::ToV8( +Converter>::ToV8( v8::Isolate* isolate, - scoped_refptr headers) { + scoped_refptr headers) { base::DictionaryValue response_headers; if (headers) { size_t iter = 0; diff --git a/atom/common/native_mate_converters/net_converter.h b/atom/common/native_mate_converters/net_converter.h index de31f870b6..4ef9a7f339 100644 --- a/atom/common/native_mate_converters/net_converter.h +++ b/atom/common/native_mate_converters/net_converter.h @@ -35,9 +35,9 @@ struct Converter> { }; template<> -struct Converter> { +struct Converter> { static v8::Local ToV8(v8::Isolate* isolate, - scoped_refptr headers); + scoped_refptr headers); }; } // namespace mate From ad45c084ccd4755f1d8541e0d8582cdace0f3547 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Fri, 14 Oct 2016 11:37:36 +1100 Subject: [PATCH 036/148] Fix uploaddata naming --- docs/api/structures/upload-data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/structures/upload-data.md b/docs/api/structures/upload-data.md index f39b563b95..8e5c07725a 100644 --- a/docs/api/structures/upload-data.md +++ b/docs/api/structures/upload-data.md @@ -1,4 +1,4 @@ -# ThumbarButton Object +# UploadData Object * `bytes` Buffer - Content being sent. * `file` String - Path of file being uploaded. From 32c3f17f5ab9c31b783b33bb31ce3dec837a6f90 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Fri, 14 Oct 2016 13:00:03 +1100 Subject: [PATCH 037/148] Rename dcs object --- docs/api/structures/desktop-capturer-source.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/structures/desktop-capturer-source.md b/docs/api/structures/desktop-capturer-source.md index 494856bcc9..292bd014bd 100644 --- a/docs/api/structures/desktop-capturer-source.md +++ b/docs/api/structures/desktop-capturer-source.md @@ -1,4 +1,4 @@ -# Desktop Capturer Source Object +# DesktopCapturerSource Object * `id` String - The identifier of a window or screen that can be used as a `chromeMediaSourceId` constraint when calling From 10ef6749b3c17fee207948947de37ede15b72c73 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Fri, 14 Oct 2016 13:10:37 +1100 Subject: [PATCH 038/148] Source -> DesktopCapturerSource --- docs/api/desktop-capturer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/desktop-capturer.md b/docs/api/desktop-capturer.md index 56872100d5..0b6b411e03 100644 --- a/docs/api/desktop-capturer.md +++ b/docs/api/desktop-capturer.md @@ -68,7 +68,7 @@ Starts gathering information about all available desktop media sources, and calls `callback(error, sources)` when finished. `sources` is an array of [`DesktopCapturerSource`](structures/desktop-capturer-source.md) -objects, each `Source` represents a screen or an individual window that can be +objects, each `DesktopCapturerSource` represents a screen or an individual window that can be captured. [`navigator.webkitGetUserMedia`]: https://developer.mozilla.org/en/docs/Web/API/Navigator/getUserMedia From 9cc8bfae1c1ba28fb797145675479eee25bad371 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Fri, 14 Oct 2016 10:58:16 +0200 Subject: [PATCH 039/148] fixing space formatting issues. --- atom/browser/api/atom_api_url_request.cc | 6 +-- atom/browser/api/atom_api_url_request.h | 10 ++--- atom/browser/net/atom_url_request.cc | 40 +++++++++---------- atom/browser/net/atom_url_request.h | 25 ++++++------ .../native_mate_converters/net_converter.h | 5 ++- 5 files changed, 43 insertions(+), 43 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index c4df35dda3..4b0ebedb5a 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -256,7 +256,7 @@ void URLRequest::Cancel() { } bool URLRequest::SetExtraHeader(const std::string& name, - const std::string& value) { + const std::string& value) { // Request state must be in the initial non started state. if (!request_state_.NotStarted()) { // Cannot change headers after send. @@ -322,7 +322,7 @@ void URLRequest::OnAuthenticationRequired( } void URLRequest::OnResponseStarted( - scoped_refptr response_headers) { + scoped_refptr response_headers) { if (request_state_.Canceled() || request_state_.Failed() || request_state_.Closed()) { @@ -335,7 +335,7 @@ void URLRequest::OnResponseStarted( } void URLRequest::OnResponseData( - scoped_refptr buffer) { + scoped_refptr buffer) { if (request_state_.Canceled() || request_state_.Closed() || request_state_.Failed() || diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 1dcb901391..1ccbb3610d 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -95,14 +95,14 @@ class URLRequest : public mate::EventEmitter { static mate::WrappableBase* New(mate::Arguments* args); static void BuildPrototype( - v8::Isolate* isolate, - v8::Local prototype); + v8::Isolate* isolate, + v8::Local prototype); // Methods for reporting events into JavaScript. void OnAuthenticationRequired( - scoped_refptr auth_info); + scoped_refptr auth_info); void OnResponseStarted( - scoped_refptr response_headers); + scoped_refptr response_headers); void OnResponseData(scoped_refptr data); void OnResponseCompleted(); void OnRequestError(const std::string& error); @@ -110,7 +110,7 @@ class URLRequest : public mate::EventEmitter { protected: explicit URLRequest(v8::Isolate* isolate, - v8::Local wrapper); + v8::Local wrapper); ~URLRequest() override; private: diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index bbe835e926..2870e6dda5 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -14,7 +14,6 @@ #include "net/base/upload_bytes_element_reader.h" - namespace { const int kBufferSize = 4096; } // namespace @@ -23,21 +22,19 @@ namespace atom { namespace internal { - class UploadOwnedIOBufferElementReader : public net::UploadBytesElementReader { public: explicit UploadOwnedIOBufferElementReader( - scoped_refptr buffer) - : net::UploadBytesElementReader(buffer->data(), buffer->size()) - , buffer_(buffer) { + scoped_refptr buffer) + : net::UploadBytesElementReader(buffer->data(), buffer->size()), + buffer_(buffer) { } ~UploadOwnedIOBufferElementReader() override { } - static UploadOwnedIOBufferElementReader* CreateWithBuffer( - scoped_refptr buffer) { + scoped_refptr buffer) { return new UploadOwnedIOBufferElementReader(std::move(buffer)); } @@ -127,7 +124,7 @@ void AtomURLRequest::Cancel() const { } void AtomURLRequest::SetExtraHeader(const std::string& name, - const std::string& value) const { + const std::string& value) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::BrowserThread::PostTask( content::BrowserThread::IO, @@ -143,8 +140,9 @@ void AtomURLRequest::RemoveExtraHeader(const std::string& name) const { base::Bind(&AtomURLRequest::DoRemoveExtraHeader, this, name)); } -void AtomURLRequest::PassLoginInformation(const base::string16& username, - const base::string16& password) const { +void AtomURLRequest::PassLoginInformation( + const base::string16& username, + const base::string16& password) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (username.empty() || password.empty()) { content::BrowserThread::PostTask( @@ -158,8 +156,8 @@ void AtomURLRequest::PassLoginInformation(const base::string16& username, } void AtomURLRequest::DoWriteBuffer( - scoped_refptr buffer, - bool is_last) { + scoped_refptr buffer, + bool is_last) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (is_chunked_upload_) { @@ -223,8 +221,9 @@ void AtomURLRequest::DoRemoveExtraHeader(const std::string& name) const { request_->RemoveRequestHeaderByName(name); } -void AtomURLRequest::DoSetAuth(const base::string16& username, - const base::string16& password) const { +void AtomURLRequest::DoSetAuth( + const base::string16& username, + const base::string16& password) const { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); request_->SetAuth(net::AuthCredentials(username, password)); } @@ -234,8 +233,9 @@ void AtomURLRequest::DoCancelAuth() const { request_->CancelAuth(); } -void AtomURLRequest::OnAuthRequired(net::URLRequest* request, - net::AuthChallengeInfo* auth_info) { +void AtomURLRequest::OnAuthRequired( + net::URLRequest* request, + net::AuthChallengeInfo* auth_info) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); content::BrowserThread::PostTask( @@ -351,7 +351,7 @@ bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) { void AtomURLRequest::InformDelegateAuthenticationRequired( - scoped_refptr auth_info) const { + scoped_refptr auth_info) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (delegate_) delegate_->OnAuthenticationRequired(auth_info); @@ -365,7 +365,7 @@ void AtomURLRequest::InformDelegateResponseStarted( } void AtomURLRequest::InformDelegateResponseData( - scoped_refptr data) const { + scoped_refptr data) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); // Transfer ownership of the data buffer, data will be released @@ -382,7 +382,7 @@ void AtomURLRequest::InformDelegateResponseCompleted() const { } void AtomURLRequest::InformDelegateRequestErrorOccured( - const std::string& error) const { + const std::string& error) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (delegate_) @@ -390,7 +390,7 @@ void AtomURLRequest::InformDelegateRequestErrorOccured( } void AtomURLRequest::InformDelegateResponseErrorOccured( - const std::string& error) const { + const std::string& error) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (delegate_) diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index b16258e5e8..8d182a7da5 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -25,27 +25,26 @@ class AtomURLRequest : public base::RefCountedThreadSafe, public net::URLRequest::Delegate { public: static scoped_refptr Create( - AtomBrowserContext* browser_context, - const std::string& method, - const std::string& url, - base::WeakPtr delegate); + AtomBrowserContext* browser_context, + const std::string& method, + const std::string& url, + base::WeakPtr delegate); bool Write(scoped_refptr buffer, - bool is_last); + bool is_last); void SetChunkedUpload(bool is_chunked_upload); void Cancel() const; void SetExtraHeader(const std::string& name, const std::string& value) const; void RemoveExtraHeader(const std::string& name) const; void PassLoginInformation(const base::string16& username, - const base::string16& password) const; + const base::string16& password) const; protected: // Overrides of net::URLRequest::Delegate void OnAuthRequired(net::URLRequest* request, - net::AuthChallengeInfo* auth_info) override; + net::AuthChallengeInfo* auth_info) override; void OnResponseStarted(net::URLRequest* request) override; - void OnReadCompleted(net::URLRequest* request, - int bytes_read) override; + void OnReadCompleted(net::URLRequest* request, int bytes_read) override; private: friend class base::RefCountedThreadSafe; @@ -63,18 +62,18 @@ class AtomURLRequest : public base::RefCountedThreadSafe, const std::string& value) const; void DoRemoveExtraHeader(const std::string& name) const; void DoSetAuth(const base::string16& username, - const base::string16& password) const; + const base::string16& password) const; void DoCancelAuth() const; void ReadResponse(); bool CopyAndPostBuffer(int bytes_read); void InformDelegateAuthenticationRequired( - scoped_refptr auth_info) const; + scoped_refptr auth_info) const; void InformDelegateResponseStarted( - scoped_refptr) const; + scoped_refptr) const; void InformDelegateResponseData( - scoped_refptr data) const; + scoped_refptr data) const; void InformDelegateResponseCompleted() const; void InformDelegateRequestErrorOccured(const std::string& error) const; void InformDelegateResponseErrorOccured(const std::string& error) const; diff --git a/atom/common/native_mate_converters/net_converter.h b/atom/common/native_mate_converters/net_converter.h index 4ef9a7f339..e3ba6b60cc 100644 --- a/atom/common/native_mate_converters/net_converter.h +++ b/atom/common/native_mate_converters/net_converter.h @@ -36,8 +36,9 @@ struct Converter> { template<> struct Converter> { - static v8::Local ToV8(v8::Isolate* isolate, - scoped_refptr headers); + static v8::Local ToV8( + v8::Isolate* isolate, + scoped_refptr headers); }; } // namespace mate From 4347ce4a53fb957c0d388594097309c7444fe50e Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Fri, 14 Oct 2016 11:50:47 +0200 Subject: [PATCH 040/148] Formatting C++ code using ClangFormat. --- atom/browser/api/atom_api_net.cc | 19 ++-- atom/browser/api/atom_api_net.h | 2 +- atom/browser/api/atom_api_url_request.cc | 119 +++++++++-------------- atom/browser/api/atom_api_url_request.h | 1 - atom/browser/net/atom_url_request.cc | 95 +++++++----------- atom/browser/net/atom_url_request.h | 7 +- 6 files changed, 93 insertions(+), 150 deletions(-) diff --git a/atom/browser/api/atom_api_net.cc b/atom/browser/api/atom_api_net.cc index 2ce7aa3816..dac8d9ee14 100644 --- a/atom/browser/api/atom_api_net.cc +++ b/atom/browser/api/atom_api_net.cc @@ -15,9 +15,7 @@ Net::Net(v8::Isolate* isolate) { Init(isolate); } -Net::~Net() { -} - +Net::~Net() {} // static v8::Local Net::Create(v8::Isolate* isolate) { @@ -29,34 +27,33 @@ void Net::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { prototype->SetClassName(mate::StringToV8(isolate, "Net")); mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) - .SetProperty("URLRequest", &Net::URLRequest) - .SetMethod("_RequestGarbageCollectionForTesting", - &Net::RequestGarbageCollectionForTesting); + .SetProperty("URLRequest", &Net::URLRequest) + .SetMethod("_RequestGarbageCollectionForTesting", + &Net::RequestGarbageCollectionForTesting); } v8::Local Net::URLRequest(v8::Isolate* isolate) { return URLRequest::GetConstructor(isolate)->GetFunction(); } - void Net::RequestGarbageCollectionForTesting() { isolate()->RequestGarbageCollectionForTesting( v8::Isolate::GarbageCollectionType::kFullGarbageCollection); } - } // namespace api } // namespace atom - namespace { using atom::api::Net; using atom::api::URLRequest; -void Initialize(v8::Local exports, v8::Local unused, - v8::Local context, void* priv) { +void Initialize(v8::Local exports, + v8::Local unused, + v8::Local context, + void* priv) { v8::Isolate* isolate = context->GetIsolate(); URLRequest::SetConstructor(isolate, base::Bind(URLRequest::New)); diff --git a/atom/browser/api/atom_api_net.h b/atom/browser/api/atom_api_net.h index 04b882d259..0b86931978 100644 --- a/atom/browser/api/atom_api_net.h +++ b/atom/browser/api/atom_api_net.h @@ -19,6 +19,7 @@ class Net : public mate::EventEmitter { v8::Local prototype); v8::Local URLRequest(v8::Isolate* isolate); + protected: explicit Net(v8::Isolate* isolate); ~Net() override; @@ -32,5 +33,4 @@ class Net : public mate::EventEmitter { } // namespace atom - #endif // ATOM_BROWSER_API_ATOM_API_NET_H_ diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 4b0ebedb5a..393f03ddb4 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -2,9 +2,9 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. +#include "atom/browser/api/atom_api_url_request.h" #include #include "atom/browser/api/atom_api_session.h" -#include "atom/browser/api/atom_api_url_request.h" #include "atom/browser/net/atom_url_request.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/net_converter.h" @@ -12,24 +12,20 @@ #include "atom/common/node_includes.h" #include "native_mate/dictionary.h" - - namespace mate { -template<> +template <> struct Converter> { static v8::Local ToV8( v8::Isolate* isolate, scoped_refptr buffer) { - return node::Buffer::Copy(isolate, - buffer->data(), - buffer->size()).ToLocalChecked(); + return node::Buffer::Copy(isolate, buffer->data(), buffer->size()) + .ToLocalChecked(); } - static bool FromV8( - v8::Isolate* isolate, - v8::Local val, - scoped_refptr* out) { + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + scoped_refptr* out) { auto size = node::Buffer::Length(val); if (size == 0) { @@ -65,16 +61,14 @@ struct Converter> { namespace atom { namespace api { - template URLRequest::StateBase::StateBase(Flags initialState) - : state_(initialState) { -} + : state_(initialState) {} template void URLRequest::StateBase::SetFlag(Flags flag) { - state_ = static_cast(static_cast(state_) | - static_cast(flag)); + state_ = + static_cast(static_cast(state_) | static_cast(flag)); } template @@ -88,8 +82,7 @@ bool URLRequest::StateBase::IsFlagSet(Flags flag) const { } URLRequest::RequestState::RequestState() - : StateBase(RequestStateFlags::kNotStarted) { -} + : StateBase(RequestStateFlags::kNotStarted) {} bool URLRequest::RequestState::NotStarted() const { return *this == RequestStateFlags::kNotStarted; @@ -116,8 +109,7 @@ bool URLRequest::RequestState::Closed() const { } URLRequest::ResponseState::ResponseState() - : StateBase(ResponseStateFlags::kNotStarted) { -} + : StateBase(ResponseStateFlags::kNotStarted) {} bool URLRequest::ResponseState::NotStarted() const { return *this == ResponseStateFlags::kNotStarted; @@ -131,7 +123,6 @@ bool URLRequest::ResponseState::Ended() const { return IsFlagSet(ResponseStateFlags::kEnded); } - bool URLRequest::ResponseState::Failed() const { return IsFlagSet(ResponseStateFlags::kFailed); } @@ -141,8 +132,7 @@ URLRequest::URLRequest(v8::Isolate* isolate, v8::Local wrapper) InitWith(isolate, wrapper); } -URLRequest::~URLRequest() { -} +URLRequest::~URLRequest() {} // static mate::WrappableBase* URLRequest::New(mate::Arguments* args) { @@ -161,8 +151,8 @@ mate::WrappableBase* URLRequest::New(mate::Arguments* args) { auto browser_context = session->browser_context(); auto api_url_request = new URLRequest(args->isolate(), args->GetThis()); auto weak_ptr = api_url_request->weak_ptr_factory_.GetWeakPtr(); - auto atom_url_request = AtomURLRequest::Create(browser_context, method, url, - weak_ptr); + auto atom_url_request = + AtomURLRequest::Create(browser_context, method, url, weak_ptr); api_url_request->atom_request_ = atom_url_request; @@ -174,21 +164,21 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { prototype->SetClassName(mate::StringToV8(isolate, "URLRequest")); mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) - // Request API - .MakeDestroyable() - .SetMethod("write", &URLRequest::Write) - .SetMethod("cancel", &URLRequest::Cancel) - .SetMethod("setExtraHeader", &URLRequest::SetExtraHeader) - .SetMethod("removeExtraHeader", &URLRequest::RemoveExtraHeader) - .SetMethod("setChunkedUpload", &URLRequest::SetChunkedUpload) - .SetProperty("notStarted", &URLRequest::NotStarted) - .SetProperty("finished", &URLRequest::Finished) - // Response APi - .SetProperty("statusCode", &URLRequest::StatusCode) - .SetProperty("statusMessage", &URLRequest::StatusMessage) - .SetProperty("rawResponseHeaders", &URLRequest::RawResponseHeaders) - .SetProperty("httpVersionMajor", &URLRequest::ResponseHttpVersionMajor) - .SetProperty("httpVersionMinor", &URLRequest::ResponseHttpVersionMinor); + // Request API + .MakeDestroyable() + .SetMethod("write", &URLRequest::Write) + .SetMethod("cancel", &URLRequest::Cancel) + .SetMethod("setExtraHeader", &URLRequest::SetExtraHeader) + .SetMethod("removeExtraHeader", &URLRequest::RemoveExtraHeader) + .SetMethod("setChunkedUpload", &URLRequest::SetChunkedUpload) + .SetProperty("notStarted", &URLRequest::NotStarted) + .SetProperty("finished", &URLRequest::Finished) + // Response APi + .SetProperty("statusCode", &URLRequest::StatusCode) + .SetProperty("statusMessage", &URLRequest::StatusMessage) + .SetProperty("rawResponseHeaders", &URLRequest::RawResponseHeaders) + .SetProperty("httpVersionMajor", &URLRequest::ResponseHttpVersionMajor) + .SetProperty("httpVersionMinor", &URLRequest::ResponseHttpVersionMinor); } bool URLRequest::NotStarted() const { @@ -203,13 +193,10 @@ bool URLRequest::Canceled() const { return request_state_.Canceled(); } -bool URLRequest::Write( - scoped_refptr buffer, - bool is_last) { - if (request_state_.Canceled() || - request_state_.Failed() || - request_state_.Finished() || - request_state_.Closed()) { +bool URLRequest::Write(scoped_refptr buffer, + bool is_last) { + if (request_state_.Canceled() || request_state_.Failed() || + request_state_.Finished() || request_state_.Closed()) { return false; } @@ -231,10 +218,8 @@ bool URLRequest::Write( return false; } - void URLRequest::Cancel() { - if (request_state_.Canceled() || - request_state_.Closed()) { + if (request_state_.Canceled() || request_state_.Closed()) { // Cancel only once. return; } @@ -303,9 +288,8 @@ void URLRequest::SetChunkedUpload(bool is_chunked_upload) { } void URLRequest::OnAuthenticationRequired( - scoped_refptr auth_info) { - if (request_state_.Canceled() || - request_state_.Closed()) { + scoped_refptr auth_info) { + if (request_state_.Canceled() || request_state_.Closed()) { return; } @@ -315,16 +299,13 @@ void URLRequest::OnAuthenticationRequired( } EmitRequestEvent( - false, - "login", - auth_info.get(), + false, "login", auth_info.get(), base::Bind(&AtomURLRequest::PassLoginInformation, atom_request_)); } void URLRequest::OnResponseStarted( - scoped_refptr response_headers) { - if (request_state_.Canceled() || - request_state_.Failed() || + scoped_refptr response_headers) { + if (request_state_.Canceled() || request_state_.Failed() || request_state_.Closed()) { // Don't emit any event after request cancel. return; @@ -335,11 +316,9 @@ void URLRequest::OnResponseStarted( } void URLRequest::OnResponseData( - scoped_refptr buffer) { - if (request_state_.Canceled() || - request_state_.Closed() || - request_state_.Failed() || - response_state_.Failed()) { + scoped_refptr buffer) { + if (request_state_.Canceled() || request_state_.Closed() || + request_state_.Failed() || response_state_.Failed()) { // In case we received an unexpected event from Chromium net, // don't emit any data event after request cancel/error/close. return; @@ -351,10 +330,8 @@ void URLRequest::OnResponseData( } void URLRequest::OnResponseCompleted() { - if (request_state_.Canceled() || - request_state_.Closed() || - request_state_.Failed() || - response_state_.Failed()) { + if (request_state_.Canceled() || request_state_.Closed() || + request_state_.Failed() || response_state_.Failed()) { // In case we received an unexpected event from Chromium net, // don't emit any data event after request cancel/error/close. return; @@ -378,7 +355,6 @@ void URLRequest::OnResponseError(const std::string& error) { Close(); } - int URLRequest::StatusCode() const { if (response_headers_) { return response_headers_->response_code(); @@ -394,14 +370,13 @@ std::string URLRequest::StatusMessage() const { return result; } -scoped_refptr -URLRequest::RawResponseHeaders() const { +scoped_refptr URLRequest::RawResponseHeaders() const { return response_headers_; } uint32_t URLRequest::ResponseHttpVersionMajor() const { if (response_headers_) { - return response_headers_->GetHttpVersion().major_value(); + return response_headers_->GetHttpVersion().major_value(); } return 0; } diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 1ccbb3610d..e7780556bc 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -175,7 +175,6 @@ class URLRequest : public mate::EventEmitter { void RemoveExtraHeader(const std::string& name); void SetChunkedUpload(bool is_chunked_upload); - bool CanReadHeaders() const; int StatusCode() const; std::string StatusMessage() const; scoped_refptr RawResponseHeaders() const; diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index 2870e6dda5..c0d41b3fb8 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -3,17 +3,16 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. +#include "atom/browser/net/atom_url_request.h" #include #include "atom/browser/api/atom_api_url_request.h" #include "atom/browser/atom_browser_context.h" -#include "atom/browser/net/atom_url_request.h" #include "base/callback.h" #include "content/public/browser/browser_thread.h" #include "net/base/elements_upload_data_stream.h" #include "net/base/io_buffer.h" #include "net/base/upload_bytes_element_reader.h" - namespace { const int kBufferSize = 4096; } // namespace @@ -27,11 +26,9 @@ class UploadOwnedIOBufferElementReader : public net::UploadBytesElementReader { explicit UploadOwnedIOBufferElementReader( scoped_refptr buffer) : net::UploadBytesElementReader(buffer->data(), buffer->size()), - buffer_(buffer) { - } + buffer_(buffer) {} - ~UploadOwnedIOBufferElementReader() override { - } + ~UploadOwnedIOBufferElementReader() override {} static UploadOwnedIOBufferElementReader* CreateWithBuffer( scoped_refptr buffer) { @@ -49,11 +46,9 @@ class UploadOwnedIOBufferElementReader : public net::UploadBytesElementReader { AtomURLRequest::AtomURLRequest(base::WeakPtr delegate) : delegate_(delegate), is_chunked_upload_(false), - response_read_buffer_(new net::IOBuffer(kBufferSize)) { -} + response_read_buffer_(new net::IOBuffer(kBufferSize)) {} -AtomURLRequest::~AtomURLRequest() { -} +AtomURLRequest::~AtomURLRequest() {} scoped_refptr AtomURLRequest::Create( AtomBrowserContext* browser_context, @@ -71,10 +66,9 @@ scoped_refptr AtomURLRequest::Create( auto request_context_getter = browser_context->url_request_context_getter(); scoped_refptr atom_url_request(new AtomURLRequest(delegate)); if (content::BrowserThread::PostTask( - content::BrowserThread::IO, - FROM_HERE, - base::Bind(&AtomURLRequest::DoInitialize, atom_url_request, - request_context_getter, method, url))) { + content::BrowserThread::IO, FROM_HERE, + base::Bind(&AtomURLRequest::DoInitialize, atom_url_request, + request_context_getter, method, url))) { return atom_url_request; } return nullptr; @@ -90,16 +84,14 @@ void AtomURLRequest::DoInitialize( auto context = request_context_getter->GetURLRequestContext(); DCHECK(context); - request_ = context->CreateRequest(GURL(url), - net::RequestPriority::DEFAULT_PRIORITY, - this); + request_ = context->CreateRequest( + GURL(url), net::RequestPriority::DEFAULT_PRIORITY, this); request_->set_method(method); } -bool AtomURLRequest::Write( - scoped_refptr buffer, - bool is_last) { +bool AtomURLRequest::Write(scoped_refptr buffer, + bool is_last) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); return content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, @@ -117,26 +109,22 @@ void AtomURLRequest::SetChunkedUpload(bool is_chunked_upload) { void AtomURLRequest::Cancel() const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - content::BrowserThread::PostTask( - content::BrowserThread::IO, - FROM_HERE, - base::Bind(&AtomURLRequest::DoCancel, this)); + content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, + base::Bind(&AtomURLRequest::DoCancel, this)); } void AtomURLRequest::SetExtraHeader(const std::string& name, const std::string& value) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::BrowserThread::PostTask( - content::BrowserThread::IO, - FROM_HERE, + content::BrowserThread::IO, FROM_HERE, base::Bind(&AtomURLRequest::DoSetExtraHeader, this, name, value)); } void AtomURLRequest::RemoveExtraHeader(const std::string& name) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::BrowserThread::PostTask( - content::BrowserThread::IO, - FROM_HERE, + content::BrowserThread::IO, FROM_HERE, base::Bind(&AtomURLRequest::DoRemoveExtraHeader, this, name)); } @@ -174,14 +162,11 @@ void AtomURLRequest::DoWriteBuffer( if (buffer) // Non-empty buffer. - chunked_stream_writer_->AppendData(buffer->data(), - buffer->size(), + chunked_stream_writer_->AppendData(buffer->data(), buffer->size(), is_last); else if (is_last) // Empty buffer and last chunk, i.e. request.end(). - chunked_stream_writer_->AppendData(nullptr, - 0, - true); + chunked_stream_writer_->AppendData(nullptr, 0, true); if (first_call) { request_->Start(); @@ -190,8 +175,8 @@ void AtomURLRequest::DoWriteBuffer( if (buffer) { // Handling potential empty buffers. using internal::UploadOwnedIOBufferElementReader; - auto element_reader = UploadOwnedIOBufferElementReader::CreateWithBuffer( - std::move(buffer)); + auto element_reader = + UploadOwnedIOBufferElementReader::CreateWithBuffer(std::move(buffer)); upload_element_readers_.push_back( std::unique_ptr(element_reader)); } @@ -221,9 +206,8 @@ void AtomURLRequest::DoRemoveExtraHeader(const std::string& name) const { request_->RemoveRequestHeaderByName(name); } -void AtomURLRequest::DoSetAuth( - const base::string16& username, - const base::string16& password) const { +void AtomURLRequest::DoSetAuth(const base::string16& username, + const base::string16& password) const { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); request_->SetAuth(net::AuthCredentials(username, password)); } @@ -233,15 +217,13 @@ void AtomURLRequest::DoCancelAuth() const { request_->CancelAuth(); } -void AtomURLRequest::OnAuthRequired( - net::URLRequest* request, - net::AuthChallengeInfo* auth_info) { +void AtomURLRequest::OnAuthRequired(net::URLRequest* request, + net::AuthChallengeInfo* auth_info) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateAuthenticationRequired, - this, + base::Bind(&AtomURLRequest::InformDelegateAuthenticationRequired, this, scoped_refptr(auth_info))); } @@ -250,14 +232,13 @@ void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { DCHECK_EQ(request, request_.get()); scoped_refptr response_headers = - request->response_headers(); + request->response_headers(); const auto& status = request_->status(); if (status.is_success()) { // Success or pending trigger a Read. content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseStarted, - this, + base::Bind(&AtomURLRequest::InformDelegateResponseStarted, this, response_headers)); ReadResponse(); @@ -267,8 +248,7 @@ void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { auto error = net::ErrorToString(status.ToNetError()); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateRequestErrorOccured, - this, + base::Bind(&AtomURLRequest::InformDelegateRequestErrorOccured, this, std::move(error))); } // We don't report an error is the request is canceled. @@ -283,9 +263,7 @@ void AtomURLRequest::ReadResponse() { } } - -void AtomURLRequest::OnReadCompleted(net::URLRequest* request, - int bytes_read) { +void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK_EQ(request, request_.get()); @@ -308,16 +286,14 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, data_transfer_error = true; break; } - } while (request_->Read(response_read_buffer_.get(), - kBufferSize, - &bytes_read)); + } while ( + request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)); if (response_error) { DoCancel(); auto error = net::ErrorToString(status.ToNetError()); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured, - this, + base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured, this, std::move(error))); } else if (data_ended) { content::BrowserThread::PostTask( @@ -328,8 +304,7 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, DoCancel(); content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured, - this, + base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured, this, "Failed to transfer data from IO to UI thread.")); } } @@ -344,12 +319,10 @@ bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) { return content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseData, - this, + base::Bind(&AtomURLRequest::InformDelegateResponseData, this, buffer_copy)); } - void AtomURLRequest::InformDelegateAuthenticationRequired( scoped_refptr auth_info) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index 8d182a7da5..1acfd32204 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -30,8 +30,7 @@ class AtomURLRequest : public base::RefCountedThreadSafe, const std::string& url, base::WeakPtr delegate); - bool Write(scoped_refptr buffer, - bool is_last); + bool Write(scoped_refptr buffer, bool is_last); void SetChunkedUpload(bool is_chunked_upload); void Cancel() const; void SetExtraHeader(const std::string& name, const std::string& value) const; @@ -50,7 +49,7 @@ class AtomURLRequest : public base::RefCountedThreadSafe, friend class base::RefCountedThreadSafe; explicit AtomURLRequest(base::WeakPtr delegate); - ~AtomURLRequest()override; + ~AtomURLRequest() override; void DoInitialize(scoped_refptr, const std::string& method, @@ -85,7 +84,7 @@ class AtomURLRequest : public base::RefCountedThreadSafe, std::unique_ptr chunked_stream_; std::unique_ptr chunked_stream_writer_; std::vector> - upload_element_readers_; + upload_element_readers_; scoped_refptr response_read_buffer_; DISALLOW_COPY_AND_ASSIGN(AtomURLRequest); From c0c9e3ac3d675286550463d82aa2e7352ce43fd6 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Fri, 14 Oct 2016 11:51:45 +0200 Subject: [PATCH 041/148] Formatting C++ code using ClangFormat. --- atom/browser/api/atom_api_url_request.h | 52 ++++++++++++------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index e7780556bc..3198338a1b 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -94,9 +94,8 @@ class URLRequest : public mate::EventEmitter { public: static mate::WrappableBase* New(mate::Arguments* args); - static void BuildPrototype( - v8::Isolate* isolate, - v8::Local prototype); + static void BuildPrototype(v8::Isolate* isolate, + v8::Local prototype); // Methods for reporting events into JavaScript. void OnAuthenticationRequired( @@ -109,8 +108,7 @@ class URLRequest : public mate::EventEmitter { void OnResponseError(const std::string& error); protected: - explicit URLRequest(v8::Isolate* isolate, - v8::Local wrapper); + explicit URLRequest(v8::Isolate* isolate, v8::Local wrapper); ~URLRequest() override; private: @@ -118,21 +116,23 @@ class URLRequest : public mate::EventEmitter { class StateBase { public: void SetFlag(Flags flag); + protected: explicit StateBase(Flags initialState); bool operator==(Flags flag) const; bool IsFlagSet(Flags flag) const; + private: - Flags state_; + Flags state_; }; enum class RequestStateFlags { - kNotStarted = 0x0, - kStarted = 0x1, - kFinished = 0x2, - kCanceled = 0x4, - kFailed = 0x8, - kClosed = 0x10 + kNotStarted = 0x0, + kStarted = 0x1, + kFinished = 0x2, + kCanceled = 0x4, + kFailed = 0x8, + kClosed = 0x10 }; class RequestState : public StateBase { @@ -168,8 +168,7 @@ class URLRequest : public mate::EventEmitter { bool Finished() const; bool Canceled() const; bool Failed() const; - bool Write(scoped_refptr buffer, - bool is_last); + bool Write(scoped_refptr buffer, bool is_last); void Cancel(); bool SetExtraHeader(const std::string& name, const std::string& value); void RemoveExtraHeader(const std::string& name); @@ -181,14 +180,14 @@ class URLRequest : public mate::EventEmitter { uint32_t ResponseHttpVersionMajor() const; uint32_t ResponseHttpVersionMinor() const; - template - std::array, sizeof...(ArgTypes)> - BuildArgsArray(ArgTypes... args) const; + template + std::array, sizeof...(ArgTypes)> BuildArgsArray( + ArgTypes... args) const; - template + template void EmitRequestEvent(ArgTypes... args); - template + template void EmitResponseEvent(ArgTypes... args); void Close(); @@ -204,35 +203,34 @@ class URLRequest : public mate::EventEmitter { scoped_refptr response_headers_; base::WeakPtrFactory weak_ptr_factory_; - DISALLOW_COPY_AND_ASSIGN(URLRequest); }; -template +template std::array, sizeof...(ArgTypes)> URLRequest::BuildArgsArray(ArgTypes... args) const { - std::array, sizeof...(ArgTypes)> result - = { { mate::ConvertToV8(isolate(), args)... } }; + std::array, sizeof...(ArgTypes)> result = { + {mate::ConvertToV8(isolate(), args)...}}; return result; } -template +template void URLRequest::EmitRequestEvent(ArgTypes... args) { auto arguments = BuildArgsArray(args...); v8::Local _emitRequestEvent; auto wrapper = GetWrapper(); if (mate::Dictionary(isolate(), wrapper) - .Get("_emitRequestEvent", &_emitRequestEvent)) + .Get("_emitRequestEvent", &_emitRequestEvent)) _emitRequestEvent->Call(wrapper, arguments.size(), arguments.data()); } -template +template void URLRequest::EmitResponseEvent(ArgTypes... args) { auto arguments = BuildArgsArray(args...); v8::Local _emitResponseEvent; auto wrapper = GetWrapper(); if (mate::Dictionary(isolate(), wrapper) - .Get("_emitResponseEvent", &_emitResponseEvent)) + .Get("_emitResponseEvent", &_emitResponseEvent)) _emitResponseEvent->Call(wrapper, arguments.size(), arguments.data()); } From ba91bbd3979d34ad693895e8bc9e32840e39313b Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Fri, 14 Oct 2016 22:54:04 +1100 Subject: [PATCH 042/148] Fix spaces --- docs/api/structures/cookie.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/api/structures/cookie.md b/docs/api/structures/cookie.md index 7fdaa03d90..d00c35b61d 100644 --- a/docs/api/structures/cookie.md +++ b/docs/api/structures/cookie.md @@ -1,14 +1,14 @@ -# Certificate Object +# Cookie Object -* `name` String - The name of the cookie. -* `value` String - The value of the cookie. -* `domain` String - The domain of the cookie. -* `hostOnly` String - Whether the cookie is a host-only cookie. -* `path` String - The path of the cookie. -* `secure` Boolean - Whether the cookie is marked as secure. -* `httpOnly` Boolean - Whether the cookie is marked as HTTP only. -* `session` Boolean - Whether the cookie is a session cookie or a persistent - cookie with an expiration date. -* `expirationDate` Double (optional) - The expiration date of the cookie as - the number of seconds since the UNIX epoch. Not provided for session - cookies. +* `name` String - The name of the cookie. +* `value` String - The value of the cookie. +* `domain` String - The domain of the cookie. +* `hostOnly` String - Whether the cookie is a host-only cookie. +* `path` String - The path of the cookie. +* `secure` Boolean - Whether the cookie is marked as secure. +* `httpOnly` Boolean - Whether the cookie is marked as HTTP only. +* `session` Boolean - Whether the cookie is a session cookie or a persistent + cookie with an expiration date. +* `expirationDate` Double (optional) - The expiration date of the cookie as + the number of seconds since the UNIX epoch. Not provided for session + cookies. From ac9e6eda9526e8b1e163e1c6e2136e85b06d25b2 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Fri, 14 Oct 2016 17:37:39 +0200 Subject: [PATCH 043/148] Fixing a crash with pending URLRequests on shutdown. --- atom/browser/api/atom_api_url_request.cc | 32 ++++-- atom/browser/api/atom_api_url_request.h | 3 +- atom/browser/net/atom_url_request.cc | 124 ++++++++++++++++------- atom/browser/net/atom_url_request.h | 19 +++- 4 files changed, 122 insertions(+), 56 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 393f03ddb4..9a9fb28892 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -132,7 +132,14 @@ URLRequest::URLRequest(v8::Isolate* isolate, v8::Local wrapper) InitWith(isolate, wrapper); } -URLRequest::~URLRequest() {} +URLRequest::~URLRequest() { + // A request has been created in JS, it was not used and then + // it got collected, no close event to cleanup, only destructor + // is called. + if (atom_request_) { + atom_request_->Terminate(); + } +} // static mate::WrappableBase* URLRequest::New(mate::Arguments* args) { @@ -341,17 +348,15 @@ void URLRequest::OnResponseCompleted() { Close(); } -void URLRequest::OnRequestError(const std::string& error) { +void URLRequest::OnError(const std::string& error, bool isRequestError) { auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error)); - request_state_.SetFlag(RequestStateFlags::kFailed); - EmitRequestEvent(false, "error", error_object); - Close(); -} - -void URLRequest::OnResponseError(const std::string& error) { - auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error)); - response_state_.SetFlag(ResponseStateFlags::kFailed); - EmitResponseEvent(false, "error", error_object); + if (isRequestError) { + request_state_.SetFlag(RequestStateFlags::kFailed); + EmitRequestEvent(false, "error", error_object); + } else { + response_state_.SetFlag(ResponseStateFlags::kFailed); + EmitResponseEvent(false, "error", error_object); + } Close(); } @@ -398,6 +403,11 @@ void URLRequest::Close() { EmitRequestEvent(true, "close"); } unpin(); + if (atom_request_) { + // A request has been created in JS, used and then it ended. + // We release unneeded net resources. + atom_request_->Terminate(); + } atom_request_ = nullptr; } diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 3198338a1b..7a2ea6949f 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -104,8 +104,7 @@ class URLRequest : public mate::EventEmitter { scoped_refptr response_headers); void OnResponseData(scoped_refptr data); void OnResponseCompleted(); - void OnRequestError(const std::string& error); - void OnResponseError(const std::string& error); + void OnError(const std::string& error, bool isRequestError); protected: explicit URLRequest(v8::Isolate* isolate, v8::Local wrapper); diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index c0d41b3fb8..576036819f 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -48,7 +48,10 @@ AtomURLRequest::AtomURLRequest(base::WeakPtr delegate) is_chunked_upload_(false), response_read_buffer_(new net::IOBuffer(kBufferSize)) {} -AtomURLRequest::~AtomURLRequest() {} +AtomURLRequest::~AtomURLRequest() { + DCHECK(!request_context_getter_); + DCHECK(!request_); +} scoped_refptr AtomURLRequest::Create( AtomBrowserContext* browser_context, @@ -59,11 +62,15 @@ scoped_refptr AtomURLRequest::Create( DCHECK(browser_context); DCHECK(!url.empty()); - if (!browser_context || url.empty()) { + DCHECK(delegate); + if (!browser_context || url.empty() || !delegate) { return nullptr; } - auto request_context_getter = browser_context->url_request_context_getter(); + DCHECK(request_context_getter); + if (!request_context_getter) { + return nullptr; + } scoped_refptr atom_url_request(new AtomURLRequest(delegate)); if (content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, @@ -74,6 +81,13 @@ scoped_refptr AtomURLRequest::Create( return nullptr; } +void AtomURLRequest::Terminate() { + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + content::BrowserThread::PostTask( + content::BrowserThread::IO, FROM_HERE, + base::Bind(&AtomURLRequest::DoTerminate, this)); +} + void AtomURLRequest::DoInitialize( scoped_refptr request_context_getter, const std::string& method, @@ -81,15 +95,34 @@ void AtomURLRequest::DoInitialize( DCHECK_CURRENTLY_ON(content::BrowserThread::IO); DCHECK(request_context_getter); - auto context = request_context_getter->GetURLRequestContext(); + request_context_getter_ = request_context_getter; + request_context_getter_->AddObserver(this); + auto context = request_context_getter_->GetURLRequestContext(); + if (!context) { + // Called after shutdown. + DoCancelWithError("Cannot start a request after shutdown.", true); + return; + } DCHECK(context); request_ = context->CreateRequest( GURL(url), net::RequestPriority::DEFAULT_PRIORITY, this); - + if (!request_) { + DoCancelWithError("Failed to create a net::URLRequest.", true); + return; + } request_->set_method(method); } +void AtomURLRequest::DoTerminate() { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + request_.reset(); + if (request_context_getter_) { + request_context_getter_->RemoveObserver(this); + request_context_getter_ = nullptr; + } +} + bool AtomURLRequest::Write(scoped_refptr buffer, bool is_last) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); @@ -107,7 +140,7 @@ void AtomURLRequest::SetChunkedUpload(bool is_chunked_upload) { is_chunked_upload_ = is_chunked_upload; } -void AtomURLRequest::Cancel() const { +void AtomURLRequest::Cancel() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, base::Bind(&AtomURLRequest::DoCancel, this)); @@ -147,6 +180,9 @@ void AtomURLRequest::DoWriteBuffer( scoped_refptr buffer, bool is_last) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!request_) { + return; + } if (is_chunked_upload_) { // Chunked encoding case. @@ -191,32 +227,56 @@ void AtomURLRequest::DoWriteBuffer( } } -void AtomURLRequest::DoCancel() const { +void AtomURLRequest::DoCancel() { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - request_->Cancel(); + if (request_) { + request_->Cancel(); + } + DoTerminate(); } void AtomURLRequest::DoSetExtraHeader(const std::string& name, const std::string& value) const { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!request_) { + return; + } request_->SetExtraRequestHeaderByName(name, value, true); } void AtomURLRequest::DoRemoveExtraHeader(const std::string& name) const { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!request_) { + return; + } request_->RemoveRequestHeaderByName(name); } void AtomURLRequest::DoSetAuth(const base::string16& username, const base::string16& password) const { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!request_) { + return; + } request_->SetAuth(net::AuthCredentials(username, password)); } void AtomURLRequest::DoCancelAuth() const { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!request_) { + return; + } request_->CancelAuth(); } +void AtomURLRequest::DoCancelWithError(const std::string& error, + bool isRequestError) { + DoCancel(); + content::BrowserThread::PostTask( + content::BrowserThread::UI, FROM_HERE, + base::Bind(&AtomURLRequest::InformDelegateErrorOccured, this, error, + isRequestError)); +} + void AtomURLRequest::OnAuthRequired(net::URLRequest* request, net::AuthChallengeInfo* auth_info) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); @@ -229,6 +289,9 @@ void AtomURLRequest::OnAuthRequired(net::URLRequest* request, void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!request_) { + return; + } DCHECK_EQ(request, request_.get()); scoped_refptr response_headers = @@ -240,16 +303,10 @@ void AtomURLRequest::OnResponseStarted(net::URLRequest* request) { content::BrowserThread::UI, FROM_HERE, base::Bind(&AtomURLRequest::InformDelegateResponseStarted, this, response_headers)); - ReadResponse(); } else if (status.status() == net::URLRequestStatus::Status::FAILED) { // Report error on Start. - DoCancel(); - auto error = net::ErrorToString(status.ToNetError()); - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateRequestErrorOccured, this, - std::move(error))); + DoCancelWithError(net::ErrorToString(status.ToNetError()), true); } // We don't report an error is the request is canceled. } @@ -265,7 +322,9 @@ void AtomURLRequest::ReadResponse() { void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - + if (!request_) { + return; + } DCHECK_EQ(request, request_.get()); const auto status = request_->status(); @@ -289,26 +348,23 @@ void AtomURLRequest::OnReadCompleted(net::URLRequest* request, int bytes_read) { } while ( request_->Read(response_read_buffer_.get(), kBufferSize, &bytes_read)); if (response_error) { - DoCancel(); - auto error = net::ErrorToString(status.ToNetError()); - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured, this, - std::move(error))); + DoCancelWithError(net::ErrorToString(status.ToNetError()), false); } else if (data_ended) { content::BrowserThread::PostTask( content::BrowserThread::UI, FROM_HERE, base::Bind(&AtomURLRequest::InformDelegateResponseCompleted, this)); + DoTerminate(); } else if (data_transfer_error) { // We abort the request on corrupted data transfer. - DoCancel(); - content::BrowserThread::PostTask( - content::BrowserThread::UI, FROM_HERE, - base::Bind(&AtomURLRequest::InformDelegateResponseErrorOccured, this, - "Failed to transfer data from IO to UI thread.")); + DoCancelWithError("Failed to transfer data from IO to UI thread.", false); } } +void AtomURLRequest::OnContextShuttingDown() { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + DoCancel(); +} + bool AtomURLRequest::CopyAndPostBuffer(int bytes_read) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); @@ -354,20 +410,12 @@ void AtomURLRequest::InformDelegateResponseCompleted() const { delegate_->OnResponseCompleted(); } -void AtomURLRequest::InformDelegateRequestErrorOccured( - const std::string& error) const { +void AtomURLRequest::InformDelegateErrorOccured(const std::string& error, + bool isRequestError) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (delegate_) - delegate_->OnRequestError(error); -} - -void AtomURLRequest::InformDelegateResponseErrorOccured( - const std::string& error) const { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - if (delegate_) - delegate_->OnResponseError(error); + delegate_->OnError(error, isRequestError); } } // namespace atom diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index 1acfd32204..3efccae50f 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -18,21 +18,24 @@ #include "net/base/upload_element_reader.h" #include "net/http/http_response_headers.h" #include "net/url_request/url_request.h" +#include "net/url_request/url_request_context_getter_observer.h" namespace atom { class AtomURLRequest : public base::RefCountedThreadSafe, - public net::URLRequest::Delegate { + public net::URLRequest::Delegate, + public net::URLRequestContextGetterObserver { public: static scoped_refptr Create( AtomBrowserContext* browser_context, const std::string& method, const std::string& url, base::WeakPtr delegate); + void Terminate(); bool Write(scoped_refptr buffer, bool is_last); void SetChunkedUpload(bool is_chunked_upload); - void Cancel() const; + void Cancel(); void SetExtraHeader(const std::string& name, const std::string& value) const; void RemoveExtraHeader(const std::string& name) const; void PassLoginInformation(const base::string16& username, @@ -45,6 +48,9 @@ class AtomURLRequest : public base::RefCountedThreadSafe, void OnResponseStarted(net::URLRequest* request) override; void OnReadCompleted(net::URLRequest* request, int bytes_read) override; + // Overrides of net::URLRequestContextGetterObserver + void OnContextShuttingDown() override; + private: friend class base::RefCountedThreadSafe; @@ -54,15 +60,17 @@ class AtomURLRequest : public base::RefCountedThreadSafe, void DoInitialize(scoped_refptr, const std::string& method, const std::string& url); + void DoTerminate(); void DoWriteBuffer(scoped_refptr buffer, bool is_last); - void DoCancel() const; + void DoCancel(); void DoSetExtraHeader(const std::string& name, const std::string& value) const; void DoRemoveExtraHeader(const std::string& name) const; void DoSetAuth(const base::string16& username, const base::string16& password) const; void DoCancelAuth() const; + void DoCancelWithError(const std::string& error, bool isRequestError); void ReadResponse(); bool CopyAndPostBuffer(int bytes_read); @@ -74,11 +82,12 @@ class AtomURLRequest : public base::RefCountedThreadSafe, void InformDelegateResponseData( scoped_refptr data) const; void InformDelegateResponseCompleted() const; - void InformDelegateRequestErrorOccured(const std::string& error) const; - void InformDelegateResponseErrorOccured(const std::string& error) const; + void InformDelegateErrorOccured(const std::string& error, + bool isRequestError) const; base::WeakPtr delegate_; std::unique_ptr request_; + scoped_refptr request_context_getter_; bool is_chunked_upload_; std::unique_ptr chunked_stream_; From 0e13b8dd015439798afe1ae3c79ecad7064ed8b0 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Fri, 14 Oct 2016 17:57:37 +0200 Subject: [PATCH 044/148] making the net module usable only after the ready event. --- lib/browser/api/net.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 74d6c05063..a0d39c636e 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -7,6 +7,7 @@ const Readable = require('stream').Readable const binding = process.atomBinding('net') const {net, Net} = binding const {URLRequest} = net +const {app} = require('electron') Object.setPrototypeOf(Net.prototype, EventEmitter.prototype) Object.setPrototypeOf(URLRequest.prototype, EventEmitter.prototype) @@ -106,6 +107,10 @@ class ClientRequest extends EventEmitter { constructor (options, callback) { super() + if (!app.isReady()) { + throw new Error('net module can only be used after app is ready') + } + if (typeof options === 'string') { options = url.parse(options) } else { From bd34db256b589cba38d25013917aafc66064d20d Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Sat, 15 Oct 2016 01:00:54 +0530 Subject: [PATCH 045/148] browser: fix race in creation of default browser context by AtomAccessTokenStore --- atom/browser/atom_access_token_store.cc | 43 +++++++++++++------------ atom/browser/atom_access_token_store.h | 9 ++++++ 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/atom/browser/atom_access_token_store.cc b/atom/browser/atom_access_token_store.cc index b4e19086d4..a92112db82 100644 --- a/atom/browser/atom_access_token_store.cc +++ b/atom/browser/atom_access_token_store.cc @@ -17,7 +17,7 @@ using content::BrowserThread; namespace atom { -namespace { +namespace internal { // Loads access tokens and other necessary data on the UI thread, and // calls back to the originator on the originating thread. @@ -27,12 +27,15 @@ class TokenLoadingJob : public base::RefCountedThreadSafe { const content::AccessTokenStore::LoadAccessTokensCallback& callback) : callback_(callback), request_context_getter_(nullptr) {} - void Run() { - BrowserThread::PostTaskAndReply( - BrowserThread::UI, - FROM_HERE, - base::Bind(&TokenLoadingJob::PerformWorkOnUIThread, this), - base::Bind(&TokenLoadingJob::RespondOnOriginatingThread, this)); + void Run(AtomBrowserContext* browser_context) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + request_context_getter_ = browser_context->GetRequestContext(); + std::unique_ptr env(base::Environment::Create()); + if (!env->GetVar("GOOGLE_API_KEY", &api_key_)) + api_key_ = GOOGLEAPIS_API_KEY; + BrowserThread::PostTask( + BrowserThread::IO, FROM_HERE, + base::Bind(&TokenLoadingJob::RespondOnIOThread, this)); } private: @@ -40,16 +43,7 @@ class TokenLoadingJob : public base::RefCountedThreadSafe { ~TokenLoadingJob() {} - void PerformWorkOnUIThread() { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - auto browser_context = AtomBrowserContext::From("", false); - request_context_getter_ = browser_context->GetRequestContext(); - std::unique_ptr env(base::Environment::Create()); - if (!env->GetVar("GOOGLE_API_KEY", &api_key_)) - api_key_ = GOOGLEAPIS_API_KEY; - } - - void RespondOnOriginatingThread() { + void RespondOnIOThread() { // Equivalent to access_token_map[kGeolocationProviderURL]. // Somehow base::string16 is causing compilation errors when used in a pair // of std::map on Linux, this can work around it. @@ -66,9 +60,10 @@ class TokenLoadingJob : public base::RefCountedThreadSafe { std::string api_key_; }; -} // namespace +} // namespace internal AtomAccessTokenStore::AtomAccessTokenStore() { + browser_context_ = AtomBrowserContext::From("", false); content::GeolocationProvider::GetInstance()->UserDidOptIntoLocationServices(); } @@ -77,8 +72,16 @@ AtomAccessTokenStore::~AtomAccessTokenStore() { void AtomAccessTokenStore::LoadAccessTokens( const LoadAccessTokensCallback& callback) { - scoped_refptr job(new TokenLoadingJob(callback)); - job->Run(); + scoped_refptr job( + new internal::TokenLoadingJob(callback)); + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, + base::Bind(&AtomAccessTokenStore::RunTokenLoadingJob, + this, base::RetainedRef(job))); +} + +void AtomAccessTokenStore::RunTokenLoadingJob( + scoped_refptr job) { + job->Run(browser_context_.get()); } void AtomAccessTokenStore::SaveAccessToken(const GURL& server_url, diff --git a/atom/browser/atom_access_token_store.h b/atom/browser/atom_access_token_store.h index d70d44a0cd..4ebe1a0bc3 100644 --- a/atom/browser/atom_access_token_store.h +++ b/atom/browser/atom_access_token_store.h @@ -9,6 +9,12 @@ namespace atom { +class AtomBrowserContext; + +namespace internal { +class TokenLoadingJob; +} + class AtomAccessTokenStore : public content::AccessTokenStore { public: AtomAccessTokenStore(); @@ -21,6 +27,9 @@ class AtomAccessTokenStore : public content::AccessTokenStore { const base::string16& access_token) override; private: + void RunTokenLoadingJob(scoped_refptr job); + + scoped_refptr browser_context_; DISALLOW_COPY_AND_ASSIGN(AtomAccessTokenStore); }; From 194b14100e08a9043364e308f83d53433b52fb05 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Fri, 14 Oct 2016 17:16:39 -0500 Subject: [PATCH 046/148] add the 'webpreferences' attribute to webviews --- docs/api/web-view-tag.md | 14 +++++++++++ lib/browser/guest-view-manager.js | 25 ++++++++++++++++++++ lib/renderer/web-view/web-view-attributes.js | 8 +++++++ lib/renderer/web-view/web-view-constants.js | 1 + 4 files changed, 48 insertions(+) diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index 512300c9f6..c5d7c7b958 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -194,6 +194,20 @@ value will fail with a DOM exception. If "on", the guest page will be allowed to open new windows. +### `webpreferences` + +```html + +``` + +A list of strings which specifies the web preferences to be set on the webview, separated by `,`. +The full list of supported preference strings can be found in [BrowserWindow](browser-window.md#new-browserwindowoptions) + +The string follows the same format as the features string in `window.open`. +A name by itself is given a `true` boolean value. +A preference can be set to another value by including an `=`, followed by the value. +Special values `yes` and `1` are interpreted as true, while `no` and `0` are interpreted as false. + ### `blinkfeatures` ```html diff --git a/lib/browser/guest-view-manager.js b/lib/browser/guest-view-manager.js index df2589a9bc..b62e7cf2bf 100644 --- a/lib/browser/guest-view-manager.js +++ b/lib/browser/guest-view-manager.js @@ -184,6 +184,31 @@ const attachGuest = function (embedder, elementInstanceId, guestInstanceId, para disableBlinkFeatures: params.disableblinkfeatures } + // parse the 'webpreferences' attribute string, if set + // this uses the same parsing rules as window.open uses for its features + if (typeof params.webpreferences === 'string') { + // split the attribute's value by ',' + let webpreferencesTokens = params.webpreferences.split(/,\s*/) + for (i = 0, len = webpreferencesTokens.length; i < len; i++) { + // expected form is either a name by itself (true boolean flag) + // or a key/value, in the form of 'name=value' + // split the tokens by '=' + let pref = webpreferencesTokens[i] + let prefTokens = pref.split(/\s*=/) + name = prefTokens[0] + value = prefTokens[1] + if (!name) continue + + // interpret the value as a boolean, if possible + value = (value === 'yes' || value === '1') ? true : (value === 'no' || value === '0') ? false : value + if (value === undefined) { + // no value was specified, default it to true + value = true + } + webPreferences[name] = value + } + } + if (params.preload) { webPreferences.preloadURL = params.preload } diff --git a/lib/renderer/web-view/web-view-attributes.js b/lib/renderer/web-view/web-view-attributes.js index 3bbc833111..7c5cf81e4b 100644 --- a/lib/renderer/web-view/web-view-attributes.js +++ b/lib/renderer/web-view/web-view-attributes.js @@ -312,6 +312,13 @@ class DisableBlinkFeaturesAttribute extends WebViewAttribute { } } +// Attribute that specifies the web preferences to be enabled. +class WebPreferencesAttribute extends WebViewAttribute { + constructor (webViewImpl) { + super(webViewConstants.ATTRIBUTE_WEBPREFERENCES, webViewImpl) + } +} + // Sets up all of the webview attributes. WebViewImpl.prototype.setupWebViewAttributes = function () { this.attributes = {} @@ -328,6 +335,7 @@ WebViewImpl.prototype.setupWebViewAttributes = function () { this.attributes[webViewConstants.ATTRIBUTE_BLINKFEATURES] = new BlinkFeaturesAttribute(this) this.attributes[webViewConstants.ATTRIBUTE_DISABLEBLINKFEATURES] = new DisableBlinkFeaturesAttribute(this) this.attributes[webViewConstants.ATTRIBUTE_GUESTINSTANCE] = new GuestInstanceAttribute(this) + this.attributes[webviewConstants.ATTRIBUTE_WEBPREFERENCES] = new WebPreferencesAttribute(this) const autosizeAttributes = [webViewConstants.ATTRIBUTE_MAXHEIGHT, webViewConstants.ATTRIBUTE_MAXWIDTH, webViewConstants.ATTRIBUTE_MINHEIGHT, webViewConstants.ATTRIBUTE_MINWIDTH] autosizeAttributes.forEach((attribute) => { diff --git a/lib/renderer/web-view/web-view-constants.js b/lib/renderer/web-view/web-view-constants.js index 5aed6d5ea9..80fcaf91f2 100644 --- a/lib/renderer/web-view/web-view-constants.js +++ b/lib/renderer/web-view/web-view-constants.js @@ -18,6 +18,7 @@ module.exports = { ATTRIBUTE_BLINKFEATURES: 'blinkfeatures', ATTRIBUTE_DISABLEBLINKFEATURES: 'disableblinkfeatures', ATTRIBUTE_GUESTINSTANCE: 'guestinstance', + ATTRIBUTE_WEBPREFERENCES: 'webpreferences', // Internal attribute. ATTRIBUTE_INTERNALINSTANCEID: 'internalinstanceid', From e7962c7ba2421c809134f38fd82d0e5ca2e2c2a9 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Fri, 14 Oct 2016 18:04:33 -0500 Subject: [PATCH 047/148] fixes and tests for webview 'webpreferences' attr --- lib/browser/guest-view-manager.js | 5 ++-- lib/renderer/web-view/web-view-attributes.js | 2 +- spec/webview-spec.js | 27 ++++++++++++++++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/lib/browser/guest-view-manager.js b/lib/browser/guest-view-manager.js index b62e7cf2bf..c4b0022f67 100644 --- a/lib/browser/guest-view-manager.js +++ b/lib/browser/guest-view-manager.js @@ -188,6 +188,7 @@ const attachGuest = function (embedder, elementInstanceId, guestInstanceId, para // this uses the same parsing rules as window.open uses for its features if (typeof params.webpreferences === 'string') { // split the attribute's value by ',' + let i, len let webpreferencesTokens = params.webpreferences.split(/,\s*/) for (i = 0, len = webpreferencesTokens.length; i < len; i++) { // expected form is either a name by itself (true boolean flag) @@ -195,8 +196,8 @@ const attachGuest = function (embedder, elementInstanceId, guestInstanceId, para // split the tokens by '=' let pref = webpreferencesTokens[i] let prefTokens = pref.split(/\s*=/) - name = prefTokens[0] - value = prefTokens[1] + let name = prefTokens[0] + let value = prefTokens[1] if (!name) continue // interpret the value as a boolean, if possible diff --git a/lib/renderer/web-view/web-view-attributes.js b/lib/renderer/web-view/web-view-attributes.js index 7c5cf81e4b..f87fca3122 100644 --- a/lib/renderer/web-view/web-view-attributes.js +++ b/lib/renderer/web-view/web-view-attributes.js @@ -335,7 +335,7 @@ WebViewImpl.prototype.setupWebViewAttributes = function () { this.attributes[webViewConstants.ATTRIBUTE_BLINKFEATURES] = new BlinkFeaturesAttribute(this) this.attributes[webViewConstants.ATTRIBUTE_DISABLEBLINKFEATURES] = new DisableBlinkFeaturesAttribute(this) this.attributes[webViewConstants.ATTRIBUTE_GUESTINSTANCE] = new GuestInstanceAttribute(this) - this.attributes[webviewConstants.ATTRIBUTE_WEBPREFERENCES] = new WebPreferencesAttribute(this) + this.attributes[webViewConstants.ATTRIBUTE_WEBPREFERENCES] = new WebPreferencesAttribute(this) const autosizeAttributes = [webViewConstants.ATTRIBUTE_MAXHEIGHT, webViewConstants.ATTRIBUTE_MAXWIDTH, webViewConstants.ATTRIBUTE_MINHEIGHT, webViewConstants.ATTRIBUTE_MINWIDTH] autosizeAttributes.forEach((attribute) => { diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 1c49688ade..059fc72288 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -406,6 +406,33 @@ describe(' tag', function () { }) }) + describe('webpreferences attribute', function () { + it('can enable nodeintegration', function (done) { + webview.addEventListener('console-message', function (e) { + assert.equal(e.message, 'function object object') + done() + }) + webview.setAttribute('webpreferences', 'nodeIntegration') + webview.src = 'file://' + fixtures + '/pages/d.html' + document.body.appendChild(webview) + }) + + it('can disables web security and enable nodeintegration', function (done) { + var jqueryPath = path.join(__dirname, '/static/jquery-2.0.3.min.js') + var src = ` ` + var encoded = btoa(unescape(encodeURIComponent(src))) + var listener = function (e) { + assert.equal(e.message, 'ok function') + webview.removeEventListener('console-message', listener) + done() + } + webview.addEventListener('console-message', listener) + webview.setAttribute('webpreferences', 'webSecurity=no, nodeIntegration=yes') + webview.src = 'data:text/html;base64,' + encoded + document.body.appendChild(webview) + }) + }) + describe('new-window event', function () { if (process.env.TRAVIS === 'true' && process.platform === 'darwin') { return From c6ae27c7c95272611125fea7bc9dc763934d54cb Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Mon, 17 Oct 2016 10:38:10 +0200 Subject: [PATCH 048/148] Adding a stability test: non referenced, unused requests are collected without crash. --- spec/api-net-spec.js | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index e1970494a8..e2236438ec 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -25,7 +25,7 @@ const kOneKiloByte = 1024 const kOneMegaByte = kOneKiloByte * kOneKiloByte describe('net module', function () { - // this.timeout(0) + this.timeout(0) describe('HTTP basics', function () { let server beforeEach(function (done) { @@ -1154,4 +1154,34 @@ describe('net module', function () { urlRequest.end() }) }) + describe('Stability and performance', function(done) { + let server + beforeEach(function (done) { + server = http.createServer() + server.listen(0, '127.0.0.1', function () { + server.url = 'http://127.0.0.1:' + server.address().port + done() + }) + }) + + afterEach(function () { + server.close() + server = null + }) + + it.only('should free unreferenced, never-started request objects', function() { + const requestUrl = '/requestUrl' + const urlRequest = net.request( `${server.url}${requestUrl}`) + process.nextTick(function() { + net._RequestGarbageCollectionForTesting() + process.nextTick(done) + }) + }) + it.skip('should not collect on-going requests', function(done) { + assert(false) + }) + it.skip('should collect unreferenced, ended requests', function(done) { + assert(false) + }) + } }) From 9b4e9c642ab4b8ba5004ae3552e787f7979d335a Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Mon, 17 Oct 2016 11:51:20 +0200 Subject: [PATCH 049/148] Making test code run directly in main browser context to avoid rpc persistent handles. --- spec/api-net-spec.js | 17 +++++++++++++---- spec/static/main.js | 2 ++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index e2236438ec..4b1c2f48af 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -1,5 +1,6 @@ const assert = require('assert') const {remote} = require('electron') +const {ipcRenderer} = require('electron') const http = require('http') const url = require('url') const {net} = remote @@ -1169,13 +1170,21 @@ describe('net module', function () { server = null }) - it.only('should free unreferenced, never-started request objects', function() { + it.only('should free unreferenced, never-started request objects', function(done) { const requestUrl = '/requestUrl' - const urlRequest = net.request( `${server.url}${requestUrl}`) + ipcRenderer.on('api-net-spec-done', function() { + done() + }) + const testCode = ` + // Load the net module in the main browser process. + const {net} = require('electron') + const urlRequest = net.request('${server.url}${requestUrl}') process.nextTick(function() { net._RequestGarbageCollectionForTesting() - process.nextTick(done) + event.sender.send('api-net-spec-done') }) + ` + ipcRenderer.send('eval', testCode) }) it.skip('should not collect on-going requests', function(done) { assert(false) @@ -1183,5 +1192,5 @@ describe('net module', function () { it.skip('should collect unreferenced, ended requests', function(done) { assert(false) }) - } + }) }) diff --git a/spec/static/main.js b/spec/static/main.js index e910e4de2c..9a30fd8170 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -8,6 +8,7 @@ const ipcMain = electron.ipcMain const dialog = electron.dialog const BrowserWindow = electron.BrowserWindow const protocol = electron.protocol +const v8 = require('v8'); const Coverage = require('electabul').Coverage const fs = require('fs') @@ -24,6 +25,7 @@ var argv = require('yargs') var window = null process.port = 0 // will be used by crash-reporter spec. +v8.setFlagsFromString('--expose_gc') app.commandLine.appendSwitch('js-flags', '--expose_gc') app.commandLine.appendSwitch('ignore-certificate-errors') app.commandLine.appendSwitch('disable-renderer-backgrounding') From 5cbbd6efe600daafc2a46539b82642316870b6af Mon Sep 17 00:00:00 2001 From: deepak1556 Date: Mon, 17 Oct 2016 16:03:24 +0530 Subject: [PATCH 050/148] session: exclude hosts from CT verification if they are handled by custom cert verifiers --- atom/browser/atom_browser_context.cc | 15 +++++++++--- atom/browser/atom_browser_context.h | 4 +++ atom/browser/net/atom_cert_verifier.cc | 19 +++++++++----- atom/browser/net/atom_cert_verifier.h | 5 +++- atom/browser/net/atom_ct_delegate.cc | 34 ++++++++++++++++++++++++++ atom/browser/net/atom_ct_delegate.h | 33 +++++++++++++++++++++++++ filenames.gypi | 2 ++ 7 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 atom/browser/net/atom_ct_delegate.cc create mode 100644 atom/browser/net/atom_ct_delegate.h diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index 63c8c81fb4..e076fe85c1 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -12,6 +12,7 @@ #include "atom/browser/browser.h" #include "atom/browser/net/asar/asar_protocol_handler.h" #include "atom/browser/net/atom_cert_verifier.h" +#include "atom/browser/net/atom_ct_delegate.h" #include "atom/browser/net/atom_network_delegate.h" #include "atom/browser/net/atom_ssl_config_service.h" #include "atom/browser/net/atom_url_request_job_factory.h" @@ -67,10 +68,11 @@ std::string RemoveWhitespace(const std::string& str) { } // namespace -AtomBrowserContext::AtomBrowserContext( - const std::string& partition, bool in_memory, - const base::DictionaryValue& options) +AtomBrowserContext::AtomBrowserContext(const std::string& partition, + bool in_memory, + const base::DictionaryValue& options) : brightray::BrowserContext(partition, in_memory), + ct_delegate_(new AtomCTDelegate), network_delegate_(new AtomNetworkDelegate), cookie_delegate_(new AtomCookieDelegate) { // Construct user agent string. @@ -190,7 +192,7 @@ content::PermissionManager* AtomBrowserContext::GetPermissionManager() { } std::unique_ptr AtomBrowserContext::CreateCertVerifier() { - return base::WrapUnique(new AtomCertVerifier); + return base::WrapUnique(new AtomCertVerifier(ct_delegate_.get())); } net::SSLConfigService* AtomBrowserContext::CreateSSLConfigService() { @@ -205,6 +207,11 @@ std::vector AtomBrowserContext::GetCookieableSchemes() { return default_schemes; } +net::TransportSecurityState::RequireCTDelegate* +AtomBrowserContext::GetRequireCTDelegate() { + return ct_delegate_.get(); +} + void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) { pref_registry->RegisterFilePathPref(prefs::kSelectFileLastDirectory, base::FilePath()); diff --git a/atom/browser/atom_browser_context.h b/atom/browser/atom_browser_context.h index 0ff1cc6321..f149e62cb2 100644 --- a/atom/browser/atom_browser_context.h +++ b/atom/browser/atom_browser_context.h @@ -15,6 +15,7 @@ namespace atom { class AtomBlobReader; +class AtomCTDelegate; class AtomDownloadManagerDelegate; class AtomNetworkDelegate; class AtomPermissionManager; @@ -42,6 +43,8 @@ class AtomBrowserContext : public brightray::BrowserContext { std::unique_ptr CreateCertVerifier() override; net::SSLConfigService* CreateSSLConfigService() override; std::vector GetCookieableSchemes() override; + net::TransportSecurityState::RequireCTDelegate* GetRequireCTDelegate() + override; // content::BrowserContext: content::DownloadManagerDelegate* GetDownloadManagerDelegate() override; @@ -67,6 +70,7 @@ class AtomBrowserContext : public brightray::BrowserContext { std::unique_ptr guest_manager_; std::unique_ptr permission_manager_; std::unique_ptr blob_reader_; + std::unique_ptr ct_delegate_; std::string user_agent_; bool use_cache_; diff --git a/atom/browser/net/atom_cert_verifier.cc b/atom/browser/net/atom_cert_verifier.cc index 7fb2ce7229..9892845cc8 100644 --- a/atom/browser/net/atom_cert_verifier.cc +++ b/atom/browser/net/atom_cert_verifier.cc @@ -5,9 +5,11 @@ #include "atom/browser/net/atom_cert_verifier.h" #include "atom/browser/browser.h" +#include "atom/browser/net/atom_ct_delegate.h" #include "atom/common/native_mate_converters/net_converter.h" #include "content/public/browser/browser_thread.h" #include "net/base/net_errors.h" +#include "net/cert/cert_verify_result.h" #include "net/cert/crl_set.h" #include "net/cert/x509_certificate.h" @@ -28,12 +30,11 @@ void OnResult( } // namespace -AtomCertVerifier::AtomCertVerifier() - : default_cert_verifier_(net::CertVerifier::CreateDefault()) { -} +AtomCertVerifier::AtomCertVerifier(AtomCTDelegate* ct_delegate) + : default_cert_verifier_(net::CertVerifier::CreateDefault()), + ct_delegate_(ct_delegate) {} -AtomCertVerifier::~AtomCertVerifier() { -} +AtomCertVerifier::~AtomCertVerifier() {} void AtomCertVerifier::SetVerifyProc(const VerifyProc& proc) { verify_proc_ = proc; @@ -48,9 +49,15 @@ int AtomCertVerifier::Verify( const net::BoundNetLog& net_log) { DCHECK_CURRENTLY_ON(BrowserThread::IO); - if (verify_proc_.is_null()) + if (verify_proc_.is_null()) { + ct_delegate_->ClearCTExcludedHostsList(); return default_cert_verifier_->Verify( params, crl_set, verify_result, callback, out_req, net_log); + } + + verify_result->Reset(); + verify_result->verified_cert = params.certificate(); + ct_delegate_->AddCTExcludedHost(params.hostname()); BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, diff --git a/atom/browser/net/atom_cert_verifier.h b/atom/browser/net/atom_cert_verifier.h index 74b8f2784c..7582fae74f 100644 --- a/atom/browser/net/atom_cert_verifier.h +++ b/atom/browser/net/atom_cert_verifier.h @@ -12,9 +12,11 @@ namespace atom { +class AtomCTDelegate; + class AtomCertVerifier : public net::CertVerifier { public: - AtomCertVerifier(); + explicit AtomCertVerifier(AtomCTDelegate* ct_delegate); virtual ~AtomCertVerifier(); using VerifyProc = @@ -37,6 +39,7 @@ class AtomCertVerifier : public net::CertVerifier { private: VerifyProc verify_proc_; std::unique_ptr default_cert_verifier_; + AtomCTDelegate* ct_delegate_; DISALLOW_COPY_AND_ASSIGN(AtomCertVerifier); }; diff --git a/atom/browser/net/atom_ct_delegate.cc b/atom/browser/net/atom_ct_delegate.cc new file mode 100644 index 0000000000..66d6c93adb --- /dev/null +++ b/atom/browser/net/atom_ct_delegate.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2016 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/net/atom_ct_delegate.h" + +#include "content/public/browser/browser_thread.h" + +namespace atom { + +AtomCTDelegate::AtomCTDelegate() {} + +AtomCTDelegate::~AtomCTDelegate() {} + +void AtomCTDelegate::AddCTExcludedHost(const std::string& host) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + ct_excluded_hosts_.insert(host); +} + +void AtomCTDelegate::ClearCTExcludedHostsList() { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + ct_excluded_hosts_.clear(); +} + +AtomCTDelegate::CTRequirementLevel AtomCTDelegate::IsCTRequiredForHost( + const std::string& host) { + DCHECK_CURRENTLY_ON(content::BrowserThread::IO); + if (!ct_excluded_hosts_.empty() && + (ct_excluded_hosts_.find(host) != ct_excluded_hosts_.end())) + return CTRequirementLevel::NOT_REQUIRED; + return CTRequirementLevel::DEFAULT; +} + +} // namespace atom diff --git a/atom/browser/net/atom_ct_delegate.h b/atom/browser/net/atom_ct_delegate.h new file mode 100644 index 0000000000..680071eaa0 --- /dev/null +++ b/atom/browser/net/atom_ct_delegate.h @@ -0,0 +1,33 @@ +// Copyright (c) 2016 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_NET_ATOM_CT_DELEGATE_H_ +#define ATOM_BROWSER_NET_ATOM_CT_DELEGATE_H_ + +#include +#include + +#include "net/http/transport_security_state.h" + +namespace atom { + +class AtomCTDelegate : public net::TransportSecurityState::RequireCTDelegate { + public: + AtomCTDelegate(); + ~AtomCTDelegate() override; + + void AddCTExcludedHost(const std::string& host); + void ClearCTExcludedHostsList(); + + // net::TransportSecurityState::RequireCTDelegate: + CTRequirementLevel IsCTRequiredForHost(const std::string& host) override; + + private: + std::set ct_excluded_hosts_; + DISALLOW_COPY_AND_ASSIGN(AtomCTDelegate); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_NET_ATOM_CT_DELEGATE_H_ diff --git a/filenames.gypi b/filenames.gypi index 9c4b42f622..f1ee8d069c 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -227,6 +227,8 @@ 'atom/browser/net/asar/url_request_asar_job.h', 'atom/browser/net/atom_cert_verifier.cc', 'atom/browser/net/atom_cert_verifier.h', + 'atom/browser/net/atom_ct_delegate.cc', + 'atom/browser/net/atom_ct_delegate.h', 'atom/browser/net/atom_cookie_delegate.cc', 'atom/browser/net/atom_cookie_delegate.h', 'atom/browser/net/atom_network_delegate.cc', From c198828e58a9fa4f0131957e4699bebe351a1230 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Mon, 17 Oct 2016 19:02:25 +0200 Subject: [PATCH 051/148] Adding gc tests: fixing a memory leak with C++ URLRequest objects. --- atom/browser/api/atom_api_url_request.h | 2 + lib/browser/api/net.js | 2 +- spec/api-net-spec.js | 116 +++++++++++++++++++----- spec/static/main.js | 2 +- 4 files changed, 95 insertions(+), 27 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 7a2ea6949f..f59f8bc72f 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -215,6 +215,7 @@ URLRequest::BuildArgsArray(ArgTypes... args) const { template void URLRequest::EmitRequestEvent(ArgTypes... args) { + v8::HandleScope handle_scope(isolate()); auto arguments = BuildArgsArray(args...); v8::Local _emitRequestEvent; auto wrapper = GetWrapper(); @@ -225,6 +226,7 @@ void URLRequest::EmitRequestEvent(ArgTypes... args) { template void URLRequest::EmitResponseEvent(ArgTypes... args) { + v8::HandleScope handle_scope(isolate()); auto arguments = BuildArgsArray(args...); v8::Local _emitResponseEvent; auto wrapper = GetWrapper(); diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index a0d39c636e..ef76984ae6 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -95,7 +95,7 @@ URLRequest.prototype._emitRequestEvent = function (async, ...rest) { URLRequest.prototype._emitResponseEvent = function (async, ...rest) { if (async) { process.nextTick(() => { - this.clientRequest.emit.apply(this._response, rest) + this._response.emit.apply(this._response, rest) }) } else { this._response.emit.apply(this._response, rest) diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index 4b1c2f48af..0ebb252030 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -26,7 +26,7 @@ const kOneKiloByte = 1024 const kOneMegaByte = kOneKiloByte * kOneKiloByte describe('net module', function () { - this.timeout(0) + // this.timeout(0) describe('HTTP basics', function () { let server beforeEach(function (done) { @@ -1155,42 +1155,108 @@ describe('net module', function () { urlRequest.end() }) }) - describe('Stability and performance', function(done) { + describe('Stability and performance', function (done) { let server beforeEach(function (done) { - server = http.createServer() - server.listen(0, '127.0.0.1', function () { - server.url = 'http://127.0.0.1:' + server.address().port - done() - }) + server = http.createServer() + server.listen(0, '127.0.0.1', function () { + server.url = 'http://127.0.0.1:' + server.address().port + done() + }) }) afterEach(function () { - server.close() - server = null + server.close() + server = null }) - it.only('should free unreferenced, never-started request objects', function(done) { + it('should free unreferenced, never-started request objects', function (done) { const requestUrl = '/requestUrl' - ipcRenderer.on('api-net-spec-done', function() { + ipcRenderer.once('api-net-spec-unused-done', function () { done() }) - const testCode = ` - // Load the net module in the main browser process. - const {net} = require('electron') - const urlRequest = net.request('${server.url}${requestUrl}') - process.nextTick(function() { - net._RequestGarbageCollectionForTesting() - event.sender.send('api-net-spec-done') + ipcRenderer.send('eval', ` + const {net} = require('electron') + const urlRequest = net.request('${server.url}${requestUrl}') + process.nextTick(function () { + net._RequestGarbageCollectionForTesting() + event.sender.send('api-net-spec-unused-done') + }) + `) + }) + it('should not collect on-going requests', function (done) { + const requestUrl = '/requestUrl' + server.on('request', function (request, response) { + switch (request.url) { + case requestUrl: + response.statusCode = 200 + response.statusMessage = 'OK' + response.write(randomString(kOneKiloByte)) + ipcRenderer.once('api-net-spec-ongoing-resume-response', function () { + response.write(randomString(kOneKiloByte)) + response.end() + }) + break + default: + assert(false) + } }) - ` - ipcRenderer.send('eval', testCode) + ipcRenderer.once('api-net-spec-ongoing-done', function () { + done() + }) + // Execute below code directly within the browser context without + // using the remote module. + ipcRenderer.send('eval', ` + const {net} = require('electron') + const urlRequest = net.request('${server.url}${requestUrl}') + urlRequest.on('response', function (response) { + response.on('data', function () { + }) + response.on('end', function () { + event.sender.send('api-net-spec-ongoing-done') + }) + process.nextTick(function () { + // Trigger a garbage collection. + net._RequestGarbageCollectionForTesting() + event.sender.send('api-net-spec-ongoing-resume-response') + }) + }) + urlRequest.end() + `) }) - it.skip('should not collect on-going requests', function(done) { - assert(false) - }) - it.skip('should collect unreferenced, ended requests', function(done) { - assert(false) + it('should collect unreferenced, ended requests', function (done) { + const requestUrl = '/requestUrl' + server.on('request', function (request, response) { + switch (request.url) { + case requestUrl: + response.statusCode = 200 + response.statusMessage = 'OK' + response.end() + break + default: + assert(false) + } + }) + ipcRenderer.once('api-net-spec-done', function () { + done() + }) + ipcRenderer.send('eval', ` + const {net} = require('electron') + const urlRequest = net.request('${server.url}${requestUrl}') + urlRequest.on('response', function (response) { + response.on('data', function () { + }) + response.on('end', function () { + }) + }) + urlRequest.on('close', function () { + process.nextTick(function () { + net._RequestGarbageCollectionForTesting() + event.sender.send('api-net-spec-done') + }) + }) + urlRequest.end() + `) }) }) }) diff --git a/spec/static/main.js b/spec/static/main.js index 9a30fd8170..58d8a1970a 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -8,7 +8,7 @@ const ipcMain = electron.ipcMain const dialog = electron.dialog const BrowserWindow = electron.BrowserWindow const protocol = electron.protocol -const v8 = require('v8'); +const v8 = require('v8') const Coverage = require('electabul').Coverage const fs = require('fs') From 9d0d1c8341bfc1ebecf0718176c84e8dd1281e02 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Tue, 18 Oct 2016 15:47:18 +1100 Subject: [PATCH 052/148] Fix bd object name --- docs/api/structures/bluetooth-device.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/structures/bluetooth-device.md b/docs/api/structures/bluetooth-device.md index 422fd21a11..33d3bb51f9 100644 --- a/docs/api/structures/bluetooth-device.md +++ b/docs/api/structures/bluetooth-device.md @@ -1,4 +1,4 @@ -# Bluetooth Device Object +# BluetoothDevice Object * `deviceName` String * `deviceId` String From 43113fcfb465e32b7f4bacbb646ae482a9970a19 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 18 Oct 2016 10:28:35 +0200 Subject: [PATCH 053/148] Fixing net response objects being piped into writable streams test. --- spec/api-net-spec.js | 74 ++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index 0ebb252030..fa73d7722c 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -1040,12 +1040,10 @@ describe('net module', function () { urlRequest.end() }) - it.skip('should be able to pipe a net response into a writable stream', function (done) { + it('should be able to pipe a net response into a writable stream', function (done) { const nodeRequestUrl = '/nodeRequestUrl' const netRequestUrl = '/netRequestUrl' const bodyData = randomString(kOneMegaByte) - let nodeRequestReceived = false - let nodeRequestEnded = false server.on('request', function (request, response) { switch (request.url) { case netRequestUrl: @@ -1055,13 +1053,11 @@ describe('net module', function () { response.end() break case nodeRequestUrl: - nodeRequestReceived = true let receivedBodyData = '' request.on('data', function (chunk) { receivedBodyData += chunk.toString() }) request.on('end', function (chunk) { - nodeRequestEnded = true if (chunk) { receivedBodyData += chunk.toString() } @@ -1073,30 +1069,34 @@ describe('net module', function () { assert(false) } }) - - const netRequest = net.request(`${server.url}${netRequestUrl}`) - netRequest.on('response', function (netResponse) { - assert.equal(netResponse.statusCode, 200) - const serverUrl = url.parse(server.url) - const nodeOptions = { - method: 'POST', - path: nodeRequestUrl, - port: serverUrl.port - } - let nodeRequest = http.request(nodeOptions) - - nodeRequest.on('response', function (nodeResponse) { - nodeResponse.on('data', function (chunk) { - }) - nodeResponse.on('end', function (chunk) { - assert(nodeRequestReceived) - assert(nodeRequestEnded) - done() - }) - }) - netResponse.pipe(nodeRequest) + ipcRenderer.once('api-net-spec-done', function () { + done() }) - netRequest.end() + // Execute below code directly within the browser context without + // using the remote module. + ipcRenderer.send('eval', ` + const {net} = require('electron') + const http = require('http') + const netRequest = net.request('${server.url}${netRequestUrl}') + netRequest.on('response', function (netResponse) { + const serverUrl = url.parse('${server.url}') + const nodeOptions = { + method: 'POST', + path: '${nodeRequestUrl}', + port: serverUrl.port + } + let nodeRequest = http.request(nodeOptions) + nodeRequest.on('response', function (nodeResponse) { + nodeResponse.on('data', function (chunk) { + }) + nodeResponse.on('end', function (chunk) { + event.sender.send('api-net-spec-done') + }) + }) + netResponse.pipe(nodeRequest) + }) + netRequest.end() + `) }) it('should not emit any event after close', function (done) { @@ -1170,9 +1170,9 @@ describe('net module', function () { server = null }) - it('should free unreferenced, never-started request objects', function (done) { + it('should free unreferenced, never-started request objects without crash', function (done) { const requestUrl = '/requestUrl' - ipcRenderer.once('api-net-spec-unused-done', function () { + ipcRenderer.once('api-net-spec-done', function () { done() }) ipcRenderer.send('eval', ` @@ -1180,11 +1180,11 @@ describe('net module', function () { const urlRequest = net.request('${server.url}${requestUrl}') process.nextTick(function () { net._RequestGarbageCollectionForTesting() - event.sender.send('api-net-spec-unused-done') + event.sender.send('api-net-spec-done') }) `) }) - it('should not collect on-going requests', function (done) { + it('should not collect on-going requests without crash', function (done) { const requestUrl = '/requestUrl' server.on('request', function (request, response) { switch (request.url) { @@ -1192,7 +1192,7 @@ describe('net module', function () { response.statusCode = 200 response.statusMessage = 'OK' response.write(randomString(kOneKiloByte)) - ipcRenderer.once('api-net-spec-ongoing-resume-response', function () { + ipcRenderer.once('api-net-spec-resume', function () { response.write(randomString(kOneKiloByte)) response.end() }) @@ -1201,7 +1201,7 @@ describe('net module', function () { assert(false) } }) - ipcRenderer.once('api-net-spec-ongoing-done', function () { + ipcRenderer.once('api-net-spec-done', function () { done() }) // Execute below code directly within the browser context without @@ -1213,18 +1213,18 @@ describe('net module', function () { response.on('data', function () { }) response.on('end', function () { - event.sender.send('api-net-spec-ongoing-done') + event.sender.send('api-net-spec-done') }) process.nextTick(function () { // Trigger a garbage collection. net._RequestGarbageCollectionForTesting() - event.sender.send('api-net-spec-ongoing-resume-response') + event.sender.send('api-net-spec-resume') }) }) urlRequest.end() `) }) - it('should collect unreferenced, ended requests', function (done) { + it('should collect unreferenced, ended requests without crash', function (done) { const requestUrl = '/requestUrl' server.on('request', function (request, response) { switch (request.url) { From 9bddc2cbaacd13247688e3fff0c968060a48abc1 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 18 Oct 2016 19:14:43 +0200 Subject: [PATCH 054/148] Adding net documentation skeleton. --- docs/api/electron.md | 79 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 docs/api/electron.md diff --git a/docs/api/electron.md b/docs/api/electron.md new file mode 100644 index 0000000000..718238e254 --- /dev/null +++ b/docs/api/electron.md @@ -0,0 +1,79 @@ +# net + +> Issue HTTP/HTTPS requests + +The `net` module is a client-side API for issuing HTTP requests. It is similar to the [HTTP](https://nodejs.org/api/http.html) and [HTTPS](https://nodejs.org/api/https.html) modules of Node.js but uses Chromium networking library instead of the Node.js stack offering therefore a much grater support regarding web proxies. + +Following is a non-exhaustive list of why you may need to use the `net` module instead of Node.js [HTTP](https://nodejs.org/api/http.html): +* Automatic management of system proxy configuration, support of the wpad protocol and proxy pac configuration files. +* Automatic tunneling of HTTPS requests. +* Support for authenticating proxies using basic, digest, NTLM, Kerberos or negotiate authentication schemes. +* Support for traffic monitoring proxies: Fiddler-like proxies used for access control and monitoring. + +The following example quickly shows how the net API mgiht be used: +```javascript +const {app} = require('electron') + +app.on('ready', () => { + const {net} = require('electron') + const request = net.request('https://github.com') + request.on('response', (response) => { + console.log(`STATUS: ${response.statusCode}`); + console.log(`HEADERS: ${JSON.stringify(response.headers)}`); + response.on('data', (chunk) => { + console.log(`BODY: ${chunk}`) + }) + response.on('end', () => { + console.log('No more data in response.'); + }) + }) + request.end() +}) +``` + +## Methods + +### `net.request` + +## Class: ClientRequest + +### Instance Events + +#### Event: 'response' + +#### Event: 'login' + +#### Event: 'finish' + +#### Event: 'abort' + +#### Event: 'error' + +#### Event: 'close' + +### Instance Methods + +#### `request.setHeader(name, value)` + +#### `request.getHeader(name)` + +#### `request.removeHeader(name)` + +#### `request.write(chunk, [encoding], [callback])` + +#### `request.end(chunk, [encoding], [callback])` + +#### `request.abort()` + +### Instance Properties + +#### `request.chunkedEncoding` + +## Class: IncomingMessage + +#### Event: + + + + + From a5c62bb2641412740bfe266cac73b05790f655a1 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Tue, 18 Oct 2016 15:52:41 -0500 Subject: [PATCH 055/148] add options to webFrame.registerURLSchemeAsPrivileged --- atom/renderer/api/atom_api_web_frame.cc | 45 +++++++++--- atom/renderer/api/atom_api_web_frame.h | 5 +- docs/api/web-frame.md | 16 +++- spec/api-web-frame-spec.js | 97 +++++++++++++++++++++---- 4 files changed, 136 insertions(+), 27 deletions(-) diff --git a/atom/renderer/api/atom_api_web_frame.cc b/atom/renderer/api/atom_api_web_frame.cc index ddcea9e8c8..d4cf54b684 100644 --- a/atom/renderer/api/atom_api_web_frame.cc +++ b/atom/renderer/api/atom_api_web_frame.cc @@ -140,17 +140,44 @@ void WebFrame::RegisterURLSchemeAsBypassingCSP(const std::string& scheme) { blink::WebString::fromUTF8(scheme)); } -void WebFrame::RegisterURLSchemeAsPrivileged(const std::string& scheme) { +void WebFrame::RegisterURLSchemeAsPrivileged(const std::string& scheme, + mate::Arguments* args) { + // Read optional flags + bool secure = true; + bool bypassCSP = true; + bool allowServiceWorkers = true; + bool supportFetchAPI = true; + bool corsEnabled = true; + if (args->Length() == 2) { + mate::Dictionary options; + if (args->GetNext(&options)) { + options.Get("secure", &secure); + options.Get("bypassCSP", &bypassCSP); + options.Get("allowServiceWorkers", &allowServiceWorkers); + options.Get("supportFetchAPI", &supportFetchAPI); + options.Get("corsEnabled", &corsEnabled); + } + } // Register scheme to privileged list (https, wss, data, chrome-extension) blink::WebString privileged_scheme(blink::WebString::fromUTF8(scheme)); - blink::WebSecurityPolicy::registerURLSchemeAsSecure(privileged_scheme); - blink::WebSecurityPolicy::registerURLSchemeAsBypassingContentSecurityPolicy( - privileged_scheme); - blink::WebSecurityPolicy::registerURLSchemeAsAllowingServiceWorkers( - privileged_scheme); - blink::WebSecurityPolicy::registerURLSchemeAsSupportingFetchAPI( - privileged_scheme); - blink::WebSecurityPolicy::registerURLSchemeAsCORSEnabled(privileged_scheme); + if (secure) { + blink::WebSecurityPolicy::registerURLSchemeAsSecure(privileged_scheme); + } + if (bypassCSP) { + blink::WebSecurityPolicy::registerURLSchemeAsBypassingContentSecurityPolicy( + privileged_scheme); + } + if (allowServiceWorkers) { + blink::WebSecurityPolicy::registerURLSchemeAsAllowingServiceWorkers( + privileged_scheme); + } + if (supportFetchAPI) { + blink::WebSecurityPolicy::registerURLSchemeAsSupportingFetchAPI( + privileged_scheme); + } + if (corsEnabled) { + blink::WebSecurityPolicy::registerURLSchemeAsCORSEnabled(privileged_scheme); + } } void WebFrame::InsertText(const std::string& text) { diff --git a/atom/renderer/api/atom_api_web_frame.h b/atom/renderer/api/atom_api_web_frame.h index 570a9dfc06..ebfd19c5a5 100644 --- a/atom/renderer/api/atom_api_web_frame.h +++ b/atom/renderer/api/atom_api_web_frame.h @@ -63,7 +63,10 @@ class WebFrame : public mate::Wrappable { void RegisterURLSchemeAsSecure(const std::string& scheme); void RegisterURLSchemeAsBypassingCSP(const std::string& scheme); - void RegisterURLSchemeAsPrivileged(const std::string& scheme); + void RegisterURLSchemeAsPrivileged( + const std::string& scheme, + mate::Arguments* args + ); // Editing. void InsertText(const std::string& text); diff --git a/docs/api/web-frame.md b/docs/api/web-frame.md index e26ad9edae..3d2e3b02db 100644 --- a/docs/api/web-frame.md +++ b/docs/api/web-frame.md @@ -83,13 +83,27 @@ attackers. Resources will be loaded from this `scheme` regardless of the current page's Content Security Policy. -### `webFrame.registerURLSchemeAsPrivileged(scheme)` +### `webFrame.registerURLSchemeAsPrivileged(scheme[, options])` * `scheme` String +* `options` Object (optional) + * `secure` Default true. + * `bypassCSP` Default true. + * `allowServiceWorkers` Default true. + * `supportFetchAPI` Default true. + * `corsEnabled` Default true. Registers the `scheme` as secure, bypasses content security policy for resources, allows registering ServiceWorker and supports fetch API. +Specify an option with the value of `false` to omit it from the registration. +An example of registering a privileged scheme, without bypassing Content Security Policy: + +```javascript +const {webFrame} = require('electron') +webFrame.registerURLSchemeAsPrivileged('foo', { bypassCSP: false }) +``` + ### `webFrame.insertText(text)` * `text` String diff --git a/spec/api-web-frame-spec.js b/spec/api-web-frame-spec.js index a41bc47701..09e6b63a64 100644 --- a/spec/api-web-frame-spec.js +++ b/spec/api-web-frame-spec.js @@ -7,7 +7,7 @@ const {BrowserWindow, protocol, ipcMain} = remote describe('webFrame module', function () { var fixtures = path.resolve(__dirname, 'fixtures') describe('webFrame.registerURLSchemeAsPrivileged', function () { - it('supports fetch api', function (done) { + it('supports fetch api by default', function (done) { webFrame.registerURLSchemeAsPrivileged('file') var url = 'file://' + fixtures + '/assets/logo.png' window.fetch(url).then(function (response) { @@ -18,21 +18,86 @@ describe('webFrame module', function () { }) }) - it('allows CORS requests', function (done) { - const standardScheme = remote.getGlobal('standardScheme') + it('allows CORS requests by default', function (done) { + allowsCORSRequests(200, ` + + `, done) + }) + + it('allows CORS and fetch requests when specified', function (done) { + allowsCORSRequests(200, ` + + `, done) + }) + + it('allows CORS and fetch requests when half-specified', function (done) { + allowsCORSRequests(200, ` + + `, done) + }) + + it('disallows CORS, but allows fetch requests, when specified', function (done) { + allowsCORSRequests('failed', ` + + `, done) + }) + + it('allows CORS, but disallows fetch requests, when specified', function (done) { + allowsCORSRequests('failed', ` + + `, done) + }) + + var runNumber = 1 + function allowsCORSRequests (expected, content, done) { + const standardScheme = remote.getGlobal('standardScheme') + runNumber + const corsScheme = 'cors' + runNumber + runNumber++ + const url = standardScheme + '://fake-host' - const content = ` - - ` var w = new BrowserWindow({show: false}) after(function (done) { - protocol.unregisterProtocol('cors', function () { + protocol.unregisterProtocol(corsScheme, function () { protocol.unregisterProtocol(standardScheme, function () { closeWindow(w).then(function () { w = null @@ -49,16 +114,16 @@ describe('webFrame module', function () { if (error) return done(error) }) - protocol.registerStringProtocol('cors', function (request, callback) { + protocol.registerStringProtocol(corsScheme, function (request, callback) { callback('') }, function (error) { if (error) return done(error) ipcMain.once('response', function (event, status) { - assert.equal(status, 200) + assert.equal(status, expected) done() }) w.loadURL(url) }) - }) + } }) }) From 0345b6236916575085036db69959379e079de7d7 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Tue, 18 Oct 2016 17:13:33 -0500 Subject: [PATCH 056/148] update webFrame.registerURLSchemeAsPrivileged docs to be more specific --- docs/api/web-frame.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/api/web-frame.md b/docs/api/web-frame.md index 3d2e3b02db..663c3fd5e5 100644 --- a/docs/api/web-frame.md +++ b/docs/api/web-frame.md @@ -87,11 +87,11 @@ Content Security Policy. * `scheme` String * `options` Object (optional) - * `secure` Default true. - * `bypassCSP` Default true. - * `allowServiceWorkers` Default true. - * `supportFetchAPI` Default true. - * `corsEnabled` Default true. + * `secure` (optional) Default true. + * `bypassCSP` (optional) Default true. + * `allowServiceWorkers` (optional) Default true. + * `supportFetchAPI` (optional) Default true. + * `corsEnabled` (optional) Default true. Registers the `scheme` as secure, bypasses content security policy for resources, allows registering ServiceWorker and supports fetch API. From f651b21cda317d13fa37474809fa4866af9fb38f Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 19 Oct 2016 09:24:59 +0200 Subject: [PATCH 057/148] Fixing net doc file name. --- docs/api/{electron.md => net.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/api/{electron.md => net.md} (100%) diff --git a/docs/api/electron.md b/docs/api/net.md similarity index 100% rename from docs/api/electron.md rename to docs/api/net.md From 5cd20a8e5d15bf03b5498ecae2f0dd53b06ec792 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 19 Oct 2016 15:34:21 +0200 Subject: [PATCH 058/148] Documenting net.ClientRequest --- docs/api/net.md | 133 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 116 insertions(+), 17 deletions(-) diff --git a/docs/api/net.md b/docs/api/net.md index 718238e254..225d084b95 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -15,63 +15,162 @@ The following example quickly shows how the net API mgiht be used: const {app} = require('electron') app.on('ready', () => { - const {net} = require('electron') - const request = net.request('https://github.com') - request.on('response', (response) => { - console.log(`STATUS: ${response.statusCode}`); - console.log(`HEADERS: ${JSON.stringify(response.headers)}`); - response.on('data', (chunk) => { - console.log(`BODY: ${chunk}`) - }) - response.on('end', () => { - console.log('No more data in response.'); - }) - }) - request.end() +const {net} = require('electron') +const request = net.request('https://github.com') +request.on('response', (response) => { + console.log(`STATUS: ${response.statusCode}`); + console.log(`HEADERS: ${JSON.stringify(response.headers)}`); + response.on('data', (chunk) => { + console.log(`BODY: ${chunk}`) + }) + response.on('end', () => { + console.log('No more data in response.'); + }) +}) +request.end() }) ``` ## Methods -### `net.request` +The `net` module has the following methods: + +### `net.request(options)` + +Create a `ClientRequest` instance using the provided `options` object. + +Returns `ClientRequest` ## Class: ClientRequest +### `new ClientRequest(options)` + +* `options` Object or String - If `options` is a String, it is interpreted as the request URL. If it is an object, it is expected to fully specify an HTTP request via the following properties: + * `method` String (optional) - The HTTP request method. Defaults to the GET method. + * `url` String (required) - The request URL. Must be provided in the absolute form with the protocol scheme specified as http or https. + * `protocol` String (optional) - The protocol scheme in the form 'scheme:'. Current supported values are 'http:' or 'https:'. Defaults to 'http:'. + * `host` String (optional) - The server host provided as a concatenation of a hostname and a port number 'hostname:port' + * `hostname` String (optional) - The server host name. + * `port` Integer (optional) - The server's listening port number. + * `path` String (optional) - The path part of the request URL. + +`options` properties `protocol`, `host`, `hostname`, `port` and `path` strictly follow the Node.js model as described in the [URL](https://nodejs.org/api/url.html) module. + ### Instance Events #### Event: 'response' +Returns: + +* `response` IncomingMessage - An object representing the HTTP response message. + #### Event: 'login' +Returns: + +* `callback` Function + +Emitted when an authenticating proxy is asking for user credentials. + +The `callback` function is expected to be called back with user credentials: + +* `usrename` String +* `password` String + +Providing empty credentials will cancel the request. + #### Event: 'finish' +Emitted just after the last chunk of the `request`'s data has been written into the `request` object. + #### Event: 'abort' +Emitted when the `request` is aborted. The abort event will not be fired if the `request` is already closed. + #### Event: 'error' +Returns: + +* `error` Error - an error object providing some information about the failure. + +Emitted when the `net` module fails to issue a network request. Typically when the `request` object emits an error event, a close event will subsequently follow and no response object will be provided. + #### Event: 'close' +Emitted as the last event in the HTTP request-response transaction. The close event indicates that no more events will be emitted on either the `request` or `response` objects. + ### Instance Methods #### `request.setHeader(name, value)` +* `name` String - An extra header name. +* `value` String - An extra header value. + +Adds an extra HTTP header. The header name will issued as it is without lowercasing. + #### `request.getHeader(name)` +* `name` String - Specify an extra header name. + +Returns String - The value of a previously set extra header name. + #### `request.removeHeader(name)` -#### `request.write(chunk, [encoding], [callback])` +* `name` String - Specify an extra header name. -#### `request.end(chunk, [encoding], [callback])` +Removes a previously set extra header name. + +#### `request.write(chunk, [encoding, callback])` + +* `chunk` String or Buffer - A chunk of the request body' data. If it is a string, it is converted into a Buffer object using the specified encoding. +* `encoding` String (optional) - Used to convert string chunks into Buffer objects. Defaults to 'utf-8'. +* `callback` Function (optional) - Called after the write operation ends. + +Adds a chunk of data to the request body. Generally, the first write operation causes the request headers to be issued on the wire. +After the first write operation, it is not allowed to add or remove a custom header. + +#### `request.end([chunk, encoding, callback])` + +* `chunk` String or Buffer (optional) +* `encoding` String (optional) +* `callback` Function (optional) + +Sends the last chunk of the request data. Subsequent write or end operations will not be allowed. The finish event is emitted just after the end operation. #### `request.abort()` +Cancels an ongoing HTTP transaction. If the request has already closed, the abort operation will have no effect. +Otherwise an ongoing event will emit abort and close events. Additionally, if there is an ongoing response object, +it will emit the aborted event. + ### Instance Properties #### `request.chunkedEncoding` ## Class: IncomingMessage -#### Event: +### Instance Events + +#### Event 'data' + +#### Event 'end' + +#### Event 'aborted' + +#### Event 'error' + +### Instance properties + +#### `response.statusCode` + +#### `response.statusMessage` + +#### `response.headers` + +#### `response.httpVersion` + + + From 0d82fbcf370da077da91165e8c9d23f3f6ab1d6e Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 19 Oct 2016 16:51:44 +0200 Subject: [PATCH 059/148] Documenting net.IncomingMessage. --- docs/api/net.md | 52 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/docs/api/net.md b/docs/api/net.md index 225d084b95..bbe8e72371 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -37,12 +37,16 @@ The `net` module has the following methods: ### `net.request(options)` -Create a `ClientRequest` instance using the provided `options` object. +* `options`: Object or String - The `ClientRequest` constructor options. Returns `ClientRequest` +Create a `ClientRequest` instance using the provided `options` object. + ## Class: ClientRequest +`ClientRequest` is a [Writable Stream](https://nodejs.org/api/stream.html#stream_writable_streams). + ### `new ClientRequest(options)` * `options` Object or String - If `options` is a String, it is interpreted as the request URL. If it is an object, it is expected to fully specify an HTTP request via the following properties: @@ -62,7 +66,7 @@ Returns `ClientRequest` Returns: -* `response` IncomingMessage - An object representing the HTTP response message. +* `response` IncomingMessage - An object representing an HTTP response message. #### Event: 'login' @@ -99,6 +103,17 @@ Emitted when the `net` module fails to issue a network request. Typically when t Emitted as the last event in the HTTP request-response transaction. The close event indicates that no more events will be emitted on either the `request` or `response` objects. +### Instance Properties + +#### `request.chunkedEncoding` + +A Boolean specifying whether the request will use HTTP chunked transfer encoding or not. Defaults to false. The property is readable and writable, +however it can be set only before the first write operation as the HTTP headers are not yet put on the wire. Trying to set the `chunkedEncoding` property +after a write will throw an error. + +Using chunked encoding is strongly recommended if you need to send a large request body as data will be streamed as small chunks instead of being internally buffered +in Electron memory. + ### Instance Methods #### `request.setHeader(name, value)` @@ -120,7 +135,7 @@ Returns String - The value of a previously set extra header name. Removes a previously set extra header name. -#### `request.write(chunk, [encoding, callback])` +#### `request.write(chunk[, encoding][, callback])` * `chunk` String or Buffer - A chunk of the request body' data. If it is a string, it is converted into a Buffer object using the specified encoding. * `encoding` String (optional) - Used to convert string chunks into Buffer objects. Defaults to 'utf-8'. @@ -129,7 +144,7 @@ Removes a previously set extra header name. Adds a chunk of data to the request body. Generally, the first write operation causes the request headers to be issued on the wire. After the first write operation, it is not allowed to add or remove a custom header. -#### `request.end([chunk, encoding, callback])` +#### `request.end([chunk][, encoding][, callback])` * `chunk` String or Buffer (optional) * `encoding` String (optional) @@ -143,32 +158,55 @@ Cancels an ongoing HTTP transaction. If the request has already closed, the abor Otherwise an ongoing event will emit abort and close events. Additionally, if there is an ongoing response object, it will emit the aborted event. -### Instance Properties - -#### `request.chunkedEncoding` ## Class: IncomingMessage +`IncomingMessage` is a [Readable Stream](https://nodejs.org/api/stream.html#stream_readable_streams). It represents an HTTP response message. + ### Instance Events #### Event 'data' +Returns: + +* `chunk`: Buffer - A chunk of response body's data. + #### Event 'end' +Indicates that response body has ended. + #### Event 'aborted' +Emitted when a request has been canceled during an ongoing HTTP transaction. + #### Event 'error' +Returns + +`error` Error + +Emitted if an error is encountered + ### Instance properties +An `IncomingMessage` instance has the following readable properties: + #### `response.statusCode` +An Integer indicating the HTTP response status code. + #### `response.statusMessage` +A String representing the HTTP status message. + #### `response.headers` +An Object representing the response HTTP headers. + #### `response.httpVersion` +A String indicating the HTTP protocol version number. Typical values are '1.0' or '1.1'. Additionally `httpVersionMajor` and +`httpVersionMinor` are two Integer-valued readable properties that return respectively the HTTP major and minor version numbers. From 3b620b8c0c5df821140fe21bf5399d5fdb2d61ec Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 19 Oct 2016 18:05:38 +0200 Subject: [PATCH 060/148] Documenting net module: various fixes. --- docs/api/net.md | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/docs/api/net.md b/docs/api/net.md index bbe8e72371..01de63c3bd 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -10,24 +10,24 @@ Following is a non-exhaustive list of why you may need to use the `net` module i * Support for authenticating proxies using basic, digest, NTLM, Kerberos or negotiate authentication schemes. * Support for traffic monitoring proxies: Fiddler-like proxies used for access control and monitoring. -The following example quickly shows how the net API mgiht be used: +The following example quickly shows how the `net` API mgiht be used: + ```javascript const {app} = require('electron') - app.on('ready', () => { -const {net} = require('electron') -const request = net.request('https://github.com') -request.on('response', (response) => { - console.log(`STATUS: ${response.statusCode}`); - console.log(`HEADERS: ${JSON.stringify(response.headers)}`); - response.on('data', (chunk) => { - console.log(`BODY: ${chunk}`) + const {net} = require('electron') + const request = net.request('https://github.com') + request.on('response', (response) => { + console.log(`STATUS: ${response.statusCode}`); + console.log(`HEADERS: ${JSON.stringify(response.headers)}`); + response.on('data', (chunk) => { + console.log(`BODY: ${chunk}`) + }) + response.on('end', () => { + console.log('No more data in response.'); + }) }) - response.on('end', () => { - console.log('No more data in response.'); - }) -}) -request.end() + request.end() }) ``` @@ -45,7 +45,7 @@ Create a `ClientRequest` instance using the provided `options` object. ## Class: ClientRequest -`ClientRequest` is a [Writable Stream](https://nodejs.org/api/stream.html#stream_writable_streams). +`ClientRequest` implements the [Writable Stream](https://nodejs.org/api/stream.html#stream_writable_streams) interface. ### `new ClientRequest(options)` @@ -201,7 +201,11 @@ A String representing the HTTP status message. #### `response.headers` -An Object representing the response HTTP headers. +An Object representing the response HTTP headers. The `headers` object is formatted as follows: + +* All header names are lowercased. +* Each header name produces an array-valued property on the headers object. +* Each header value is pushed into the array associated with its header name. #### `response.httpVersion` From 6e5951b764ecfb15a10cfd515887918f33d33485 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 19 Oct 2016 18:11:07 +0200 Subject: [PATCH 061/148] Documenting net module: formatting. --- docs/api/net.md | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/docs/api/net.md b/docs/api/net.md index 01de63c3bd..8570fe4103 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -1,8 +1,10 @@ # net -> Issue HTTP/HTTPS requests +> Issue HTTP/HTTPS requests. -The `net` module is a client-side API for issuing HTTP requests. It is similar to the [HTTP](https://nodejs.org/api/http.html) and [HTTPS](https://nodejs.org/api/https.html) modules of Node.js but uses Chromium networking library instead of the Node.js stack offering therefore a much grater support regarding web proxies. +The `net` module is a client-side API for issuing HTTP(S) requests. It is similar to the +[HTTP](https://nodejs.org/api/http.html) and [HTTPS](https://nodejs.org/api/https.html) modules of Node.js +but uses Chromium networking library instead of the Node.js stack offering therefore a much grater support regarding web proxies. Following is a non-exhaustive list of why you may need to use the `net` module instead of Node.js [HTTP](https://nodejs.org/api/http.html): * Automatic management of system proxy configuration, support of the wpad protocol and proxy pac configuration files. @@ -14,19 +16,28 @@ The following example quickly shows how the `net` API mgiht be used: ```javascript const {app} = require('electron') + app.on('ready', () => { + const {net} = require('electron') + const request = net.request('https://github.com') + request.on('response', (response) => { + console.log(`STATUS: ${response.statusCode}`); console.log(`HEADERS: ${JSON.stringify(response.headers)}`); + response.on('data', (chunk) => { console.log(`BODY: ${chunk}`) }) + response.on('end', () => { console.log('No more data in response.'); }) + }) + request.end() }) ``` @@ -49,7 +60,8 @@ Create a `ClientRequest` instance using the provided `options` object. ### `new ClientRequest(options)` -* `options` Object or String - If `options` is a String, it is interpreted as the request URL. If it is an object, it is expected to fully specify an HTTP request via the following properties: +* `options` Object or String - If `options` is a String, it is interpreted as the request URL. +If it is an object, it is expected to fully specify an HTTP request via the following properties: * `method` String (optional) - The HTTP request method. Defaults to the GET method. * `url` String (required) - The request URL. Must be provided in the absolute form with the protocol scheme specified as http or https. * `protocol` String (optional) - The protocol scheme in the form 'scheme:'. Current supported values are 'http:' or 'https:'. Defaults to 'http:'. @@ -58,7 +70,8 @@ Create a `ClientRequest` instance using the provided `options` object. * `port` Integer (optional) - The server's listening port number. * `path` String (optional) - The path part of the request URL. -`options` properties `protocol`, `host`, `hostname`, `port` and `path` strictly follow the Node.js model as described in the [URL](https://nodejs.org/api/url.html) module. +`options` properties `protocol`, `host`, `hostname`, `port` and `path` strictly +follow the Node.js model as described in the [URL](https://nodejs.org/api/url.html) module. ### Instance Events @@ -97,21 +110,26 @@ Returns: * `error` Error - an error object providing some information about the failure. -Emitted when the `net` module fails to issue a network request. Typically when the `request` object emits an error event, a close event will subsequently follow and no response object will be provided. +Emitted when the `net` module fails to issue a network request. Typically when the `request` +object emits an error event, a close event will subsequently follow and no response object will be provided. #### Event: 'close' -Emitted as the last event in the HTTP request-response transaction. The close event indicates that no more events will be emitted on either the `request` or `response` objects. +Emitted as the last event in the HTTP request-response transaction. The close event indicates +that no more events will be emitted on either the `request` or `response` objects. ### Instance Properties #### `request.chunkedEncoding` -A Boolean specifying whether the request will use HTTP chunked transfer encoding or not. Defaults to false. The property is readable and writable, -however it can be set only before the first write operation as the HTTP headers are not yet put on the wire. Trying to set the `chunkedEncoding` property +A Boolean specifying whether the request will use HTTP chunked transfer encoding or +not. Defaults to false. The property is readable and writable, +however it can be set only before the first write operation as the HTTP headers are +not yet put on the wire. Trying to set the `chunkedEncoding` property after a write will throw an error. -Using chunked encoding is strongly recommended if you need to send a large request body as data will be streamed as small chunks instead of being internally buffered +Using chunked encoding is strongly recommended if you need to send a large request body as +data will be streamed as small chunks instead of being internally buffered in Electron memory. ### Instance Methods @@ -137,7 +155,8 @@ Removes a previously set extra header name. #### `request.write(chunk[, encoding][, callback])` -* `chunk` String or Buffer - A chunk of the request body' data. If it is a string, it is converted into a Buffer object using the specified encoding. +* `chunk` String or Buffer - A chunk of the request body' data. If it is a string, +it is converted into a Buffer object using the specified encoding. * `encoding` String (optional) - Used to convert string chunks into Buffer objects. Defaults to 'utf-8'. * `callback` Function (optional) - Called after the write operation ends. @@ -150,7 +169,8 @@ After the first write operation, it is not allowed to add or remove a custom hea * `encoding` String (optional) * `callback` Function (optional) -Sends the last chunk of the request data. Subsequent write or end operations will not be allowed. The finish event is emitted just after the end operation. +Sends the last chunk of the request data. Subsequent write or end operations will not +be allowed. The finish event is emitted just after the end operation. #### `request.abort()` From fddbde2fd5327465a5c553532d1eb13886cc9e3e Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 19 Oct 2016 18:19:28 +0200 Subject: [PATCH 062/148] Documenting net module: various fixes. --- docs/api/net.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/api/net.md b/docs/api/net.md index 8570fe4103..34cffd63d5 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -4,15 +4,19 @@ The `net` module is a client-side API for issuing HTTP(S) requests. It is similar to the [HTTP](https://nodejs.org/api/http.html) and [HTTPS](https://nodejs.org/api/https.html) modules of Node.js -but uses Chromium networking library instead of the Node.js stack offering therefore a much grater support regarding web proxies. +but it uses Chromium native networking library instead of the Node.js implementation offering +therefore a much greater support regarding web proxies. -Following is a non-exhaustive list of why you may need to use the `net` module instead of Node.js [HTTP](https://nodejs.org/api/http.html): +Following is a non-exhaustive list of why you may consider using the `net` module instead of the native Node.js modules: * Automatic management of system proxy configuration, support of the wpad protocol and proxy pac configuration files. * Automatic tunneling of HTTPS requests. * Support for authenticating proxies using basic, digest, NTLM, Kerberos or negotiate authentication schemes. * Support for traffic monitoring proxies: Fiddler-like proxies used for access control and monitoring. -The following example quickly shows how the `net` API mgiht be used: +The `net` module API has been specifically designed to mimic, as much closely as possible, the familiar Node.js API. +The API components including classes, methods, properties and event names are similar to those commonly used in Node.js. + +For instance, the following example quickly shows how the `net` API might be used: ```javascript const {app} = require('electron') @@ -42,6 +46,9 @@ app.on('ready', () => { }) ``` +By the way, it is almost identical to the way you would normally use the +[HTTP](https://nodejs.org/api/http.html)/[HTTPS](https://nodejs.org/api/https.html) modules of Node.js + ## Methods The `net` module has the following methods: @@ -52,7 +59,8 @@ The `net` module has the following methods: Returns `ClientRequest` -Create a `ClientRequest` instance using the provided `options` object. +Create a `ClientRequest` instance using the provided `options` object which is directly +passed to the `ClientRequest` constructor. ## Class: ClientRequest From 7549adcfce72bf2d2dca665d54a932839c67a28c Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 19 Oct 2016 18:31:08 +0200 Subject: [PATCH 063/148] Documenting net module: various fixes. --- docs/api/net.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/docs/api/net.md b/docs/api/net.md index 34cffd63d5..e9932fb2d8 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -60,11 +60,13 @@ The `net` module has the following methods: Returns `ClientRequest` Create a `ClientRequest` instance using the provided `options` object which is directly -passed to the `ClientRequest` constructor. +passed to the `ClientRequest` constructor. The `net.request` method would be used to issue +both secure and insecure HTTP requests according to the specified protocol scheme in the `options` object. ## Class: ClientRequest -`ClientRequest` implements the [Writable Stream](https://nodejs.org/api/stream.html#stream_writable_streams) interface. +`ClientRequest` implements the [Writable Stream](https://nodejs.org/api/stream.html#stream_writable_streams) interface +and it is therefore an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter). ### `new ClientRequest(options)` @@ -189,7 +191,9 @@ it will emit the aborted event. ## Class: IncomingMessage -`IncomingMessage` is a [Readable Stream](https://nodejs.org/api/stream.html#stream_readable_streams). It represents an HTTP response message. +`IncomingMessage` represents an HTTP response message. +It is a [Readable Stream](https://nodejs.org/api/stream.html#stream_readable_streams) and therefore +an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter). ### Instance Events @@ -199,6 +203,8 @@ Returns: * `chunk`: Buffer - A chunk of response body's data. +The data event is the usual method of transferring response data into applicative code. + #### Event 'end' Indicates that response body has ended. @@ -211,9 +217,11 @@ Emitted when a request has been canceled during an ongoing HTTP transaction. Returns -`error` Error +`error` Error - Typically holds an error string identifying failure root cause. -Emitted if an error is encountered +Emitted if an error is encountered while streaming response data events. For instance, +if the server closes the underlying socket while streaming the response, an error event +will be emitted on the response object and a close event will subsequently follow in the request object. ### Instance properties From 43ae784a401082ed9108a9d977121cffa4938ffd Mon Sep 17 00:00:00 2001 From: tinydew4 Date: Thu, 20 Oct 2016 08:58:48 +0000 Subject: [PATCH 064/148] Translate releasing --- .../ko-KR/development/releasing.md | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 docs-translations/ko-KR/development/releasing.md diff --git a/docs-translations/ko-KR/development/releasing.md b/docs-translations/ko-KR/development/releasing.md new file mode 100644 index 0000000000..231eac1307 --- /dev/null +++ b/docs-translations/ko-KR/development/releasing.md @@ -0,0 +1,110 @@ +# ๋ฆด๋ฆฌ์ฆˆ + +์ด ๋ฌธ์„œ๋Š” Electron ์˜ ์ƒˆ๋ฒ„์ „ ์ถœ์‹œ ์ ˆ์ฐจ๋ฅผ ์„ค๋ช…ํ•ฉ๋‹ˆ๋‹ค. + +## ๋ฆด๋ฆฌ์ฆˆ ๋…ธํŠธ ํŽธ์ง‘ + +ํ˜„์žฌ ์ ˆ์ฐจ๋Š” ๋กœ์ปฌ ํŒŒ์ผ์„ ์œ ์ง€ํ•˜๊ณ  ๋ณ‘ํ•ฉ๋œ ํ’€ ์š”์ฒญ๊ณผ ๊ฐ™์€ ์ค‘์š”ํ•œ ๋ณ€ํ™”์˜ ์ถ”์ฒ™์„ +๋ณด์กดํ•˜๋Š” ๊ฒƒ ์ž…๋‹ˆ๋‹ค. ๋…ธํŠธ ํ˜•์‹์— ๋Œ€ํ•œ ์˜ˆ์ œ๋Š”, [๋ฆด๋ฆฌ์ฆˆ ํŽ˜์ด์ง€]์—์„œ ์ด์ „ ๋ฆด๋ฆฌ์ฆˆ๋ฅผ +๋ณด์„ธ์š”. + +## ์ž„์‹œ ๋ธŒ๋žœ์น˜ ์ƒ์„ฑ + +`release` ์ด๋ฆ„์˜ ์ƒˆ ๋ธŒ๋žœ์น˜๋ฅผ `master` ๋กœ๋ถ€ํ„ฐ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +```sh +git checkout master +git pull +git checkout -b release +``` + +์ด ๋ธŒ๋žœ์น˜๋Š” ์ž„์‹œ ๋ฆด๋ฆฌ์ฆˆ ๋ธŒ๋žœ์น˜๊ฐ€ ์ƒ์„ฑ๋˜๊ณ  CI ๋นŒ๋“œ๊ฐ€ ์™„๋ฃŒ๋˜๋Š” ๋™์•ˆ ์•„๋ฌด๋„ ๋ชจ๋ฅด๋Š” +PR ๋ณ‘ํ•ฉ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ์œ„ํ•œ ์˜ˆ๋ฐฉ์กฐ์น˜๋กœ์จ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. + +## ๋ฒ„์ „ ์˜ฌ๋ฆฌ๊ธฐ + +`major`, `minor`, `patch` ๋ฅผ ์ธ์ˆ˜๋กœ ์ „๋‹ฌํ•˜์—ฌ, `bump-version` ์Šคํฌ๋ฆฝํŠธ๋ฅผ +์‹คํ–‰ํ•˜์„ธ์š”: + +```sh +npm run bump-version -- patch +git push origin HEAD +``` + +์ด๊ฒƒ์€ ์—ฌ๋Ÿฌ ํŒŒ์ผ์˜ ๋ฒ„์ „ ๋ฒˆํ˜ธ๋ฅผ ์˜ฌ๋ฆด ๊ฒƒ ์ž…๋‹ˆ๋‹ค. ์˜ˆ์‹œ๋กœ [์ด ๋ฒ”ํ”„ ์ปค๋ฐ‹]์„ ๋ณด์„ธ์š”. + +๋Œ€๋ถ€๋ถ„์˜ ๋ฆด๋ฆฌ์ฆˆ๋Š” `patch` ์ˆ˜์ค€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. Chrome ๋˜๋Š” ๋‹ค๋ฅธ ์ฃผ์š” ๋ณ€ํ™”๋Š” +`minor` ๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ์ •๋ณด๋Š”, [Electron ๋ฒ„์ „ ๊ด€๋ฆฌ]๋ฅผ ๋ณด์„ธ์š”. + +## ๋ฆด๋ฆฌ์ฆˆ ์ดˆ์•ˆ ํŽธ์ง‘ + +1. [๋ฆด๋ฆฌ์ฆˆ ํŽ˜์ด์ง€]์— ๊ฐ€๋ฉด ๋ฆด๋ฆฌ์ฆˆ ๋…ธํŠธ ์ดˆ์•ˆ๊ณผ ์ž๋ฆฌ ํ‘œ์‹œ์ž๋กœ์จ ๋ฆด๋ฆฌ์ฆˆ ๋…ธํŠธ๋ฅผ ๋ณผ ์ˆ˜ + ์žˆ์Šต๋‹ˆ๋‹ค. +1. ๋ฆด๋ฆฌ์ฆˆ๋ฅผ ํŽธ์ง‘ํ•˜๊ณ  ๋ฆด๋ฆฌ์ฆˆ ๋…ธํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜์„ธ์š”. +1. 'Save draft' ๋ฅผ ํด๋ฆญํ•˜์„ธ์š”. **'Publish release' ๋ฅผ ๋ˆ„๋ฅด๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค!** +1. ๋ชจ๋“  ๋นŒ๋“œ๊ฐ€ ํ†ต๊ณผํ•  ๋•Œ ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์„ธ์š”. :hourglass_flowing_sand: + +## ์ž„์‹œ ๋ธŒ๋žœ์น˜ ๋ณ‘ํ•ฉ + +์ž„์‹œ๋ฅผ ๋งˆ์Šคํ„ฐ๋กœ ๋จธ์ง€ ์ปค๋ฐ‹ ์ƒ์„ฑ์—†์ด ๋ณ‘ํ•ฉํ•ฉ๋‹ˆ๋‹ค. + +```sh +git merge release master --no-commit +git push origin master +``` +์‹คํŒจํ•˜๋ฉด, ๋งˆ์Šคํ„ฐ๋กœ ๋ฆฌ๋ฒ ์ด์Šคํ•˜๊ณ  ๋‹ค์‹œ ๋นŒ๋“œํ•ฉ๋‹ˆ๋‹ค: + +```sh +git pull +git checkout release +git rebase master +git push origin HEAD +``` + +## ๋กœ์ปฌ ๋””๋ฒ„๊ทธ ๋นŒ๋“œ ์‹คํ–‰ + +๋‹น์‹ ์ด ์‹ค์ œ๋กœ ์›ํ•˜๋Š” ๋ฒ„์ „์„ ๊ตฌ์ถ•ํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ๋กœ์ปฌ ๋””๋ฒ„๊ทธ ๋นŒ๋“œ๋ฅผ +์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๋•Œ๋•Œ๋กœ ์ƒˆ ๋ฒ„์ „์„ ๋ฆด๋ฆฌ์ฆˆํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ, ์•„๋‹Œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. + +```sh +npm run build +npm start +``` + +์ฐฝ์ด ํ˜„์žฌ ์—…๋ฐ์ดํŠธ๋œ ๋ฒ„์ „์„ ํ‘œ์‹œํ•˜๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. + +## ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์„ค์ • + +๋ฆด๋ฆฌ์ฆˆ๋ฅผ ๊ฒŒ์‹œํ•˜๋ ค๋ฉด ๋‹ค์Œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ์ด ์ž๊ฒฉ์ฆ๋ช…์— ๋Œ€ํ•ด ๋‹ค๋ฅธ ํŒ€ +๊ตฌ์„ฑ์›์—๊ฒŒ ๋ฌธ์˜ํ•˜์„ธ์š”. + +- `ELECTRON_S3_BUCKET` +- `ELECTRON_S3_ACCESS_KEY` +- `ELECTRON_S3_SECRET_KEY` +- `ELECTRON_GITHUB_TOKEN` - "์ €์žฅ์†Œ" ์˜์—ญ์— ๋Œ€ํ•œ ๊ฐœ์ธ ์ ‘๊ทผ ํ† ํฐ. + +์ด๊ฒƒ์€ ํ•œ๋ฒˆ๋งŒ ์ˆ˜ํ–‰ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. + +## ๋ฆด๋ฆฌ์ฆˆ ๊ฒŒ์‹œ + +์ด ์Šคํฌ๋ฆฝํŠธ๋Š” ๋ฐ”์ด๋„ˆ๋ฆฌ๋ฅผ ๋‚ด๋ ค๋ฐ›๊ณ  ๋„ค์ดํ‹ฐ๋ธŒ ๋ชจ๋“ˆ ๊ตฌ์ถ•์„ ์œ„ํ•ด node-gyp ์œผ๋กœ +์œˆ๋„์šฐ์—์„œ ์‚ฌ์šฉ๋˜๋Š” ๋…ธ๋“œ ํ—ค๋”์™€ .lib ๋ง์ปค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. + +```sh +npm run release +``` + +์ฐธ๊ณ : ๋งŽ์€ ํŒŒ์ด์ฌ์˜ ๋ฐฐํฌํŒ๋“ค์€ ์—ฌ์ „ํžˆ ์˜ค๋ž˜๋œ HTTPS ์ธ์ฆ์„œ์™€ ํ•จ๊ป˜ ์ œ๊ณต๋ฉ๋‹ˆ๋‹ค. +`InsecureRequestWarning` ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ฌด์‹œํ•ด๋„ ๋ฉ๋‹ˆ๋‹ค. + +## ์ž„์‹œ ๋ธŒ๋žœ์น˜ ์‚ญ์ œ + +```sh +git checkout master +git branch -D release # ๋กœ์ปฌ ๋ธŒ๋žœ์น˜ ์‚ญ์ œ +git push origin :release # ์›๊ฒฉ ๋ธŒ๋žœ์น˜ ์‚ญ์ œ +``` + +[๋ฆด๋ฆฌ์ฆˆ ํŽ˜์ด์ง€]: https://github.com/electron/electron/releases +[์ด ๋ฒ”ํ”„ ์ปค๋ฐ‹]: https://github.com/electron/electron/commit/78ec1b8f89b3886b856377a1756a51617bc33f5a +[Electron ๋ฒ„์ „ ๊ด€๋ฆฌ]: ../tutorial/electron-versioning.md From 7f8b180f7065b9ee91f56c964267d8803448b203 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 20 Oct 2016 11:43:26 +0200 Subject: [PATCH 065/148] Fixing authentication cancel with null/undefined credentials. --- atom/browser/api/atom_api_url_request.cc | 5 ++--- lib/browser/api/net.js | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 9a9fb28892..42f08c8f05 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -305,9 +305,8 @@ void URLRequest::OnAuthenticationRequired( return; } - EmitRequestEvent( - false, "login", auth_info.get(), - base::Bind(&AtomURLRequest::PassLoginInformation, atom_request_)); + Emit("login", auth_info.get(), + base::Bind(&AtomURLRequest::PassLoginInformation, atom_request_)); } void URLRequest::OnResponseStarted( diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index ef76984ae6..7fb2c61495 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -192,6 +192,25 @@ class ClientRequest extends EventEmitter { this.emit('response', response) }) + urlRequest.on('login', (event, authInfo, callback) => { + this.emit('login', authInfo, (username, password) => { + // If null or undefined usrename/password, force to empty string. + if (username === null || username === undefined) { + username = '' + } + if (typeof username !== 'string') { + throw new Error('username must be a string') + } + if (password === null || password === undefined) { + password = '' + } + if (typeof password !== 'string') { + throw new Error('password must be a string') + } + callback(username, password) + }) + }) + if (callback) { this.once('response', callback) } From fdfa0f4a6d9141f402e24bd5669e82c4ce8519c0 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 20 Oct 2016 11:45:45 +0200 Subject: [PATCH 066/148] Documenting the login event. --- docs/api/net.md | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/api/net.md b/docs/api/net.md index e9932fb2d8..9459b0cb3d 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -95,6 +95,12 @@ Returns: Returns: +* `authInfo` Object + * `isProxy` Boolean + * `scheme` String + * `host` String + * `port` Integer + * `realm` String * `callback` Function Emitted when an authenticating proxy is asking for user credentials. @@ -104,7 +110,24 @@ The `callback` function is expected to be called back with user credentials: * `usrename` String * `password` String -Providing empty credentials will cancel the request. +```JavaScript +request.on('login', (authInfo, callback) => { + callback('username', 'password') +}) +``` +Providing empty credentials will cancel the request and report an authentication error on the response object: + +```JavaScript +request.on('response', (response) => { + console.log(`STATUS: ${response.statusCode}`); + response.on('error', (error) => { + console.log(`ERROR: ${JSON.stringify(error)}`) + }) +}) +request.on('login', (authInfo, callback) => { + callback() +}) +``` #### Event: 'finish' From 69790bd7edc9babd4c927e8be7507956157bc80f Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 20 Oct 2016 11:58:06 +0200 Subject: [PATCH 067/148] Documenting ClientRequest constructor options. --- docs/api/net.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/api/net.md b/docs/api/net.md index 9459b0cb3d..ff23f88204 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -83,6 +83,18 @@ If it is an object, it is expected to fully specify an HTTP request via the foll `options` properties `protocol`, `host`, `hostname`, `port` and `path` strictly follow the Node.js model as described in the [URL](https://nodejs.org/api/url.html) module. +For instance, we could have created the same request to 'github.com' as follows: + +```JavaScript +const request = net.request({ + method: 'GET', + protocol: 'https:', + hostname: 'github.com', + port: 443, + path: '/' +}) +``` + ### Instance Events #### Event: 'response' From 9f151912807c614d00c8dea6a24f71a9e2429ad2 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 20 Oct 2016 12:30:03 +0200 Subject: [PATCH 068/148] Formatting net documentation. --- docs/api/net.md | 174 +++++++++++++++++++++++++++--------------------- 1 file changed, 99 insertions(+), 75 deletions(-) diff --git a/docs/api/net.md b/docs/api/net.md index ff23f88204..d99d9d562f 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -2,52 +2,52 @@ > Issue HTTP/HTTPS requests. -The `net` module is a client-side API for issuing HTTP(S) requests. It is similar to the -[HTTP](https://nodejs.org/api/http.html) and [HTTPS](https://nodejs.org/api/https.html) modules of Node.js -but it uses Chromium native networking library instead of the Node.js implementation offering -therefore a much greater support regarding web proxies. +The `net` module is a client-side API for issuing HTTP(S) requests. It is +similar to the [HTTP](https://nodejs.org/api/http.html) and +[HTTPS](https://nodejs.org/api/https.html) modules of Node.js but it uses +Chromium native networking library instead of the Node.js implementation +offering therefore a much greater support regarding web proxies. -Following is a non-exhaustive list of why you may consider using the `net` module instead of the native Node.js modules: -* Automatic management of system proxy configuration, support of the wpad protocol and proxy pac configuration files. +Following is a non-exhaustive list of why you may consider using the `net` +module instead of the native Node.js modules: +* Automatic management of system proxy configuration, support of the wpad +protocol and proxy pac configuration files. * Automatic tunneling of HTTPS requests. -* Support for authenticating proxies using basic, digest, NTLM, Kerberos or negotiate authentication schemes. -* Support for traffic monitoring proxies: Fiddler-like proxies used for access control and monitoring. +* Support for authenticating proxies using basic, digest, NTLM, Kerberos or +negotiate authentication schemes. +* Support for traffic monitoring proxies: Fiddler-like proxies used for access +control and monitoring. -The `net` module API has been specifically designed to mimic, as much closely as possible, the familiar Node.js API. -The API components including classes, methods, properties and event names are similar to those commonly used in Node.js. +The `net` module API has been specifically designed to mimic, as much closely as +possible, the familiar Node.js API. The API components including classes, +methods, properties and event names are similar to those commonly used in +Node.js. -For instance, the following example quickly shows how the `net` API might be used: +For instance, the following example quickly shows how the `net` API might be +used: ```javascript const {app} = require('electron') - app.on('ready', () => { - const {net} = require('electron') - const request = net.request('https://github.com') - request.on('response', (response) => { - console.log(`STATUS: ${response.statusCode}`); console.log(`HEADERS: ${JSON.stringify(response.headers)}`); - response.on('data', (chunk) => { console.log(`BODY: ${chunk}`) }) - response.on('end', () => { console.log('No more data in response.'); }) - }) - request.end() }) ``` -By the way, it is almost identical to the way you would normally use the -[HTTP](https://nodejs.org/api/http.html)/[HTTPS](https://nodejs.org/api/https.html) modules of Node.js +By the way, it is almost identical to how you would normally use the +[HTTP](https://nodejs.org/api/http.html)/[HTTPS](https://nodejs.org/api/https.html) +modules of Node.js ## Methods @@ -59,29 +59,37 @@ The `net` module has the following methods: Returns `ClientRequest` -Create a `ClientRequest` instance using the provided `options` object which is directly -passed to the `ClientRequest` constructor. The `net.request` method would be used to issue -both secure and insecure HTTP requests according to the specified protocol scheme in the `options` object. +Creates a `ClientRequest` instance using the provided `options` which are +directly forwarded to the `ClientRequest` constructor. The `net.request` method +would be used to issue both secure and insecure HTTP requests according to the +specified protocol scheme in the `options` object. ## Class: ClientRequest -`ClientRequest` implements the [Writable Stream](https://nodejs.org/api/stream.html#stream_writable_streams) interface -and it is therefore an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter). +`ClientRequest` implements the [Writable Stream](https://nodejs.org/api/stream.html#stream_writable_streams) +interface and it is therefore an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter). ### `new ClientRequest(options)` -* `options` Object or String - If `options` is a String, it is interpreted as the request URL. -If it is an object, it is expected to fully specify an HTTP request via the following properties: - * `method` String (optional) - The HTTP request method. Defaults to the GET method. - * `url` String (required) - The request URL. Must be provided in the absolute form with the protocol scheme specified as http or https. - * `protocol` String (optional) - The protocol scheme in the form 'scheme:'. Current supported values are 'http:' or 'https:'. Defaults to 'http:'. - * `host` String (optional) - The server host provided as a concatenation of a hostname and a port number 'hostname:port' +* `options` Object or String - If `options` is a String, it is interpreted as +the request URL. +If it is an object, it is expected to fully specify an HTTP request via the +following properties: + * `method` String (optional) - The HTTP request method. Defaults to the GET +method. + * `url` String (optional) - The request URL. Must be provided in the absolute +form with the protocol scheme specified as http or https. + * `protocol` String (optional) - The protocol scheme in the form 'scheme:'. +Currently supported values are 'http:' or 'https:'. Defaults to 'http:'. + * `host` String (optional) - The server host provided as a concatenation of +the hostname and the port number 'hostname:port' * `hostname` String (optional) - The server host name. * `port` Integer (optional) - The server's listening port number. * `path` String (optional) - The path part of the request URL. -`options` properties `protocol`, `host`, `hostname`, `port` and `path` strictly -follow the Node.js model as described in the [URL](https://nodejs.org/api/url.html) module. +`options` properties such as `protocol`, `host`, `hostname`, `port` and `path` +strictly follow the Node.js model as described in the +[URL](https://nodejs.org/api/url.html) module. For instance, we could have created the same request to 'github.com' as follows: @@ -101,7 +109,7 @@ const request = net.request({ Returns: -* `response` IncomingMessage - An object representing an HTTP response message. +* `response` IncomingMessage - An object representing the HTTP response message. #### Event: 'login' @@ -127,7 +135,8 @@ request.on('login', (authInfo, callback) => { callback('username', 'password') }) ``` -Providing empty credentials will cancel the request and report an authentication error on the response object: +Providing empty credentials will cancel the request and report an authentication +error on the response object: ```JavaScript request.on('response', (response) => { @@ -143,11 +152,13 @@ request.on('login', (authInfo, callback) => { #### Event: 'finish' -Emitted just after the last chunk of the `request`'s data has been written into the `request` object. +Emitted just after the last chunk of the `request`'s data has been written into +the `request` object. #### Event: 'abort' -Emitted when the `request` is aborted. The abort event will not be fired if the `request` is already closed. +Emitted when the `request` is aborted. The `abort` event will not be fired if +the `request` is already closed. #### Event: 'error' @@ -155,36 +166,40 @@ Returns: * `error` Error - an error object providing some information about the failure. -Emitted when the `net` module fails to issue a network request. Typically when the `request` -object emits an error event, a close event will subsequently follow and no response object will be provided. +Emitted when the `net` module fails to issue a network request. Typically when +the `request` object emits an `error` event, a `close` event will subsequently +follow and no response object will be provided. #### Event: 'close' -Emitted as the last event in the HTTP request-response transaction. The close event indicates -that no more events will be emitted on either the `request` or `response` objects. +Emitted as the last event in the HTTP request-response transaction. The `close` +event indicates that no more events will be emitted on either the `request` or +`response` objects. ### Instance Properties #### `request.chunkedEncoding` -A Boolean specifying whether the request will use HTTP chunked transfer encoding or -not. Defaults to false. The property is readable and writable, -however it can be set only before the first write operation as the HTTP headers are -not yet put on the wire. Trying to set the `chunkedEncoding` property -after a write will throw an error. +A Boolean specifying whether the request will use HTTP chunked transfer encoding +or not. Defaults to false. The property is readable and writable, however it can +be set only before the first write operation as the HTTP headers are not yet put +on the wire. Trying to set the `chunkedEncoding` property after the first write +will throw an error. -Using chunked encoding is strongly recommended if you need to send a large request body as -data will be streamed as small chunks instead of being internally buffered -in Electron memory. +Using chunked encoding is strongly recommended if you need to send a large +request body as data will be streamed in small chunks instead of being +internally buffered inside Electron process memory. ### Instance Methods #### `request.setHeader(name, value)` -* `name` String - An extra header name. -* `value` String - An extra header value. +* `name` String - An extra HTTP header name. +* `value` String - An extra HTTP header value. -Adds an extra HTTP header. The header name will issued as it is without lowercasing. +Adds an extra HTTP header. The header name will issued as it is without +lowercasing. It can be called only before first write. Calling this method after +the first write will throw an error. #### `request.getHeader(name)` @@ -196,17 +211,20 @@ Returns String - The value of a previously set extra header name. * `name` String - Specify an extra header name. -Removes a previously set extra header name. +Removes a previously set extra header name. This method can be called only +before first write. Trying to call it after the first write will throw an error. #### `request.write(chunk[, encoding][, callback])` -* `chunk` String or Buffer - A chunk of the request body' data. If it is a string, -it is converted into a Buffer object using the specified encoding. -* `encoding` String (optional) - Used to convert string chunks into Buffer objects. Defaults to 'utf-8'. +* `chunk` String or Buffer - A chunk of the request body's data. If it is a +string, it is converted into a Buffer using the specified encoding. +* `encoding` String (optional) - Used to convert string chunks into Buffer +objects. Defaults to 'utf-8'. * `callback` Function (optional) - Called after the write operation ends. -Adds a chunk of data to the request body. Generally, the first write operation causes the request headers to be issued on the wire. -After the first write operation, it is not allowed to add or remove a custom header. +Adds a chunk of data to the request body. The first write operation may cause +the request headers to be issued on the wire. After the first write operation, +it is not allowed to add or remove a custom header. #### `request.end([chunk][, encoding][, callback])` @@ -214,21 +232,22 @@ After the first write operation, it is not allowed to add or remove a custom hea * `encoding` String (optional) * `callback` Function (optional) -Sends the last chunk of the request data. Subsequent write or end operations will not -be allowed. The finish event is emitted just after the end operation. +Sends the last chunk of the request data. Subsequent write or end operations +will not be allowed. The `finish` event is emitted just after the end operation. #### `request.abort()` -Cancels an ongoing HTTP transaction. If the request has already closed, the abort operation will have no effect. -Otherwise an ongoing event will emit abort and close events. Additionally, if there is an ongoing response object, -it will emit the aborted event. +Cancels an ongoing HTTP transaction. If the request has already emitted the +`close` event, the abort operation will have no effect. Otherwise an ongoing +event will emit `abort` and `close` events. Additionally, if there is an ongoing +response object,it will emit the `aborted` event. ## Class: IncomingMessage `IncomingMessage` represents an HTTP response message. -It is a [Readable Stream](https://nodejs.org/api/stream.html#stream_readable_streams) and therefore -an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter). +It is a [Readable Stream](https://nodejs.org/api/stream.html#stream_readable_streams) +and consequently an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter). ### Instance Events @@ -238,7 +257,8 @@ Returns: * `chunk`: Buffer - A chunk of response body's data. -The data event is the usual method of transferring response data into applicative code. +The `data` event is the usual method of transferring response data into +applicative code. #### Event 'end' @@ -250,13 +270,14 @@ Emitted when a request has been canceled during an ongoing HTTP transaction. #### Event 'error' -Returns +Returns: `error` Error - Typically holds an error string identifying failure root cause. -Emitted if an error is encountered while streaming response data events. For instance, -if the server closes the underlying socket while streaming the response, an error event -will be emitted on the response object and a close event will subsequently follow in the request object. +Emitted when an error was encountered while streaming response data events. For +instance, if the server closes the underlying while the response is still +streaming, an `error` event will be emitted on the response object and a `close` +event will subsequently follow on the request object. ### Instance properties @@ -272,7 +293,8 @@ A String representing the HTTP status message. #### `response.headers` -An Object representing the response HTTP headers. The `headers` object is formatted as follows: +An Object representing the response HTTP headers. The `headers` object is +formatted as follows: * All header names are lowercased. * Each header name produces an array-valued property on the headers object. @@ -280,8 +302,10 @@ An Object representing the response HTTP headers. The `headers` object is format #### `response.httpVersion` -A String indicating the HTTP protocol version number. Typical values are '1.0' or '1.1'. Additionally `httpVersionMajor` and -`httpVersionMinor` are two Integer-valued readable properties that return respectively the HTTP major and minor version numbers. +A String indicating the HTTP protocol version number. Typical values are '1.0' +or '1.1'. Additionally `httpVersionMajor` and `httpVersionMinor` are two +Integer-valued readable properties that return respectively the HTTP major and +minor version numbers. From 8c19d3b210eec1b40d770ce8eb41b7834ebcd14e Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 20 Oct 2016 13:57:08 +0200 Subject: [PATCH 069/148] Documenting net module: various fixes. --- docs/api/net.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docs/api/net.md b/docs/api/net.md index d99d9d562f..4cf7079adf 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -4,7 +4,7 @@ The `net` module is a client-side API for issuing HTTP(S) requests. It is similar to the [HTTP](https://nodejs.org/api/http.html) and -[HTTPS](https://nodejs.org/api/https.html) modules of Node.js but it uses +[HTTPS](https://nodejs.org/api/https.html) modules of Node.js but uses Chromium native networking library instead of the Node.js implementation offering therefore a much greater support regarding web proxies. @@ -18,7 +18,7 @@ negotiate authentication schemes. * Support for traffic monitoring proxies: Fiddler-like proxies used for access control and monitoring. -The `net` module API has been specifically designed to mimic, as much closely as +The `net` module API has been specifically designed to mimic, as closely as possible, the familiar Node.js API. The API components including classes, methods, properties and event names are similar to those commonly used in Node.js. @@ -49,6 +49,9 @@ By the way, it is almost identical to how you would normally use the [HTTP](https://nodejs.org/api/http.html)/[HTTPS](https://nodejs.org/api/https.html) modules of Node.js +The `net` API can be used only after the application emits the `ready` event. +Trying to use the module before the `ready` event will throw an error. + ## Methods The `net` module has the following methods: From 7c17aeb6da9312079342cb53fd5cf5fc988335e9 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 20 Oct 2016 14:42:15 +0200 Subject: [PATCH 070/148] Documenting net module: fixing linter issues. --- docs/api/net.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/net.md b/docs/api/net.md index 4cf7079adf..88497bf40a 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -32,13 +32,13 @@ app.on('ready', () => { const {net} = require('electron') const request = net.request('https://github.com') request.on('response', (response) => { - console.log(`STATUS: ${response.statusCode}`); - console.log(`HEADERS: ${JSON.stringify(response.headers)}`); + console.log(`STATUS: ${response.statusCode}`) + console.log(`HEADERS: ${JSON.stringify(response.headers)}`) response.on('data', (chunk) => { console.log(`BODY: ${chunk}`) }) response.on('end', () => { - console.log('No more data in response.'); + console.log('No more data in response.') }) }) request.end() From 0c44d19249101d913470c1f2612a203c780ed41c Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Thu, 20 Oct 2016 15:48:36 +0200 Subject: [PATCH 071/148] net module: documenting the session property. --- docs/api/net.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/api/net.md b/docs/api/net.md index 88497bf40a..0fab893c56 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -82,6 +82,8 @@ following properties: method. * `url` String (optional) - The request URL. Must be provided in the absolute form with the protocol scheme specified as http or https. + * `session` String (optional) - The name of the [`Session`](session.md) +instance with which the request is associated. Defaults to the empty string. * `protocol` String (optional) - The protocol scheme in the form 'scheme:'. Currently supported values are 'http:' or 'https:'. Defaults to 'http:'. * `host` String (optional) - The server host provided as a concatenation of From 98387e50cc3134352db1fe18cab31bba6d5cb775 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 24 Oct 2016 11:42:15 +0900 Subject: [PATCH 072/148] Focus window on menu bar click --- atom/browser/native_window_views.cc | 2 +- atom/browser/ui/views/menu_bar.cc | 8 ++++++-- atom/browser/ui/views/menu_bar.h | 4 +++- atom/browser/ui/views/submenu_button.cc | 4 ---- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index d2f2077151..2ae36bc36b 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -846,7 +846,7 @@ void NativeWindowViews::SetMenu(AtomMenuModel* menu_model) { if (!menu_bar_) { gfx::Size content_size = GetContentSize(); - menu_bar_.reset(new MenuBar); + menu_bar_.reset(new MenuBar(this)); menu_bar_->set_owned_by_client(); if (!menu_bar_autohide_) { diff --git a/atom/browser/ui/views/menu_bar.cc b/atom/browser/ui/views/menu_bar.cc index bd7c4fcac9..f01edaa5b3 100644 --- a/atom/browser/ui/views/menu_bar.cc +++ b/atom/browser/ui/views/menu_bar.cc @@ -47,9 +47,10 @@ void GetMenuBarColor(SkColor* enabled, SkColor* disabled, SkColor* highlight, } // namespace -MenuBar::MenuBar() +MenuBar::MenuBar(NativeWindow* window) : background_color_(kDefaultColor), - menu_model_(NULL) { + menu_model_(NULL), + window_(window) { UpdateMenuBarColor(); SetLayoutManager(new views::BoxLayout( views::BoxLayout::kHorizontal, 0, 0, 0)); @@ -142,6 +143,9 @@ void MenuBar::OnMenuButtonClicked(views::MenuButton* source, if (!menu_model_) return; + if (!window_->IsFocused()) + window_->Focus(true); + int id = source->tag(); AtomMenuModel::ItemType type = menu_model_->GetTypeAt(id); if (type != AtomMenuModel::TYPE_SUBMENU) { diff --git a/atom/browser/ui/views/menu_bar.h b/atom/browser/ui/views/menu_bar.h index 0f371ea0ce..761e31b98e 100644 --- a/atom/browser/ui/views/menu_bar.h +++ b/atom/browser/ui/views/menu_bar.h @@ -5,6 +5,7 @@ #ifndef ATOM_BROWSER_UI_VIEWS_MENU_BAR_H_ #define ATOM_BROWSER_UI_VIEWS_MENU_BAR_H_ +#include "atom/browser/native_window.h" #include "atom/browser/ui/atom_menu_model.h" #include "ui/views/controls/button/menu_button_listener.h" #include "ui/views/view.h" @@ -20,7 +21,7 @@ class MenuDelegate; class MenuBar : public views::View, public views::MenuButtonListener { public: - MenuBar(); + explicit MenuBar(NativeWindow* window); virtual ~MenuBar(); // Replaces current menu with a new one. @@ -66,6 +67,7 @@ class MenuBar : public views::View, SkColor hover_color_; #endif + NativeWindow* window_; AtomMenuModel* menu_model_; DISALLOW_COPY_AND_ASSIGN(MenuBar); diff --git a/atom/browser/ui/views/submenu_button.cc b/atom/browser/ui/views/submenu_button.cc index 2b35620228..f7f954824f 100644 --- a/atom/browser/ui/views/submenu_button.cc +++ b/atom/browser/ui/views/submenu_button.cc @@ -52,10 +52,6 @@ SubmenuButton::SubmenuButton(const base::string16& title, SetHasInkDrop(true); set_ink_drop_base_color( color_utils::BlendTowardOppositeLuma(background_color_, 0x61)); - - set_request_focus_on_press(true); - SetFocusForPlatform(); - SetFocusPainter(nullptr); } SubmenuButton::~SubmenuButton() { From 189ae977324be2fb4074eb7dc6971d32be6ab4f7 Mon Sep 17 00:00:00 2001 From: tinydew4 Date: Mon, 24 Oct 2016 06:32:28 +0000 Subject: [PATCH 073/148] Apply the changes till the 'b2559d7' commit. --- docs-translations/ko-KR/api/app.md | 13 +- docs-translations/ko-KR/api/browser-window.md | 1 + .../ko-KR/api/content-tracing.md | 7 +- .../ko-KR/api/desktop-capturer.md | 17 +- docs-translations/ko-KR/api/dialog.md | 3 + docs-translations/ko-KR/api/menu-item.md | 3 + docs-translations/ko-KR/api/protocol.md | 105 +++++++++--- docs-translations/ko-KR/api/session.md | 160 +++++++++--------- .../api/structures/desktop-capturer-source.md | 12 ++ .../ko-KR/api/structures/upload-data.md | 7 + .../ko-KR/api/system-preferences.md | 4 + docs-translations/ko-KR/api/web-contents.md | 18 +- docs-translations/ko-KR/api/web-view-tag.md | 2 +- .../desktop-environment-integration.md | 24 +++ docs-translations/ko-KR/tutorial/security.md | 96 +++++++---- .../tutorial/using-pepper-flash-plugin.md | 4 + 16 files changed, 310 insertions(+), 166 deletions(-) create mode 100644 docs-translations/ko-KR/api/structures/desktop-capturer-source.md create mode 100644 docs-translations/ko-KR/api/structures/upload-data.md diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index 531ca4fa84..9372a6d34b 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -194,6 +194,7 @@ Returns: * `validExpiry` Integer - ์ดˆ ๋‹จ์œ„์˜ ์ธ์ฆ์„œ๊ฐ€ ๋งŒ๋ฃŒ๋˜๋Š” ๋‚ ์งœ * `fingerprint` String - ์ธ์ฆ์„œ์˜ ์ง€๋ฌธ * `callback` Function + * `isTrusted` Boolean - ์ธ์ฆ์„œ๋ฅผ ์‹ ๋ขฐํ• ์ง€ ์—ฌ๋ถ€ `url`์— ๋Œ€ํ•œ `certificate` ์ธ์ฆ์„œ์˜ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์— ์‹คํŒจํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค. ์ธ์ฆ์„œ๋ฅผ ์‹ ๋ขฐํ•œ๋‹ค๋ฉด `event.preventDefault()` ์™€ `callback(true)`๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ @@ -222,6 +223,7 @@ Returns: * `url` URL * `certificateList` [Certificate[]](structures/certificate.md) * `callback` Function + * `certificate` [Certificate](structures/certificate.md) ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์ด ์š”์ฒญ๋˜์—ˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค. @@ -256,6 +258,8 @@ Returns: * `port` Integer * `realm` String * `callback` Function + * `username` String + * `password` String `webContents`๊ฐ€ ๊ธฐ๋ณธ ์ธ์ฆ์„ ์š”์ฒญํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค. @@ -682,6 +686,8 @@ app.setJumpList([ ### `app.makeSingleInstance(callback)` * `callback` Function + * `argv` String[] - ๋‘๋ฒˆ์งธ ์ธ์Šคํ„ด์Šค์˜ ๋ช…๋ น์ค„ ์ธ์ˆ˜์˜ ๋ฐฐ์—ด + * `workingDirectory` String - ๋‘๋ฒˆ์งธ ์ธ์Šคํ„ด์Šค์˜ ์ž‘์—… ๋””๋ ‰ํ† ๋ฆฌ ํ˜„์žฌ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋‹จ์ผ ์ธ์Šคํ„ด์Šค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์—ฌ๋Ÿฌ ๋ฒˆ ์‹คํ–‰๋์„ ๋•Œ ๋‹ค์ค‘ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๋Œ€์‹  ํ•œ ๊ฐœ์˜ ์ฃผ @@ -814,8 +820,7 @@ Returns `Object`: ์—ด๋ ค์žˆ์—ˆ๋Š”์ง€ ์—ฌ๋ถ€. ์ด๋Š” ์•ฑ์ด ๋งˆ์ง€๋ง‰์œผ๋กœ ์ข…๋ฃŒ๋˜์—ˆ๋˜ ๋•Œ์— ์—ด๋ ค์žˆ์—ˆ๋˜ ์œˆ๋„์šฐ๋ฅผ ๋ณต์›ํ•˜๋Š” ๊ฒƒ์„ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ด ์„ค์ •์€ macOS์—์„œ๋งŒ ์ง€์›๋ฉ๋‹ˆ๋‹ค. -**์ฐธ๊ณ :** ์ด API ๋Š” [MAS ๋นŒ๋“œ](docs/tutorial/mac-app-store-submission-guide.md) -์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +**์ฐธ๊ณ :** ์ด API ๋Š” [MAS ๋นŒ๋“œ][mas-builds]์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ### `app.setLoginItemSettings(settings)` _macOS_ _Windows_ @@ -830,8 +835,7 @@ Returns `Object`: ์•ฑ์˜ ๋กœ๊ทธ์ธ ํ•ญ๋ชฉ ์„ค์ •์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. -**์ฐธ๊ณ :** ์ด API ๋Š” [MAS ๋นŒ๋“œ](docs/tutorial/mac-app-store-submission-guide.md) -์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +**์ฐธ๊ณ :** ์ด API ๋Š” [MAS ๋นŒ๋“œ][mas-builds]์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ### `app.isAccessibilitySupportEnabled()` _macOS_ _Windows_ @@ -939,5 +943,6 @@ dock ์•„์ด์ฝ˜์˜ `image`๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. [handoff]: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html [activity-type]: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType [unity-requiremnt]: ../tutorial/desktop-environment-integration.md#unity-launcher-shortcuts-linux +[mas-builds]: docs/tutorial/mac-app-store-submission-guide.md [JumpListBeginListMSDN]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378398(v=vs.85).aspx [about-panel-options]: https://developer.apple.com/reference/appkit/nsapplication/1428479-orderfrontstandardaboutpanelwith?language=objc diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 01f1a73645..484197c45e 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -941,6 +941,7 @@ Returns `Boolean` - ์œˆ๋„์šฐ์˜ ๋ฌธ์„œ๊ฐ€ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€. * `rect` [Rectangle](structures/rectangle.md) (optional) - ์บก์ณ๋  ํŽ˜์ด์ง€์˜ ์˜์—ญ * `callback` Function + * `image` [NativeImage](native-image.md) `webContents.capturePage([rect, ]callback)`์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. diff --git a/docs-translations/ko-KR/api/content-tracing.md b/docs-translations/ko-KR/api/content-tracing.md index 53a7c08c67..c360c35e19 100644 --- a/docs-translations/ko-KR/api/content-tracing.md +++ b/docs-translations/ko-KR/api/content-tracing.md @@ -31,7 +31,8 @@ contentTracing.startRecording(options, () => { ### `contentTracing.getCategories(callback)` -* `callback` Function +* `callback` + * `categories` String[] ์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน ์„ธํŠธ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ์นดํ…Œ๊ณ ๋ฆฌ ๊ทธ๋ฃน์€ ๋„๋‹ฌ๋œ ์ฝ”๋“œ ๊ฒฝ๋กœ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -85,6 +86,7 @@ EnableRecording ์š”์ฒญ์„ ๋ฐ›๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  child ํ”„๋กœ์„ธ์Šค๊ฐ€ `startR * `resultFilePath` String * `callback` Function + * `resultFilePath` String ๋ชจ๋“  ํ”„๋กœ์„ธ์Šค์—์„œ ๋ ˆ์ฝ”๋”ฉ์„ ์ค‘์ง€ํ•ฉ๋‹ˆ๋‹ค. @@ -127,6 +129,7 @@ Child ํ”„๋กœ์„ธ์Šค๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ถ”์  ๋ฐ์ดํ„ฐ์™€ ํฌ๊ท€ํ•œ ํ”Œ๋Ÿฌ์‹œ * `resultFilePath` String * `callback` Function + * `resultFilePath` String ํ˜„์žฌ ๋ชจ๋‹ˆํ„ฐ๋ง ์ถ”์  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. @@ -142,6 +145,8 @@ Child ํ”„๋กœ์„ธ์Šค๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ถ”์  ๋ฐ์ดํ„ฐ์™€ ํฌ๊ท€ํ•œ ํ”Œ๋Ÿฌ์‹œ ### `contentTracing.getTraceBufferUsage(callback)` * `callback` Function + * `value` Number + * `percentage` Number ์ถ”์  ๋ฒ„ํผ % ์ „์ฒด ์ƒํƒœ์˜ ํ”„๋กœ์„ธ์Šค๊ฐ„ ์ตœ๋Œ€์น˜๋ฅผ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. TraceBufferUsage ๊ฐ’์ด ๊ฒฐ์ •๋˜๋ฉด `callback`์ด ํ•œ ๋ฒˆ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. diff --git a/docs-translations/ko-KR/api/desktop-capturer.md b/docs-translations/ko-KR/api/desktop-capturer.md index 18e9418b01..68fd984783 100644 --- a/docs-translations/ko-KR/api/desktop-capturer.md +++ b/docs-translations/ko-KR/api/desktop-capturer.md @@ -62,21 +62,14 @@ function handleError (e) { * `thumbnailSize` Object (optional) - ๋ฏธ๋””์–ด ์†Œ์Šค ์„ฌ๋„ค์ผ์˜ ํฌ๊ธฐ๊ฐ€ ๋งž์ถฐ์ ธ์•ผ ํ•  ์ œ์•ˆ๋œ ํฌ๊ธฐ, ๊ธฐ๋ณธ๊ฐ’์€ `{width: 150, height: 150}`์ž…๋‹ˆ๋‹ค. * `callback` Function + * `error` Error + * `sources` [DesktopCapturerSource[]](structures/desktop-capturer-source.md) ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์Šคํฌํ†ฑ ๋ฏธ๋””์–ด ์†Œ์Šค๋ฅผ ๊ฐ€์ ธ์˜ค๊ธฐ ์‹œ์ž‘ํ•˜๊ณ  ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด `callback(error, sources)`๊ฐ€ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. -`sources`๋Š” `Source`๊ฐ์ฒด์˜ ๋ฐฐ์—ด์ด๋ฉฐ, ๊ฐ `Source`๋Š” ์บก์ณ๋  ์ˆ˜ ์žˆ๋Š” ์Šคํฌ๋ฆฐ๊ณผ ๊ฐ๊ธฐ -์œˆ๋„์šฐ๋ฅผ ํ‘œํ˜„ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค: - -* `id` String - ์œˆ๋„์šฐ ๋˜๋Š” ์Šคํฌ๋ฆฐ์˜ ์‹๋ณ„์ž๋กœ์จ [`navigator.webkitGetUserMedia`]๋ฅผ - ํ˜ธ์ถœํ•  ๋•Œ `chromeMediaSourceId` ์†์„ฑ์— ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์‹๋ณ„์ž์˜ ํ˜•์‹์€ - `window:XX` ๋˜๋Š” `screen:XX` ์ด๋ฉฐ `XX` ๋ถ€๋ถ„์€ ๋ฌด์ž‘์œ„๋กœ ์ƒ์„ฑ๋œ ์ˆซ์ž์ž…๋‹ˆ๋‹ค. -* `name` String - `Entire Screen` ๋˜๋Š” `Screen `๋กœ ์ด๋ฆ„์ง€์–ด์งˆ ์Šคํฌ๋ฆฐ - ์†Œ์Šค์ด๋ฉฐ, ์ด๋Š” ์œˆ๋„์šฐ ์ œ๋ชฉ์— ์ผ์น˜ํ•˜๋Š” ์œˆ๋„์šฐ ์†Œ์Šค์˜ ์ด๋ฆ„์ด ๋ฉ๋‹ˆ๋‹ค. -* `thumbnail` [NativeImage](native-image.md) - ์„ฌ๋„ค์ผ ์ด๋ฏธ์ง€์ž…๋‹ˆ๋‹ค. **์ฐธ๊ณ :** - `desktopCapturer.getSources`๋กœ ์ „๋‹ฌ๋œ `options` ๊ฐ์ฒด์˜ `thumnbailSize` ์†์„ฑ๊ณผ - ๊ฐ™์ด ์ด ์„ฌ๋„ค์ผ์˜ ์‚ฌ์ด์ฆˆ๊ฐ€ ์™„์ „ํžˆ ๊ฐ™์„ ๊ฒƒ์ด๋ผ๊ณ  ๋ณด์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‹ค์งˆ์ ์ธ ํฌ๊ธฐ๋Š” - ์Šคํฌ๋ฆฐ๊ณผ ์œˆ๋„์šฐ์˜ ๋น„์œจ์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +`sources` ๋Š” [`DesktopCapturerSource`](structures/desktop-capturer-source.md) +๊ฐ์ฒด์˜ ๋ฐฐ์—ด์ด๋ฉฐ, ๊ฐ `DesktopCapturerSource` ๋Š” ์บก์ณ ๊ฐ€๋Šฅํ•œ ํ™”๋ฉด ๋˜๋Š” ๊ฐœ๋ณ„ +์œˆ๋„์šฐ์ž…๋‹ˆ๋‹ค. [`navigator.webkitGetUserMedia`]: https://developer.mozilla.org/en/docs/Web/API/Navigator/getUserMedia diff --git a/docs-translations/ko-KR/api/dialog.md b/docs-translations/ko-KR/api/dialog.md index 57ed7fb7a7..5be216bf50 100644 --- a/docs-translations/ko-KR/api/dialog.md +++ b/docs-translations/ko-KR/api/dialog.md @@ -34,6 +34,7 @@ console.log(dialog) ๋‹ค์Œ์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: `openFile`, `openDirectory`, `multiSelections`, `createDirectory`, `showHiddenFiles`. * `callback` Function (optional) + * `filePaths` String[] - ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ํŒŒ์ผ ๊ฒฝ๋กœ์˜ ๋ฐฐ์—ด ์‚ฌ์šฉํ•  ๋Œ€ํ™” ์ƒ์ž์˜ ๊ธฐ๋Šฅ์ด ๋‹ด๊ธด ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. ๋‹ค์Œ์„ ํฌํ•จํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: `openFile`, `openDirectory`, `multiSelections`, `createDirectory` @@ -77,6 +78,7 @@ console.log(dialog) ๋ผ๋ฒจ์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. * `filters` String[] * `callback` Function (optional) + * `filename` String ์ž‘์—…์— ์„ฑ๊ณตํ•˜๋ฉด ์ฝœ๋ฐฑ์œผ๋กœ ์œ ์ €๊ฐ€ ์„ ํƒํ•œ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ๋ฅผ ํฌํ•จํ•œ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์™ธ์—” `undefined`๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. @@ -112,6 +114,7 @@ console.log(dialog) ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์œผ๋กœ ์•ฑ์„ ์ข€ ๋” ํ˜„๋Œ€์ ์ธ Windows ์•ฑ์ฒ˜๋Ÿผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ธฐ๋Šฅ์„ ์›ํ•˜์ง€ ์•Š์œผ๋ฉด `noLink`๋ฅผ true๋กœ ์ง€์ •ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. * `callback` Function (optional) + * `response` Number - ๋ˆŒ๋ ค์ง„ ๋ฒ„ํŠผ์˜ ์ธ๋ฑ์Šค ๋Œ€ํ™” ์ƒ์ž๋ฅผ ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. `browserWindow`๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋Œ€ํ™” ์ƒ์ž๊ฐ€ ์™„์ „ํžˆ ๋‹ซํž ๋•Œ๊นŒ์ง€ ์ง€์ •ํ•œ ์ฐฝ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์™„๋ฃŒ ์‹œ ์œ ์ €๊ฐ€ ์„ ํƒํ•œ ๋ฒ„ํŠผ์˜ ์ธ๋ฑ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs-translations/ko-KR/api/menu-item.md b/docs-translations/ko-KR/api/menu-item.md index da9473c89a..824d7c4a9f 100644 --- a/docs-translations/ko-KR/api/menu-item.md +++ b/docs-translations/ko-KR/api/menu-item.md @@ -13,6 +13,9 @@ * `options` Object * `click` Function - ๋ฉ”๋‰ด ์•„์ดํ…œ์ด ํด๋ฆญ๋  ๋•Œ `click(menuItem, browserWindow, event)` ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ ๋˜๋Š” ์ฝœ๋ฐฑ ํ•จ์ˆ˜. + * `menuItem` MenuItem + * `browserWindow` BrowserWindow + * `event` Event * `role` String - ๋ฉ”๋‰ด ์•„์ดํ…œ์˜ ์•ก์…˜์„ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ์ด ์†์„ฑ์„ ์ง€์ •ํ•˜๋ฉด `click` ์†์„ฑ์ด ๋ฌด์‹œ๋ฉ๋‹ˆ๋‹ค. * `type` String - `MenuItem`์˜ ํƒ€์ž… `normal`, `separator`, `submenu`, diff --git a/docs-translations/ko-KR/api/protocol.md b/docs-translations/ko-KR/api/protocol.md index 354f58e2cd..c4022342cf 100644 --- a/docs-translations/ko-KR/api/protocol.md +++ b/docs-translations/ko-KR/api/protocol.md @@ -75,29 +75,21 @@ app.on('ready', () => { * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `filePath` String (optional) * `completion` Function (optional) + * `error` Error `scheme`์— ํŒŒ์ผ์„ ์‘๋‹ต์œผ๋กœ ๋ณด๋‚ด๋Š” ํ”„๋กœํ† ์ฝœ์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. `handler`๋Š” `scheme`์™€ ํ•จ๊ป˜ `request`๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ `handler(request, callback)` ํ˜•์‹์œผ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. `completion` ์ฝœ๋ฐฑ์€ `scheme`๊ฐ€ ์„ฑ๊ณต์ ์œผ๋กœ ๋“ฑ๋ก๋˜์—ˆ์„ ๋•Œ `completion(null)` ํ˜•์‹์œผ๋กœ ํ˜ธ์ถœ๋˜๊ณ , ๋“ฑ๋ก์— ์‹คํŒจํ–ˆ์„ ๋• `completion(error)` ํ˜•์‹์œผ๋กœ ์—๋Ÿฌ ๋‚ด์šฉ์„ ๋‹ด์•„ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. -* `request` Object - * `url` String - * `referrer` String - * `method` String - * `uploadData` Array (optional) -* `callback` Function - -`uploadData` ๋Š” `data` ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค: - -* `data` Object - * `bytes` Buffer - ์ „์†ก๋  ์ฝ˜ํ…์ธ . - * `file` String - ์—…๋กœ๋“œ๋  ํŒŒ์ผ์˜ ๊ฒฝ๋กœ. - * `blobUUID` String - blob ๋ฐ์ดํ„ฐ์˜ UUID. ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด - [ses.getBlobData](session.md#sesgetblobdataidentifier-callback) ๋ฉ”์†Œ๋“œ๋ฅผ - ์‚ฌ์šฉํ•˜์„ธ์š”. - `request`๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋ฐ˜๋“œ์‹œ ํŒŒ์ผ ๊ฒฝ๋กœ ๋˜๋Š” `path` ์†์„ฑ์„ ํฌํ•จํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์ธ์ˆ˜์— ํฌํ•จํ•˜์—ฌ `callback`์„ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ: `callback(filePath)` ๋˜๋Š” `callback({path: filePath})`. @@ -114,7 +106,15 @@ app.on('ready', () => { * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `buffer` Buffer (optional) * `completion` Function (optional) + * `error` Error `Buffer`๋ฅผ ์‘๋‹ต์œผ๋กœ ์ „์†กํ•˜๋Š” `scheme`์˜ ํ”„๋กœํ† ์ฝœ์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. @@ -138,7 +138,15 @@ protocol.registerBufferProtocol('atom', (request, callback) => { * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `buffer` Buffer (optional) * `completion` Function (optional) + * `error` Error `String`์„ ์‘๋‹ต์œผ๋กœ ์ „์†กํ•  `scheme`์˜ ํ”„๋กœํ† ์ฝœ์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. @@ -150,7 +158,21 @@ protocol.registerBufferProtocol('atom', (request, callback) => { * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `redirectRequest` Object + * `url` String + * `method` String + * `session` Object (optional) + * `uploadData` Object (optional) + * `contentType` String - ์ฝ˜ํ…์ธ ์˜ MIME ํƒ€์ž…. + * `data` String - ์ „์†กํ•  ์ฝ˜ํ…์ธ . * `completion` Function (optional) + * `error` Error HTTP ์š”์ฒญ์„ ์‘๋‹ต์œผ๋กœ ์ „์†กํ•  `scheme`์˜ ํ”„๋กœํ† ์ฝœ์„ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. @@ -158,25 +180,16 @@ HTTP ์š”์ฒญ์„ ์‘๋‹ต์œผ๋กœ ์ „์†กํ•  `scheme`์˜ ํ”„๋กœํ† ์ฝœ์„ ๋“ฑ๋กํ•ฉ๋‹ˆ `session` ์†์„ฑ์„ ํฌํ•จํ•˜๋Š” `redirectRequest` ๊ฐ์ฒด์™€ ํ•จ๊ป˜ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•œ๋‹ค๋Š” ์ ์„ ์ œ์™ธํ•˜๋ฉด `registerFileProtocol`๊ณผ ์‚ฌ์šฉ๋ฒ•์ด ๊ฐ™์Šต๋‹ˆ๋‹ค. -* `redirectRequest` Object - * `url` String - * `method` String - * `session` Object (optional) - * `uploadData` Object (optional) - ๊ธฐ๋ณธ์ ์œผ๋กœ HTTP ์š”์ฒญ์€ ํ˜„์žฌ ์„ธ์…˜์„ ์žฌ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์„œ๋กœ ๋‹ค๋ฅธ ์„ธ์…˜์— ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ์‹ถ์œผ๋ฉด `session`์„ `null`๋กœ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. POST ์š”์ฒญ์—๋Š” ๋ฐ˜๋“œ์‹œ `uploadData` ๊ฐ์ฒด๊ฐ€ ์ œ๊ณต๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -* `uploadData` object - * `contentType` String - ์ฝ˜ํ…์ธ ์˜ MIME ํƒ€์ž…. - * `data` String - ์ „์†กํ•  ์ฝ˜ํ…์ธ . - ### `protocol.unregisterProtocol(scheme[, completion])` * `scheme` String * `completion` Function (optional) + * `error` Error `scheme`์˜ ์ปค์Šคํ…€ ํ”„๋กœํ† ์ฝœ ๋“ฑ๋ก์„ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค. @@ -184,6 +197,7 @@ POST ์š”์ฒญ์—๋Š” ๋ฐ˜๋“œ์‹œ `uploadData` ๊ฐ์ฒด๊ฐ€ ์ œ๊ณต๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. * `scheme` String * `callback` Function + * `error` Error `scheme`์— ๋™์ž‘(handler)์ด ๋“ฑ๋ก๋˜์–ด ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. `callback`์œผ๋กœ ๊ฒฐ๊ณผ(boolean)๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. @@ -192,7 +206,15 @@ POST ์š”์ฒญ์—๋Š” ๋ฐ˜๋“œ์‹œ `uploadData` ๊ฐ์ฒด๊ฐ€ ์ œ๊ณต๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `filePath` String * `completion` Function (optional) + * `error` Error `scheme` ํ”„๋กœํ† ์ฝœ์„ ๊ฐ€๋กœ์ฑ„๊ณ  `handler`๋ฅผ ํŒŒ์ผ ์ „์†ก์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ๋™์ž‘์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. @@ -200,7 +222,15 @@ POST ์š”์ฒญ์—๋Š” ๋ฐ˜๋“œ์‹œ `uploadData` ๊ฐ์ฒด๊ฐ€ ์ œ๊ณต๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `filePath` String * `completion` Function (optional) + * `error` Error `scheme` ํ”„๋กœํ† ์ฝœ์„ ๊ฐ€๋กœ์ฑ„๊ณ  `handler`๋ฅผ ๋ฌธ์ž์—ด ์ „์†ก์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ๋™์ž‘์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. @@ -208,7 +238,15 @@ POST ์š”์ฒญ์—๋Š” ๋ฐ˜๋“œ์‹œ `uploadData` ๊ฐ์ฒด๊ฐ€ ์ œ๊ณต๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `filePath` String * `completion` Function (optional) + * `error` Error `scheme` ํ”„๋กœํ† ์ฝœ์„ ๊ฐ€๋กœ์ฑ„๊ณ  `handler`๋ฅผ `Buffer` ์ „์†ก์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ๋™์ž‘์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. @@ -217,7 +255,21 @@ POST ์š”์ฒญ์—๋Š” ๋ฐ˜๋“œ์‹œ `uploadData` ๊ฐ์ฒด๊ฐ€ ์ œ๊ณต๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. * `scheme` String * `handler` Function + * `request` Object + * `url` String + * `referrer` String + * `method` String + * `uploadData` [UploadData[]](structures/upload-data.md) + * `callback` Function + * `redirectRequest` Object + * `url` String + * `method` String + * `session` Object (optional) + * `uploadData` Object (optional) + * `contentType` String - ์ฝ˜ํ…์ธ ์˜ MIME ํƒ€์ž…. + * `data` String - ์ „์†กํ•  ์ฝ˜ํ…์ธ . * `completion` Function (optional) + * `error` Error `scheme` ํ”„๋กœํ† ์ฝœ์„ ๊ฐ€๋กœ์ฑ„๊ณ  `handler`๋ฅผ HTTP ํ”„๋กœํ† ์ฝœ์˜ ์š”์ฒญ์— ๋Œ€ํ•œ ์ƒˆ๋กœ์šด ๋™์ž‘์œผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. @@ -226,6 +278,7 @@ POST ์š”์ฒญ์—๋Š” ๋ฐ˜๋“œ์‹œ `uploadData` ๊ฐ์ฒด๊ฐ€ ์ œ๊ณต๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. * `scheme` String * `completion` Function (optional) + * `error` Error ๊ฐ€๋กœ์ฑˆ `scheme`๋ฅผ ์‚ญ์ œํ•˜๊ณ  ๊ธฐ๋ณธ ํ•ธ๋“ค๋Ÿฌ๋กœ ๋ณต๊ตฌํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs-translations/ko-KR/api/session.md b/docs-translations/ko-KR/api/session.md index ce42a108da..85866ed4f8 100644 --- a/docs-translations/ko-KR/api/session.md +++ b/docs-translations/ko-KR/api/session.md @@ -201,6 +201,7 @@ proxyURL = ["://"][":"] * `url` URL * `callback` Function + * `proxy` Object `url`์˜ ํ”„๋ก์‹œ ์ •๋ณด๋ฅผ ํ•ด์„ํ•ฉ๋‹ˆ๋‹ค. `callback`์€ ์š”์ฒญ์ด ์ˆ˜ํ–‰๋˜์—ˆ์„ ๋•Œ `callback(proxy)` ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. @@ -244,7 +245,11 @@ window.webContents.session.enableNetworkEmulation({offline: true}) #### `ses.setCertificateVerifyProc(proc)` - * `proc` Function +* `proc` Function + * `hostname` String + * `certificate` [Certificate](structures/certificate.md) + * `callback` Function + * `isTrusted` Boolean - ์ธ์ฆ์„œ๋ฅผ ์‹ ๋ขฐํ•ด์•ผํ•˜๋Š”์ง€ ๊ฒฐ์ • `session`์— ์ธ์ฆ์„œ์˜ ์œ ํšจ์„ฑ์„ ํ™•์ธํ•˜๋Š” ํ”„๋กœ์„ธ์Šค(proc)๋ฅผ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. `proc`์€ ์„œ๋ฒ„ ์ธ์ฆ์„œ ์œ ํšจ์„ฑ ๊ฒ€์ฆ ์š”์ฒญ์ด ๋“ค์–ด์™”์„ ๋•Œ ์–ธ์ œ๋‚˜ `proc(hostname, certificate, callback)` @@ -267,7 +272,8 @@ win.webContents.session.setCertificateVerifyProc((hostname, cert, callback) => { * `webContents` Object - [WebContents](web-contents.md) ๊ถŒํ•œ์„ ์š”์ฒญ. * `permission` String - 'media', 'geolocation', 'notifications', 'midiSysex', 'pointerLock', 'fullscreen', 'openExternal'์˜ ๋‚˜์—ด. - * `callback` Function - ๊ถŒํ•œ ํ—ˆ์šฉ ๋ฐ ๊ฑฐ๋ถ€. + * `callback` Function + * `permissionGranted` Boolean - ๊ถŒํ•œ ํ—ˆ์šฉ ๋ฐ ๊ฑฐ๋ถ€. `session`์˜ ๊ถŒํ•œ ์š”์ฒญ์— ์‘๋‹ต์„ ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ•˜๋Š” ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. `callback(true)`๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๊ถŒํ•œ ์ œ๊ณต์„ ํ—ˆ์šฉํ•˜๊ณ  `callback(false)`๋ฅผ @@ -423,6 +429,8 @@ session.defaultSession.cookies.set(cookie, (error) => { * `secure` Boolean (optional) - ๋ณด์•ˆ ์†์„ฑ์— ๋”ฐ๋ผ ์ฟ ํ‚ค๋ฅผ ํ•„ํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค. * `session` Boolean (optional) - ์„ธ์…˜ ๋˜๋Š” ์ง€์†์„ฑ ์ฟ ํ‚ค๋ฅผ ํ•„ํ„ฐ๋งํ•ฉ๋‹ˆ๋‹ค. * `callback` Function + * `error` Error + * `cookies` Cookies[] `details` ๊ฐ์ฒด์—์„œ ๋ฌ˜์‚ฌํ•œ ๋ชจ๋“  ์ฟ ํ‚ค๋ฅผ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ์ž‘์—…์ด ๋๋‚˜๋ฉด `callback`์ด `callback(error, cookies)` ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. @@ -458,6 +466,7 @@ session.defaultSession.cookies.set(cookie, (error) => { ๋Œ€ํ•œ ์ดˆ ๋‹จ์œ„ ์‹œ๊ฐ„์ž…๋‹ˆ๋‹ค. ์ƒ๋žต๋˜๋ฉด ์ฟ ํ‚ค๊ฐ€ ์„ธ์…˜ ์ฟ ๊ธฐ๊ฐ€ ๋˜๋ฉฐ ์„ธ์…˜ ์‚ฌ์ด์— ์œ ์ง€๋˜์ง€ ์•Š๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. * `callback` Function + * `error` Error `details` ๊ฐ์ฒด์— ๋”ฐ๋ผ ์ฟ ํ‚ค๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ž‘์—…์ด ์™„๋ฃŒ๋˜๋ฉด `callback`์ด `callback(error)` ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. @@ -521,24 +530,16 @@ session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback * `method` String * `resourceType` String * `timestamp` Double - * `uploadData` Array (optional) + * `uploadData` [UploadData[]](structures/upload-data.md) * `callback` Function + * `response` Object + * `cancel` Boolean (optional) + * `redirectURL` String (optional) - ์›๋ž˜ ์š”์ฒญ์ด ์ „์†ก๋˜๊ฑฐ๋‚˜ ์™„๋ฃŒ๋˜๋Š” ๊ฒƒ์„ + ๋ฐฉ์ง€ํ•˜๊ณ  ์ง€์ •๋œ URL ๋กœ ๋ฆฌ๋””๋ ‰์…˜๋ฉ๋‹ˆ๋‹ค. -`uploadData`๋Š” `data` ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค: +`uploadData`๋Š” `uploadData` ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. -* `data` Object - * `bytes` Buffer - ์ „์†ก๋  ์ฝ˜ํ…์ธ . - * `file` String - ์—…๋กœ๋“œ๋  ํŒŒ์ผ์˜ ๊ฒฝ๋กœ. - * `blobUUID` String - blob ๋ฐ์ดํ„ฐ์˜ UUID. ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•ด - [ses.getBlobData](session.md#sesgetblobdataidentifier-callback) ๋ฉ”์†Œ๋“œ๋ฅผ - ์‚ฌ์šฉํ•˜์„ธ์š”. - -`callback`์€ `response` ๊ฐ์ฒด์™€ ํ•จ๊ป˜ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: - -* `response` Object - * `cancel` Boolean (optional) - * `redirectURL` String (optional) - ์›๋ž˜ ์š”์ฒญ์€ ์ „์†ก๊ณผ ์™„๋ฃŒ๊ฐ€ ๋ฐฉ์ง€๋˜์ง€๋งŒ ์ด - ์†์„ฑ์„ ์ง€์ •ํ•˜๋ฉด ํ•ด๋‹น URL๋กœ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๋ฉ๋‹ˆ๋‹ค. +`callback`์€ `response` ๊ฐ์ฒด์™€ ํ•จ๊ป˜ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. #### `webRequest.onBeforeSendHeaders([filter, ]listener)` @@ -557,31 +558,29 @@ HTTP ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „ ์š”์ฒญ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๋•Œ `listener * `timestamp` Double * `requestHeaders` Object * `callback` Function + * `response` Object + * `cancel` Boolean (optional) + * `requestHeaders` Object (optional) - ์ด ์†์„ฑ์ด ์ œ๊ณต๋˜๋ฉด, ์š”์ฒญ์€ ์ด ํ—ค๋”๋กœ + ๋งŒ๋“ค์–ด ์ง‘๋‹ˆ๋‹ค. -`callback`์€ `response` ๊ฐ์ฒด์™€ ํ•จ๊ป˜ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: - -* `response` Object - * `cancel` Boolean (optional) - * `requestHeaders` Object (optional) - ์ด ์†์„ฑ์ด ์ œ๊ณต๋˜๋ฉด, ์š”์ฒญ์€ ์ด ํ—ค๋”๋กœ - ๋งŒ๋“ค์–ด ์ง‘๋‹ˆ๋‹ค. +`callback`์€ `response` ๊ฐ์ฒด์™€ ํ•จ๊ป˜ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. #### `webRequest.onSendHeaders([filter, ]listener)` * `filter` Object * `listener` Function + * `details` Object + * `id` Integer + * `url` String + * `method` String + * `resourceType` String + * `timestamp` Double + * `requestHeaders` Object ์„œ๋ฒ„์— ์š”์ฒญ์ด ์ „์†ก๋˜๊ธฐ ๋ฐ”๋กœ ์ „์— `listener`๊ฐ€ `listener(details)` ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ด์ „ `onBeforeSendHeaders`์˜ response์™€ ๋‹ค๋ฅธ์ ์€ ๋ฆฌ์Šค๋„ˆ๊ฐ€ ํ˜ธ์ถœ๋˜๋Š” ์‹œ๊ฐ„์œผ๋กœ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -* `details` Object - * `id` Integer - * `url` String - * `method` String - * `resourceType` String - * `timestamp` Double - * `requestHeaders` Object - #### `webRequest.onHeadersReceived([filter, ]listener)` * `filter` Object @@ -600,86 +599,81 @@ HTTP ์š”์ฒญ์„ ๋ณด๋‚ด๊ธฐ ์ „ ์š”์ฒญ ํ—ค๋”๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ๋•Œ `listener * `statusCode` Integer * `responseHeaders` Object * `callback` Function + * `response` Object + * `cancel` Boolean + * `responseHeaders` Object (optional) - ์ด ์†์„ฑ์ด ์ œ๊ณต๋˜๋ฉด ์„œ๋ฒ„๋Š” ์ด ํ—ค๋”์™€ + ํ•จ๊ป˜ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค. + * `statusLine` String (optional) - `responseHeaders`๋ฅผ ๋ฎ์–ด์“ธ ๋•, ํ—ค๋”์˜ + ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด ๋ฐ˜๋“œ์‹œ ์ง€์ •๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ, ๊ธฐ์กด์˜ + ์‘๋‹ต ํ—ค๋”์˜ ์ƒํƒœ๊ฐ€ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. -`callback`์€ `response` ๊ฐ์ฒด์™€ ํ•จ๊ป˜ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค: - -* `response` Object - * `cancel` Boolean - * `responseHeaders` Object (optional) - ์ด ์†์„ฑ์ด ์ œ๊ณต๋˜๋ฉด ์„œ๋ฒ„๋Š” ์ด ํ—ค๋”์™€ - ํ•จ๊ป˜ ์‘๋‹ตํ•ฉ๋‹ˆ๋‹ค. - * `statusLine` String (optional) - `responseHeaders`๋ฅผ ๋ฎ์–ด์“ธ ๋•, ํ—ค๋”์˜ ์ƒํƒœ๋ฅผ - ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด ๋ฐ˜๋“œ์‹œ ์ง€์ •๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ, ๊ธฐ์กด์˜ ์‘๋‹ต ํ—ค๋”์˜ ์ƒํƒœ๊ฐ€ - ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. +`callback`์€ `response` ๊ฐ์ฒด์™€ ํ•จ๊ป˜ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. #### `webRequest.onResponseStarted([filter, ]listener)` * `filter` Object * `listener` Function + * `details` Object + * `id` Integer + * `url` String + * `method` String + * `resourceType` String + * `timestamp` Double + * `responseHeaders` Object + * `fromCache` Boolean - ์‘๋‹ต์„ ๋””์Šคํฌ ์บ์‹œ์—์„œ ๊ฐ€์ ธ์˜ฌ์ง€์— ๋Œ€ํ•œ ์—ฌ๋ถ€. + * `statusCode` Integer + * `statusLine` String ์š”์ฒญ ๋ณธ๋ฌธ์˜ ์ฒซ ๋ฒˆ์งธ ๋ฐ”์ดํŠธ๋ฅผ ๋ฐ›์•˜์„ ๋•Œ `listener`๊ฐ€ `listener(details)` ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ด๋Š” HTTP ์š”์ฒญ์—์„œ ์ƒํƒœ ์ค„๊ณผ ์š”์ฒญ ํ—ค๋”๊ฐ€ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. -* `details` Object - * `id` Integer - * `url` String - * `method` String - * `resourceType` String - * `timestamp` Double - * `responseHeaders` Object - * `fromCache` Boolean - ์‘๋‹ต์„ ๋””์Šคํฌ ์บ์‹œ์—์„œ ๊ฐ€์ ธ์˜ฌ์ง€์— ๋Œ€ํ•œ ์—ฌ๋ถ€. - * `statusCode` Integer - * `statusLine` String - #### `webRequest.onBeforeRedirect([filter, ]listener)` * `filter` Object * `listener` Function + * `details` Object + * `id` String + * `url` String + * `method` String + * `resourceType` String + * `timestamp` Double + * `redirectURL` String + * `statusCode` Integer + * `ip` String (optional) - ์š”์ฒญ์ด ์‹ค์งˆ์ ์œผ๋กœ ์ „์†ก๋  ์„œ๋ฒ„ ์•„์ดํ”ผ ์ฃผ์†Œ. + * `fromCache` Boolean + * `responseHeaders` Object ์„œ๋ฒ„์—์„œ ์‹œ์ž‘๋œ ๋ฆฌ๋‹ค์ด๋ ‰ํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ `listener`๊ฐ€ `listener(details)` ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. -* `details` Object - * `id` String - * `url` String - * `method` String - * `resourceType` String - * `timestamp` Double - * `redirectURL` String - * `statusCode` Integer - * `ip` String (optional) - ์š”์ฒญ์ด ์‹ค์งˆ์ ์œผ๋กœ ์ „์†ก๋  ์„œ๋ฒ„ ์•„์ดํ”ผ ์ฃผ์†Œ. - * `fromCache` Boolean - * `responseHeaders` Object - #### `webRequest.onCompleted([filter, ]listener)` * `filter` Object * `listener` Function + * `details` Object + * `id` Integer + * `url` String + * `method` String + * `resourceType` String + * `timestamp` Double + * `responseHeaders` Object + * `fromCache` Boolean + * `statusCode` Integer + * `statusLine` String ์š”์ฒญ์ด ์™„๋ฃŒ๋˜๋ฉด `listener`๊ฐ€ `listener(details)` ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. -* `details` Object - * `id` Integer - * `url` String - * `method` String - * `resourceType` String - * `timestamp` Double - * `responseHeaders` Object - * `fromCache` Boolean - * `statusCode` Integer - * `statusLine` String - #### `webRequest.onErrorOccurred([filter, ]listener)` * `filter` Object * `listener` Function + * `details` Object + * `id` Integer + * `url` String + * `method` String + * `resourceType` String + * `timestamp` Double + * `fromCache` Boolean + * `error` String - ์—๋Ÿฌ ์„ค๋ช…. ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด `listener`๊ฐ€ `listener(details)` ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. - -* `details` Object - * `id` Integer - * `url` String - * `method` String - * `resourceType` String - * `timestamp` Double - * `fromCache` Boolean - * `error` String - ์—๋Ÿฌ ์„ค๋ช…. diff --git a/docs-translations/ko-KR/api/structures/desktop-capturer-source.md b/docs-translations/ko-KR/api/structures/desktop-capturer-source.md new file mode 100644 index 0000000000..e0b54d0217 --- /dev/null +++ b/docs-translations/ko-KR/api/structures/desktop-capturer-source.md @@ -0,0 +1,12 @@ +# DesktopCapturerSource Object + +* `id` String - [`navigator.webkitGetUserMedia`] ๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ + `chromeMediaSourceId` ์ œํ•œ์œผ๋กœ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ์œˆ๋„์šฐ ๋˜๋Š” ํ™”๋ฉด์˜ ์‹๋ณ„์ž. + ์‹๋ณ„์ž์˜ ํ˜•์‹์€ `window:XX` ๋˜๋Š” `screen:XX` ์ด ๋  ๊ฒƒ ์ด๋ฉฐ, `XX` ๋Š” ๋ฌด์ž‘์œ„๋กœ + ์ƒ์„ฑ๋œ ์ˆซ์ž์ž…๋‹ˆ๋‹ค. +* `name` String - ์œˆ๋„์šฐ ์†Œ์Šค์˜ ์ด๋ฆ„์ด ์œˆ๋„์šฐ ์ œ๋ชฉ๊ณผ ์ผ์น˜ํ•˜๋ฉด, ํ™”๋ฉด ์†Œ์Šค๋Š” + `Entire Screen` ๋˜๋Š” `Screen ` ์œผ๋กœ ๋ช…๋ช…๋  ๊ฒƒ ์ž…๋‹ˆ๋‹ค. +* `thumbnail` [NativeImage](../native-image.md) - ์„ฌ๋„ค์ผ ์ด๋ฏธ์ง€. **์ฐธ๊ณ :** + `desktopCapturer.getSources` ์— ๋„˜๊ฒจ์ง„ `options` ์— ๋ช…์‹œ๋œ `thumbnailSize` ์™€ + ์„ฌ๋„ค์ผ์˜ ํฌ๊ธฐ๊ฐ€ ๊ฐ™์Œ์„ ๋ณด์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์‹ค์ œ ํฌ๊ธฐ๋Š” ํ™”๋ฉด์ด๋‚˜ ์œˆ๋„์šฐ์˜ ๊ทœ๋ชจ์— + ์˜ํ•ด ๊ฒฐ์ •๋ฉ๋‹ˆ๋‹ค. diff --git a/docs-translations/ko-KR/api/structures/upload-data.md b/docs-translations/ko-KR/api/structures/upload-data.md new file mode 100644 index 0000000000..60940bbfc3 --- /dev/null +++ b/docs-translations/ko-KR/api/structures/upload-data.md @@ -0,0 +1,7 @@ +# UploadData Object + +* `bytes` Buffer - ์ „์†ก๋˜๋Š” ๋‚ด์šฉ. +* `file` String - ์—…๋กœ๋“œ๋˜๋Š” ํŒŒ์ผ์˜ ๊ฒฝ๋กœ. +* `blobUUID` String - BLOB ๋ฐ์ดํ„ฐ์˜ UUID. ๋ฐ์ดํ„ฐ๋ฅผ ์ด์šฉํ•˜๋ ค๋ฉด + [ses.getBlobData](../session.md#sesgetblobdataidentifier-callback) ๋ฉ”์†Œ๋“œ๋ฅผ + ์‚ฌ์šฉํ•˜์„ธ์š”. diff --git a/docs-translations/ko-KR/api/system-preferences.md b/docs-translations/ko-KR/api/system-preferences.md index 2960315ea1..2df4d0f107 100644 --- a/docs-translations/ko-KR/api/system-preferences.md +++ b/docs-translations/ko-KR/api/system-preferences.md @@ -62,6 +62,8 @@ macOS ์˜ ๊ธฐ๋ณธ ์•Œ๋ฆผ์œผ๋กœ `event` ๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. `userInfo` ๋Š” ์•Œ๋ฆผ * `event` String * `callback` Function + * `event` String + * `userInfo` Object macOS์˜ ๊ธฐ๋ณธ ์•Œ๋ฆผ์„ ๊ตฌ๋…ํ•˜๋ฉฐ, ํ•ด๋‹นํ•˜๋Š” `event`๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด `callback`์ด `callback(event, userInfo)` ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. `userInfo`๋Š” ์•Œ๋ฆผ๊ณผ ํ•จ๊ป˜ ์ „์†ก๋˜๋Š” @@ -87,6 +89,8 @@ macOS์˜ ๊ธฐ๋ณธ ์•Œ๋ฆผ์„ ๊ตฌ๋…ํ•˜๋ฉฐ, ํ•ด๋‹นํ•˜๋Š” `event`๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด `ca * `event` String * `callback` Function + * `event` String + * `userInfo` Object `subscribeNotification`์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ๋กœ์ปฌ ๊ธฐ๋ณธ๊ฐ’์— ๋Œ€ํ•ด `NSNotificationCenter`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” `NSUserDefaultsDidChangeNotification`์™€ diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index 10af2a66c8..117a6d9dca 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -246,6 +246,8 @@ Returns: * `error` String - ์—๋Ÿฌ ์ฝ”๋“œ * `certificate` [Certificate](structures/certificate.md) * `callback` Function + * `isTrusted` Boolean - ์ธ์ฆ์„œ๊ฐ€ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ + ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค `url`์— ๋Œ€ํ•œ `certificate` ์ธ์ฆ์„œ์˜ ์œ ํšจ์„ฑ ๊ฒ€์ฆ์— ์‹คํŒจํ–ˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค. @@ -258,8 +260,10 @@ Returns: * `event` Event * `url` URL -* `certificateList` Certificate[] +* `certificateList` [Certificate[]](structures/certificate.md) * `callback` Function + * `certificate` [Certificate](structures/certificate.md) - ์ธ์ฆ์„œ๋Š” ์ฃผ์–ด์ง„ + ๋ชฉ๋ก์— ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์ธ์ฆ์ด ์š”์ฒญ๋˜์—ˆ์„ ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค. @@ -282,6 +286,8 @@ Returns: * `port` Integer * `realm` String * `callback` Function + * `username` String + * `password` String `webContents`๊ฐ€ ๊ธฐ๋ณธ ์ธ์ฆ์„ ์ˆ˜ํ–‰ํ•˜๊ธธ ์›ํ•  ๋•Œ ๋ฐœ์ƒ๋˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค. @@ -611,7 +617,7 @@ CSS ์ฝ”๋“œ๋ฅผ ํ˜„์žฌ ์›น ํŽ˜์ด์ง€์— ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค. * `code` String * `userGesture` Boolean (optional) * `callback` Function (optional) - ์Šคํฌ๋ฆฝํŠธ์˜ ์‹คํ–‰์ด ์™„๋ฃŒ๋˜๋ฉด ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. - * `result` + * `result` Any ํŽ˜์ด์ง€์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. @@ -638,6 +644,7 @@ CSS ์ฝ”๋“œ๋ฅผ ํ˜„์žฌ ์›น ํŽ˜์ด์ง€์— ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค. #### `contents.getZoomFactor(callback)` * `callback` Function + * `zoomFactor` Number ํ˜„์žฌ ์คŒ ์ˆ˜์น˜ ๊ฐ’์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค. `callback`์€ `callback(zoomFactor)` ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. @@ -651,6 +658,7 @@ CSS ์ฝ”๋“œ๋ฅผ ํ˜„์žฌ ์›น ํŽ˜์ด์ง€์— ์‚ฝ์ž…ํ•ฉ๋‹ˆ๋‹ค. #### `contents.getZoomLevel(callback)` * `callback` Function + * `zoomLevel` Number ํ˜„์žฌ ์คŒ ์ˆ˜์ค€ ๊ฐ’์„ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค. `callback`์€ `callback(zoomLevel)` ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. @@ -779,6 +787,7 @@ console.log(requestId) #### `contents.hasServiceWorker(callback)` * `callback` Function + * `hasWorker` Boolean ServiceWorker๊ฐ€ ๋“ฑ๋ก๋˜์–ด์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  `callback`์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ boolean ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. @@ -786,6 +795,7 @@ ServiceWorker๊ฐ€ ๋“ฑ๋ก๋˜์–ด์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ  `callback`์— ๋Œ€ํ•œ ์‘๋‹ต #### `contents.unregisterServiceWorker(callback)` * `callback` Function + * `success` Boolean ServiceWorker๊ฐ€ ์กด์žฌํ•˜๋ฉด ๋ชจ๋‘ ๋“ฑ๋ก์„ ํ•ด์ œํ•˜๊ณ  JS Promise๊ฐ€ ๋งŒ์กฑ๋  ๋•Œ `callback`์— ๋Œ€ํ•œ ์‘๋‹ต์œผ๋กœ boolean์„ ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜ JS Promise๊ฐ€ ๋งŒ์กฑ๋˜์ง€ ์•Š์„ ๋•Œ `false`๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. @@ -817,6 +827,8 @@ ServiceWorker๊ฐ€ ์กด์žฌํ•˜๋ฉด ๋ชจ๋‘ ๋“ฑ๋ก์„ ํ•ด์ œํ•˜๊ณ  JS Promise๊ฐ€ ๋งŒ์กฑ * `landscape` Boolean - landscape์„ ์œ„ํ•ด์„  `true`๋ฅผ, portrait๋ฅผ ์œ„ํ•ด์„  `false`๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. * `callback` Function - `(error, data) => {}` + * `error` Error + * `data` Buffer Chromium์˜ ๋ฏธ๋ฆฌ๋ณด๊ธฐ ํ”„๋ฆฐํŒ… ์ปค์Šคํ…€ ์„ค์ •์„ ์ด์šฉํ•˜์—ฌ ์œˆ๋„์šฐ์˜ ์›น ํŽ˜์ด์ง€๋ฅผ PDF๋กœ ํ”„๋ฆฐํŠธํ•ฉ๋‹ˆ๋‹ค. @@ -1034,6 +1046,8 @@ Input `event`๋ฅผ ์›น ํŽ˜์ด์ง€๋กœ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. * `onlyDirty` Boolean (optional) - ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. * `callback` Function + * `frameBuffer` Buffer + * `dirtyRect` [Rectangle](structures/rectangle.md) ์บก์ฒ˜๋œ ํ”„๋ ˆ์ž„๊ณผ ํ”„๋ ˆ์  ํ…Œ์ด์…˜ ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…ํ•˜๊ธฐ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. `callback`์€ ํ”„๋ ˆ์  ํ…Œ์ด์…˜ ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ `callback(frameBuffer, dirtyRect)` ํ˜•ํƒœ๋กœ diff --git a/docs-translations/ko-KR/api/web-view-tag.md b/docs-translations/ko-KR/api/web-view-tag.md index 2688d9c17f..e4d17504e1 100644 --- a/docs-translations/ko-KR/api/web-view-tag.md +++ b/docs-translations/ko-KR/api/web-view-tag.md @@ -338,7 +338,7 @@ Webview์— ์›น ํŽ˜์ด์ง€ `url`์„ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค. `url`์€ `http://`, `file://` * `code` String * `userGesture` Boolean * `callback` Function (optional) - ์Šคํฌ๋ฆฝํŠธ์˜ ์‹คํ–‰์ด ์™„๋ฃŒ๋˜๋ฉด ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. - * `result` + * `result` Any ํŽ˜์ด์ง€์—์„œ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. diff --git a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md index cf6a2e8d79..4d70bc9edf 100644 --- a/docs-translations/ko-KR/tutorial/desktop-environment-integration.md +++ b/docs-translations/ko-KR/tutorial/desktop-environment-integration.md @@ -299,6 +299,29 @@ let win = new BrowserWindow() win.setOverlayIcon('path/to/overlay.png', 'Description for overlay') ``` +## ํ”„๋ ˆ์ž„ ๊นœ๋นก์ด๊ธฐ (์œˆ๋„์šฐ์ฆˆ) + +์œˆ๋„์šฐ์ฆˆ์—์„œ ์‚ฌ์šฉ์ž์˜ ๊ด€์‹ฌ์„ ๋Œ๊ธฐ ์œ„ํ•ดใ…ฃ ์ž‘์—…ํ‘œ์‹œ์ค„ ๋ฒ„ํŠผ์„ ๊ฐ•์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด๊ฒƒ์€ macOS ์˜ ๋… ์•„์ด์ฝ˜์„ ํŠ•๊ธฐ๋Š” ๊ฒƒ๊ณผ ์œ ์‚ฌํ•ฉ๋‹ˆ๋‹ค. +MSDN์—์„œ ์ธ์šฉํ•˜์ž๋ฉด (์˜๋ฌธ): + +> Typically, a window is flashed to inform the user that the window requires +> attention but that it does not currently have the keyboard focus. + +BrowserWindow ์ž‘์—…ํ‘œ์‹œ์ค„ ๋ฒ„ํŠผ์„ ๊นœ๋นก์ด๋ ค๋ฉด, +[BrowserWindow.flashFrame][flashframe] API ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด๋ฉ๋‹ˆ๋‹ค: + +```javascript +const {BrowserWindow} = require('electron') +let win = new BrowserWindow() +win.once('focus', () => win.flashFrame(false)) +win.flashFrame(true) +``` + +`flashFrame` ๋ฉ”์†Œ๋“œ๋ฅผ `false` ์ธ์ž๋กœ ํ˜ธ์ถœํ•˜์—ฌ ๊นœ๋นก์ž„์„ ์ค‘๋‹จ์‹œํ‚ค๋Š” ๊ฒƒ์„ +์žŠ์ง€๋งˆ์„ธ์š”. ์œ„์˜ ์˜ˆ์ œ์—์„œ, ์œˆ๋„์šฐ๊ฐ€ ํฌ์ปค์Šค๋˜์—ˆ์„ ๋•Œ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํƒ€์ž„์•„์›ƒ +๋˜๋Š” ๋‹ค๋ฅธ ์ด๋ฒคํŠธ์—์„œ ๋น„ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + ## ๋Œ€ํ‘œ ํŒŒ์ผ ์ œ์‹œ (macOS) macOS๋Š” ์ฐฝ์—์„œ ๋Œ€ํ‘œ ํŒŒ์ผ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํƒ€์ดํ‹€๋ฐ”์—์„œ ํŒŒ์ผ ์•„์ด์ฝ˜์ด ์žˆ๊ณ , ์‚ฌ์šฉ์ž๊ฐ€ @@ -364,3 +387,4 @@ ipcMain.on('ondragstart', (event, filePath) => { [tray-balloon]: ../api/tray.md#traydisplayballoonoptions-windows [app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx [notification-spec]: https://developer.gnome.org/notification-spec/ +[flashframe]: ../api/browser-window.md#winflashframeflag diff --git a/docs-translations/ko-KR/tutorial/security.md b/docs-translations/ko-KR/tutorial/security.md index 5a53d2b8bd..e13cd1e999 100644 --- a/docs-translations/ko-KR/tutorial/security.md +++ b/docs-translations/ko-KR/tutorial/security.md @@ -1,53 +1,54 @@ # ๋ณด์•ˆ, ๋„ค์ดํ‹ฐ๋ธŒ ํ˜ธํ™˜์„ฑ, ๊ทธ๋ฆฌ๊ณ  ์‹ ๋ขฐ์„ฑ -์›น ๊ฐœ๋ฐœ์ž๋กœ์จ, ์šฐ๋ฆฌ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €์˜ ๊ฐ•๋ ฅํ•œ ์›น ๋ณด์•ˆ์„ ์ž˜ ์ด์šฉํ•ด์™”์Šต๋‹ˆ๋‹ค - ์ž‘์„ฑํ•œ -์ฝ”๋“œ์— ๊ด€๋ จ๋œ ๋ณด์•ˆ ๋ฌธ์ œ๋Š” ์•„์ฃผ ์ ์—ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์›น ์‚ฌ์ดํŠธ์˜ ์ƒŒ๋“œ๋ฐ•์Šค์•ˆ์—์„œ ํ—ˆ์šฉ๋œ -์ƒ๋‹นํžˆ ์ œํ•œ๋œ ๊ถŒํ•œ๊ณผ ๊ธฐ๋Šฅ์— ์˜์กดํ•ด์™”์œผ๋ฉฐ, ์šฐ๋ฆฌ๋Š” ์ƒˆ๋กœ์šด ๋ณด์•ˆ ์œ„ํ˜‘์— ๋Œ€ํ•ด ๋ฐœ ๋น ๋ฅด๊ฒŒ -๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๋Š” ์—”์ง€๋‹ˆ์–ด๋“ค๋กœ ์ด๋ฃจ์–ด์ง„ ์ปค๋‹ค๋ž€ ํŒ€์œผ๋กœ๋ถ€ํ„ฐ ๋งŒ๋“ค์–ด์ง„ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์‚ฌ์šฉ์ž๋“ค์ด -๋งˆ์Œ ๋†“๊ณ  ์ฆ๊ธธ ๊ฒƒ์ด๋ผ๊ณ  ๋ฏฟ์–ด์™”์Šต๋‹ˆ๋‹ค. +์›น ๊ฐœ๋ฐœ์ž๋กœ์จ, ์šฐ๋ฆฌ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ๋ธŒ๋ผ์šฐ์ €์˜ ๊ฐ•๋ ฅํ•œ ์›น ๋ณด์•ˆ์„ ์ž˜ ์ด์šฉํ•ด์™”์Šต๋‹ˆ๋‹ค +- ์ž‘์„ฑํ•œ ์ฝ”๋“œ์— ๊ด€๋ จ๋œ ๋ณด์•ˆ ๋ฌธ์ œ๋Š” ์•„์ฃผ ์ ์—ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์›น ์‚ฌ์ดํŠธ์˜ +์ƒŒ๋“œ๋ฐ•์Šค์•ˆ์—์„œ ํ—ˆ์šฉ๋œ ์ƒ๋‹นํžˆ ์ œํ•œ๋œ ๊ถŒํ•œ๊ณผ ๊ธฐ๋Šฅ์— ์˜์กดํ•ด์™”์œผ๋ฉฐ, ์šฐ๋ฆฌ๋Š” ์ƒˆ๋กœ์šด +๋ณด์•ˆ ์œ„ํ˜‘์— ๋Œ€ํ•ด ๋ฐœ ๋น ๋ฅด๊ฒŒ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๋Š” ์—”์ง€๋‹ˆ์–ด๋“ค๋กœ ์ด๋ฃจ์–ด์ง„ ์ปค๋‹ค๋ž€ +ํŒ€์œผ๋กœ๋ถ€ํ„ฐ ๋งŒ๋“ค์–ด์ง„ ๋ธŒ๋ผ์šฐ์ €๋ฅผ ์‚ฌ์šฉ์ž๋“ค์ด ๋งˆ์Œ ๋†“๊ณ  ์ฆ๊ธธ ๊ฒƒ์ด๋ผ๊ณ  ๋ฏฟ์–ด์™”์Šต๋‹ˆ๋‹ค. -ํ•˜์ง€๋งŒ Electron์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…ํ•œ๋‹ค๋ฉด, Electron์€ ์›น ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•ด -๋‘์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Electron์€ ์นœ๊ทผํ•œ ์›น ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ’๋ถ€ํ•œ ๊ธฐ๋Šฅ์˜ ๋ฐ์Šคํฌํ†ฑ +ํ•˜์ง€๋งŒ Electron์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž‘์—…ํ•œ๋‹ค๋ฉด, Electron์€ ์›น ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์•„๋‹ˆ๋ผ๋Š” ๊ฒƒ์„ +๊ธฐ์–ตํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Electron์€ ์นœ๊ทผํ•œ ์›น ๊ธฐ์ˆ ์„ ์‚ฌ์šฉํ•˜์—ฌ ํ’๋ถ€ํ•œ ๊ธฐ๋Šฅ์˜ ๋ฐ์Šคํฌํ†ฑ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ์ง€๋งŒ ๊ทธ๋งŒํผ ์ฝ”๋“œ๊ฐ€ ๋” ํฐ ํž˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. -JavaScript๊ฐ€ ํŒŒ์ผ ์‹œ์Šคํ…œ, ์œ ์ € ์‰˜, ๊ทธ์™ธ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๊ธฐ๋Šฅ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ -๋Šฅ๋ ฅ์€ ๋†’์€ ํ€„๋ฆฌํ‹ฐ๋ฅผ ๊ฐ€์ง„ ๋„ค์ดํ‹ฐ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ์ง€๋งŒ ์ฝ”๋“œ์— -๋ถ€์—ฌ๋œ ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ๋งŒํผ ๊ณ ์œ ํ•œ ๋ณด์•ˆ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. +์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ํŒŒ์ผ ์‹œ์Šคํ…œ, ์œ ์ € ์‰˜, ๊ทธ์™ธ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๊ธฐ๋Šฅ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์ด๋Ÿฌํ•œ ๋Šฅ๋ ฅ์€ ๋†’์€ ํ€„๋ฆฌํ‹ฐ๋ฅผ ๊ฐ€์ง„ ๋„ค์ดํ‹ฐ๋ธŒ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋„๋ก +ํ•ด์ฃผ์ง€๋งŒ ์ฝ”๋“œ์— ๋ถ€์—ฌ๋œ ์ถ”๊ฐ€์ ์ธ ๊ธฐ๋Šฅ๋งŒํผ ๊ณ ์œ ํ•œ ๋ณด์•ˆ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด +์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์—ผ๋‘ํ•ด๋‘๊ณ , ์‹ ๋ขฐํ•  ์ˆ˜ ์—†๋Š” ์ถœ์ฒ˜์˜ ์ž„์˜์˜ ์ฝ˜ํ…์ธ ๋ฅผ ํ‘œ์‹œํ•  ๋•Œ Electron์—์„œ -์ž์ฒด์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š” ์‹ฌ๊ฐํ•œ ๋ณด์•ˆ ๋ฌธ์ œ๋ฅผ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์ฃผ์˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. -์‹ค์ œ๋กœ๋„, ๊ฐ€์žฅ ์œ ๋ช…ํ•œ Electron ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋“ค์€ (Atom, Slack, Visual Studio Code, -๋“ฑ) ์ฃผ๋กœ ๋กœ์ปฌ ์ฝ˜ํ…์ธ ๋ฅผ (๋˜๋Š” Node ํ†ตํ•ฉ์ด ์ œ์™ธ๋œ ์‹ ๋ขฐ๋œ, ๋ณด์•ˆ๋œ ์›๊ฒฉ ์ฝ˜ํ…์ธ ) ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค -- ๋งŒ์•ฝ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์˜จ๋ผ์ธ ์ถœ์ฒ˜์—์„œ ๊ฐ€์ ธ์˜จ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค๋ฉด, ๊ทธ ์ฝ”๋“œ๊ฐ€ ์•…์„ฑ ์ฝ”๋“œ๊ฐ€ -์•„๋‹Œ์ง€ ํŒ๋ณ„ํ•˜๋Š” ๊ฒƒ์€ ๋ณธ์ธ์˜ ์ฑ…์ž„์ž…๋‹ˆ๋‹ค. +์ž์ฒด์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š” ์‹ฌ๊ฐํ•œ ๋ณด์•ˆ ๋ฌธ์ œ๋ฅผ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ์ฃผ์˜ํ•ด์•ผ +ํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ๋„, ๊ฐ€์žฅ ์œ ๋ช…ํ•œ Electron ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๋“ค์€ (Atom, Slack, Visual +Studio Code, ๋“ฑ) ์ฃผ๋กœ ๋กœ์ปฌ ์ฝ˜ํ…์ธ ๋ฅผ (๋˜๋Š” Node ํ†ตํ•ฉ์ด ์ œ์™ธ๋œ ์‹ ๋ขฐ๋œ, ๋ณด์•ˆ๋œ ์›๊ฒฉ +์ฝ˜ํ…์ธ ) ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค - ๋งŒ์•ฝ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์˜จ๋ผ์ธ ์ถœ์ฒ˜์—์„œ ๊ฐ€์ ธ์˜จ ์ฝ”๋“œ๋ฅผ +์‹คํ–‰ํ•œ๋‹ค๋ฉด, ๊ทธ ์ฝ”๋“œ๊ฐ€ ์•…์„ฑ ์ฝ”๋“œ๊ฐ€ ์•„๋‹Œ์ง€ ํŒ๋ณ„ํ•˜๋Š” ๊ฒƒ์€ ๋ณธ์ธ์˜ ์ฑ…์ž„์ž…๋‹ˆ๋‹ค. ## Chromium ๋ณด์•ˆ ๋ฌธ์ œ์™€ ์—…๊ทธ๋ ˆ์ด๋“œ Electron์ด ์ƒˆ๋กœ์šด ๋ฒ„์ „์˜ Chromium์„ ๊ฐ€๋Šฅํ•œ ํ•œ ๋น ๋ฅด๊ฒŒ ์ง€์›ํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•˜์ง€๋งŒ, -๊ฐœ๋ฐœ์ž๋Š” ์ด๋Ÿฌํ•œ ์—…๊ทธ๋ ˆ์ด๋”ฉ ์ž‘์—…์€ ๋งค์šฐ ํž˜๋“  ์ž‘์—…์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค - ๊ฐ ๊ด€๋ จ๋œ -์ˆ˜์‹ญ์—์„œ ์‹ฌ์ง€์–ด ๋ฐฑ์ž๋ฆฌ ๊ฐœ์ˆ˜์˜ ํŒŒ์ผ๋“ค์„ ์†์ˆ˜ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ ์ž์›๊ณผ ํ˜„์žฌ -๊ธฐ์—ฌ๋„๋ฅผ ์ƒ๊ฐํ•œ๋‹ค๋ฉด, Electron์€ ํ•ญ์ƒ ์ตœ์‹  ๋ฒ„์ „์˜ Chromium์„ ์œ ์ง€ํ•˜์ง€ ๋ชปํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, -๋ฉฐ์น ๋ถ€ํ„ฐ ๋ช‡ ์ฃผ๊นŒ์ง€ ๋” ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +๊ฐœ๋ฐœ์ž๋Š” ์ด๋Ÿฌํ•œ ์—…๊ทธ๋ ˆ์ด๋”ฉ ์ž‘์—…์€ ๋งค์šฐ ํž˜๋“  ์ž‘์—…์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค - ๊ฐ +๊ด€๋ จ๋œ ์ˆ˜์‹ญ์—์„œ ์‹ฌ์ง€์–ด ๋ฐฑ์ž๋ฆฌ ๊ฐœ์ˆ˜์˜ ํŒŒ์ผ๋“ค์„ ์†์ˆ˜ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฃผ์–ด์ง„ +์ž์›๊ณผ ํ˜„์žฌ ๊ธฐ์—ฌ๋„๋ฅผ ์ƒ๊ฐํ•œ๋‹ค๋ฉด, Electron์€ ํ•ญ์ƒ ์ตœ์‹  ๋ฒ„์ „์˜ Chromium์„ ์œ ์ง€ํ•˜์ง€ +๋ชปํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๋ฉฐ์น ๋ถ€ํ„ฐ ๋ช‡ ์ฃผ๊นŒ์ง€ ๋” ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ Chromium ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์‹œ์Šคํ…œ์€ ์šฐ๋ฆฌ๊ฐ€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ž์›๊ณผ ์ด -ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋œ ๋Œ€๋ถ€๋ถ„์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์š”๊ตฌํ•˜๋Š” ๊ฒƒ ์‚ฌ์ด์—์„œ ์ ์ ˆํ•œ ๊ท ํ˜•์„ -์œ ์ง€ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ๋А๋ผ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ํ™•์‹คํžˆ Electron ์œ„์— ๋ฌด์–ธ๊ฐ€๋ฅผ ๋งŒ๋“œ๋Š” ์‚ฌ๋žŒ๋“ค์˜ -์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์„ ๋“ฃ๋Š” ๊ฒƒ์— ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋…ธ๋ ฅ์„ ์ง€์›ํ•˜๋Š” Pull -request์™€ ๊ธฐ์—ฌ๋Š” ์–ธ์ œ๋‚˜ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค. +ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•๋œ ๋Œ€๋ถ€๋ถ„์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์š”๊ตฌํ•˜๋Š” ๊ฒƒ ์‚ฌ์ด์—์„œ ์ ์ ˆํ•œ +๊ท ํ˜•์„ ์œ ์ง€ํ•˜๊ณ  ์žˆ๋‹ค๊ณ  ๋А๋ผ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ํ™•์‹คํžˆ Electron ์œ„์— ๋ฌด์–ธ๊ฐ€๋ฅผ +๋งŒ๋“œ๋Š” ์‚ฌ๋žŒ๋“ค์˜ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์„ ๋“ฃ๋Š” ๊ฒƒ์— ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ +๋…ธ๋ ฅ์„ ์ง€์›ํ•˜๋Š” Pull ์š”์ฒญ๊ณผ ๊ธฐ์—ฌ๋Š” ์–ธ์ œ๋‚˜ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค. ## ์œ„ ์กฐ์–ธ ๋ฌด์‹œํ•˜๊ธฐ -์›๊ฒฉ ์œ„์น˜์—์„œ ๋ฐ›์•„์˜จ ์ฝ”๋“œ๋ฅผ ๋กœ์ปฌ์—์„œ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ์–ธ์ œ๋‚˜ ๋ณด์•ˆ ๋ฌธ์ œ๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. -์˜ˆ๋ฅผ ๋“ค์–ด, ์›๊ฒฉ ์›น ์‚ฌ์ดํŠธ๊ฐ€ ๋ธŒ๋ผ์šฐ์ € ์œˆ๋„์šฐ์—์„œ ํ‘œ์‹œ๋  ๋•Œ๋ฅผ ์ƒ๊ฐํ•ด๋ณผ ๋•Œ, ๋งŒ์•ฝ ๊ณต๊ฒฉ์ž๊ฐ€ -์–ด๋– ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์›น ํŽ˜์ด์ง€์˜ ์ฝ˜ํ…์ธ ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ (์†Œ์Šค๋ฅผ ์ง์ ‘์ ์œผ๋กœ ๊ณต๊ฒฉํ•˜๊ฑฐ๋‚˜ -์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ์‹ค์งˆ์ ์ธ ์œ„์น˜ ์‚ฌ์ด์—์„œ ๊ณต๊ฒฉํ•˜๋Š” ๋“ฑ), ๊ณต๊ฐน์ž๋Š” ์‚ฌ์šฉ์ž์˜ ๊ธฐ๊ธฐ์—์„œ ๋„ค์ดํ‹ฐ๋ธŒ -์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +์›๊ฒฉ ์œ„์น˜์—์„œ ๋ฐ›์•„์˜จ ์ฝ”๋“œ๋ฅผ ๋กœ์ปฌ์—์„œ ์‹คํ–‰ํ•˜๋Š” ๊ฒฝ์šฐ ์–ธ์ œ๋‚˜ ๋ณด์•ˆ ๋ฌธ์ œ๊ฐ€ +์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์›๊ฒฉ ์›น ์‚ฌ์ดํŠธ๊ฐ€ ๋ธŒ๋ผ์šฐ์ € ์œˆ๋„์šฐ์—์„œ ํ‘œ์‹œ๋  ๋•Œ๋ฅผ ์ƒ๊ฐํ•ด๋ณผ +๋•Œ, ๋งŒ์•ฝ ๊ณต๊ฒฉ์ž๊ฐ€ ์–ด๋– ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์›น ํŽ˜์ด์ง€์˜ ์ฝ˜ํ…์ธ ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒฝ์šฐ (์†Œ์Šค๋ฅผ +์ง์ ‘์ ์œผ๋กœ ๊ณต๊ฒฉํ•˜๊ฑฐ๋‚˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ์‹ค์งˆ์ ์ธ ์œ„์น˜ ์‚ฌ์ด์—์„œ ๊ณต๊ฒฉํ•˜๋Š” ๋“ฑ), +๊ณต๊ฒฉ์ž๋Š” ์‚ฌ์šฉ์ž์˜ ๊ธฐ๊ธฐ์—์„œ ๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -> :warning: ์–ด๋– ํ•œ ์ƒํ™ฉ์—์„œ๋„ ์›๊ฒฉ ์ฝ”๋“œ๋ฅผ ๋กœ๋“œํ•˜๊ณ  ์‹คํ–‰ํ•  ๋• Node ํ†ตํ•ฉ ๊ธฐ๋Šฅ์„ -๋น„ํ™œ์„ฑํ™”ํ•˜๊ณ , ๋กœ์ปฌ ํŒŒ์ผ๋งŒ (์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํŒจํ‚ค์ง€ ๋‚ด๋ถ€์— ํฌํ•จ๋œ) Node ์ฝ”๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ -์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์›๊ฒฉ ์ฝ˜ํ…์ธ ๋ฅผ ํ‘œ์‹œํ•  ๋•, ํ•ญ์ƒ `webview`๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  -`nodeIntegration`์ด ๋น„ํ™œ์„ฑํ™”๋˜์–ด์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. +> :๊ฒฝ๊ณ : ์–ด๋– ํ•œ ์ƒํ™ฉ์—์„œ๋„ ์›๊ฒฉ ์ฝ”๋“œ๋ฅผ ๋กœ๋“œํ•˜๊ณ  ์‹คํ–‰ํ•  ๋• Node ํ†ตํ•ฉ ๊ธฐ๋Šฅ์„ +๋น„ํ™œ์„ฑํ™”ํ•˜๊ณ , ๋กœ์ปฌ ํŒŒ์ผ๋งŒ (์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ํŒจํ‚ค์ง€ ๋‚ด๋ถ€์— ํฌํ•จ๋œ) Node ์ฝ”๋“œ๋ฅผ +์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ์›๊ฒฉ ์ฝ˜ํ…์ธ ๋ฅผ ํ‘œ์‹œํ•  ๋•, ํ•ญ์ƒ `webview`๋ฅผ +์‚ฌ์šฉํ•˜๊ณ  `nodeIntegration`์ด ๋น„ํ™œ์„ฑํ™”๋˜์–ด์žˆ๋Š”์ง€ ํ™•์ธํ•˜์„ธ์š”. -#### ์ฒดํฌ ๋ฆฌ์ŠคํŠธ +#### ํ™•์ธ ์‚ฌํ•ญ ์ด ๋ฆฌ์ŠคํŠธ๋Š” ์™„๋ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค, ํ•˜์ง€๋งŒ ์ตœ์†Œํ•œ ๋‹ค์Œ ์‚ฌํ•ญ์€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค: @@ -64,12 +65,33 @@ request์™€ ๊ธฐ์—ฌ๋Š” ์–ธ์ œ๋‚˜ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค. * `allowRunningInsecureContent`๋ฅผ `true`๋กœ ์„ค์ •ํ•˜์ง€ ๋งˆ์„ธ์š”. * ๋ฌด์—‡์„ ํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์‹คํžˆ ์•Œ๊ณ  ์žˆ์ง€์•Š๋Š” ์ด์ƒ `experimentalFeatures` ๋˜๋Š” `experimentalCanvasFeatures`๋ฅผ ํ™œ์„ฑํ™”ํ•˜์ง€ ๋งˆ์„ธ์š”. -* ๋ฌด์—‡์„ ํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์‹คํžˆ ์•Œ๊ณ  ์žˆ์ง€์•Š๋Š” ์ด์ƒ `blinkFeatures`๋ฅผ ํ™œ์„ฑํ™”ํ•˜์ง€ ๋งˆ์„ธ์š”. -* WebViews: `nodeintegration`๋ฅผ `false`๋กœ ์„ค์ •ํ•˜์„ธ์š”. +* ๋ฌด์—‡์„ ํ•˜๊ณ  ์žˆ๋Š”์ง€ ํ™•์‹คํžˆ ์•Œ๊ณ  ์žˆ์ง€์•Š๋Š” ์ด์ƒ `blinkFeatures`๋ฅผ ํ™œ์„ฑํ™”ํ•˜์ง€ + ๋งˆ์„ธ์š”. +* WebViews: `nodeintegration` ์†์„ฑ์„ ์ถ”๊ฐ€ํ•˜์ง€๋งˆ์„ธ์š”. * WebViews: `disablewebsecurity`๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. * WebViews: `allowpopups`๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. * WebViews: ์›๊ฒฉ CSS/JS์™€ `insertCSS` ๋˜๋Š” `executeJavaScript`๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์ง€ ๋งˆ์„ธ์š”. -๋‹ค์‹œ ๋งํ•˜์ง€๋งŒ, ์ด ๋ฆฌ์ŠคํŠธ๋Š” ๊ทธ์ € ์œ„ํ—˜์„ ์ตœ์†Œํ™”ํ•  ๋ฟ์ด๋ฉฐ ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ -๋ชฉ์ ์ด ๊ทธ์ € ์›น ์‚ฌ์ดํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด๋ผ๋ฉด ์ผ๋ฐ˜ ์›น ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋” ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. +๋‹ค์‹œ ๋งํ•˜์ง€๋งŒ, ์ด ๋ฆฌ์ŠคํŠธ๋Š” ๊ทธ์ € ์œ„ํ—˜์„ ์ตœ์†Œํ™”ํ•  ๋ฟ์ด๋ฉฐ ์™„์ „ํžˆ ์ œ๊ฑฐํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. +๋งŒ์•ฝ ๋ชฉ์ ์ด ๊ทธ์ € ์›น ์‚ฌ์ดํŠธ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด๋ผ๋ฉด ์ผ๋ฐ˜ ์›น ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ๋” ์•ˆ์ „ํ•œ +๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. + +## Buffer Global + +๋…ธ๋“œ์˜ [Buffer](https://nodejs.org/api/buffer.html) ํด๋ž˜์Šค๋Š” ํ˜„์žฌ +`nodeintegration` ์†์„ฑ์ด ์ถ”๊ฐ€๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋„ ์ „์—ญ์œผ๋กœ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. +`preload` ์Šคํฌ๋ฆฝํŠธ์—์„œ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•˜์—ฌ ์•ฑ์—์„œ ์ด๊ฒƒ์„ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: + +```js +delete global.Buffer +``` + +๋งŽ์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์ด ๋‹ค์Œ์„ ํ†ตํ•ด ์ง์ ‘ ์š”๊ตฌํ•˜๋Š” ๋Œ€์‹  ์ „์—ญ์„ ๊ธฐ๋Œ€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ +์‚ญ์ œํ•˜๋ฉด ์‚ฌ์ „์— ์„ค์น˜๋œ ์Šคํฌ๋ฆฝํŠธ์™€ ์•ฑ์—์„œ ์‚ฌ์šฉ๋˜๋Š” Node ๋ชจ๋“ˆ์ด ๊นจ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + +```js +const {Buffer} = require('buffer') +``` + +์ „์—ญ `Buffer` ๋Š” ํ–ฅํ›„ Electron ์ฃผ ๋ฒ„์ „์—์„œ ์ œ๊ฑฐ๋  ๊ฒƒ ์ž…๋‹ˆ๋‹ค. diff --git a/docs-translations/ko-KR/tutorial/using-pepper-flash-plugin.md b/docs-translations/ko-KR/tutorial/using-pepper-flash-plugin.md index 7394f1ff42..bb7b361195 100644 --- a/docs-translations/ko-KR/tutorial/using-pepper-flash-plugin.md +++ b/docs-translations/ko-KR/tutorial/using-pepper-flash-plugin.md @@ -75,3 +75,7 @@ Pepper ํ”Œ๋ž˜์‹œ ํ”Œ๋Ÿฌ๊ทธ์ธ์˜ ๊ตฌ์กฐ๋Š” Electron๊ณผ ์ผ์น˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. W Windows์—์„  `--ppapi-flash-path`๋กœ ์ „๋‹ฌ๋˜๋Š” ๊ฒฝ๋กœ์˜ ๋ถ„๋ฆฌ์ž๋กœ `\`๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. POSIX-์Šคํƒ€์ผ ๊ฒฝ๋กœ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. + +RTMP ๋ฅผ ์‚ฌ์šฉํ•œ ๋ฏธ๋””์–ด ์ŠคํŠธ๋ฆฌ๋ฐ๊ฐ™์€ ์ผ๋ถ€ ์ž‘์—…์˜ ๊ฒฝ์šฐ ํ”Œ๋ ˆ์ด์–ด์˜ `.swf` ํŒŒ์ผ์— +ํญ๋„“์€ ๊ถŒํ•œ์„ ๋ถ€์—ฌํ•  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๊ธฐ ์œ„ํ•œ ํ•œ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์€, +[nw-flash-trust](https://github.com/szwacz/nw-flash-trust)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. From 67a09d9fe0c02208edd96fc95d5984504bb7e992 Mon Sep 17 00:00:00 2001 From: tinydew4 Date: Mon, 24 Oct 2016 06:34:09 +0000 Subject: [PATCH 074/148] Fix typo, and trimming. --- docs/api/protocol.md | 1 - docs/api/session.md | 6 +++--- docs/api/structures/desktop-capturer-source.md | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/api/protocol.md b/docs/api/protocol.md index f689b38e3d..4050ea110f 100644 --- a/docs/api/protocol.md +++ b/docs/api/protocol.md @@ -286,7 +286,6 @@ which sends a new HTTP request as a response. * `completion` Function (optional) * `error` Error - Remove the interceptor installed for `scheme` and restore its original handler. [net-error]: https://code.google.com/p/chromium/codesearch#chromium/src/net/base/net_error_list.h diff --git a/docs/api/session.md b/docs/api/session.md index 1c1030ac42..2d0ee42c73 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -549,9 +549,9 @@ The following methods are available on instances of `WebRequest`: The `listener` will be called with `listener(details, callback)` when a request is about to occur. -The `uploadData` is an array of `UploadData` objects: +The `uploadData` is an array of `UploadData` objects. -The `callback` has to be called with an `response` object: +The `callback` has to be called with an `response` object. #### `webRequest.onBeforeSendHeaders([filter, ]listener)` @@ -575,7 +575,7 @@ TCP connection is made to the server, but before any http data is sent. * `requestHeaders` Object (optional) - When provided, request will be made with these headers. -The `callback` has to be called with an `response` object: +The `callback` has to be called with an `response` object. #### `webRequest.onSendHeaders([filter, ]listener)` diff --git a/docs/api/structures/desktop-capturer-source.md b/docs/api/structures/desktop-capturer-source.md index 292bd014bd..3ebe4ce49c 100644 --- a/docs/api/structures/desktop-capturer-source.md +++ b/docs/api/structures/desktop-capturer-source.md @@ -9,6 +9,6 @@ title. * `thumbnail` [NativeImage](../native-image.md) - A thumbnail image. **Note:** There is no guarantee that the size of the thumbnail is the same as the - `thumnbailSize` specified in the `options` passed to + `thumbnailSize` specified in the `options` passed to `desktopCapturer.getSources`. The actual size depends on the scale of the screen or window. From 83f47bc9804343f1aa69d9fe2255c4e27db5b51b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 24 Oct 2016 15:44:21 +0900 Subject: [PATCH 075/148] Upgrade brighray for RequireCTDelegate --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 8b074eca12..a55f26ec2f 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 8b074eca1217db6621553a3f7764c907ef617547 +Subproject commit a55f26ec2f53ccd961381234c941564b4fd4403f From 271733fc53692d3b40dfed10675c499fbdaba4f5 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 24 Oct 2016 16:12:49 +0900 Subject: [PATCH 076/148] Add tests for ses.setCertificateVerifyProc --- spec/api-session-spec.js | 59 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/spec/api-session-spec.js b/spec/api-session-spec.js index c01abcc6ed..8451fc0cc9 100644 --- a/spec/api-session-spec.js +++ b/spec/api-session-spec.js @@ -1,5 +1,6 @@ const assert = require('assert') const http = require('http') +const https = require('https') const path = require('path') const fs = require('fs') const {closeWindow} = require('./window-helpers') @@ -457,7 +458,7 @@ describe('session module', function () { }) }) - describe('ses.getblobData(identifier, callback)', function () { + describe('ses.getBlobData(identifier, callback)', function () { it('returns blob data for uuid', function (done) { const scheme = 'temp' const protocol = session.defaultSession.protocol @@ -507,4 +508,60 @@ describe('session module', function () { }) }) }) + + describe('ses.setCertificateVerifyProc(callback)', function () { + var server = null + + beforeEach(function (done) { + var certPath = path.join(__dirname, 'fixtures', 'certificates') + var options = { + key: fs.readFileSync(path.join(certPath, 'server.key')), + cert: fs.readFileSync(path.join(certPath, 'server.pem')), + ca: [ + fs.readFileSync(path.join(certPath, 'rootCA.pem')), + fs.readFileSync(path.join(certPath, 'intermediateCA.pem')) + ], + requestCert: true, + rejectUnauthorized: false + } + + server = https.createServer(options, function (req, res) { + res.writeHead(200) + res.end('hello') + }) + server.listen(0, '127.0.0.1', done) + }) + + afterEach(function () { + session.defaultSession.setCertificateVerifyProc(null) + server.close() + }) + + it('accepts the request when the callback is called with true', function (done) { + session.defaultSession.setCertificateVerifyProc(function (hostname, certificate, callback) { + callback(true) + }) + + w.webContents.once('did-finish-load', function () { + assert.equal(w.webContents.getTitle(), 'hello') + done() + }) + w.loadURL(`https://127.0.0.1:${server.address().port}`) + }) + + it('rejects the request when the callback is called with false', function (done) { + session.defaultSession.setCertificateVerifyProc(function (hostname, certificate, callback) { + assert.equal(hostname, '127.0.0.1') + assert.equal(certificate.issuerName, 'Intermediate CA') + callback(false) + }) + + var url = `https://127.0.0.1:${server.address().port}` + w.webContents.once('did-finish-load', function () { + assert.equal(w.webContents.getTitle(), url) + done() + }) + w.loadURL(url) + }) + }) }) From 0841c4291a83c417759b7bac067b3a3b33c06ebb Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 24 Oct 2016 16:27:54 +0900 Subject: [PATCH 077/148] Remove RegisterURLSchemeAsPrivileged lint error --- atom/renderer/api/atom_api_web_frame.h | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/atom/renderer/api/atom_api_web_frame.h b/atom/renderer/api/atom_api_web_frame.h index ebfd19c5a5..f530612a48 100644 --- a/atom/renderer/api/atom_api_web_frame.h +++ b/atom/renderer/api/atom_api_web_frame.h @@ -63,10 +63,8 @@ class WebFrame : public mate::Wrappable { void RegisterURLSchemeAsSecure(const std::string& scheme); void RegisterURLSchemeAsBypassingCSP(const std::string& scheme); - void RegisterURLSchemeAsPrivileged( - const std::string& scheme, - mate::Arguments* args - ); + void RegisterURLSchemeAsPrivileged(const std::string& scheme, + mate::Arguments* args); // Editing. void InsertText(const std::string& text); From 2c50f143466341c72d038a1f38bb1cd41a398ee7 Mon Sep 17 00:00:00 2001 From: tinydew4 Date: Mon, 24 Oct 2016 07:41:15 +0000 Subject: [PATCH 078/148] Apply the changes till the 'a2a4462' commit. --- docs-translations/ko-KR/api/session.md | 17 ++--------------- .../ko-KR/api/structures/bluetooth-device.md | 4 ++++ .../ko-KR/api/structures/cookie.md | 13 +++++++++++++ docs-translations/ko-KR/api/web-contents.md | 13 ++++++------- docs-translations/ko-KR/api/web-frame.md | 18 ++++++++++++++++-- 5 files changed, 41 insertions(+), 24 deletions(-) create mode 100644 docs-translations/ko-KR/api/structures/bluetooth-device.md create mode 100644 docs-translations/ko-KR/api/structures/cookie.md diff --git a/docs-translations/ko-KR/api/session.md b/docs-translations/ko-KR/api/session.md index 85866ed4f8..0c49cc5e50 100644 --- a/docs-translations/ko-KR/api/session.md +++ b/docs-translations/ko-KR/api/session.md @@ -402,7 +402,7 @@ session.defaultSession.cookies.set(cookie, (error) => { #### Event: 'changed' * `event` Event -* `cookie` Object - ๋ณ€๊ฒฝ๋œ ์ฟ ํ‚ค +* `cookie` [Cookie](structures/cookie.md) - ๋ณ€๊ฒฝ๋œ ์ฟ ํ‚ค * `cause` String - ๋‹ค์Œ ๊ฐ’ ์ค‘ ํ•˜๋‚˜์ธ ๋ณ€๊ฒฝ๋œ ์ด์œ : * `explicit` - ์ฟ ํ‚ค๊ฐ€ ์†Œ๋น„์ž์˜ ํ–‰์œ„์— ์˜ํ•ด ์ง์ ‘ ๋ณ€๊ฒฝ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. * `overwrite` - ์ฟ ํ‚ค๋ฅผ ๋ฎ์–ด์“ฐ๋Š” ์‚ฝ์ž… ๋™์ž‘์— ์˜ํ•ด ์ž๋™์œผ๋กœ ์ œ๊ฑฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. @@ -435,20 +435,7 @@ session.defaultSession.cookies.set(cookie, (error) => { `details` ๊ฐ์ฒด์—์„œ ๋ฌ˜์‚ฌํ•œ ๋ชจ๋“  ์ฟ ํ‚ค๋ฅผ ์š”์ฒญํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ์ž‘์—…์ด ๋๋‚˜๋ฉด `callback`์ด `callback(error, cookies)` ํ˜•ํƒœ๋กœ ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. -`cookies`๋Š” `cookie` ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. - -* `cookie` Object - * `name` String - ์ฟ ํ‚ค์˜ ์ด๋ฆ„. - * `value` String - ์ฟ ํ‚ค์˜ ๊ฐ’. - * `domain` String - ์ฟ ํ‚ค์˜ ๋„๋ฉ”์ธ. - * `hostOnly` String - ์ฟ ํ‚ค๊ฐ€ ํ˜ธ์ŠคํŠธ ์ „์šฉ์ธ๊ฐ€์— ๋Œ€ํ•œ ์—ฌ๋ถ€. - * `path` String - ์ฟ ํ‚ค์˜ ๊ฒฝ๋กœ. - * `secure` Boolean - ์ฟ ํ‚ค๊ฐ€ ์•ˆ์ „ํ•œ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œ๋˜๋Š”์ง€์— ๋Œ€ํ•œ ์—ฌ๋ถ€. - * `httpOnly` Boolean - ์ฟ ํ‚ค๊ฐ€ HTTP๋กœ๋งŒ ํ‘œ์‹œ๋˜๋Š”์ง€์— ๋Œ€ํ•œ ์—ฌ๋ถ€. - * `session` Boolean - ์ฟ ํ‚ค๊ฐ€ ์„ธ์…˜ ์ฟ ํ‚ค ๋˜๋Š” ๋งŒ๋ฃŒ์ผ์ด ์žˆ๋Š” ์˜๊ตฌ ์ฟ ํ‚ค์ธ์ง€์— ๋Œ€ํ•œ - ์—ฌ๋ถ€. - * `expirationDate` Double - (Option) UNIX ์‹œ๊ฐ„์œผ๋กœ ํ‘œ์‹œ๋˜๋Š” ์ฟ ํ‚ค์˜ ๋งŒ๋ฃŒ์ผ์— - ๋Œ€ํ•œ ์ดˆ ๋‹จ์œ„ ์‹œ๊ฐ„. ์„ธ์…˜ ์ฟ ํ‚ค๋Š” ์ง€์›๋˜์ง€ ์•Š์Œ. +`cookies`๋Š” [`cookie`](structures/cookie.md) ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์ž…๋‹ˆ๋‹ค. #### `ses.cookies.set(details, callback)` diff --git a/docs-translations/ko-KR/api/structures/bluetooth-device.md b/docs-translations/ko-KR/api/structures/bluetooth-device.md new file mode 100644 index 0000000000..33d3bb51f9 --- /dev/null +++ b/docs-translations/ko-KR/api/structures/bluetooth-device.md @@ -0,0 +1,4 @@ +# BluetoothDevice Object + +* `deviceName` String +* `deviceId` String diff --git a/docs-translations/ko-KR/api/structures/cookie.md b/docs-translations/ko-KR/api/structures/cookie.md new file mode 100644 index 0000000000..c3bacbad74 --- /dev/null +++ b/docs-translations/ko-KR/api/structures/cookie.md @@ -0,0 +1,13 @@ +# Cookie Object + +* `name` String - ์ฟ ํ‚ค์˜ ์ด๋ฆ„. +* `value` String - ์ฟ ํ‚ค์˜ ๊ฐ’. +* `domain` String - ์ฟ ํ‚ค์˜ ๋„๋ฉ”์ธ. +* `hostOnly` String - ์ฟ ํ‚ค๊ฐ€ ํ˜ธ์ŠคํŠธ ์ „์šฉ์ธ๊ฐ€์— ๋Œ€ํ•œ ์—ฌ๋ถ€. +* `path` String - ์ฟ ํ‚ค์˜ ๊ฒฝ๋กœ. +* `secure` Boolean - ์ฟ ํ‚ค๊ฐ€ ์•ˆ์ „ํ•œ ๊ฒƒ์œผ๋กœ ํ‘œ์‹œ๋๋Š”์ง€์— ๋Œ€ํ•œ ์—ฌ๋ถ€. +* `httpOnly` Boolean - ์ฟ ํ‚ค๊ฐ€ HTTP ์ „์šฉ์œผ๋กœ ํ‘œ์‹œ๋๋Š”์ง€์— ๋Œ€ํ•œ ์—ฌ๋ถ€. +* `session` Boolean - ์ฟ ํ‚ค๊ฐ€ ์„ธ์…˜ ์ฟ ํ‚ค์ธ์ง€ ๋งŒ๋ฃŒ์ผ์ด ์žˆ๋Š” ์˜๊ตฌ ์ฟ ํ‚ค์ธ์ง€์— ๋Œ€ํ•œ + ์—ฌ๋ถ€. +* `expirationDate` Double - (Optional) UNIX ์‹œ๊ฐ„์œผ๋กœ ํ‘œ์‹œ๋˜๋Š” ์ฟ ํ‚ค์˜ ๋งŒ๋ฃŒ์ผ์— + ๋Œ€ํ•œ ์ดˆ ๋‹จ์œ„ ์‹œ๊ฐ„. ์„ธ์…˜ ์ฟ ํ‚ค๋Š” ์ง€์›๋˜์ง€ ์•Š์Œ. diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index 117a6d9dca..b788afddb3 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -145,9 +145,10 @@ Returns: * `frameName` String * `disposition` String - `default`, `foreground-tab`, `background-tab`, `new-window`, `save-to-disk`, `other`์ค‘ ํ•˜๋‚˜์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -* `options` Object - ์ƒˆ๋กœ์šด `BrowserWindow` ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ์˜ต์…˜ ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. -* `additionalFeatures` Array - `window.open()` ์— ์ฃผ์–ด์ง„ (Chromium ๋˜๋Š” Electron - ์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๋Š”) ๋น„ํ‘œ์ค€ ๊ธฐ๋Šฅ. +* `options` Object - ์ƒˆ๋กœ์šด `BrowserWindow` ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค ๋•Œ ์‚ฌ์šฉ๋˜๋Š” ์˜ต์…˜ + ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. +* `additionalFeatures` String[] - `window.open()` ์— ์ฃผ์–ด์ง„ (Chromium ๋˜๋Š” + Electron ์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๋Š”) ๋น„ํ‘œ์ค€ ๊ธฐ๋Šฅ. ํŽ˜์ด์ง€๊ฐ€ `url`์— ๋Œ€ํ•˜์—ฌ ์ƒˆ๋กœ์šด ์œˆ๋„์šฐ๋ฅผ ์—ด๊ธฐ์œ„ํ•ด ์š”์ฒญํ•œ ๊ฒฝ์šฐ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค. `window.open`์ด๋‚˜ ``๊ณผ ๊ฐ™์€ ์™ธ๋ถ€ ๋งํฌ์— ์˜ํ•ด ์š”์ฒญ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. @@ -423,9 +424,7 @@ Returns: Returns: * `event` Event -* `devices` [Objects] - * `deviceName` String - * `deviceId` String +* `devices` [BluetoothDevice[]](structures/bluetooth-device.md) * `callback` Function * `deviceId` String @@ -1069,7 +1068,7 @@ Input `event`๋ฅผ ์›น ํŽ˜์ด์ง€๋กœ ์ „์†กํ•ฉ๋‹ˆ๋‹ค. #### `contents.startDrag(item)` -* `item` object +* `item` Object * `file` String * `icon` [NativeImage](native-image.md) diff --git a/docs-translations/ko-KR/api/web-frame.md b/docs-translations/ko-KR/api/web-frame.md index 0e92da6b11..c9d9893747 100644 --- a/docs-translations/ko-KR/api/web-frame.md +++ b/docs-translations/ko-KR/api/web-frame.md @@ -81,13 +81,27 @@ webFrame.setSpellCheckProvider('en-US', true, { ํ˜„์žฌ ํŽ˜์ด์ง€ ์ฝ˜ํ…์ธ ์˜ ๋ณด์•ˆ ์ •์ฑ…์— ์ƒ๊ด€์—†์ด `scheme`๋กœ๋ถ€ํ„ฐ ๋ฆฌ์†Œ์Šค๊ฐ€ ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค. -### `webFrame.registerURLSchemeAsPrivileged(scheme)` +### `webFrame.registerURLSchemeAsPrivileged(scheme[, options])` - * `scheme` String +* `scheme` String +* `options` Object(optional) + * `secure` (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. + * `bypassCSP` (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. + * `allowServiceWorkers` (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. + * `supportFetchAPI` (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. + * `corsEnabled` (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. `scheme`๋ฅผ ๋ณด์•ˆ๋œ ์Šคํ‚ด์œผ๋กœ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•ด ๋ณด์•ˆ ์ •์ฑ…์„ ์šฐํšŒํ•˜๋ฉฐ, ServiceWorker์˜ ๋“ฑ๋ก๊ณผ fetch API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. +๋“ฑ๋ก์—์„œ ๊ทธ๊ฒƒ์„ ๋นผ๋ ค๋ฉด `false` ๊ฐ’์œผ๋กœ ์˜ต์…˜์„ ์ง€์ •ํ•˜์„ธ์š”. +์ฝ˜ํ…์ธ  ๋ณด์•ˆ ์ •์ฑ…์„ ์šฐํšŒํ•˜์ง€ ์•Š๊ณ , ํŠน๊ถŒ ์Šคํ‚ด์„ ๋“ฑ๋กํ•˜๋Š” ์˜ˆ: + +```javascript +const {webFrame} = require('electron') +webFrame.registerURLSchemeAsPrivileged('foo', { bypassCSP: false }) +``` + ### `webFrame.insertText(text)` * `text` String From 1a03e627173b1e17ede7e09ec74edd3c53632756 Mon Sep 17 00:00:00 2001 From: Zeke Sikelianos Date: Mon, 24 Oct 2016 12:04:37 -0700 Subject: [PATCH 079/148] update docs linter to support parsing of function parameter types --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 06a5d9596b..2978869387 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "asar": "^0.11.0", "browserify": "^13.1.0", "electabul": "~0.0.4", - "electron-docs-linter": "^1.8.2", + "electron-docs-linter": "^1.10.0", "request": "*", "standard": "^8.4.0", "standard-markdown": "^2.1.1" From f35536bdc5a8ee49d7dfa6705038d7364bf385e2 Mon Sep 17 00:00:00 2001 From: Paul Frazee Date: Mon, 24 Oct 2016 20:21:42 -0500 Subject: [PATCH 080/148] factor out parse-features-string.js --- lib/browser/guest-view-manager.js | 19 +++---------------- lib/common/parse-features-string.js | 24 ++++++++++++++++++++++++ lib/renderer/override.js | 21 ++++++++------------- 3 files changed, 35 insertions(+), 29 deletions(-) create mode 100644 lib/common/parse-features-string.js diff --git a/lib/browser/guest-view-manager.js b/lib/browser/guest-view-manager.js index c4b0022f67..de11b03206 100644 --- a/lib/browser/guest-view-manager.js +++ b/lib/browser/guest-view-manager.js @@ -2,6 +2,7 @@ const ipcMain = require('electron').ipcMain const webContents = require('electron').webContents +const parseFeaturesString = require('../common/parse-features-string') // Doesn't exist in early initialization. let webViewManager = null @@ -187,27 +188,13 @@ const attachGuest = function (embedder, elementInstanceId, guestInstanceId, para // parse the 'webpreferences' attribute string, if set // this uses the same parsing rules as window.open uses for its features if (typeof params.webpreferences === 'string') { - // split the attribute's value by ',' - let i, len - let webpreferencesTokens = params.webpreferences.split(/,\s*/) - for (i = 0, len = webpreferencesTokens.length; i < len; i++) { - // expected form is either a name by itself (true boolean flag) - // or a key/value, in the form of 'name=value' - // split the tokens by '=' - let pref = webpreferencesTokens[i] - let prefTokens = pref.split(/\s*=/) - let name = prefTokens[0] - let value = prefTokens[1] - if (!name) continue - - // interpret the value as a boolean, if possible - value = (value === 'yes' || value === '1') ? true : (value === 'no' || value === '0') ? false : value + parseFeaturesString(params.webpreferences, function (key, value) { if (value === undefined) { // no value was specified, default it to true value = true } webPreferences[name] = value - } + }) } if (params.preload) { diff --git a/lib/common/parse-features-string.js b/lib/common/parse-features-string.js new file mode 100644 index 0000000000..da0381bbcf --- /dev/null +++ b/lib/common/parse-features-string.js @@ -0,0 +1,24 @@ +// parses a feature string that has the format used in window.open() +// - `str` input string +// - `emit` function(key, value) - called for each parsed KV +module.exports = function parseFeaturesString (str, emit) { + // split the string by ',' + let i, len + let strTokens = params.str.split(/,\s*/) + for (i = 0, len = strTokens.length; i < len; i++) { + // expected form is either a key by itself (true boolean flag) + // or a key/value, in the form of 'key=value' + // split the tokens by '=' + let kv = strTokens[i] + let kvTokens = kv.split(/\s*=/) + let key = kvTokens[0] + let value = kvTokens[1] + if (!key) continue + + // interpret the value as a boolean, if possible + value = (value === 'yes' || value === '1') ? true : (value === 'no' || value === '0') ? false : value + + // emit the parsed pair + emit(key, value) + } +} diff --git a/lib/renderer/override.js b/lib/renderer/override.js index 9358a06a09..8c00661ddb 100644 --- a/lib/renderer/override.js +++ b/lib/renderer/override.js @@ -2,6 +2,7 @@ const ipcRenderer = require('electron').ipcRenderer const remote = require('electron').remote +const parseFeaturesString = require('../common/parse-features-string') // Helper function to resolve relative url. var a = window.top.document.createElement('a') @@ -104,27 +105,21 @@ window.open = function (url, frameName, features) { // Used to store additional features additionalFeatures = [] - // Make sure to get rid of excessive whitespace in the property name - ref1 = features.split(/,\s*/) - for (i = 0, len = ref1.length; i < len; i++) { - feature = ref1[i] - ref2 = feature.split(/\s*=/) - name = ref2[0] - value = ref2[1] - value = value === 'yes' || value === '1' ? true : value === 'no' || value === '0' ? false : value + // Parse the features + parseFeaturesString(features, function (key, value) { if (value === undefined) { - additionalFeatures.push(feature) + additionalFeatures.push(key) } else { - if (webPreferences.includes(name)) { + if (webPreferences.includes(key)) { if (options.webPreferences == null) { options.webPreferences = {} } - options.webPreferences[name] = value + options.webPreferences[key] = value } else { - options[name] = value + options[key] = value } } - } + }) if (options.left) { if (options.x == null) { options.x = options.left From 2556ed87449257d58a19a2a26631a06cd9e2bbd1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Oct 2016 10:28:36 +0900 Subject: [PATCH 081/148] Add parse-features-strings.js --- filenames.gypi | 1 + 1 file changed, 1 insertion(+) diff --git a/filenames.gypi b/filenames.gypi index 9c4b42f622..b410f96bd7 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -48,6 +48,7 @@ 'lib/common/api/native-image.js', 'lib/common/api/shell.js', 'lib/common/init.js', + 'lib/common/parse-features-string.js', 'lib/common/reset-search-paths.js', 'lib/renderer/chrome-api.js', 'lib/renderer/content-scripts-injector.js', From 3aad6a0c993fa4617bbe16c85d8b13651a0137ca Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Oct 2016 10:31:50 +0900 Subject: [PATCH 082/148] Use forEach and destructuring for parsing features --- lib/browser/guest-view-manager.js | 2 +- lib/common/parse-features-string.js | 17 ++++++----------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/lib/browser/guest-view-manager.js b/lib/browser/guest-view-manager.js index de11b03206..2f8ffefebc 100644 --- a/lib/browser/guest-view-manager.js +++ b/lib/browser/guest-view-manager.js @@ -193,7 +193,7 @@ const attachGuest = function (embedder, elementInstanceId, guestInstanceId, para // no value was specified, default it to true value = true } - webPreferences[name] = value + webPreferences[key] = value }) } diff --git a/lib/common/parse-features-string.js b/lib/common/parse-features-string.js index da0381bbcf..2c74c3463d 100644 --- a/lib/common/parse-features-string.js +++ b/lib/common/parse-features-string.js @@ -1,24 +1,19 @@ // parses a feature string that has the format used in window.open() // - `str` input string // - `emit` function(key, value) - called for each parsed KV -module.exports = function parseFeaturesString (str, emit) { +module.exports = function parseFeaturesString (features, emit) { // split the string by ',' - let i, len - let strTokens = params.str.split(/,\s*/) - for (i = 0, len = strTokens.length; i < len; i++) { + features.split(/,\s*/).forEach((feature) => { // expected form is either a key by itself (true boolean flag) // or a key/value, in the form of 'key=value' // split the tokens by '=' - let kv = strTokens[i] - let kvTokens = kv.split(/\s*=/) - let key = kvTokens[0] - let value = kvTokens[1] - if (!key) continue + let [key, value] = feature.split(/\s*=/) + if (!key) return - // interpret the value as a boolean, if possible + // interpret the value as a boolean, if possible value = (value === 'yes' || value === '1') ? true : (value === 'no' || value === '0') ? false : value // emit the parsed pair emit(key, value) - } + }) } From 68c2c9825fab05f5a6e674b49a0672de542890eb Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Oct 2016 10:36:43 +0900 Subject: [PATCH 083/148] Remove lint warnings --- lib/common/parse-features-string.js | 7 +++---- lib/renderer/override.js | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/common/parse-features-string.js b/lib/common/parse-features-string.js index 2c74c3463d..a700617e6c 100644 --- a/lib/common/parse-features-string.js +++ b/lib/common/parse-features-string.js @@ -1,12 +1,11 @@ // parses a feature string that has the format used in window.open() -// - `str` input string +// - `features` input string // - `emit` function(key, value) - called for each parsed KV module.exports = function parseFeaturesString (features, emit) { // split the string by ',' features.split(/,\s*/).forEach((feature) => { - // expected form is either a key by itself (true boolean flag) - // or a key/value, in the form of 'key=value' - // split the tokens by '=' + // expected form is either a key by itself or a key/value pair in the form of + // 'key=value' let [key, value] = feature.split(/\s*=/) if (!key) return diff --git a/lib/renderer/override.js b/lib/renderer/override.js index 8c00661ddb..6b5e0e1615 100644 --- a/lib/renderer/override.js +++ b/lib/renderer/override.js @@ -89,7 +89,7 @@ if (process.guestInstanceId == null) { // Make the browser window or guest view emit "new-window" event. window.open = function (url, frameName, features) { - var feature, guestId, i, j, len, len1, name, options, ref1, ref2, value, additionalFeatures + var guestId, j, len1, name, options, additionalFeatures if (frameName == null) { frameName = '' } From b4cc3541a8cb103136ccdb8484f6bbef41976a3b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Oct 2016 12:08:19 +0900 Subject: [PATCH 084/148] Minor tweaks to webpreferences docs --- docs/api/web-view-tag.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/web-view-tag.md b/docs/api/web-view-tag.md index c5d7c7b958..88f042f65e 100644 --- a/docs/api/web-view-tag.md +++ b/docs/api/web-view-tag.md @@ -201,12 +201,12 @@ If "on", the guest page will be allowed to open new windows. ``` A list of strings which specifies the web preferences to be set on the webview, separated by `,`. -The full list of supported preference strings can be found in [BrowserWindow](browser-window.md#new-browserwindowoptions) +The full list of supported preference strings can be found in [BrowserWindow](browser-window.md#new-browserwindowoptions). The string follows the same format as the features string in `window.open`. A name by itself is given a `true` boolean value. A preference can be set to another value by including an `=`, followed by the value. -Special values `yes` and `1` are interpreted as true, while `no` and `0` are interpreted as false. +Special values `yes` and `1` are interpreted as `true`, while `no` and `0` are interpreted as `false`. ### `blinkfeatures` From 65e6da2673af008c739c10f59ee420eb25c937f6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Oct 2016 12:35:18 +0900 Subject: [PATCH 085/148] Add newlines before lists --- docs/api/app.md | 1 + docs/api/clipboard.md | 1 + docs/api/crash-reporter.md | 2 ++ docs/api/process.md | 2 ++ docs/api/screen.md | 1 + docs/api/web-frame.md | 1 + docs/api/window-open.md | 1 + 7 files changed, 9 insertions(+) diff --git a/docs/api/app.md b/docs/api/app.md index 9dc1259334..764840dd1e 100644 --- a/docs/api/app.md +++ b/docs/api/app.md @@ -542,6 +542,7 @@ Returns `Boolean` - Whether the call succeeded. ### `app.getJumpListSettings()` _Windows_ Returns `Object`: + * `minItems` Integer - The minimum number of items that will be shown in the Jump List (for a more detailed description of this value see the [MSDN docs][JumpListBeginListMSDN]). diff --git a/docs/api/clipboard.md b/docs/api/clipboard.md index 58f8b4613c..a6e9392c8a 100644 --- a/docs/api/clipboard.md +++ b/docs/api/clipboard.md @@ -79,6 +79,7 @@ Writes the `text` into the clipboard in RTF. ### `clipboard.readBookmark()` _macOS_ _Windows_ Returns `Object`: + * `title` String * `url` String diff --git a/docs/api/crash-reporter.md b/docs/api/crash-reporter.md index 2887577101..20ee2c26ac 100644 --- a/docs/api/crash-reporter.md +++ b/docs/api/crash-reporter.md @@ -57,6 +57,7 @@ crash reports. ### `crashReporter.getLastCrashReport()` Returns `Object`: + * `date` String * `ID` Integer @@ -66,6 +67,7 @@ sent or the crash reporter has not been started, `null` is returned. ### `crashReporter.getUploadedReports()` Returns `Object[]`: + * `date` String * `ID` Integer diff --git a/docs/api/process.md b/docs/api/process.md index 1dff88377a..3fe90fc06d 100644 --- a/docs/api/process.md +++ b/docs/api/process.md @@ -84,6 +84,7 @@ limit, whichever is lower for the current process. ### `process.getProcessMemoryInfo()` Returns `Object`: + * `workingSetSize` Integer - The amount of memory currently pinned to actual physical RAM. * `peakWorkingSetSize` Integer - The maximum amount of memory that has ever been pinned @@ -99,6 +100,7 @@ that all statistics are reported in Kilobytes. ### `process.getSystemMemoryInfo()` Returns `Object`: + * `total` Integer - The total amount of physical memory in Kilobytes available to the system. * `free` Integer - The total amount of memory not being used by applications or disk diff --git a/docs/api/screen.md b/docs/api/screen.md index 2467b646db..f366cddf24 100644 --- a/docs/api/screen.md +++ b/docs/api/screen.md @@ -90,6 +90,7 @@ The `screen` module has the following methods: ### `screen.getCursorScreenPoint()` Returns `Object`: + * `x` Integer * `y` Integer diff --git a/docs/api/web-frame.md b/docs/api/web-frame.md index 663c3fd5e5..eae07a92de 100644 --- a/docs/api/web-frame.md +++ b/docs/api/web-frame.md @@ -124,6 +124,7 @@ this limitation. ### `webFrame.getResourceUsage()` Returns `Object`: + * `images` [MemoryUsageDetails](structures/memory-usage-details.md) * `cssStyleSheets` [MemoryUsageDetails](structures/memory-usage-details.md) * `xslStyleSheets` [MemoryUsageDetails](structures/memory-usage-details.md) diff --git a/docs/api/window-open.md b/docs/api/window-open.md index cbe3aed230..2c0d9cb453 100644 --- a/docs/api/window-open.md +++ b/docs/api/window-open.md @@ -26,6 +26,7 @@ The `features` string follows the format of standard browser, but each feature has to be a field of `BrowserWindow`'s options. **Notes:** + * Node integration will always be disabled in the opened `window` if it is disabled on the parent window. * Non-standard features (that are not handled by Chromium or Electron) given in From 6f64ad30cb14867391e2ec7124ee8f14b27b493b Mon Sep 17 00:00:00 2001 From: Mike Engel Date: Mon, 24 Oct 2016 22:04:45 -0600 Subject: [PATCH 086/148] Clarify the setMenuBarVisibility api The setMenuBarVisibility api is only supported on Windows and Linux. This adds some minor documentation to make that clearer. Fixes #7686 --- docs-translations/ko-KR/api/browser-window.md | 2 +- docs-translations/pt-BR/api/browser-window.md | 2 +- docs-translations/zh-CN/api/browser-window.md | 2 +- docs/api/browser-window.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index 484197c45e..cacd2d893b 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -1099,7 +1099,7 @@ Returns `Boolean` - ๋ฒ„ํŠผ์ด ์„ฑ๊ณต์ ์œผ๋กœ ์ถ”๊ฐ€๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€ Returns `Boolean` - ๋ฉ”๋‰ด ๋ง‰๋Œ€ ์ž๋™ ์ˆจ๊น€ ์ƒํƒœ ์—ฌ๋ถ€. -#### `win.setMenuBarVisibility(visible)` +#### `win.setMenuBarVisibility(visible)` _Windows_ _Linux_ * `visible` Boolean diff --git a/docs-translations/pt-BR/api/browser-window.md b/docs-translations/pt-BR/api/browser-window.md index 1d992be632..f03411efae 100644 --- a/docs-translations/pt-BR/api/browser-window.md +++ b/docs-translations/pt-BR/api/browser-window.md @@ -597,7 +597,7 @@ Se a barra de menu jรก estiver visรญvel, chamar `setAutoHideMenuBar(true)` nรฃo Retorna um boolean indicando se a barra de menu se esconde automaticamente. -### `win.setMenuBarVisibility(visible)` +### `win.setMenuBarVisibility(visible)` _Windows_ _Linux_ * `visible` Boolean diff --git a/docs-translations/zh-CN/api/browser-window.md b/docs-translations/zh-CN/api/browser-window.md index 13fe2ec526..8635724bc8 100644 --- a/docs-translations/zh-CN/api/browser-window.md +++ b/docs-translations/zh-CN/api/browser-window.md @@ -720,7 +720,7 @@ windowsไธŠๅฅๆŸ„็ฑปๅž‹ไธบ `HWND` ๏ผŒmacOS `NSView*` ๏ผŒ Linux `Window`. ่ฟ”ๅ›ž boolean,็ช—ๅฃ็š„่œๅ•ๆ ๆ˜ฏๅฆๅฏไปฅ่‡ชๅŠจ้š่—. -### `win.setMenuBarVisibility(visible)` +### `win.setMenuBarVisibility(visible)` _Windows_ _Linux_ * `visible` Boolean diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 7bec8987b1..345419eed2 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -1114,7 +1114,7 @@ hide it immediately. Returns `Boolean` - Whether menu bar automatically hides itself. -#### `win.setMenuBarVisibility(visible)` +#### `win.setMenuBarVisibility(visible)` _Windows_ _Linux_ * `visible` Boolean From 144a61c5a37f122f4d060450c97e9aaa46c0ae8d Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 24 Oct 2016 17:13:34 +0900 Subject: [PATCH 087/148] Add find text support to clipboard --- atom/common/api/atom_api_clipboard.cc | 101 ++++++++++++---------- atom/common/api/atom_api_clipboard.h | 59 +++++++++++++ atom/common/api/atom_api_clipboard_mac.mm | 24 +++++ filenames.gypi | 2 + 4 files changed, 140 insertions(+), 46 deletions(-) create mode 100644 atom/common/api/atom_api_clipboard.h create mode 100644 atom/common/api/atom_api_clipboard_mac.mm diff --git a/atom/common/api/atom_api_clipboard.cc b/atom/common/api/atom_api_clipboard.cc index 01e670be92..31e6b7c133 100644 --- a/atom/common/api/atom_api_clipboard.cc +++ b/atom/common/api/atom_api_clipboard.cc @@ -2,24 +2,20 @@ // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. -#include -#include +#include "atom/common/api/atom_api_clipboard.h" #include "atom/common/native_mate_converters/image_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" #include "base/strings/utf_string_conversions.h" -#include "native_mate/arguments.h" -#include "native_mate/dictionary.h" -#include "third_party/skia/include/core/SkBitmap.h" -#include "ui/base/clipboard/clipboard.h" #include "ui/base/clipboard/scoped_clipboard_writer.h" -#include "ui/gfx/image/image.h" #include "atom/common/node_includes.h" -namespace { +namespace atom { -ui::ClipboardType GetClipboardType(mate::Arguments* args) { +namespace api { + +ui::ClipboardType Clipboard::GetClipboardType(mate::Arguments* args) { std::string type; if (args->GetNext(&type) && type == "selection") return ui::CLIPBOARD_TYPE_SELECTION; @@ -27,7 +23,7 @@ ui::ClipboardType GetClipboardType(mate::Arguments* args) { return ui::CLIPBOARD_TYPE_COPY_PASTE; } -std::vector AvailableFormats(mate::Arguments* args) { +std::vector Clipboard::AvailableFormats(mate::Arguments* args) { std::vector format_types; bool ignore; ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); @@ -35,14 +31,14 @@ std::vector AvailableFormats(mate::Arguments* args) { return format_types; } -bool Has(const std::string& format_string, mate::Arguments* args) { +bool Clipboard::Has(const std::string& format_string, mate::Arguments* args) { ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); ui::Clipboard::FormatType format(ui::Clipboard::GetFormatType(format_string)); return clipboard->IsFormatAvailable(format, GetClipboardType(args)); } -std::string Read(const std::string& format_string, - mate::Arguments* args) { +std::string Clipboard::Read(const std::string& format_string, + mate::Arguments* args) { ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); ui::Clipboard::FormatType format(ui::Clipboard::GetFormatType(format_string)); @@ -51,8 +47,7 @@ std::string Read(const std::string& format_string, return data; } -void Write(const mate::Dictionary& data, - mate::Arguments* args) { +void Clipboard::Write(const mate::Dictionary& data, mate::Arguments* args) { ui::ScopedClipboardWriter writer(GetClipboardType(args)); base::string16 text, html, bookmark; gfx::Image image; @@ -76,7 +71,7 @@ void Write(const mate::Dictionary& data, writer.WriteImage(image.AsBitmap()); } -base::string16 ReadText(mate::Arguments* args) { +base::string16 Clipboard::ReadText(mate::Arguments* args) { base::string16 data; ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); auto type = GetClipboardType(args); @@ -92,24 +87,24 @@ base::string16 ReadText(mate::Arguments* args) { return data; } -void WriteText(const base::string16& text, mate::Arguments* args) { +void Clipboard::WriteText(const base::string16& text, mate::Arguments* args) { ui::ScopedClipboardWriter writer(GetClipboardType(args)); writer.WriteText(text); } -base::string16 ReadRtf(mate::Arguments* args) { +base::string16 Clipboard::ReadRtf(mate::Arguments* args) { std::string data; ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); clipboard->ReadRTF(GetClipboardType(args), &data); return base::UTF8ToUTF16(data); } -void WriteRtf(const std::string& text, mate::Arguments* args) { +void Clipboard::WriteRtf(const std::string& text, mate::Arguments* args) { ui::ScopedClipboardWriter writer(GetClipboardType(args)); writer.WriteRTF(text); } -base::string16 ReadHtml(mate::Arguments* args) { +base::string16 Clipboard::ReadHtml(mate::Arguments* args) { base::string16 data; base::string16 html; std::string url; @@ -121,12 +116,12 @@ base::string16 ReadHtml(mate::Arguments* args) { return data; } -void WriteHtml(const base::string16& html, mate::Arguments* args) { +void Clipboard::WriteHtml(const base::string16& html, mate::Arguments* args) { ui::ScopedClipboardWriter writer(GetClipboardType(args)); writer.WriteHTML(html, std::string()); } -v8::Local ReadBookmark(mate::Arguments* args) { +v8::Local Clipboard::ReadBookmark(mate::Arguments* args) { base::string16 title; std::string url; mate::Dictionary dict = mate::Dictionary::CreateEmpty(args->isolate()); @@ -137,51 +132,65 @@ v8::Local ReadBookmark(mate::Arguments* args) { return dict.GetHandle(); } -void WriteBookmark(const base::string16& title, const std::string& url, - mate::Arguments* args) { +void Clipboard::WriteBookmark(const base::string16& title, + const std::string& url, + mate::Arguments* args) { ui::ScopedClipboardWriter writer(GetClipboardType(args)); writer.WriteBookmark(title, url); } -gfx::Image ReadImage(mate::Arguments* args) { +gfx::Image Clipboard::ReadImage(mate::Arguments* args) { ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread(); SkBitmap bitmap = clipboard->ReadImage(GetClipboardType(args)); return gfx::Image::CreateFrom1xBitmap(bitmap); } -void WriteImage(const gfx::Image& image, mate::Arguments* args) { +void Clipboard::WriteImage(const gfx::Image& image, mate::Arguments* args) { ui::ScopedClipboardWriter writer(GetClipboardType(args)); writer.WriteImage(image.AsBitmap()); } -void Clear(mate::Arguments* args) { +#if !defined(OS_MACOSX) +void Clipboard::WriteFindText(const base::string16& text) {} +base::string16 Clipboard::ReadFindText() { return ""; } +#endif + +void Clipboard::Clear(mate::Arguments* args) { ui::Clipboard::GetForCurrentThread()->Clear(GetClipboardType(args)); } +} // namespace api + +} // namespace atom + +namespace { + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { mate::Dictionary dict(context->GetIsolate(), exports); - dict.SetMethod("availableFormats", &AvailableFormats); - dict.SetMethod("has", &Has); - dict.SetMethod("read", &Read); - dict.SetMethod("write", &Write); - dict.SetMethod("readText", &ReadText); - dict.SetMethod("writeText", &WriteText); - dict.SetMethod("readRTF", &ReadRtf); - dict.SetMethod("writeRTF", &WriteRtf); - dict.SetMethod("readHTML", &ReadHtml); - dict.SetMethod("writeHTML", &WriteHtml); - dict.SetMethod("readBookmark", &ReadBookmark); - dict.SetMethod("writeBookmark", &WriteBookmark); - dict.SetMethod("readImage", &ReadImage); - dict.SetMethod("writeImage", &WriteImage); - dict.SetMethod("clear", &Clear); + dict.SetMethod("availableFormats", &atom::api::Clipboard::AvailableFormats); + dict.SetMethod("has", &atom::api::Clipboard::Has); + dict.SetMethod("read", &atom::api::Clipboard::Read); + dict.SetMethod("write", &atom::api::Clipboard::Write); + dict.SetMethod("readText", &atom::api::Clipboard::ReadText); + dict.SetMethod("writeText", &atom::api::Clipboard::WriteText); + dict.SetMethod("readRTF", &atom::api::Clipboard::ReadRtf); + dict.SetMethod("writeRTF", &atom::api::Clipboard::WriteRtf); + dict.SetMethod("readHTML", &atom::api::Clipboard::ReadHtml); + dict.SetMethod("writeHTML", &atom::api::Clipboard::WriteHtml); + dict.SetMethod("readBookmark", &atom::api::Clipboard::ReadBookmark); + dict.SetMethod("writeBookmark", &atom::api::Clipboard::WriteBookmark); + dict.SetMethod("readImage", &atom::api::Clipboard::ReadImage); + dict.SetMethod("writeImage", &atom::api::Clipboard::WriteImage); + dict.SetMethod("readFindText", &atom::api::Clipboard::ReadFindText); + dict.SetMethod("writeFindText", &atom::api::Clipboard::WriteFindText); + dict.SetMethod("clear", &atom::api::Clipboard::Clear); // TODO(kevinsawicki): Remove in 2.0, deprecate before then with warnings - dict.SetMethod("readRtf", &ReadRtf); - dict.SetMethod("writeRtf", &WriteRtf); - dict.SetMethod("readHtml", &ReadHtml); - dict.SetMethod("writeHtml", &WriteHtml); + dict.SetMethod("readRtf", &atom::api::Clipboard::ReadRtf); + dict.SetMethod("writeRtf", &atom::api::Clipboard::WriteRtf); + dict.SetMethod("readHtml", &atom::api::Clipboard::ReadHtml); + dict.SetMethod("writeHtml", &atom::api::Clipboard::WriteHtml); } } // namespace diff --git a/atom/common/api/atom_api_clipboard.h b/atom/common/api/atom_api_clipboard.h new file mode 100644 index 0000000000..e46e035b31 --- /dev/null +++ b/atom/common/api/atom_api_clipboard.h @@ -0,0 +1,59 @@ +// Copyright (c) 2016 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_COMMON_API_ATOM_API_CLIPBOARD_H_ +#define ATOM_COMMON_API_ATOM_API_CLIPBOARD_H_ + +#include +#include + +#include "native_mate/arguments.h" +#include "native_mate/dictionary.h" +#include "ui/base/clipboard/clipboard.h" +#include "ui/gfx/image/image.h" + +namespace atom { + +namespace api { + +class Clipboard { + public: + static ui::ClipboardType GetClipboardType(mate::Arguments* args); + static std::vector AvailableFormats(mate::Arguments* args); + static bool Has(const std::string& format_string, mate::Arguments* args); + static void Clear(mate::Arguments* args); + + static std::string Read(const std::string& format_string, + mate::Arguments* args); + static void Write(const mate::Dictionary& data, mate::Arguments* args); + + static base::string16 ReadText(mate::Arguments* args); + static void WriteText(const base::string16& text, mate::Arguments* args); + + static base::string16 ReadRtf(mate::Arguments* args); + static void WriteRtf(const std::string& text, mate::Arguments* args); + + static base::string16 ReadHtml(mate::Arguments* args); + static void WriteHtml(const base::string16& html, mate::Arguments* args); + + static v8::Local ReadBookmark(mate::Arguments* args); + static void WriteBookmark(const base::string16& title, + const std::string& url, + mate::Arguments* args); + + static gfx::Image ReadImage(mate::Arguments* args); + static void WriteImage(const gfx::Image& image, mate::Arguments* args); + + static base::string16 ReadFindText(); + static void WriteFindText(const base::string16& text); + + private: + DISALLOW_COPY_AND_ASSIGN(Clipboard); +}; + +} // namespace api + +} // namespace atom + +#endif // ATOM_COMMON_API_ATOM_API_CLIPBOARD_H_ diff --git a/atom/common/api/atom_api_clipboard_mac.mm b/atom/common/api/atom_api_clipboard_mac.mm new file mode 100644 index 0000000000..3caec2c1dd --- /dev/null +++ b/atom/common/api/atom_api_clipboard_mac.mm @@ -0,0 +1,24 @@ +// Copyright (c) 2016 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/common/api/atom_api_clipboard.h" +#include "base/strings/sys_string_conversions.h" +#include "ui/base/cocoa/find_pasteboard.h" + +namespace atom { + +namespace api { + +void Clipboard::WriteFindText(const base::string16& text) { + NSString* text_ns = base::SysUTF16ToNSString(text); + [[FindPasteboard sharedInstance] setFindText:text_ns]; +} + +base::string16 Clipboard::ReadFindText() { + return GetFindPboardText(); +} + +} // namespace api + +} // namespace atom diff --git a/filenames.gypi b/filenames.gypi index ed1329b9bf..1ea49106bd 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -340,6 +340,8 @@ 'atom/common/api/api_messages.h', 'atom/common/api/atom_api_asar.cc', 'atom/common/api/atom_api_clipboard.cc', + 'atom/common/api/atom_api_clipboard.h', + 'atom/common/api/atom_api_clipboard_mac.mm', 'atom/common/api/atom_api_crash_reporter.cc', 'atom/common/api/atom_api_key_weak_map.h', 'atom/common/api/atom_api_native_image.cc', From 1718697ef0d761fff1318cf83106331eb0e777cc Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Oct 2016 13:43:24 +0900 Subject: [PATCH 088/148] Read/write find pasteboard text via IPC in renderer process --- lib/common/api/clipboard.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/common/api/clipboard.js b/lib/common/api/clipboard.js index 7186f8b634..b52524d759 100644 --- a/lib/common/api/clipboard.js +++ b/lib/common/api/clipboard.js @@ -2,5 +2,14 @@ if (process.platform === 'linux' && process.type === 'renderer') { // On Linux we could not access clipboard in renderer process. module.exports = require('electron').remote.clipboard } else { - module.exports = process.atomBinding('clipboard') + const clipboard = process.atomBinding('clipboard') + + // Read/write to find pasteboard over IPC since only main process is notified + // of changes + if (process.platform === 'darwin' && process.type === 'renderer') { + clipboard.readFindText = require('electron').remote.clipboard.readFindText + clipboard.writeFindText = require('electron').remote.clipboard.writeFindText + } + + module.exports = clipboard } From 1c3b5835f467e28edec5a55da47d39a321e3e525 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Oct 2016 13:59:04 +0900 Subject: [PATCH 089/148] Add spec for read/write find text --- atom/common/api/atom_api_clipboard.cc | 2 +- spec/api-clipboard-spec.js | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/atom/common/api/atom_api_clipboard.cc b/atom/common/api/atom_api_clipboard.cc index 31e6b7c133..d2de0f5166 100644 --- a/atom/common/api/atom_api_clipboard.cc +++ b/atom/common/api/atom_api_clipboard.cc @@ -152,7 +152,7 @@ void Clipboard::WriteImage(const gfx::Image& image, mate::Arguments* args) { #if !defined(OS_MACOSX) void Clipboard::WriteFindText(const base::string16& text) {} -base::string16 Clipboard::ReadFindText() { return ""; } +base::string16 Clipboard::ReadFindText() { return base::string16(); } #endif void Clipboard::Clear(mate::Arguments* args) { diff --git a/spec/api-clipboard-spec.js b/spec/api-clipboard-spec.js index 25b65b4784..f0d730d7b0 100644 --- a/spec/api-clipboard-spec.js +++ b/spec/api-clipboard-spec.js @@ -84,4 +84,13 @@ describe('clipboard module', function () { } }) }) + + describe('clipboard.read/writeFindText(text)', function () { + it('reads and write text to the find pasteboard', function () { + if (process.platform !== 'darwin') return this.skip() + + clipboard.writeFindText('find this') + assert.equal(clipboard.readFindText(), 'find this') + }) + }) }) From 7ffc1faf5b4e54d56f1b876bc6f6dcebba2029d1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 25 Oct 2016 14:09:42 +0900 Subject: [PATCH 090/148] Document read/writeFindText --- docs/api/clipboard.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/api/clipboard.md b/docs/api/clipboard.md index a6e9392c8a..ba2438d36c 100644 --- a/docs/api/clipboard.md +++ b/docs/api/clipboard.md @@ -106,6 +106,19 @@ clipboard.write({ }) ``` +### `clipboard.readFindText()` _macOS_ + +Returns `String` - The text on the find pasteboard. This method uses synchronous +IPC when called from the renderer process. The cached value is reread from the +find pasteboard whenever the application is activated. + +### `clipboard.writeFindText(text)` _macOS_ + +* `text` String + +Writes the `text` into the find pasteboard as plain text. This method uses +synchronous IPC when called from the renderer process. + ### `clipboard.clear([type])` * `type` String (optional) From 61278f9aceaca9454c7aaa1d4d78222f17f64de7 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 25 Oct 2016 12:41:01 +0200 Subject: [PATCH 091/148] Fixing code review issues. --- atom/browser/api/atom_api_net.cc | 11 +-- atom/browser/api/atom_api_net.h | 3 +- atom/browser/api/atom_api_url_request.cc | 75 +++++++++++++------ atom/browser/api/atom_api_url_request.h | 52 +++---------- atom/browser/api/atom_api_web_contents.cc | 4 +- atom/browser/net/atom_url_request.cc | 2 +- atom/browser/net/atom_url_request.h | 2 +- atom/common/api/atom_api_v8_util.cc | 7 ++ .../native_mate_converters/net_converter.cc | 5 +- .../native_mate_converters/net_converter.h | 9 +-- docs/api/net.md | 12 ++- filenames.gypi | 4 +- lib/browser/api/net.js | 23 +++--- spec/api-net-spec.js | 9 ++- 14 files changed, 106 insertions(+), 112 deletions(-) diff --git a/atom/browser/api/atom_api_net.cc b/atom/browser/api/atom_api_net.cc index dac8d9ee14..24008ed7ae 100644 --- a/atom/browser/api/atom_api_net.cc +++ b/atom/browser/api/atom_api_net.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2013 GitHub, Inc. +// Copyright (c) 2016 GitHub, Inc. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. @@ -27,20 +27,13 @@ void Net::BuildPrototype(v8::Isolate* isolate, v8::Local prototype) { prototype->SetClassName(mate::StringToV8(isolate, "Net")); mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate()) - .SetProperty("URLRequest", &Net::URLRequest) - .SetMethod("_RequestGarbageCollectionForTesting", - &Net::RequestGarbageCollectionForTesting); + .SetProperty("URLRequest", &Net::URLRequest); } v8::Local Net::URLRequest(v8::Isolate* isolate) { return URLRequest::GetConstructor(isolate)->GetFunction(); } -void Net::RequestGarbageCollectionForTesting() { - isolate()->RequestGarbageCollectionForTesting( - v8::Isolate::GarbageCollectionType::kFullGarbageCollection); -} - } // namespace api } // namespace atom diff --git a/atom/browser/api/atom_api_net.h b/atom/browser/api/atom_api_net.h index 0b86931978..2a0fa4140c 100644 --- a/atom/browser/api/atom_api_net.h +++ b/atom/browser/api/atom_api_net.h @@ -1,4 +1,4 @@ -// Copyright (c) 2013 GitHub, Inc. +// Copyright (c) 2016 GitHub, Inc. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. @@ -25,7 +25,6 @@ class Net : public mate::EventEmitter { ~Net() override; private: - void RequestGarbageCollectionForTesting(); DISALLOW_COPY_AND_ASSIGN(Net); }; diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 42f08c8f05..fc5c053648 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2013 GitHub, Inc. +// Copyright (c) 2016 GitHub, Inc. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. @@ -42,22 +42,53 @@ struct Converter> { return false; } - auto io_buffer = new net::IOBufferWithSize(size); - if (!io_buffer) { - // Assuming allocation failed. - return false; - } - + *out = new net::IOBufferWithSize(size); // We do a deep copy. We could have used Buffer's internal memory // but that is much more complicated to be properly handled. - memcpy(io_buffer->data(), data, size); - *out = io_buffer; + memcpy((*out)->data(), data, size); return true; } }; } // namespace mate +namespace { + +template +std::array, sizeof...(ArgTypes)> BuildArgsArray( + v8::Isolate* isolate, + ArgTypes... args) { + std::array, sizeof...(ArgTypes)> result = { + {mate::ConvertToV8(isolate, args)...}}; + return result; +} + +template +void EmitRequestEvent(v8::Isolate* isolate, + v8::Local object, + ArgTypes... args) { + v8::HandleScope handle_scope(isolate); + auto arguments = BuildArgsArray(isolate, args...); + v8::Local _emitRequestEvent; + if (mate::Dictionary(isolate, object) + .Get("_emitRequestEvent", &_emitRequestEvent)) + _emitRequestEvent->Call(object, arguments.size(), arguments.data()); +} + +template +void EmitResponseEvent(v8::Isolate* isolate, + v8::Local object, + ArgTypes... args) { + v8::HandleScope handle_scope(isolate); + auto arguments = BuildArgsArray(isolate, args...); + v8::Local _emitResponseEvent; + if (mate::Dictionary(isolate, object) + .Get("_emitResponseEvent", &_emitResponseEvent)) + _emitResponseEvent->Call(object, arguments.size(), arguments.data()); +} + +} // namespace + namespace atom { namespace api { @@ -210,12 +241,12 @@ bool URLRequest::Write(scoped_refptr buffer, if (request_state_.NotStarted()) { request_state_.SetFlag(RequestStateFlags::kStarted); // Pin on first write. - pin(); + Pin(); } if (is_last) { request_state_.SetFlag(RequestStateFlags::kFinished); - EmitRequestEvent(true, "finish"); + EmitRequestEvent(isolate(), GetWrapper(), true, "finish"); } DCHECK(atom_request_); @@ -239,10 +270,10 @@ void URLRequest::Cancel() { // Really cancel if it was started. atom_request_->Cancel(); } - EmitRequestEvent(true, "abort"); + EmitRequestEvent(isolate(), GetWrapper(), true, "abort"); if (response_state_.Started() && !response_state_.Ended()) { - EmitResponseEvent(true, "aborted"); + EmitResponseEvent(isolate(), GetWrapper(), true, "aborted"); } Close(); } @@ -351,10 +382,10 @@ void URLRequest::OnError(const std::string& error, bool isRequestError) { auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error)); if (isRequestError) { request_state_.SetFlag(RequestStateFlags::kFailed); - EmitRequestEvent(false, "error", error_object); + EmitRequestEvent(isolate(), GetWrapper(), false, "error", error_object); } else { response_state_.SetFlag(ResponseStateFlags::kFailed); - EmitResponseEvent(false, "error", error_object); + EmitResponseEvent(isolate(), GetWrapper(), false, "error", error_object); } Close(); } @@ -374,8 +405,8 @@ std::string URLRequest::StatusMessage() const { return result; } -scoped_refptr URLRequest::RawResponseHeaders() const { - return response_headers_; +net::HttpResponseHeaders* URLRequest::RawResponseHeaders() const { + return response_headers_.get(); } uint32_t URLRequest::ResponseHttpVersionMajor() const { @@ -397,11 +428,11 @@ void URLRequest::Close() { request_state_.SetFlag(RequestStateFlags::kClosed); if (response_state_.Started()) { // Emit a close event if we really have a response object. - EmitResponseEvent(true, "close"); + EmitResponseEvent(isolate(), GetWrapper(), true, "close"); } - EmitRequestEvent(true, "close"); + EmitRequestEvent(isolate(), GetWrapper(), true, "close"); } - unpin(); + Unpin(); if (atom_request_) { // A request has been created in JS, used and then it ended. // We release unneeded net resources. @@ -410,13 +441,13 @@ void URLRequest::Close() { atom_request_ = nullptr; } -void URLRequest::pin() { +void URLRequest::Pin() { if (wrapper_.IsEmpty()) { wrapper_.Reset(isolate(), GetWrapper()); } } -void URLRequest::unpin() { +void URLRequest::Unpin() { wrapper_.Reset(); } diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index f59f8bc72f..935b9df3af 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -1,4 +1,4 @@ -// Copyright (c) 2013 GitHub, Inc. +// Copyright (c) 2016 GitHub, Inc. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. @@ -175,23 +175,23 @@ class URLRequest : public mate::EventEmitter { int StatusCode() const; std::string StatusMessage() const; - scoped_refptr RawResponseHeaders() const; + net::HttpResponseHeaders* RawResponseHeaders() const; uint32_t ResponseHttpVersionMajor() const; uint32_t ResponseHttpVersionMinor() const; - template - std::array, sizeof...(ArgTypes)> BuildArgsArray( - ArgTypes... args) const; + // template + // std::array, sizeof...(ArgTypes)> BuildArgsArray( + // ArgTypes... args) const; - template - void EmitRequestEvent(ArgTypes... args); + // template + // void EmitRequestEvent(ArgTypes... args); - template - void EmitResponseEvent(ArgTypes... args); + // template + // void EmitResponseEvent(ArgTypes... args); void Close(); - void pin(); - void unpin(); + void Pin(); + void Unpin(); scoped_refptr atom_request_; RequestState request_state_; @@ -205,36 +205,6 @@ class URLRequest : public mate::EventEmitter { DISALLOW_COPY_AND_ASSIGN(URLRequest); }; -template -std::array, sizeof...(ArgTypes)> -URLRequest::BuildArgsArray(ArgTypes... args) const { - std::array, sizeof...(ArgTypes)> result = { - {mate::ConvertToV8(isolate(), args)...}}; - return result; -} - -template -void URLRequest::EmitRequestEvent(ArgTypes... args) { - v8::HandleScope handle_scope(isolate()); - auto arguments = BuildArgsArray(args...); - v8::Local _emitRequestEvent; - auto wrapper = GetWrapper(); - if (mate::Dictionary(isolate(), wrapper) - .Get("_emitRequestEvent", &_emitRequestEvent)) - _emitRequestEvent->Call(wrapper, arguments.size(), arguments.data()); -} - -template -void URLRequest::EmitResponseEvent(ArgTypes... args) { - v8::HandleScope handle_scope(isolate()); - auto arguments = BuildArgsArray(args...); - v8::Local _emitResponseEvent; - auto wrapper = GetWrapper(); - if (mate::Dictionary(isolate(), wrapper) - .Get("_emitResponseEvent", &_emitResponseEvent)) - _emitResponseEvent->Call(wrapper, arguments.size(), arguments.data()); -} - } // namespace api } // namespace atom diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index bd7de5a22a..a1dc5203b6 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -664,7 +664,7 @@ void WebContents::DidGetResourceResponseStart( details.http_response_code, details.method, details.referrer, - details.headers, + details.headers.get(), ResourceTypeToString(details.resource_type)); } @@ -678,7 +678,7 @@ void WebContents::DidGetRedirectForResourceRequest( details.http_response_code, details.method, details.referrer, - details.headers); + details.headers.get()); } void WebContents::DidFinishNavigation( diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index 576036819f..5d46beac80 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2013 GitHub, Inc. +// Copyright (c) 2016 GitHub, Inc. // Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index 3efccae50f..27cdbb5b3c 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -1,4 +1,4 @@ -// Copyright (c) 2013 GitHub, Inc. +// Copyright (c) 2016 GitHub, Inc. // Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by the MIT license that can be // found in the LICENSE file. diff --git a/atom/common/api/atom_api_v8_util.cc b/atom/common/api/atom_api_v8_util.cc index ddacbb0808..a587cd772a 100644 --- a/atom/common/api/atom_api_v8_util.cc +++ b/atom/common/api/atom_api_v8_util.cc @@ -92,6 +92,11 @@ void TakeHeapSnapshot(v8::Isolate* isolate) { isolate->GetHeapProfiler()->TakeHeapSnapshot(); } +void RequestGarbageCollectionForTesting(v8::Isolate* isolate) { + isolate->RequestGarbageCollectionForTesting( + v8::Isolate::GarbageCollectionType::kFullGarbageCollection); +} + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, void* priv) { mate::Dictionary dict(context->GetIsolate(), exports); @@ -105,6 +110,8 @@ void Initialize(v8::Local exports, v8::Local unused, dict.SetMethod("createIDWeakMap", &atom::api::KeyWeakMap::Create); dict.SetMethod("createDoubleIDWeakMap", &atom::api::KeyWeakMap>::Create); + dict.SetMethod("requestGarbageCollectionForTesting", + &RequestGarbageCollectionForTesting); } } // namespace diff --git a/atom/common/native_mate_converters/net_converter.cc b/atom/common/native_mate_converters/net_converter.cc index 89120c94ab..00a06566a2 100644 --- a/atom/common/native_mate_converters/net_converter.cc +++ b/atom/common/native_mate_converters/net_converter.cc @@ -60,10 +60,9 @@ v8::Local Converter>::ToV8( } // static -v8::Local -Converter>::ToV8( +v8::Local Converter::ToV8( v8::Isolate* isolate, - scoped_refptr headers) { + net::HttpResponseHeaders* headers) { base::DictionaryValue response_headers; if (headers) { size_t iter = 0; diff --git a/atom/common/native_mate_converters/net_converter.h b/atom/common/native_mate_converters/net_converter.h index e3ba6b60cc..16013e34f9 100644 --- a/atom/common/native_mate_converters/net_converter.h +++ b/atom/common/native_mate_converters/net_converter.h @@ -34,11 +34,10 @@ struct Converter> { const scoped_refptr& val); }; -template<> -struct Converter> { - static v8::Local ToV8( - v8::Isolate* isolate, - scoped_refptr headers); +template <> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, + net::HttpResponseHeaders* headers); }; } // namespace mate diff --git a/docs/api/net.md b/docs/api/net.md index 0fab893c56..cf7a456e5a 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -226,6 +226,11 @@ string, it is converted into a Buffer using the specified encoding. * `encoding` String (optional) - Used to convert string chunks into Buffer objects. Defaults to 'utf-8'. * `callback` Function (optional) - Called after the write operation ends. +`callback` is essentially a dummy function introduced in the purpose of keeping +similarity with the Node.js API. It is called asynchronously in the next tick +after `chunk` content have been delivered to the Chromium networking layer. +Contrary to the Node.js implementation, it is not guaranteed that `chunk` +content have been flushed on the wire before `callback` is called. Adds a chunk of data to the request body. The first write operation may cause the request headers to be issued on the wire. After the first write operation, @@ -311,10 +316,3 @@ A String indicating the HTTP protocol version number. Typical values are '1.0' or '1.1'. Additionally `httpVersionMajor` and `httpVersionMinor` are two Integer-valued readable properties that return respectively the HTTP major and minor version numbers. - - - - - - - diff --git a/filenames.gypi b/filenames.gypi index 20375c6f4e..1834a9949e 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -23,7 +23,7 @@ 'lib/browser/api/menu-item.js', 'lib/browser/api/menu-item-roles.js', 'lib/browser/api/navigation-controller.js', - 'lib/browser/api/net.js', + 'lib/browser/api/net.js', 'lib/browser/api/power-monitor.js', 'lib/browser/api/power-save-blocker.js', 'lib/browser/api/protocol.js', @@ -238,7 +238,7 @@ 'atom/browser/net/atom_network_delegate.h', 'atom/browser/net/atom_ssl_config_service.cc', 'atom/browser/net/atom_ssl_config_service.h', - 'atom/browser/net/atom_url_request.cc', + 'atom/browser/net/atom_url_request.cc', 'atom/browser/net/atom_url_request.h', 'atom/browser/net/atom_url_request_job_factory.cc', 'atom/browser/net/atom_url_request_job_factory.h', diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 7fb2c61495..1cb285184a 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -3,18 +3,15 @@ const url = require('url') const {EventEmitter} = require('events') const util = require('util') -const Readable = require('stream').Readable -const binding = process.atomBinding('net') -const {net, Net} = binding -const {URLRequest} = net +const {Readable} = require('stream') const {app} = require('electron') +const {net, Net} = process.atomBinding('net') +const {URLRequest} = net Object.setPrototypeOf(Net.prototype, EventEmitter.prototype) Object.setPrototypeOf(URLRequest.prototype, EventEmitter.prototype) -let kSupportedProtocols = new Set() -kSupportedProtocols.add('http:') -kSupportedProtocols.add('https:') +const kSupportedProtocols = new Set(['http:', 'https:']) class IncomingMessage extends Readable { constructor (urlRequest) { @@ -82,8 +79,8 @@ class IncomingMessage extends Readable { } -URLRequest.prototype._emitRequestEvent = function (async, ...rest) { - if (async) { +URLRequest.prototype._emitRequestEvent = function (isAsync, ...rest) { + if (isAsync) { process.nextTick(() => { this.clientRequest.emit.apply(this.clientRequest, rest) }) @@ -92,8 +89,8 @@ URLRequest.prototype._emitRequestEvent = function (async, ...rest) { } } -URLRequest.prototype._emitResponseEvent = function (async, ...rest) { - if (async) { +URLRequest.prototype._emitResponseEvent = function (isAsync, ...rest) { + if (isAsync) { process.nextTick(() => { this._response.emit.apply(this._response, rest) }) @@ -175,9 +172,7 @@ class ClientRequest extends EventEmitter { this.extraHeaders = {} if (options.headers) { - const keys = Object.keys(options.headers) - for (let i = 0, l = keys.length; i < l; i++) { - const key = keys[i] + for (let key in options.headers) { this.setHeader(key, options.headers[key]) } } diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index fa73d7722c..08ec337ecb 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -1179,7 +1179,8 @@ describe('net module', function () { const {net} = require('electron') const urlRequest = net.request('${server.url}${requestUrl}') process.nextTick(function () { - net._RequestGarbageCollectionForTesting() + const v8Util = process.atomBinding('v8_util') + v8Util.requestGarbageCollectionForTesting() event.sender.send('api-net-spec-done') }) `) @@ -1217,7 +1218,8 @@ describe('net module', function () { }) process.nextTick(function () { // Trigger a garbage collection. - net._RequestGarbageCollectionForTesting() + const v8Util = process.atomBinding('v8_util') + v8Util.requestGarbageCollectionForTesting() event.sender.send('api-net-spec-resume') }) }) @@ -1251,7 +1253,8 @@ describe('net module', function () { }) urlRequest.on('close', function () { process.nextTick(function () { - net._RequestGarbageCollectionForTesting() + const v8Util = process.atomBinding('v8_util') + v8Util.requestGarbageCollectionForTesting() event.sender.send('api-net-spec-done') }) }) From 6d7f179a9bbb73fa7189599e42fb8e3144428d4a Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 25 Oct 2016 15:02:35 +0200 Subject: [PATCH 092/148] Fixing code review issues: making delegate_ a raw pointer. --- atom/browser/api/atom_api_url_request.cc | 6 ++---- atom/browser/api/atom_api_url_request.h | 1 - atom/browser/net/atom_url_request.cc | 5 +++-- atom/browser/net/atom_url_request.h | 6 +++--- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index fc5c053648..60d163fe88 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -158,8 +158,7 @@ bool URLRequest::ResponseState::Failed() const { return IsFlagSet(ResponseStateFlags::kFailed); } -URLRequest::URLRequest(v8::Isolate* isolate, v8::Local wrapper) - : weak_ptr_factory_(this) { +URLRequest::URLRequest(v8::Isolate* isolate, v8::Local wrapper) { InitWith(isolate, wrapper); } @@ -188,9 +187,8 @@ mate::WrappableBase* URLRequest::New(mate::Arguments* args) { auto browser_context = session->browser_context(); auto api_url_request = new URLRequest(args->isolate(), args->GetThis()); - auto weak_ptr = api_url_request->weak_ptr_factory_.GetWeakPtr(); auto atom_url_request = - AtomURLRequest::Create(browser_context, method, url, weak_ptr); + AtomURLRequest::Create(browser_context, method, url, api_url_request); api_url_request->atom_request_ = atom_url_request; diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 935b9df3af..83873f977b 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -200,7 +200,6 @@ class URLRequest : public mate::EventEmitter { // Used to implement pin/unpin. v8::Global wrapper_; scoped_refptr response_headers_; - base::WeakPtrFactory weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(URLRequest); }; diff --git a/atom/browser/net/atom_url_request.cc b/atom/browser/net/atom_url_request.cc index 5d46beac80..628d316164 100644 --- a/atom/browser/net/atom_url_request.cc +++ b/atom/browser/net/atom_url_request.cc @@ -43,7 +43,7 @@ class UploadOwnedIOBufferElementReader : public net::UploadBytesElementReader { } // namespace internal -AtomURLRequest::AtomURLRequest(base::WeakPtr delegate) +AtomURLRequest::AtomURLRequest(api::URLRequest* delegate) : delegate_(delegate), is_chunked_upload_(false), response_read_buffer_(new net::IOBuffer(kBufferSize)) {} @@ -57,7 +57,7 @@ scoped_refptr AtomURLRequest::Create( AtomBrowserContext* browser_context, const std::string& method, const std::string& url, - base::WeakPtr delegate) { + api::URLRequest* delegate) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK(browser_context); @@ -83,6 +83,7 @@ scoped_refptr AtomURLRequest::Create( void AtomURLRequest::Terminate() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + delegate_ = nullptr; content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, base::Bind(&AtomURLRequest::DoTerminate, this)); diff --git a/atom/browser/net/atom_url_request.h b/atom/browser/net/atom_url_request.h index 27cdbb5b3c..d0b367e2d3 100644 --- a/atom/browser/net/atom_url_request.h +++ b/atom/browser/net/atom_url_request.h @@ -30,7 +30,7 @@ class AtomURLRequest : public base::RefCountedThreadSafe, AtomBrowserContext* browser_context, const std::string& method, const std::string& url, - base::WeakPtr delegate); + api::URLRequest* delegate); void Terminate(); bool Write(scoped_refptr buffer, bool is_last); @@ -54,7 +54,7 @@ class AtomURLRequest : public base::RefCountedThreadSafe, private: friend class base::RefCountedThreadSafe; - explicit AtomURLRequest(base::WeakPtr delegate); + explicit AtomURLRequest(api::URLRequest* delegate); ~AtomURLRequest() override; void DoInitialize(scoped_refptr, @@ -85,7 +85,7 @@ class AtomURLRequest : public base::RefCountedThreadSafe, void InformDelegateErrorOccured(const std::string& error, bool isRequestError) const; - base::WeakPtr delegate_; + api::URLRequest* delegate_; std::unique_ptr request_; scoped_refptr request_context_getter_; From 6a36deec3beb4b595467d07afa8892fd767ccc30 Mon Sep 17 00:00:00 2001 From: tinydew4 Date: Tue, 25 Oct 2016 13:34:48 +0000 Subject: [PATCH 093/148] Update the korean docs depend on the '1c7d5df' commit. --- docs-translations/ko-KR/api/app.md | 1 + docs-translations/ko-KR/api/clipboard.md | 1 + docs-translations/ko-KR/api/crash-reporter.md | 2 ++ docs-translations/ko-KR/api/process.md | 2 ++ docs-translations/ko-KR/api/screen.md | 1 + docs-translations/ko-KR/api/web-frame.md | 1 + docs-translations/ko-KR/api/web-view-tag.md | 15 +++++++++++++++ docs-translations/ko-KR/api/window-open.md | 1 + 8 files changed, 24 insertions(+) diff --git a/docs-translations/ko-KR/api/app.md b/docs-translations/ko-KR/api/app.md index 9372a6d34b..f6b9124fca 100644 --- a/docs-translations/ko-KR/api/app.md +++ b/docs-translations/ko-KR/api/app.md @@ -546,6 +546,7 @@ Returns `Boolean` - ํ˜ธ์ถœ ์„ฑ๊ณต ์—ฌ๋ถ€. ### `app.getJumpListSettings()` _Windows_ Returns `Object`: + * `minItems` Integer - ์ ํ”„ ๋ชฉ๋ก์—์„œ ๋ณด์—ฌ์งˆ ํ•ญ๋ชฉ์˜ ์ตœ์†Œ ์ˆ˜ (์ด ๊ฐ’์— ๋Œ€ํ•œ ์ž์„ธํ•œ ์„ค๋ช…์€ [MSDN ๋ฌธ์„œ][JumpListBeginListMSDN])๋ฅผ ๋ณด์„ธ์š”. * `removedItems` [JumpListItem[]](structures/jump-list-item.md) - ์ ํ”„ ๋ชฉ๋ก์˜ ์‚ฌ์šฉ์ž ์ •์˜ ์นดํ…Œ๊ณ ๋ฆฌ์—์„œ ์‚ฌ์šฉ์ž๊ฐ€ ์‚ญ์ œํ•œ diff --git a/docs-translations/ko-KR/api/clipboard.md b/docs-translations/ko-KR/api/clipboard.md index 0c4fbc6bb5..890b2349df 100644 --- a/docs-translations/ko-KR/api/clipboard.md +++ b/docs-translations/ko-KR/api/clipboard.md @@ -80,6 +80,7 @@ Returns `String` - RTF ํ˜•์‹์˜ ํด๋ฆฝ๋ณด๋“œ ๋‚ด์šฉ. ### `clipboard.readBookmark()` _macOS_ _Windows_ Returns `Object`: + * `title` String * `url` String diff --git a/docs-translations/ko-KR/api/crash-reporter.md b/docs-translations/ko-KR/api/crash-reporter.md index c08851f5f4..aef9368043 100644 --- a/docs-translations/ko-KR/api/crash-reporter.md +++ b/docs-translations/ko-KR/api/crash-reporter.md @@ -53,6 +53,7 @@ crashReporter.start({ ### `crashReporter.getLastCrashReport()` Returns `Object`: + * `date` String * `ID` Integer @@ -62,6 +63,7 @@ Returns `Object`: ### `crashReporter.getUploadedReports()` Returns `Object[]`: + * `date` String * `ID` Integer diff --git a/docs-translations/ko-KR/api/process.md b/docs-translations/ko-KR/api/process.md index 8dcf948a02..e8d1f7cc6f 100644 --- a/docs-translations/ko-KR/api/process.md +++ b/docs-translations/ko-KR/api/process.md @@ -84,6 +84,7 @@ Mac App Store ๋นŒ๋“œ์—์„  ์ด ์†์„ฑ์ด `true`๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ๋นŒ๋“œ์— ### `process.getProcessMemoryInfo()` Returns `Object`: + * `workingSetSize` Integer - ํ˜„์žฌ ์‹ค์ œ ๋ฌผ๋ฆฌ์  RAM์— ์˜ˆ์•ฝ๋œ ๋ฉ”๋ชจ๋ฆฌ์˜ ์–‘. * `peakWorkingSetSize` Integer - ๋ฌผ๋ฆฌ์  RAM์— ์˜ˆ์•ฝ๋œ ๋ฉ”๋ชจ๋ฆฌ์˜ ์ตœ๋Œ€ ์‚ฌ์šฉ๋Ÿ‰. * `privateBytes` Integer - ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์— ๊ณต์œ ๋˜์ง€ ์•Š์€ JS ํž™ ๋˜๋Š” HTML ์ฝ˜ํ…์ธ ์™€ @@ -97,6 +98,7 @@ Returns `Object`: ### `process.getSystemMemoryInfo()` Returns `Object`: + * `total` Integer - ์‹œ์Šคํ…œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ํ‚ฌ๋กœ๋ฐ”์ดํŠธ ๋‹จ์œ„์˜ ์ „์ฒด ๋ฌผ๋ฆฌ์  ๋ฉ”๋ชจ๋ฆฌ์˜ ์–‘. * `free` Integer - ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด๋‚˜ ๋””์Šคํฌ ์บ์‹œ๋กœ ์‚ฌ์šฉ๋˜์ง€ ์•Š์€ ๋ฉ”๋ชจ๋ฆฌ์˜ ์–‘. diff --git a/docs-translations/ko-KR/api/screen.md b/docs-translations/ko-KR/api/screen.md index c9b7ee1cd1..4bf293bb1d 100644 --- a/docs-translations/ko-KR/api/screen.md +++ b/docs-translations/ko-KR/api/screen.md @@ -90,6 +90,7 @@ Returns: ### `screen.getCursorScreenPoint()` Returns `Object`: + * `x` Integer * `y` Integer diff --git a/docs-translations/ko-KR/api/web-frame.md b/docs-translations/ko-KR/api/web-frame.md index c9d9893747..7c88d176d9 100644 --- a/docs-translations/ko-KR/api/web-frame.md +++ b/docs-translations/ko-KR/api/web-frame.md @@ -121,6 +121,7 @@ webFrame.registerURLSchemeAsPrivileged('foo', { bypassCSP: false }) ### `webFrame.getResourceUsage()` Returns `Object`: + * `images` [MemoryUsageDetails](structures/memory-usage-details.md) * `cssStyleSheets` [MemoryUsageDetails](structures/memory-usage-details.md) * `xslStyleSheets` [MemoryUsageDetails](structures/memory-usage-details.md) diff --git a/docs-translations/ko-KR/api/web-view-tag.md b/docs-translations/ko-KR/api/web-view-tag.md index e4d17504e1..d119253b97 100644 --- a/docs-translations/ko-KR/api/web-view-tag.md +++ b/docs-translations/ko-KR/api/web-view-tag.md @@ -187,6 +187,21 @@ API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋‚ด๋ถ€์—์„œ ๋กœ์šฐ๋ ˆ๋ฒจ "on"์œผ๋กœ ์ง€์ •ํ•˜๋ฉด ํŽ˜์ด์ง€์—์„œ ์ƒˆ๋กœ์šด ์ฐฝ์„ ์—ด ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. +### `webpreferences` + +```html + +``` +์›น๋ทฐ์— ์„ค์ •๋  ์›น ํ™˜๊ฒฝ์„ค์ •์„ ๋‚˜ํƒ€๋‚ด๋Š” `,` ๋กœ ๊ตฌ๋ถ„๋œ ๋ฌธ์ž์—ด์˜ ๋ชฉ๋ก์ž…๋‹ˆ๋‹ค. +์ง€์›๋˜๋Š” ํ™˜๊ฒฝ์„ค์ • ๋ฌธ์ž์—ด์˜ ์ „์ฒด ๋ชฉ๋ก์€ +[BrowserWindow](browser-window.md#new-browserwindowoptions) ์—์„œ ์ฐพ์„ ์ˆ˜ +์žˆ์Šต๋‹ˆ๋‹ค. + +๋ฌธ์ž์—ด์€ `window.open` ์˜ ๊ธฐ๋Šฅ ๋ฌธ์ž์—ด๊ณผ ๊ฐ™์€ ํ˜•์‹์„ ๋”ฐ๋ฆ…๋‹ˆ๋‹ค. ์ด๋ฆ„๋งŒ ์žˆ์œผ๋ฉด +`true` ๋ถˆ๋ฆฐ ๊ฐ’์ด ์ฃผ์–ด์ง‘๋‹ˆ๋‹ค. ํ™˜๊ฒฝ์„ค์ •์€ ๋’ค์— ๊ฐ’์ด ์˜ค๋Š” `=` ์„ ๋„ฃ์–ด์„œ ๋‹ค๋ฅธ ๊ฐ’์„ +์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํŠน๋ณ„ํ•œ ๊ฐ’ `yes` ์™€ `1` ๋Š” `true` ๋กœ ํ•ด์„๋˜๊ณ , `no` ์™€ `0` ์€ +`false` ๋กœ ํ•ด์„๋ฉ๋‹ˆ๋‹ค. + ### `blinkfeatures` ```html diff --git a/docs-translations/ko-KR/api/window-open.md b/docs-translations/ko-KR/api/window-open.md index 91100276fa..e6c89af68b 100644 --- a/docs-translations/ko-KR/api/window-open.md +++ b/docs-translations/ko-KR/api/window-open.md @@ -25,6 +25,7 @@ ์˜ต์…˜์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. **์ฐธ๊ณ :** + * Node ํ†ตํ•ฉ ๊ธฐ๋Šฅ์€ ์—ด๋ฆฐ `window` ์—์„œ ๋ถ€๋ชจ ์œˆ๋„์šฐ๊ฐ€ ํ•ด๋‹น ์˜ต์…˜์ด ๋น„ํ™œ์„ฑํ™” ๋˜์–ด์žˆ๋Š” ๊ฒฝ์šฐ ํ•ญ์ƒ ๋น„ํ™œ์„ฑํ™”๋ฉ๋‹ˆ๋‹ค. * `features` ์— ์žˆ๋Š” (Chromium ๋˜๋Š” Electron ์— ์˜ํ•ด ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๋Š”) ๋น„ํ‘œ์ค€ From b44d5290e28760bce86a6d49ccc11fa847700651 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 25 Oct 2016 15:47:54 +0200 Subject: [PATCH 094/148] Fixing code review issues: adding a partition options and making the session option only takes Session objects. --- atom/browser/api/atom_api_url_request.cc | 17 +++++++++++------ docs/api/net.md | 8 ++++++-- lib/browser/api/net.js | 24 +++++++++++++++++++----- spec/api-net-spec.js | 8 ++++---- 4 files changed, 40 insertions(+), 17 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 60d163fe88..cde0eecd58 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -175,16 +175,21 @@ URLRequest::~URLRequest() { mate::WrappableBase* URLRequest::New(mate::Arguments* args) { v8::Local options; args->GetNext(&options); - mate::Dictionary dict(args->isolate(), options); + auto isolate = args->isolate(); + mate::Dictionary dict(isolate, options); std::string method; dict.Get("method", &method); std::string url; dict.Get("url", &url); - std::string session_name; - dict.Get("session", &session_name); - - auto session = Session::FromPartition(args->isolate(), session_name); - + std::string partition; + mate::Handle session; + if (dict.Get("session", &session)) { + } else if (dict.Get("partition", &partition)) { + session = Session::FromPartition(isolate, partition); + } else { + // Use the default session if not specified. + session = Session::FromPartition(isolate, ""); + } auto browser_context = session->browser_context(); auto api_url_request = new URLRequest(args->isolate(), args->GetThis()); auto atom_url_request = diff --git a/docs/api/net.md b/docs/api/net.md index cf7a456e5a..d14fe3dc02 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -82,8 +82,12 @@ following properties: method. * `url` String (optional) - The request URL. Must be provided in the absolute form with the protocol scheme specified as http or https. - * `session` String (optional) - The name of the [`Session`](session.md) -instance with which the request is associated. Defaults to the empty string. + * `session` Object (optional) - The [`Session`](session.md) instance with +which the request is associated. + * `partition` String (optional) - The name of the [`partition`](session.md) + with which the request is associated. Defaults to the empty string. The +`session` option prevails on `partition`. Thus if a `session` is explicitly +specified, `partition` is ignored. * `protocol` String (optional) - The protocol scheme in the form 'scheme:'. Currently supported values are 'http:' or 'https:'. Defaults to 'http:'. * `host` String (optional) - The server host provided as a concatenation of diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 1cb285184a..3bf43b8715 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -5,6 +5,7 @@ const {EventEmitter} = require('events') const util = require('util') const {Readable} = require('stream') const {app} = require('electron') +const {session} = require('electron') const {net, Net} = process.atomBinding('net') const {URLRequest} = net @@ -155,12 +156,25 @@ class ClientRequest extends EventEmitter { urlStr = url.format(urlObj) } - const sessionName = options.session || '' - let urlRequest = new URLRequest({ + let urlRequestOptions = { method: method, - url: urlStr, - session: sessionName - }) + url: urlStr + } + if (options.session) { + if (options.session instanceof session.Session) { + urlRequestOptions.session = options.session + } else { + throw new TypeError('`session` should be an instance of the Session class.') + } + } else if (options.partition) { + if (typeof options.partition === 'string') { + urlRequestOptions.partition = options.partition + } else { + throw new TypeError('`partition` should be an a string.') + } + } + + let urlRequest = new URLRequest(urlRequestOptions) // Set back and forward links. this.urlRequest = urlRequest diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index 08ec337ecb..a6315dc84d 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -797,10 +797,10 @@ describe('net module', function () { urlRequest.end() }) - it('should to able to create and intercept a request on a custom session', function (done) { + it('should to able to create and intercept a request using a custom parition name', function (done) { const requestUrl = '/requestUrl' const redirectUrl = '/redirectUrl' - const customSessionName = 'custom-session' + const customPartitionName = 'custom-partition' let requestIsRedirected = false server.on('request', function (request, response) { switch (request.url) { @@ -821,7 +821,7 @@ describe('net module', function () { assert(false, 'Request should not be intercepted by the default session') }) - let customSession = session.fromPartition(customSessionName, { + let customSession = session.fromPartition(customPartitionName, { cache: false }) let requestIsIntercepted = false @@ -841,7 +841,7 @@ describe('net module', function () { const urlRequest = net.request({ url: `${server.url}${requestUrl}`, - session: customSessionName + partition: customPartitionName }) urlRequest.on('response', function (response) { assert.equal(response.statusCode, 200) From bdb3f4d4cbd7243fbd3ff69458ebf0c2dd5f6cc1 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 25 Oct 2016 16:19:26 +0200 Subject: [PATCH 095/148] Fixing code review issues: adding some test cases for partition/session options. --- atom/browser/api/atom_api_url_request.cc | 2 +- atom/browser/api/atom_api_url_request.h | 17 ++--- lib/browser/api/net.js | 4 +- spec/api-net-spec.js | 85 +++++++++++++++++++++++- 4 files changed, 91 insertions(+), 17 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index cde0eecd58..465ee3e53c 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -173,9 +173,9 @@ URLRequest::~URLRequest() { // static mate::WrappableBase* URLRequest::New(mate::Arguments* args) { + auto isolate = args->isolate(); v8::Local options; args->GetNext(&options); - auto isolate = args->isolate(); mate::Dictionary dict(isolate, options); std::string method; dict.Get("method", &method); diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 83873f977b..8b2c327828 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -86,9 +86,10 @@ namespace api { // more complex. // // We chose to split the implementation into two classes linked via a -// strong/weak pointers. A URLRequest instance is deleted if it is unpinned and -// the corresponding JS wrapper object is garbage collected. On the other hand, -// an AtmURLRequest instance lifetime is totally governed by reference counting. +// reference counted/raw pointers. A URLRequest instance is deleted if it is +// unpinned and the corresponding JS wrapper object is garbage collected. On the +// other hand, an AtmURLRequest instance lifetime is totally governed by +// reference counting. // class URLRequest : public mate::EventEmitter { public: @@ -179,16 +180,6 @@ class URLRequest : public mate::EventEmitter { uint32_t ResponseHttpVersionMajor() const; uint32_t ResponseHttpVersionMinor() const; - // template - // std::array, sizeof...(ArgTypes)> BuildArgsArray( - // ArgTypes... args) const; - - // template - // void EmitRequestEvent(ArgTypes... args); - - // template - // void EmitResponseEvent(ArgTypes... args); - void Close(); void Pin(); void Unpin(); diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index 3bf43b8715..e8b6f2a473 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -5,7 +5,7 @@ const {EventEmitter} = require('events') const util = require('util') const {Readable} = require('stream') const {app} = require('electron') -const {session} = require('electron') +const {Session} = process.atomBinding('session') const {net, Net} = process.atomBinding('net') const {URLRequest} = net @@ -161,7 +161,7 @@ class ClientRequest extends EventEmitter { url: urlStr } if (options.session) { - if (options.session instanceof session.Session) { + if (options.session instanceof Session) { urlRequestOptions.session = options.session } else { throw new TypeError('`session` should be an instance of the Session class.') diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index a6315dc84d..dca649f64e 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -797,7 +797,79 @@ describe('net module', function () { urlRequest.end() }) - it('should to able to create and intercept a request using a custom parition name', function (done) { + it('should to able to create and intercept a request using a custom session object', function (done) { + const requestUrl = '/requestUrl' + const redirectUrl = '/redirectUrl' + const customPartitionName = 'custom-partition' + let requestIsRedirected = false + server.on('request', function (request, response) { + switch (request.url) { + case requestUrl: + assert(false) + break + case redirectUrl: + requestIsRedirected = true + response.end() + break + default: + assert(false) + } + }) + + session.defaultSession.webRequest.onBeforeRequest( + function (details, callback) { + assert(false, 'Request should not be intercepted by the default session') + }) + + let customSession = session.fromPartition(customPartitionName, { + cache: false + }) + let requestIsIntercepted = false + customSession.webRequest.onBeforeRequest( + function (details, callback) { + if (details.url === `${server.url}${requestUrl}`) { + requestIsIntercepted = true + callback({ + redirectURL: `${server.url}${redirectUrl}` + }) + } else { + callback({ + cancel: false + }) + } + }) + + const urlRequest = net.request({ + url: `${server.url}${requestUrl}`, + session: customSession + }) + urlRequest.on('response', function (response) { + assert.equal(response.statusCode, 200) + response.pause() + response.on('data', function (chunk) { + }) + response.on('end', function () { + assert(requestIsRedirected, 'The server should receive a request to the forward URL') + assert(requestIsIntercepted, 'The request should be intercepted by the webRequest module') + done() + }) + response.resume() + }) + urlRequest.end() + }) + + it('should throw if given an invalid session option', function (done) { + try { + const urlRequest = net.request({ + url: `${server.url}${requestUrl}`, + session: 1 + }) + } catch (exception) { + done() + } + }) + + it('should to able to create and intercept a request using a custom partition name', function (done) { const requestUrl = '/requestUrl' const redirectUrl = '/redirectUrl' const customPartitionName = 'custom-partition' @@ -858,6 +930,17 @@ describe('net module', function () { urlRequest.end() }) + it('should throw if given an invalid partition option', function (done) { + try { + const urlRequest = net.request({ + url: `${server.url}${requestUrl}`, + partition: 1 + }) + } catch (exception) { + done() + } + }) + it('should be able to create a request with options', function (done) { const requestUrl = '/' const customHeaderName = 'Some-Custom-Header-Name' From e9db926b486135ae79b822a858dd65a949464c96 Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Tue, 25 Oct 2016 16:55:17 +0200 Subject: [PATCH 096/148] Fixing code review issues: fixing linter issues in spec file. --- spec/api-net-spec.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/api-net-spec.js b/spec/api-net-spec.js index dca649f64e..9ddc11986c 100644 --- a/spec/api-net-spec.js +++ b/spec/api-net-spec.js @@ -859,11 +859,13 @@ describe('net module', function () { }) it('should throw if given an invalid session option', function (done) { + const requestUrl = '/requestUrl' try { const urlRequest = net.request({ url: `${server.url}${requestUrl}`, session: 1 }) + urlRequest } catch (exception) { done() } @@ -931,11 +933,13 @@ describe('net module', function () { }) it('should throw if given an invalid partition option', function (done) { + const requestUrl = '/requestUrl' try { const urlRequest = net.request({ url: `${server.url}${requestUrl}`, partition: 1 }) + urlRequest } catch (exception) { done() } From 082cd9b72c423ad5aca5b2d3629b062504e68cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Meneghini=20Fauth?= Date: Tue, 25 Oct 2016 15:53:33 -0200 Subject: [PATCH 097/148] :memo: Fix links in docs-translations/pt-BR/README.md [ci skip] --- docs-translations/pt-BR/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs-translations/pt-BR/README.md b/docs-translations/pt-BR/README.md index 8dbd3e830b..3f26f64e75 100644 --- a/docs-translations/pt-BR/README.md +++ b/docs-translations/pt-BR/README.md @@ -9,7 +9,7 @@ selecione a *tag* que corresponde ร  sua versรฃo. ## FAQ Existem muitas perguntas comuns que sรฃo feitas, verifique antes de criar uma issue. -* [Electron FAQ](../../docs/faq.md) +* [Electron FAQ](faq.md) ## Guias @@ -40,15 +40,15 @@ Existem muitas perguntas comuns que sรฃo feitas, verifique antes de criar uma is ### Elementos DOM Personalizados: -* [Objeto `File`](../../docs-translations/pt-BR/api/file-object.md) +* [Objeto `File`](api/file-object.md) * [Tag ``](../../docs/api/web-view-tag.md) -* [Funรงรฃo `window.open`](../../docs/api/window-open.md) +* [Funรงรฃo `window.open`](api/window-open.md) ### Mรณdulos para o Processo Principal: * [app](api/app.md) * [autoUpdater](api/auto-updater.md) -* [BrowserWindow](../../docs/api/browser-window.md) +* [BrowserWindow](api/browser-window.md) * [contentTracing](../../docs/api/content-tracing.md) * [dialog](../../docs/api/dialog.md) * [globalShortcut](../../docs/api/global-shortcut.md) @@ -85,5 +85,5 @@ Existem muitas perguntas comuns que sรฃo feitas, verifique antes de criar uma is * [Visรฃo Geral do Build](../../docs/development/build-system-overview.md) * [Instruรงรฃo de Build (Mac)](development/build-instructions-osx.md) * [Instruรงรฃo de Build (Windows)](../../docs/development/build-instructions-windows.md) -* [Instruรงรฃo de Build (Linux)](../../docs/development/build-instructions-linux.md) +* [Instruรงรฃo de Build (Linux)](development/build-instructions-linux.md) * [Configurando um Symbol Server no Debugger](../../docs/development/setting-up-symbol-server.md) From 9e425cd01e153ded028425e88c00b55d53a8d0e1 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Wed, 26 Oct 2016 10:04:18 +1100 Subject: [PATCH 098/148] Update web-frame.md --- docs/api/web-frame.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/api/web-frame.md b/docs/api/web-frame.md index eae07a92de..078ced9725 100644 --- a/docs/api/web-frame.md +++ b/docs/api/web-frame.md @@ -87,11 +87,11 @@ Content Security Policy. * `scheme` String * `options` Object (optional) - * `secure` (optional) Default true. - * `bypassCSP` (optional) Default true. - * `allowServiceWorkers` (optional) Default true. - * `supportFetchAPI` (optional) Default true. - * `corsEnabled` (optional) Default true. + * `secure` Boolean - (optional) Default true. + * `bypassCSP` Boolean - (optional) Default true. + * `allowServiceWorkers` Boolean - (optional) Default true. + * `supportFetchAPI` Boolean - (optional) Default true. + * `corsEnabled` Boolean - (optional) Default true. Registers the `scheme` as secure, bypasses content security policy for resources, allows registering ServiceWorker and supports fetch API. From 9ae18c6194ffce3bbe868b5406af4f8d72cf62b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maur=C3=ADcio=20Meneghini=20Fauth?= Date: Tue, 25 Oct 2016 21:48:22 -0200 Subject: [PATCH 099/148] :memo: Update docs-translations/pt-BR/api/window-open.md [ci skip] --- docs-translations/pt-BR/api/window-open.md | 91 ++++++++++++++-------- 1 file changed, 60 insertions(+), 31 deletions(-) diff --git a/docs-translations/pt-BR/api/window-open.md b/docs-translations/pt-BR/api/window-open.md index eb2b31cd0e..ec0a93ea38 100644 --- a/docs-translations/pt-BR/api/window-open.md +++ b/docs-translations/pt-BR/api/window-open.md @@ -1,67 +1,96 @@ -# The `window.open` function +# Funรงรฃo `window.open` -Qunado `window.open` รฉ chamado para criar uma nova janela de uma pagina web uma nova instรขncia de `BrowserWindow` serรก criado para a `url` e um proxy serรก devolvido para o `windows.open`, para permitir que a pรกgina tenha limitado controle sobre ele. +> Abre uma nova janela e carrega uma URL. -O proxy tem funcionalidade limitada padrรฃo implementada para ser compatรญvel com as pรกginas web tradicionais. -Para controle total da nova janela vocรช deveria criar um `BrowserWindow` diretamente +Quando `window.open` รฉ chamada para criar uma nova janela de uma pรกgina web, uma +nova instรขncia de `BrowserWindow` serรก criada para a `url` e um proxy serรก +devolvido para o `window.open` para permitir que a pรกgina tenha controle +limitado sobre ele. +O proxy tem uma funcionalidade padrรฃo implementada de forma limitada para ser +compatรญvel com pรกginas web tradicionais. Para ter controle total de uma nova +janela, vocรช deverรก criar diretamente um `BrowserWindow`. -The newly created `BrowserWindow` will inherit parent window's options by -default, to override inherited options you can set them in the `features` -string. +O `BrowserWindow` recรฉm-criado herdarรก as opรงรตes da janela pai por padrรฃo. Para +substituir as opรงรตes herdadas, vocรช poderรก defini-las na string `features`. -O recรฉm-criado `BrowserWindow` herdarรก as opรงรตes da janela pai por padrรฃo, para substituir as opรงรตes herdadas vocรช pode definilos no `features`(string). ### `window.open(url[, frameName][, features])` * `url` String * `frameName` String (opcional) * `features` String (opcional) -Cria uma nova janela e retorna uma instรขncia da classe `BrowserWindowProxy'. +Retorna `BrowserWindowProxy` - Cria uma nova janela e retorna uma instรขncia da +classe `BrowserWindowProxy`. -A string `features` segue o formato padrรฃo do browser, mas cada recurso (feature) tem que ser um campo de opรงรตes do `BrowserWindow`. +A string `features` segue o formato de um navegador padrรฃo, mas cada recurso +(feature) tem de ser um campo das opรงรตes do `BrowserWindow`. + +**Notas:** + +* Integraรงรฃo com Node sempre estarรก desativada no `window` aberto se ela + estiver desativada na janela pai. +* Recursos fora do padrรฃo (que nรฃo sรฃo manipulados pelo Chromium ou pelo + Electron) fornecidos em `features` serรฃo passados para qualquer manipulador + de eventos `new-window` do `webContent` registrado no argumento + `additionalFeatures`. ### `window.opener.postMessage(message, targetOrigin)` * `message` String * `targetOrigin` String -Envia uma mensagem para a janela pai com a origem especificada ou `*` preferรชncia de origem nรฃo especificada. -Sends a message to the parent window with the specified origin or `*` -origin preference. +Envia uma mensagem para a janela pai com a origem especificada ou `*` para +nenhuma preferรชncia de origem. -## Class: BrowserWindowProxy +## Classe: BrowserWindowProxy -O objeto `BrowserWindowProxy` รฉ retornado de `window.open` e fornece uma funcionalidade limitada para a janela filha. +> Manipula a janela de navegador filha -### `BrowserWindowProxy.blur()` +O objeto `BrowserWindowProxy` รฉ retornado de `window.open` e fornece uma +funcionalidade limitada para a janela filha. + +### Mรฉtodos de Instรขncia + +O objeto `BrowserWindowProxy` possui os seguintes mรฉtodos de instรขncia: + +#### `win.blur()` Remove o foco da janela filha. -### `BrowserWindowProxy.close()` +#### `win.close()` -Forรงadamente fecha a janela filha sem chamar o evento de descarregamento. +Fecha forรงadamente a janela filha sem chamar seu evento de descarregamento. -### `BrowserWindowProxy.closed` - -Define como true apรณs a janela filha ficar fechada. - -### `BrowserWindowProxy.eval(code)` +#### `win.eval(code)` * `code` String -Avalia o cรณdigo na jรกnela filha. +Avalia o cรณdigo na janela filha. -### `BrowserWindowProxy.focus()` +#### `win.focus()` -Concentra-se a janela filha (traz a janela para frente) -### `BrowserWindowProxy.postMessage(message, targetOrigin)` +Foca na janela filha (traz a janela para frente). + +#### `win.print()` + +Invoca o diรกlogo de impressรฃo na janela filha. + +#### `win.postMessage(message, targetOrigin)` * `message` String * `targetOrigin` String -Sends a message to the child window with the specified origin or `*` for no -origin preference. +Envia uma mensagem para a janela filha com a origem especificada ou `*` para +nenhuma preferรชncia de origem. -In addition to these methods, the child window implements `window.opener` object -with no properties and a single method. +Alรฉm desses mรฉtodos, a janela filha implementa o objeto `window.opener` sem +propriedades e com apenas um mรฉtodo. + +### Propriedades de Instรขncia + +O objeto `BrowserWindowProxy` possui as seguintes propriedades de instรขncia: + +#### `win.closed` + +Um booleano que รฉ definido como true apรณs a janela filha ser fechada. From fb444f646b19ee4e2c4715fe5ae3e654b4af9664 Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Tue, 11 Oct 2016 18:08:01 -0700 Subject: [PATCH 100/148] default template for PreviewFile --- atom/browser/api/atom_api_window.cc | 5 +++++ atom/browser/api/atom_api_window.h | 1 + atom/browser/native_window.cc | 3 +++ atom/browser/native_window.h | 1 + atom/browser/native_window_mac.h | 1 + atom/browser/native_window_mac.mm | 12 ++++++++++++ 6 files changed, 23 insertions(+) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index d5f1964517..dccf6a77ce 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -729,6 +729,10 @@ void Window::SetAspectRatio(double aspect_ratio, mate::Arguments* args) { window_->SetAspectRatio(aspect_ratio, extra_size); } +void Window::PreviewFile(const base::string16& filepath) { + window_->PreviewFile(filepath); +} + void Window::SetParentWindow(v8::Local value, mate::Arguments* args) { if (IsModal()) { @@ -825,6 +829,7 @@ void Window::BuildPrototype(v8::Isolate* isolate, .SetMethod("setFullScreen", &Window::SetFullScreen) .SetMethod("isFullScreen", &Window::IsFullscreen) .SetMethod("setAspectRatio", &Window::SetAspectRatio) + .SetMethod("previewFile", &Window::PreviewFile) #if !defined(OS_WIN) .SetMethod("setParentWindow", &Window::SetParentWindow) #endif diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 317f5b51ec..abd19f9d5b 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -170,6 +170,7 @@ class Window : public mate::TrackableObject, void SetMenuBarVisibility(bool visible); bool IsMenuBarVisible(); void SetAspectRatio(double aspect_ratio, mate::Arguments* args); + void PreviewFile(const base::string16& filepath); void SetParentWindow(v8::Local value, mate::Arguments* args); v8::Local GetParentWindow() const; std::vector> GetChildWindows() const; diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 1cf5a23b6e..b6ea285159 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -374,6 +374,9 @@ void NativeWindow::SetAspectRatio(double aspect_ratio, aspect_ratio_extraSize_ = extra_size; } +void NativeWindow::PreviewFile(const base::string16& filepath) { +} + void NativeWindow::RequestToClosePage() { bool prevent_default = false; FOR_EACH_OBSERVER(NativeWindowObserver, diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index d8c022d606..c15868c5f4 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -176,6 +176,7 @@ class NativeWindow : public base::SupportsUserData, double GetAspectRatio(); gfx::Size GetAspectRatioExtraSize(); virtual void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size); + virtual void PreviewFile(const base::string16& filepath); base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 4fd7bcc3c2..35649ae7d3 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -55,6 +55,7 @@ class NativeWindowMac : public NativeWindow, void SetMovable(bool movable) override; void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size) override; + void PreviewFile(const base::string16& filepath) override; bool IsMovable() override; void SetMinimizable(bool minimizable) override; bool IsMinimizable() override; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 98e8d4b656..1e18efcc71 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -10,6 +10,8 @@ #include "atom/common/color_util.h" #include "atom/common/draggable_region.h" #include "atom/common/options_switches.h" +#include "atom/common/native_mate_converters/string16_converter.h" +#include "base/strings/utf_string_conversions.h" #include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" #include "base/strings/sys_string_conversions.h" @@ -25,6 +27,7 @@ #include "third_party/skia/include/core/SkRegion.h" #include "ui/gfx/skia_util.h" + namespace { // Prevents window from resizing during the scope. @@ -899,6 +902,15 @@ void NativeWindowMac::SetAspectRatio(double aspect_ratio, [window_ setResizeIncrements:NSMakeSize(1.0, 1.0)]; } +void NativeWindowMac::PreviewFile(const base::string16& filepath) { + std::string rtf = base::UTF16ToUTF8(filepath); + + NSString *path = [NSString stringWithCString:rtf.c_str() + encoding:[NSString defaultCStringEncoding]]; + NSAlert *alert = [NSAlert alertWithMessageText:path defaultButton:@"Close anyway" alternateButton:@"Cancel" otherButton:nil informativeTextWithFormat:@""]; + [alert runModal]; +} + void NativeWindowMac::SetMovable(bool movable) { [window_ setMovable:movable]; } From 526debb5ab5bdf6d72a71a0fc4c6f7f7f53ba5b7 Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Wed, 12 Oct 2016 17:21:56 -0700 Subject: [PATCH 101/148] Adding easy way to preview files --- atom/browser/api/atom_api_window.cc | 4 +- atom/browser/api/atom_api_window.h | 2 +- atom/browser/native_window.cc | 2 +- atom/browser/native_window.h | 2 +- atom/browser/native_window_mac.h | 3 +- atom/browser/native_window_mac.mm | 72 ++++++++++++++++++++++++++--- electron.gyp | 1 + 7 files changed, 73 insertions(+), 13 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index dccf6a77ce..408f738c4b 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -729,8 +729,8 @@ void Window::SetAspectRatio(double aspect_ratio, mate::Arguments* args) { window_->SetAspectRatio(aspect_ratio, extra_size); } -void Window::PreviewFile(const base::string16& filepath) { - window_->PreviewFile(filepath); +void Window::PreviewFile(const base::string16& filepath, const base::string16& filename) { + window_->PreviewFile(filepath, filename); } void Window::SetParentWindow(v8::Local value, diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index abd19f9d5b..e92960f339 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -170,7 +170,7 @@ class Window : public mate::TrackableObject, void SetMenuBarVisibility(bool visible); bool IsMenuBarVisible(); void SetAspectRatio(double aspect_ratio, mate::Arguments* args); - void PreviewFile(const base::string16& filepath); + void PreviewFile(const base::string16& filepath, const base::string16& filename); void SetParentWindow(v8::Local value, mate::Arguments* args); v8::Local GetParentWindow() const; std::vector> GetChildWindows() const; diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index b6ea285159..f9b762f544 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -374,7 +374,7 @@ void NativeWindow::SetAspectRatio(double aspect_ratio, aspect_ratio_extraSize_ = extra_size; } -void NativeWindow::PreviewFile(const base::string16& filepath) { +void NativeWindow::PreviewFile(const base::string16& filepath, const base::string16& filename) { } void NativeWindow::RequestToClosePage() { diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index c15868c5f4..c10cb90725 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -176,7 +176,7 @@ class NativeWindow : public base::SupportsUserData, double GetAspectRatio(); gfx::Size GetAspectRatioExtraSize(); virtual void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size); - virtual void PreviewFile(const base::string16& filepath); + virtual void PreviewFile(const base::string16& filepath, const base::string16& filename); base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 35649ae7d3..6e3f586703 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -9,6 +9,7 @@ #include #include +#include #include "atom/browser/native_window.h" #include "base/mac/scoped_nsobject.h" @@ -55,7 +56,7 @@ class NativeWindowMac : public NativeWindow, void SetMovable(bool movable) override; void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size) override; - void PreviewFile(const base::string16& filepath) override; + void PreviewFile(const base::string16& filepath, const base::string16& filename) override; bool IsMovable() override; void SetMinimizable(bool minimizable) override; bool IsMinimizable() override; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 1e18efcc71..cf9e863b86 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -5,6 +5,7 @@ #include "atom/browser/native_window_mac.h" #include +#include #include "atom/browser/window_list.h" #include "atom/common/color_util.h" @@ -280,7 +281,29 @@ bool ScopedDisableResize::disable_resize_ = false; @end -@interface AtomNSWindow : EventDispatchingWindow { +@interface AtomPreviewItem : NSObject + +@property (nonatomic, retain) NSURL *previewItemURL; +@property (nonatomic, retain) NSString *previewItemTitle; + +- (id)initWithURL:(NSURL *)anURL title:(NSString *)aTitle; + +@end + +@implementation AtomPreviewItem + +- (id)initWithURL:(NSURL *)url title:(NSString *)title { + self = [super init]; + if (self) { + self.previewItemURL = url; + self.previewItemTitle = title; + } + return self; +} + +@end + +@interface AtomNSWindow : EventDispatchingWindow { @private atom::NativeWindowMac* shell_; bool enable_larger_than_screen_; @@ -290,6 +313,7 @@ bool ScopedDisableResize::disable_resize_ = false; @property BOOL disableAutoHideCursor; @property BOOL disableKeyOrMainWindow; @property NSPoint windowButtonsOffset; +@property (nonatomic, retain) AtomPreviewItem* quickLookItem; - (void)setShell:(atom::NativeWindowMac*)shell; - (void)setEnableLargerThanScreen:(bool)enable; @@ -447,6 +471,36 @@ bool ScopedDisableResize::disable_resize_ = false; return [[self contentView] superview]; } +// Quicklook methods + +- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel { + return YES; +} + +- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel { + panel.delegate = self; + panel.dataSource = self; +} + +- (void)endPreviewPanelControl:(QLPreviewPanel *)panel { + panel.delegate = nil; + panel.dataSource = nil; +} + +- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel { + return 1; +} + +- (id )previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index { + return [self quickLookItem]; +} + +- (void)previewFileAtPath:(NSString *)filepath withName:(NSString *) name { + NSURL * url = [[NSURL alloc] initFileURLWithPath:filepath]; + [self setQuickLookItem:[[AtomPreviewItem alloc] initWithURL:url title:name]]; + [[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil]; +} + @end @interface ControlRegionView : NSView @@ -902,13 +956,17 @@ void NativeWindowMac::SetAspectRatio(double aspect_ratio, [window_ setResizeIncrements:NSMakeSize(1.0, 1.0)]; } -void NativeWindowMac::PreviewFile(const base::string16& filepath) { - std::string rtf = base::UTF16ToUTF8(filepath); +void NativeWindowMac::PreviewFile(const base::string16& filepath, const base::string16& filename) { + std::string pathStr = base::UTF16ToUTF8(filepath); + std::string nameStr = base::UTF16ToUTF8(filename); - NSString *path = [NSString stringWithCString:rtf.c_str() - encoding:[NSString defaultCStringEncoding]]; - NSAlert *alert = [NSAlert alertWithMessageText:path defaultButton:@"Close anyway" alternateButton:@"Cancel" otherButton:nil informativeTextWithFormat:@""]; - [alert runModal]; + NSString *path = [NSString stringWithCString:pathStr.c_str() + encoding:[NSString defaultCStringEncoding]]; + + NSString *name = [NSString stringWithCString:nameStr.c_str() + encoding:[NSString defaultCStringEncoding]]; + + [window_ previewFileAtPath:path withName:name]; } void NativeWindowMac::SetMovable(bool movable) { diff --git a/electron.gyp b/electron.gyp index 413d6c5580..0552006e69 100644 --- a/electron.gyp +++ b/electron.gyp @@ -509,6 +509,7 @@ 'libraries': [ '$(SDKROOT)/System/Library/Frameworks/Carbon.framework', '$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework', + '$(SDKROOT)/System/Library/Frameworks/Quartz.framework', ], }, 'mac_bundle': 1, From 9673cee4d71c6856c0f76b802d079bb3dc167592 Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Wed, 12 Oct 2016 17:25:31 -0700 Subject: [PATCH 102/148] Using string from the std --- atom/browser/api/atom_api_window.cc | 2 +- atom/browser/api/atom_api_window.h | 2 +- atom/browser/native_window.cc | 2 +- atom/browser/native_window.h | 2 +- atom/browser/native_window_mac.h | 4 ++-- atom/browser/native_window_mac.mm | 9 +++------ 6 files changed, 9 insertions(+), 12 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 408f738c4b..516d322b3a 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -729,7 +729,7 @@ void Window::SetAspectRatio(double aspect_ratio, mate::Arguments* args) { window_->SetAspectRatio(aspect_ratio, extra_size); } -void Window::PreviewFile(const base::string16& filepath, const base::string16& filename) { +void Window::PreviewFile(const std::string& filepath, const std::string& filename) { window_->PreviewFile(filepath, filename); } diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index e92960f339..966b85cdb5 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -170,7 +170,7 @@ class Window : public mate::TrackableObject, void SetMenuBarVisibility(bool visible); bool IsMenuBarVisible(); void SetAspectRatio(double aspect_ratio, mate::Arguments* args); - void PreviewFile(const base::string16& filepath, const base::string16& filename); + void PreviewFile(const std::string& filepath, const std::string& filename); void SetParentWindow(v8::Local value, mate::Arguments* args); v8::Local GetParentWindow() const; std::vector> GetChildWindows() const; diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index f9b762f544..d01e6fbb21 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -374,7 +374,7 @@ void NativeWindow::SetAspectRatio(double aspect_ratio, aspect_ratio_extraSize_ = extra_size; } -void NativeWindow::PreviewFile(const base::string16& filepath, const base::string16& filename) { +void NativeWindow::PreviewFile(const std::string& filepath, const std::string& filename) { } void NativeWindow::RequestToClosePage() { diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index c10cb90725..9c4116a68b 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -176,7 +176,7 @@ class NativeWindow : public base::SupportsUserData, double GetAspectRatio(); gfx::Size GetAspectRatioExtraSize(); virtual void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size); - virtual void PreviewFile(const base::string16& filepath, const base::string16& filename); + virtual void PreviewFile(const std::string& filepath, const std::string& filename); base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 6e3f586703..9fc2627a0c 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -9,7 +9,6 @@ #include #include -#include #include "atom/browser/native_window.h" #include "base/mac/scoped_nsobject.h" @@ -56,7 +55,8 @@ class NativeWindowMac : public NativeWindow, void SetMovable(bool movable) override; void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size) override; - void PreviewFile(const base::string16& filepath, const base::string16& filename) override; + void PreviewFile(const std::string& filepath, const std::string& filename) + override; bool IsMovable() override; void SetMinimizable(bool minimizable) override; bool IsMinimizable() override; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index cf9e863b86..3be1e14de7 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -956,14 +956,11 @@ void NativeWindowMac::SetAspectRatio(double aspect_ratio, [window_ setResizeIncrements:NSMakeSize(1.0, 1.0)]; } -void NativeWindowMac::PreviewFile(const base::string16& filepath, const base::string16& filename) { - std::string pathStr = base::UTF16ToUTF8(filepath); - std::string nameStr = base::UTF16ToUTF8(filename); - - NSString *path = [NSString stringWithCString:pathStr.c_str() +void NativeWindowMac::PreviewFile(const std::string& filepath, const std::string& filename) { + NSString *path = [NSString stringWithCString:filepath.c_str() encoding:[NSString defaultCStringEncoding]]; - NSString *name = [NSString stringWithCString:nameStr.c_str() + NSString *name = [NSString stringWithCString:filename.c_str() encoding:[NSString defaultCStringEncoding]]; [window_ previewFileAtPath:path withName:name]; From 4d305b06d1c2824e76e1dbebcb3b19b168730b8b Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Wed, 12 Oct 2016 20:46:42 -0700 Subject: [PATCH 103/148] Adding documentation --- docs/api/browser-window.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 345419eed2..56478039e2 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -664,6 +664,11 @@ the player itself we would call this function with arguments of 16/9 and are within the content view--only that they exist. Just sum any extra width and height areas you have within the overall content view. +#### `win.previewFile(pathname, filename)` + +* `pathname` String - The absolute path to the file to preview with QuickLook. This is important as Quicklook uses the file name and file extension on the path to determine the content_type of the file to open. +* `filename` String - The name of the file to display on QuickLook modal view. This is purely visual and does not affect the content_type of the file. + #### `win.setBounds(bounds[, animate])` * `bounds` [Rectangle](structures/rectangle.md) From 002462ce7b4d3f0c49bceb3e94ec3c7a6cfc1dd1 Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Wed, 12 Oct 2016 20:48:40 -0700 Subject: [PATCH 104/148] Removing unused header dependencies --- atom/browser/native_window_mac.mm | 2 -- 1 file changed, 2 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 3be1e14de7..cae346a330 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -11,8 +11,6 @@ #include "atom/common/color_util.h" #include "atom/common/draggable_region.h" #include "atom/common/options_switches.h" -#include "atom/common/native_mate_converters/string16_converter.h" -#include "base/strings/utf_string_conversions.h" #include "base/mac/mac_util.h" #include "base/mac/scoped_cftyperef.h" #include "base/strings/sys_string_conversions.h" From 2f7cceb11cdfaf9bea8d93ce1532ae1a8469f412 Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Wed, 12 Oct 2016 20:49:11 -0700 Subject: [PATCH 105/148] Removing extra line break --- atom/browser/native_window_mac.mm | 1 - 1 file changed, 1 deletion(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index cae346a330..7415ce76e4 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -26,7 +26,6 @@ #include "third_party/skia/include/core/SkRegion.h" #include "ui/gfx/skia_util.h" - namespace { // Prevents window from resizing during the scope. From 18ac4178fee758c90121c8c284688724c9b401fb Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Wed, 12 Oct 2016 21:07:14 -0700 Subject: [PATCH 106/148] Validation with linter --- atom/browser/api/atom_api_window.cc | 3 ++- atom/browser/native_window.cc | 3 ++- atom/browser/native_window.h | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 516d322b3a..aa9c9cca68 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -729,7 +729,8 @@ void Window::SetAspectRatio(double aspect_ratio, mate::Arguments* args) { window_->SetAspectRatio(aspect_ratio, extra_size); } -void Window::PreviewFile(const std::string& filepath, const std::string& filename) { +void Window::PreviewFile(const std::string& filepath, + const std::string& filename) { window_->PreviewFile(filepath, filename); } diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index d01e6fbb21..140dd1e3b6 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -374,7 +374,8 @@ void NativeWindow::SetAspectRatio(double aspect_ratio, aspect_ratio_extraSize_ = extra_size; } -void NativeWindow::PreviewFile(const std::string& filepath, const std::string& filename) { +void NativeWindow::PreviewFile(const std::string& filepath, + const std::string& filename) { } void NativeWindow::RequestToClosePage() { diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index 9c4116a68b..e3b9fe563e 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -176,7 +176,8 @@ class NativeWindow : public base::SupportsUserData, double GetAspectRatio(); gfx::Size GetAspectRatioExtraSize(); virtual void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size); - virtual void PreviewFile(const std::string& filepath, const std::string& filename); + virtual void PreviewFile(const std::string& filepath, + const std::string& filename); base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); From 9736dc31156fc44c2da2264f16af6a8b64470b8b Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Wed, 12 Oct 2016 21:12:50 -0700 Subject: [PATCH 107/148] Specifying macOS only method --- docs/api/browser-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 56478039e2..b031fd47a6 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -664,7 +664,7 @@ the player itself we would call this function with arguments of 16/9 and are within the content view--only that they exist. Just sum any extra width and height areas you have within the overall content view. -#### `win.previewFile(pathname, filename)` +#### `win.previewFile(pathname, filename)` _macOS_ * `pathname` String - The absolute path to the file to preview with QuickLook. This is important as Quicklook uses the file name and file extension on the path to determine the content_type of the file to open. * `filename` String - The name of the file to display on QuickLook modal view. This is purely visual and does not affect the content_type of the file. From b44371f4bf6a30f507ae784d973ef3fa3a556c00 Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Thu, 13 Oct 2016 08:20:47 -0700 Subject: [PATCH 108/148] filename as Optional argument --- atom/browser/api/atom_api_window.cc | 7 +++++-- atom/browser/api/atom_api_window.h | 2 +- docs/api/browser-window.md | 6 ++++-- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index aa9c9cca68..12a987fe7f 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -729,8 +729,11 @@ void Window::SetAspectRatio(double aspect_ratio, mate::Arguments* args) { window_->SetAspectRatio(aspect_ratio, extra_size); } -void Window::PreviewFile(const std::string& filepath, - const std::string& filename) { +void Window::PreviewFile(const std::string& filepath, mate::Arguments* args) { + std::string filename; + if (!args->GetNext(&filename)) { + filename = filepath; + } window_->PreviewFile(filepath, filename); } diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index 966b85cdb5..a340b2c5e1 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -170,7 +170,7 @@ class Window : public mate::TrackableObject, void SetMenuBarVisibility(bool visible); bool IsMenuBarVisible(); void SetAspectRatio(double aspect_ratio, mate::Arguments* args); - void PreviewFile(const std::string& filepath, const std::string& filename); + void PreviewFile(const std::string& filepath, mate::Arguments* args); void SetParentWindow(v8::Local value, mate::Arguments* args); v8::Local GetParentWindow() const; std::vector> GetChildWindows() const; diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index b031fd47a6..fccedae527 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -664,10 +664,12 @@ the player itself we would call this function with arguments of 16/9 and are within the content view--only that they exist. Just sum any extra width and height areas you have within the overall content view. -#### `win.previewFile(pathname, filename)` _macOS_ +#### `win.previewFile(pathname[, filename])` _macOS_ * `pathname` String - The absolute path to the file to preview with QuickLook. This is important as Quicklook uses the file name and file extension on the path to determine the content_type of the file to open. -* `filename` String - The name of the file to display on QuickLook modal view. This is purely visual and does not affect the content_type of the file. +* `filename` String (Optional) - The name of the file to display on the QuickLook modal view. This is purely visual and does not affect the content_type of the file. Defaults to filepath. + +Uses QuickLook to preview a file at a given path. #### `win.setBounds(bounds[, animate])` From e759ce72b55503e4003ceed3e92f2d5f13de5b49 Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Thu, 13 Oct 2016 09:20:55 -0700 Subject: [PATCH 109/148] Using UTF8 String for filepath and filename --- atom/browser/native_window_mac.mm | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 7415ce76e4..1a51f68a93 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -954,11 +954,8 @@ void NativeWindowMac::SetAspectRatio(double aspect_ratio, } void NativeWindowMac::PreviewFile(const std::string& filepath, const std::string& filename) { - NSString *path = [NSString stringWithCString:filepath.c_str() - encoding:[NSString defaultCStringEncoding]]; - - NSString *name = [NSString stringWithCString:filename.c_str() - encoding:[NSString defaultCStringEncoding]]; + NSString *path = [NSString stringWithUTF8String:filepath.c_str()]; + NSString *name = [NSString stringWithUTF8String:filename.c_str()]; [window_ previewFileAtPath:path withName:name]; } From 6bac17fb9a521882b07b0492e42b66529864ea92 Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Thu, 13 Oct 2016 15:01:48 -0700 Subject: [PATCH 110/148] Linter --- atom/browser/api/atom_api_window.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 12a987fe7f..564c5392da 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -733,7 +733,7 @@ void Window::PreviewFile(const std::string& filepath, mate::Arguments* args) { std::string filename; if (!args->GetNext(&filename)) { filename = filepath; - } + } window_->PreviewFile(filepath, filename); } From 9b19e6ee3895a6aa7b805d4b5f1cd8b733f092ac Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Fri, 14 Oct 2016 09:42:50 -0700 Subject: [PATCH 111/148] Changing names and memory leak fix --- atom/browser/api/atom_api_window.cc | 10 +++++----- atom/browser/api/atom_api_window.h | 2 +- atom/browser/native_window.cc | 4 ++-- atom/browser/native_window.h | 4 ++-- atom/browser/native_window_mac.h | 2 +- atom/browser/native_window_mac.mm | 14 +++++++------- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index 564c5392da..a0391985d7 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -729,12 +729,12 @@ void Window::SetAspectRatio(double aspect_ratio, mate::Arguments* args) { window_->SetAspectRatio(aspect_ratio, extra_size); } -void Window::PreviewFile(const std::string& filepath, mate::Arguments* args) { - std::string filename; - if (!args->GetNext(&filename)) { - filename = filepath; +void Window::PreviewFile(const std::string& path, mate::Arguments* args) { + std::string fileName; + if (!args->GetNext(&fileName)) { + fileName = path; } - window_->PreviewFile(filepath, filename); + window_->PreviewFile(path, fileName); } void Window::SetParentWindow(v8::Local value, diff --git a/atom/browser/api/atom_api_window.h b/atom/browser/api/atom_api_window.h index a340b2c5e1..ba1a999b2b 100644 --- a/atom/browser/api/atom_api_window.h +++ b/atom/browser/api/atom_api_window.h @@ -170,7 +170,7 @@ class Window : public mate::TrackableObject, void SetMenuBarVisibility(bool visible); bool IsMenuBarVisible(); void SetAspectRatio(double aspect_ratio, mate::Arguments* args); - void PreviewFile(const std::string& filepath, mate::Arguments* args); + void PreviewFile(const std::string& path, mate::Arguments* args); void SetParentWindow(v8::Local value, mate::Arguments* args); v8::Local GetParentWindow() const; std::vector> GetChildWindows() const; diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 140dd1e3b6..9d56615e6b 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -374,8 +374,8 @@ void NativeWindow::SetAspectRatio(double aspect_ratio, aspect_ratio_extraSize_ = extra_size; } -void NativeWindow::PreviewFile(const std::string& filepath, - const std::string& filename) { +void NativeWindow::PreviewFile(const std::string& path, + const std::string& fileName) { } void NativeWindow::RequestToClosePage() { diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index e3b9fe563e..e3d1558cfa 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -176,8 +176,8 @@ class NativeWindow : public base::SupportsUserData, double GetAspectRatio(); gfx::Size GetAspectRatioExtraSize(); virtual void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size); - virtual void PreviewFile(const std::string& filepath, - const std::string& filename); + virtual void PreviewFile(const std::string& path, + const std::string& fileName); base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 9fc2627a0c..1a6d2d382c 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -55,7 +55,7 @@ class NativeWindowMac : public NativeWindow, void SetMovable(bool movable) override; void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size) override; - void PreviewFile(const std::string& filepath, const std::string& filename) + void PreviewFile(const std::string& path, const std::string& fileName) override; bool IsMovable() override; void SetMinimizable(bool minimizable) override; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 1a51f68a93..52e2111da3 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -492,9 +492,9 @@ bool ScopedDisableResize::disable_resize_ = false; return [self quickLookItem]; } -- (void)previewFileAtPath:(NSString *)filepath withName:(NSString *) name { - NSURL * url = [[NSURL alloc] initFileURLWithPath:filepath]; - [self setQuickLookItem:[[AtomPreviewItem alloc] initWithURL:url title:name]]; +- (void)previewFileAtPath:(NSString *)path withName:(NSString *) fileName { + NSURL * url = [[[NSURL alloc] initFileURLWithPath:path] autorelease]; + [self setQuickLookItem:[[[AtomPreviewItem alloc] initWithURL:url title:fileName] autorelease]]; [[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil]; } @@ -953,11 +953,11 @@ void NativeWindowMac::SetAspectRatio(double aspect_ratio, [window_ setResizeIncrements:NSMakeSize(1.0, 1.0)]; } -void NativeWindowMac::PreviewFile(const std::string& filepath, const std::string& filename) { - NSString *path = [NSString stringWithUTF8String:filepath.c_str()]; - NSString *name = [NSString stringWithUTF8String:filename.c_str()]; +void NativeWindowMac::PreviewFile(const std::string& path, const std::string& fileName) { + NSString *pathStr = [NSString stringWithUTF8String:path.c_str()]; + NSString *nameStr = [NSString stringWithUTF8String:fileName.c_str()]; - [window_ previewFileAtPath:path withName:name]; + [window_ previewFileAtPath:pathStr withName:nameStr]; } void NativeWindowMac::SetMovable(bool movable) { From 1f60aff73d765e82c5f27c37b27df321f063c3d3 Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Mon, 24 Oct 2016 11:49:30 -0700 Subject: [PATCH 112/148] linter --- atom/browser/native_window_mac.mm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 52e2111da3..0981aa5cdb 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -280,16 +280,16 @@ bool ScopedDisableResize::disable_resize_ = false; @interface AtomPreviewItem : NSObject -@property (nonatomic, retain) NSURL *previewItemURL; -@property (nonatomic, retain) NSString *previewItemTitle; +@property (nonatomic, retain) NSURL* previewItemURL; +@property (nonatomic, retain) NSString* previewItemTitle; -- (id)initWithURL:(NSURL *)anURL title:(NSString *)aTitle; +- (id)initWithURL:(NSURL*)url title:(NSString*)title; @end @implementation AtomPreviewItem -- (id)initWithURL:(NSURL *)url title:(NSString *)title { +- (id)initWithURL:(NSURL*)url title:(NSString*)title { self = [super init]; if (self) { self.previewItemURL = url; From cf5fc3f92225abe397cfe527e552c11383231824 Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Mon, 24 Oct 2016 11:54:22 -0700 Subject: [PATCH 113/148] more linter --- atom/browser/native_window_mac.mm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 0981aa5cdb..d20618b96a 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -470,21 +470,21 @@ bool ScopedDisableResize::disable_resize_ = false; // Quicklook methods -- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel *)panel { +- (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel*)panel { return YES; } -- (void)beginPreviewPanelControl:(QLPreviewPanel *)panel { +- (void)beginPreviewPanelControl:(QLPreviewPanel*)panel { panel.delegate = self; panel.dataSource = self; } -- (void)endPreviewPanelControl:(QLPreviewPanel *)panel { +- (void)endPreviewPanelControl:(QLPreviewPanel*)panel { panel.delegate = nil; panel.dataSource = nil; } -- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel *)panel { +- (NSInteger)numberOfPreviewItemsInPreviewPanel:(QLPreviewPanel*)panel { return 1; } From 0ec57cca325b6a59f6460a53d2bb52356b5c3760 Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Mon, 24 Oct 2016 11:55:48 -0700 Subject: [PATCH 114/148] last linter commit --- atom/browser/native_window_mac.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index d20618b96a..89378f2307 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -488,11 +488,11 @@ bool ScopedDisableResize::disable_resize_ = false; return 1; } -- (id )previewPanel:(QLPreviewPanel *)panel previewItemAtIndex:(NSInteger)index { +- (id )previewPanel:(QLPreviewPanel*)panel previewItemAtIndex:(NSInteger)index { return [self quickLookItem]; } -- (void)previewFileAtPath:(NSString *)path withName:(NSString *) fileName { +- (void)previewFileAtPath:(NSString*)path withName:(NSString*) fileName { NSURL * url = [[[NSURL alloc] initFileURLWithPath:path] autorelease]; [self setQuickLookItem:[[[AtomPreviewItem alloc] initWithURL:url title:fileName] autorelease]]; [[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil]; From d26601f695a9f7d65a0f56712b6836e25c91f166 Mon Sep 17 00:00:00 2001 From: Pierre Laurac Date: Tue, 25 Oct 2016 07:52:56 -0700 Subject: [PATCH 115/148] Convention naming --- atom/browser/native_window_mac.mm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 89378f2307..98fc2c8695 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -493,7 +493,7 @@ bool ScopedDisableResize::disable_resize_ = false; } - (void)previewFileAtPath:(NSString*)path withName:(NSString*) fileName { - NSURL * url = [[[NSURL alloc] initFileURLWithPath:path] autorelease]; + NSURL* url = [[[NSURL alloc] initFileURLWithPath:path] autorelease]; [self setQuickLookItem:[[[AtomPreviewItem alloc] initWithURL:url title:fileName] autorelease]]; [[QLPreviewPanel sharedPreviewPanel] makeKeyAndOrderFront:nil]; } @@ -954,8 +954,8 @@ void NativeWindowMac::SetAspectRatio(double aspect_ratio, } void NativeWindowMac::PreviewFile(const std::string& path, const std::string& fileName) { - NSString *pathStr = [NSString stringWithUTF8String:path.c_str()]; - NSString *nameStr = [NSString stringWithUTF8String:fileName.c_str()]; + NSString* pathStr = [NSString stringWithUTF8String:path.c_str()]; + NSString* nameStr = [NSString stringWithUTF8String:fileName.c_str()]; [window_ previewFileAtPath:pathStr withName:nameStr]; } From d982376fc4a1a98f01ad3665ade218f947bc66a6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 26 Oct 2016 09:47:22 +0900 Subject: [PATCH 116/148] filename -> displayName --- atom/browser/api/atom_api_window.cc | 8 ++++---- atom/browser/native_window.cc | 2 +- atom/browser/native_window.h | 2 +- atom/browser/native_window_mac.h | 2 +- atom/browser/native_window_mac.mm | 14 +++++++------- docs/api/browser-window.md | 13 +++++++++---- 6 files changed, 23 insertions(+), 18 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index a0391985d7..ae37f504ca 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -730,11 +730,11 @@ void Window::SetAspectRatio(double aspect_ratio, mate::Arguments* args) { } void Window::PreviewFile(const std::string& path, mate::Arguments* args) { - std::string fileName; - if (!args->GetNext(&fileName)) { - fileName = path; + std::string display_name; + if (!args->GetNext(&display_name)) { + display_name = path; } - window_->PreviewFile(path, fileName); + window_->PreviewFile(path, display_name); } void Window::SetParentWindow(v8::Local value, diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 9d56615e6b..6c32e79e19 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -375,7 +375,7 @@ void NativeWindow::SetAspectRatio(double aspect_ratio, } void NativeWindow::PreviewFile(const std::string& path, - const std::string& fileName) { + const std::string& display_name) { } void NativeWindow::RequestToClosePage() { diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index e3d1558cfa..3d190ba7d9 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -177,7 +177,7 @@ class NativeWindow : public base::SupportsUserData, gfx::Size GetAspectRatioExtraSize(); virtual void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size); virtual void PreviewFile(const std::string& path, - const std::string& fileName); + const std::string& display_name); base::WeakPtr GetWeakPtr() { return weak_factory_.GetWeakPtr(); diff --git a/atom/browser/native_window_mac.h b/atom/browser/native_window_mac.h index 1a6d2d382c..979d69d1a2 100644 --- a/atom/browser/native_window_mac.h +++ b/atom/browser/native_window_mac.h @@ -55,7 +55,7 @@ class NativeWindowMac : public NativeWindow, void SetMovable(bool movable) override; void SetAspectRatio(double aspect_ratio, const gfx::Size& extra_size) override; - void PreviewFile(const std::string& path, const std::string& fileName) + void PreviewFile(const std::string& path, const std::string& display_name) override; bool IsMovable() override; void SetMinimizable(bool minimizable) override; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 98fc2c8695..d9de9bd3ca 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -290,11 +290,11 @@ bool ScopedDisableResize::disable_resize_ = false; @implementation AtomPreviewItem - (id)initWithURL:(NSURL*)url title:(NSString*)title { - self = [super init]; + self = [super init]; if (self) { self.previewItemURL = url; self.previewItemTitle = title; - } + } return self; } @@ -953,11 +953,11 @@ void NativeWindowMac::SetAspectRatio(double aspect_ratio, [window_ setResizeIncrements:NSMakeSize(1.0, 1.0)]; } -void NativeWindowMac::PreviewFile(const std::string& path, const std::string& fileName) { - NSString* pathStr = [NSString stringWithUTF8String:path.c_str()]; - NSString* nameStr = [NSString stringWithUTF8String:fileName.c_str()]; - - [window_ previewFileAtPath:pathStr withName:nameStr]; +void NativeWindowMac::PreviewFile(const std::string& path, + const std::string& display_name) { + NSString* path_ns = [NSString stringWithUTF8String:path.c_str()]; + NSString* name_ns = [NSString stringWithUTF8String:display_name.c_str()]; + [window_ previewFileAtPath:path_ns withName:name_ns]; } void NativeWindowMac::SetMovable(bool movable) { diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index fccedae527..b891396dba 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -664,12 +664,16 @@ the player itself we would call this function with arguments of 16/9 and are within the content view--only that they exist. Just sum any extra width and height areas you have within the overall content view. -#### `win.previewFile(pathname[, filename])` _macOS_ +#### `win.previewFile(pathname[, displayName])` _macOS_ -* `pathname` String - The absolute path to the file to preview with QuickLook. This is important as Quicklook uses the file name and file extension on the path to determine the content_type of the file to open. -* `filename` String (Optional) - The name of the file to display on the QuickLook modal view. This is purely visual and does not affect the content_type of the file. Defaults to filepath. +* `path` String - The absolute path to the file to preview with QuickLook. This + is important as Quick Look uses the file name and file extension on the path to + determine the content type of the file to open. +* `displayName` String (Optional) - The name of the file to display on the + Quick Look modal view. This is purely visual and does not affect the content + type of the file. Defaults to `path`. -Uses QuickLook to preview a file at a given path. +Uses [Quick Look][quick-look] to preview a file at a given path. #### `win.setBounds(bounds[, animate])` @@ -1189,3 +1193,4 @@ Returns `BrowserWindow` - The parent window. Returns `BrowserWindow[]` - All child windows. [window-levels]: https://developer.apple.com/reference/appkit/nswindow/1664726-window_levels +[quick-look]: https://en.wikipedia.org/wiki/Quick_Look From d85c4da11b7e577a0b96bfef1e576962044c3daa Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 26 Oct 2016 09:55:34 +0900 Subject: [PATCH 117/148] Minor formatting tweaks --- atom/browser/api/atom_api_window.cc | 3 +-- atom/browser/native_window_mac.mm | 2 +- docs/api/browser-window.md | 6 +++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/atom/browser/api/atom_api_window.cc b/atom/browser/api/atom_api_window.cc index ae37f504ca..88b0459c26 100644 --- a/atom/browser/api/atom_api_window.cc +++ b/atom/browser/api/atom_api_window.cc @@ -731,9 +731,8 @@ void Window::SetAspectRatio(double aspect_ratio, mate::Arguments* args) { void Window::PreviewFile(const std::string& path, mate::Arguments* args) { std::string display_name; - if (!args->GetNext(&display_name)) { + if (!args->GetNext(&display_name)) display_name = path; - } window_->PreviewFile(path, display_name); } diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index d9de9bd3ca..95423e0851 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -4,8 +4,8 @@ #include "atom/browser/native_window_mac.h" -#include #include +#include #include "atom/browser/window_list.h" #include "atom/common/color_util.h" diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index b891396dba..059c9f152d 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -664,11 +664,11 @@ the player itself we would call this function with arguments of 16/9 and are within the content view--only that they exist. Just sum any extra width and height areas you have within the overall content view. -#### `win.previewFile(pathname[, displayName])` _macOS_ +#### `win.previewFile(path[, displayName])` _macOS_ * `path` String - The absolute path to the file to preview with QuickLook. This - is important as Quick Look uses the file name and file extension on the path to - determine the content type of the file to open. + is important as Quick Look uses the file name and file extension on the path + to determine the content type of the file to open. * `displayName` String (Optional) - The name of the file to display on the Quick Look modal view. This is purely visual and does not affect the content type of the file. Defaults to `path`. From 7078ed80fa16c8f6c10ae0ce02402b4d7eb167f1 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Wed, 26 Oct 2016 12:52:40 +1100 Subject: [PATCH 118/148] Move `webPreferences` and `titleBarStyle` to the correct place in the docs In their previous location `electron-docs-linter` would not output an Object structure for `webPreferences` (which is a key part of the constructor) --- docs/api/browser-window.md | 158 ++++++++++++++++++------------------- 1 file changed, 75 insertions(+), 83 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 059c9f152d..307d55f9f2 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -185,13 +185,84 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. Default is `false`. * `type` String - The type of window, default is normal window. See more about this below. - * `titleBarStyle` String - The style of window title bar. See more about this - below. + * `titleBarStyle` String - The style of window title bar. Possible values are: + * `default` or not specified, results in the standard gray opaque Mac title + bar. + * `hidden` results in a hidden title bar and a full size content window, yet + the title bar still has the standard window controls ("traffic lights") in + the top left. + * `hidden-inset` results in a hidden title bar with an alternative look + where the traffic light buttons are slightly more inset from the window edge. * `thickFrame` Boolean - Use `WS_THICKFRAME` style for frameless windows on Windows, which adds standard window frame. Setting it to `false` will remove window shadow and window animations. Default is `true`. - * `webPreferences` Object - Settings of web page's features. See more about - this below. + * `webPreferences` Object - Settings of web page's features. + * `devTools` Boolean - Whether to enable DevTools. If it is set to `false`, can not use `BrowserWindow.webContents.openDevTools()` to open DevTools. Default is `true`. + * `nodeIntegration` Boolean - Whether node integration is enabled. Default + is `true`. + * `preload` String - Specifies a script that will be loaded before other + scripts run in the page. This script will always have access to node APIs + no matter whether node integration is turned on or off. The value should + be the absolute file path to the script. + When node integration is turned off, the preload script can reintroduce + Node global symbols back to the global scope. See example + [here](process.md#event-loaded). + * `session` [Session](session.md#class-session) - Sets the session used by the + page. Instead of passing the Session object directly, you can also choose to + use the `partition` option instead, which accepts a partition string. When + both `session` and `partition` are provided, `session` will be preferred. + Default is the default session. + * `partition` String - Sets the session used by the page according to the + session's partition string. If `partition` starts with `persist:`, the page + will use a persistent session available to all pages in the app with the + same `partition`. If there is no `persist:` prefix, the page will use an + in-memory session. By assigning the same `partition`, multiple pages can share + the same session. Default is the default session. + * `zoomFactor` Number - The default zoom factor of the page, `3.0` represents + `300%`. Default is `1.0`. + * `javascript` Boolean - Enables JavaScript support. Default is `true`. + * `webSecurity` Boolean - When `false`, it will disable the + same-origin policy (usually using testing websites by people), and set + `allowDisplayingInsecureContent` and `allowRunningInsecureContent` to + `true` if these two options are not set by user. Default is `true`. + * `allowDisplayingInsecureContent` Boolean - Allow an https page to display + content like images from http URLs. Default is `false`. + * `allowRunningInsecureContent` Boolean - Allow an https page to run + JavaScript, CSS or plugins from http URLs. Default is `false`. + * `images` Boolean - Enables image support. Default is `true`. + * `textAreasAreResizable` Boolean - Make TextArea elements resizable. Default + is `true`. + * `webgl` Boolean - Enables WebGL support. Default is `true`. + * `webaudio` Boolean - Enables WebAudio support. Default is `true`. + * `plugins` Boolean - Whether plugins should be enabled. Default is `false`. + * `experimentalFeatures` Boolean - Enables Chromium's experimental features. + Default is `false`. + * `experimentalCanvasFeatures` Boolean - Enables Chromium's experimental + canvas features. Default is `false`. + * `scrollBounce` Boolean - Enables scroll bounce (rubber banding) effect on + macOS. Default is `false`. + * `blinkFeatures` String - A list of feature strings separated by `,`, like + `CSSVariables,KeyboardEventKey` to enable. The full list of supported feature + strings can be found in the [RuntimeEnabledFeatures.in][blink-feature-string] + file. + * `disableBlinkFeatures` String - A list of feature strings separated by `,`, + like `CSSVariables,KeyboardEventKey` to disable. The full list of supported + feature strings can be found in the + [RuntimeEnabledFeatures.in][blink-feature-string] file. + * `defaultFontFamily` Object - Sets the default font for the font-family. + * `standard` String - Defaults to `Times New Roman`. + * `serif` String - Defaults to `Times New Roman`. + * `sansSerif` String - Defaults to `Arial`. + * `monospace` String - Defaults to `Courier New`. + * `defaultFontSize` Integer - Defaults to `16`. + * `defaultMonospaceFontSize` Integer - Defaults to `13`. + * `minimumFontSize` Integer - Defaults to `0`. + * `defaultEncoding` String - Defaults to `ISO-8859-1`. + * `backgroundThrottling` Boolean - Whether to throttle animations and timers + when the page becomes background. Defaults to `true`. + * `offscreen` Boolean - Whether to enable offscreen rendering for the browser + window. Defaults to `false`. + * `sandbox` Boolean - Whether to enable Chromium OS-level sandbox. When setting minimum or maximum window size with `minWidth`/`maxWidth`/ `minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from @@ -212,85 +283,6 @@ Possible values are: input sparingly. * On Windows, possible type is `toolbar`. -Possible values of the `titleBarStyle` option are: - -* `default` or not specified, results in the standard gray opaque Mac title - bar. -* `hidden` results in a hidden title bar and a full size content window, yet - the title bar still has the standard window controls ("traffic lights") in - the top left. -* `hidden-inset` results in a hidden title bar with an alternative look - where the traffic light buttons are slightly more inset from the window edge. - -The `webPreferences` option is an object that can have the following properties: - -* `devTools` Boolean - Whether to enable DevTools. If it is set to `false`, can not use `BrowserWindow.webContents.openDevTools()` to open DevTools. Default is `true`. -* `nodeIntegration` Boolean - Whether node integration is enabled. Default - is `true`. -* `preload` String - Specifies a script that will be loaded before other - scripts run in the page. This script will always have access to node APIs - no matter whether node integration is turned on or off. The value should - be the absolute file path to the script. - When node integration is turned off, the preload script can reintroduce - Node global symbols back to the global scope. See example - [here](process.md#event-loaded). -* `session` [Session](session.md#class-session) - Sets the session used by the - page. Instead of passing the Session object directly, you can also choose to - use the `partition` option instead, which accepts a partition string. When - both `session` and `partition` are provided, `session` will be preferred. - Default is the default session. -* `partition` String - Sets the session used by the page according to the - session's partition string. If `partition` starts with `persist:`, the page - will use a persistent session available to all pages in the app with the - same `partition`. If there is no `persist:` prefix, the page will use an - in-memory session. By assigning the same `partition`, multiple pages can share - the same session. Default is the default session. -* `zoomFactor` Number - The default zoom factor of the page, `3.0` represents - `300%`. Default is `1.0`. -* `javascript` Boolean - Enables JavaScript support. Default is `true`. -* `webSecurity` Boolean - When `false`, it will disable the - same-origin policy (usually using testing websites by people), and set - `allowDisplayingInsecureContent` and `allowRunningInsecureContent` to - `true` if these two options are not set by user. Default is `true`. -* `allowDisplayingInsecureContent` Boolean - Allow an https page to display - content like images from http URLs. Default is `false`. -* `allowRunningInsecureContent` Boolean - Allow an https page to run - JavaScript, CSS or plugins from http URLs. Default is `false`. -* `images` Boolean - Enables image support. Default is `true`. -* `textAreasAreResizable` Boolean - Make TextArea elements resizable. Default - is `true`. -* `webgl` Boolean - Enables WebGL support. Default is `true`. -* `webaudio` Boolean - Enables WebAudio support. Default is `true`. -* `plugins` Boolean - Whether plugins should be enabled. Default is `false`. -* `experimentalFeatures` Boolean - Enables Chromium's experimental features. - Default is `false`. -* `experimentalCanvasFeatures` Boolean - Enables Chromium's experimental - canvas features. Default is `false`. -* `scrollBounce` Boolean - Enables scroll bounce (rubber banding) effect on - macOS. Default is `false`. -* `blinkFeatures` String - A list of feature strings separated by `,`, like - `CSSVariables,KeyboardEventKey` to enable. The full list of supported feature - strings can be found in the [RuntimeEnabledFeatures.in][blink-feature-string] - file. -* `disableBlinkFeatures` String - A list of feature strings separated by `,`, - like `CSSVariables,KeyboardEventKey` to disable. The full list of supported - feature strings can be found in the - [RuntimeEnabledFeatures.in][blink-feature-string] file. -* `defaultFontFamily` Object - Sets the default font for the font-family. - * `standard` String - Defaults to `Times New Roman`. - * `serif` String - Defaults to `Times New Roman`. - * `sansSerif` String - Defaults to `Arial`. - * `monospace` String - Defaults to `Courier New`. -* `defaultFontSize` Integer - Defaults to `16`. -* `defaultMonospaceFontSize` Integer - Defaults to `13`. -* `minimumFontSize` Integer - Defaults to `0`. -* `defaultEncoding` String - Defaults to `ISO-8859-1`. -* `backgroundThrottling` Boolean - Whether to throttle animations and timers - when the page becomes background. Defaults to `true`. -* `offscreen` Boolean - Whether to enable offscreen rendering for the browser - window. Defaults to `false`. -* `sandbox` Boolean - Whether to enable Chromium OS-level sandbox. - ### Instance Events Objects created with `new BrowserWindow` emit the following events: From 76da80c5e9061071b765b6844fcd1d5b6a544433 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Wed, 26 Oct 2016 16:18:55 +1100 Subject: [PATCH 119/148] Further clean up --- docs/api/web-contents.md | 46 +++++++++++++++++----------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index b9a00756ae..74b54da4bf 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -399,31 +399,25 @@ Returns: Can be `none`, `mouse`, `keyboard`, `touch`, `touchMenu`. * `mediaFlags` Object - The flags for the media element the context menu was invoked on. See more about this below. + * `inError` Boolean - Whether the media element has crashed. + * `isPaused` Boolean - Whether the media element is paused. + * `isMuted` Boolean - Whether the media element is muted. + * `hasAudio` Boolean - Whether the media element has audio. + * `isLooping` Boolean - Whether the media element is looping. + * `isControlsVisible` Boolean - Whether the media element's controls are + visible. + * `canToggleControls` Boolean - Whether the media element's controls are + toggleable. + * `canRotate` Boolean - Whether the media element can be rotated. * `editFlags` Object - These flags indicate whether the renderer believes it is able to perform the corresponding action. See more about this below. - -The `mediaFlags` is an object with the following properties: - -* `inError` Boolean - Whether the media element has crashed. -* `isPaused` Boolean - Whether the media element is paused. -* `isMuted` Boolean - Whether the media element is muted. -* `hasAudio` Boolean - Whether the media element has audio. -* `isLooping` Boolean - Whether the media element is looping. -* `isControlsVisible` Boolean - Whether the media element's controls are - visible. -* `canToggleControls` Boolean - Whether the media element's controls are - toggleable. -* `canRotate` Boolean - Whether the media element can be rotated. - -The `editFlags` is an object with the following properties: - -* `canUndo` Boolean - Whether the renderer believes it can undo. -* `canRedo` Boolean - Whether the renderer believes it can redo. -* `canCut` Boolean - Whether the renderer believes it can cut. -* `canCopy` Boolean - Whether the renderer believes it can copy -* `canPaste` Boolean - Whether the renderer believes it can paste. -* `canDelete` Boolean - Whether the renderer believes it can delete. -* `canSelectAll` Boolean - Whether the renderer believes it can select all. + * `canUndo` Boolean - Whether the renderer believes it can undo. + * `canRedo` Boolean - Whether the renderer believes it can redo. + * `canCut` Boolean - Whether the renderer believes it can cut. + * `canCopy` Boolean - Whether the renderer believes it can copy + * `canPaste` Boolean - Whether the renderer believes it can paste. + * `canDelete` Boolean - Whether the renderer believes it can delete. + * `canSelectAll` Boolean - Whether the renderer believes it can select all. Emitted when there is a new context menu that needs to be handled. @@ -982,8 +976,8 @@ app.on('ready', () => { * `parameters` Object * `screenPosition` String - Specify the screen type to emulate (default: `desktop`) - * `desktop` String - Desktop screen type - * `mobile` String - Mobile screen type + * `desktop` - Desktop screen type + * `mobile` - Mobile screen type * `screenSize` Object - Set the emulated screen size (screenPosition == mobile) * `width` Integer - Set the emulated screen width * `height` Integer - Set the emulated screen height @@ -1229,7 +1223,7 @@ Detaches the debugger from the `webContents`. * `commandParams` Object (optional) - JSON object with request parameters. * `callback` Function (optional) - Response * `error` Object - Error message indicating the failure of the command. - * `result` Object - Response defined by the 'returns' attribute of + * `result` Any - Response defined by the 'returns' attribute of the command description in the remote debugging protocol. Send given command to the debugging target. From 02a709452930c64910e472add125198ed18e3318 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Wed, 26 Oct 2016 16:19:41 +1100 Subject: [PATCH 120/148] Follow docs style guide for string ENUMS --- docs/api/browser-window.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 307d55f9f2..f04434ece4 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -185,13 +185,13 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. Default is `false`. * `type` String - The type of window, default is normal window. See more about this below. - * `titleBarStyle` String - The style of window title bar. Possible values are: - * `default` or not specified, results in the standard gray opaque Mac title + * `titleBarStyle` String - The style of window title bar. Default is `default`. Possible values are: + * `default` - Results in the standard gray opaque Mac title bar. - * `hidden` results in a hidden title bar and a full size content window, yet + * `hidden` - Results in a hidden title bar and a full size content window, yet the title bar still has the standard window controls ("traffic lights") in the top left. - * `hidden-inset` results in a hidden title bar with an alternative look + * `hidden-inset` - Results in a hidden title bar with an alternative look where the traffic light buttons are slightly more inset from the window edge. * `thickFrame` Boolean - Use `WS_THICKFRAME` style for frameless windows on Windows, which adds standard window frame. Setting it to `false` will remove From 9356843e27672230bbf311c9a336c88d27cd5b56 Mon Sep 17 00:00:00 2001 From: doraeric Date: Wed, 26 Oct 2016 14:09:36 +0800 Subject: [PATCH 121/148] add zh-tw docs --- README.md | 2 +- .../zh-TW/project/CODE_OF_CONDUCT.md | 46 +++++++++++ .../zh-TW/project/CONTRIBUTING.md | 74 ++++++++++++++++++ docs-translations/zh-TW/project/README.md | 77 +++++++++++++++++++ 4 files changed, 198 insertions(+), 1 deletion(-) create mode 100644 docs-translations/zh-TW/project/CODE_OF_CONDUCT.md create mode 100644 docs-translations/zh-TW/project/CONTRIBUTING.md create mode 100644 docs-translations/zh-TW/project/README.md diff --git a/README.md b/README.md index dd0b209eb5..67a47854eb 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ [![devDependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron?type=dev) [![Join the Electron Community on Slack](http://atom-slack.herokuapp.com/badge.svg)](http://atom-slack.herokuapp.com/) -:memo: Available Translations: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/README.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/README.md) | [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/README.md) +:memo: Available Translations: [Korean](https://github.com/electron/electron/tree/master/docs-translations/ko-KR/project/README.md) | [Simplified Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-CN/project/README.md) | [Brazilian Portuguese](https://github.com/electron/electron/tree/master/docs-translations/pt-BR/project/README.md) | [Traditional Chinese](https://github.com/electron/electron/tree/master/docs-translations/zh-TW/project/README.md) The Electron framework lets you write cross-platform desktop applications using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/) and diff --git a/docs-translations/zh-TW/project/CODE_OF_CONDUCT.md b/docs-translations/zh-TW/project/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..6eae666ab4 --- /dev/null +++ b/docs-translations/zh-TW/project/CODE_OF_CONDUCT.md @@ -0,0 +1,46 @@ +# ่ฒข็ป่€…่กŒ็‚บๅฎˆๅ‰‡ๅฅ‘็ด„ + +## ๆˆ‘ๅ€‘็š„ๆ‰ฟ่ซพ + +็‚บไบ†็‡Ÿ้€ ไธ€ๅ€‹้–‹ๆ”พๅ’Œๆบซ้ฆจ็š„็’ฐๅขƒ๏ผŒๆˆ‘ๅ€‘ไฝœ็‚บ่ฒข็ป่€…ๅ’Œ็ถญ่ญท่€…๏ผŒๆ‰ฟ่ซพๅฐๆฏๅ€‹ๅƒ่ˆ‡ๆˆ‘ๅ€‘็š„้ …็›ฎๅ’Œ็คพๅ€็š„ไบบ๏ผŒๆไพ›ไธๅ—้จทๆ“พ็š„็’ฐๅขƒ๏ผŒ็„ก่ซ–ๅนด้ฝกใ€่บซ้ซ”ๅคงๅฐใ€ๆฎ˜็–พใ€่‡ชๆˆ‘่ชๅŒ็จฎๆ—ใ€ๆ€งๅˆฅ่ชๅŒๅ’Œ่กจ้”ใ€็ถ“้ฉ—ๆฐดๆบ–ใ€ๅœ‹็ฑ๏ผŒๅ€‹ไบบๅค–่ฒŒ๏ผŒๅคฉ็”Ÿ็จฎๆ—๏ผŒๅฎ—ๆ•™ๆˆ–็”Ÿ็†ๆ€งๅˆฅๅ’Œๆ€งๅ–ๅ‘ใ€‚ + +## ๆˆ‘ๅ€‘็š„ๆจ™ๆบ– + +ๆœ‰ๅŠฉๆ–ผๅ‰ต้€ ็ฉๆฅต็’ฐๅขƒ็š„่กŒ็‚บๅŒ…ๆ‹ฌ: + +* ไฝฟ็”จๆญก่ฟŽๅ’ŒๅŒ…ๅฎนๆ€ง็š„่ชž่จ€ +* ๅฐŠ้‡ไธๅŒ็š„่ง€้ปžๅ’Œ็ถ“้ฉ— +* ๅ„ช้›…ๅœฐๆŽฅๅ—ๅปบ่จญๆ€ง็š„ๆ‰น่ฉ• +* ๅฐˆไฝๅœจ็‚บ็คพ็พคๆœ€ๅฅฝ็š„ไบ‹ๆƒ…ไธŠ +* ้กฏ็คบๅฐๅ…ถไป–็คพๅ€ๆˆๅ“ก็š„ๅŒๆƒ… + +ๅƒ่ˆ‡่€…ไธ่ขซ่จฑๅฏ็š„่กŒ็‚บไพ‹ๅญๅŒ…ๆ‹ฌ: + +* ไฝฟ็”จๆ€งๅˆฅๅŒ–่ชž่จ€ๆˆ–ๅœ–ๅƒไปฅๅŠไธๆญก่ฟŽ็š„ๆ€งๅˆฅ้—œๆณจๆˆ–ๅ…ถไป–ๆ›ด้€ฒไธ€ๆญฅ็š„่กŒ็‚บ +* ๆฏ€่ฌ—ใ€ไพฎ่พฑใ€่ฒถๆ็š„่ฉ•่ซ–ไปฅๅŠๅ€‹ไบบๆˆ–ๆ”ฟๆฒปๆ”ปๆ“Š +* ๅ…ฌๅ…ฑๆˆ–็งไบบ้จทๆ“พ +* ๆœช็ถ“ๆ˜Ž็ขบ่จฑๅฏ๏ผŒ็™ผๅธƒไป–ไบบ็š„ๅ€‹่ณ‡๏ผŒๅฆ‚ไฝๅ€ๆˆ–้›ปๅญไฟก็ฎฑ +* ๅ…ถไป–ๅฏไปฅๅˆ็†ๅœฐ่ช็‚บๅœจๅฐˆๆฅญ็’ฐๅขƒไธญไธๅˆ้ฉ็š„่กŒ็‚บ + +## ๆˆ‘ๅ€‘็š„่ฒฌไปป + +ๅฐˆๆกˆ็ถญ่ญท่€…่ฒ ่ฒฌๆพ„ๆธ…ๅฏๆŽฅๅ—็š„่กŒ็‚บๆจ™ๆบ–๏ผŒไธฆไธ”ๆ‡‰่ฉฒๅฐไปปไฝ•ไธๅฏๆŽฅๅ—็š„่กŒ็‚บๆŽกๅ–้ฉ็•ถไธ”ๅ…ฌๅนณ็š„็ณพๆญฃๆŽชๆ–ฝใ€‚ + +ๅฐˆๆกˆ็ถญ่ญท่€…ๆœ‰ๆฌŠๅˆฉๅ’Œ่ฒฌไปปๅˆช้™คใ€็ทจ่ผฏๆˆ–ๆ‹’็ต•่ˆ‡ๆœฌ่กŒ็‚บๆบ–ๅ‰‡ไธไธ€่‡ด็š„่ฉ•่ซ–ใ€ๆไบคใ€ไปฃ็ขผ๏ผŒ็ถญๅŸบ็ทจ่ผฏ๏ผŒๅ•้กŒๅ’Œๅ…ถไป–ไธๅœจๆญคๅˆ—็š„่ฒข็ปใ€‚็”š่‡ณๆšซๆ™‚ๆˆ–ๆฐธไน…็ฆๆญขไปปไฝ•่ขซ่ช็‚บๆ˜ฏไธ็•ถใ€ๅจ่„…ใ€ๆ”ปๆ“Šๆ€งๆˆ–ๆœ‰ๅฎณ็š„ๅƒ่ˆ‡่€…ใ€‚ + +## ็ฏ„ๅœ + +็•ถๅ€‹ไบบไปฃ่กจๅฐˆๆกˆๆˆ–ๅ…ถ็คพ็พคๆ™‚๏ผŒๆœฌ่กŒ็‚บๆบ–ๅ‰‡้ฉ็”จๆ–ผๅฐˆๆกˆ็ฏ„ๅœๆˆ–ๅ…ฌๅ…ฑ็ฉบ้–“ใ€‚ไปฃ่กจๅฐˆๆกˆๆˆ–็คพ็พค็š„ไพ‹ๅญๅŒ…ๆ‹ฌไฝฟ็”จๅฎ˜ๆ–น้›ปๅญ้ƒตไปถใ€้€้Žๅฎ˜ๆ–น็คพ็พคๅธณ่™Ÿ็™ผๆ–‡ใ€ๆˆ–ๅœจ็ทšไธŠๆˆ–้›ข็ทš็š„ๆดปๅ‹•ๆ“”ไปปๆŒ‡ๅฎšไปฃ่กจใ€‚ๅฐˆๆกˆ็š„่กจ็พ่กŒ็‚บๅฏ็”ฑๅฐˆๆกˆ็ถญ่ญท่€…้€ฒไธ€ๆญฅๅฎš็พฉๅ’Œๆพ„ๆธ…ใ€‚ + +## ๅผทๅˆถๅŸท่กŒ + +ๆฟซ็”จใ€้จทๆ“พๆˆ–ๅ…ถไป–ไธๅฏๆŽฅๅ—่กŒ็‚บ็š„ๅฏฆไพ‹ๅฏๅ‘ๅฐˆๆกˆๅœ˜้šŠ [electron@github.com](mailto:electron@github.com) ๅ ฑๅ‘Šใ€‚ๆ‰€ๆœ‰ๆŠ•่จดๅฐ‡่ขซๅฏฉๆŸฅๅ’Œ่ชฟๆŸฅ๏ผŒไธฆๅœจ่ขซ่ช็‚บๅฟ…่ฆๅ’Œ้ฉๅˆๆƒ…ๆณไธ‹ๅšๅ‡บๅ›žๆ‡‰ใ€‚ๅฐˆๆกˆๅœ˜้šŠๆœ‰็พฉๅ‹™ๅฐไบ‹ไปถๆๅ ฑ่€…ไฟๅฏ†ใ€‚ๅ…ท้ซ”ๅŸท่กŒๆ”ฟ็ญ–็š„้€ฒไธ€ๆญฅ็ดฐ็ฏ€ๅฏไปฅๅ–ฎ็จๅ…ฌไฝˆใ€‚ + +ๆœช็œŸ่ช ้ตๅฎˆๆˆ–ๅฏฆๆ–ฝ่กŒ็‚บๆบ–ๅ‰‡็š„ๅฐˆๆกˆ็ถญ่ญท่€…ๅฏ่ƒฝๆœƒ้ข่‡จๅฐˆๆกˆ้ ˜ๅฐŽๅฑคๆˆๅ“กๆ‰€ๆฑบๅฎš็š„ๆšซๆ™‚ๆ€งๆˆ–ๆฐธไน…ๆ€งๅฝฑ้Ÿฟใ€‚ + +## ไพ†ๆบ + +ๆœฌ่กŒ็‚บๆบ–ๅ‰‡ๆ”น็ทจ่‡ช [Contributor Covenant][homepage], 1.4็‰ˆ, ๅฏๅพž [http://contributor-covenant.org/version/1/4][version] ็ฒๅพ— + +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/4/ diff --git a/docs-translations/zh-TW/project/CONTRIBUTING.md b/docs-translations/zh-TW/project/CONTRIBUTING.md new file mode 100644 index 0000000000..4669781226 --- /dev/null +++ b/docs-translations/zh-TW/project/CONTRIBUTING.md @@ -0,0 +1,74 @@ +# Electron็ด„ๅฎš + +:+1::tada: ้ฆ–ๅ…ˆ๏ผŒๆ„Ÿ่ฌๆŠฝๅ‡บๆ™‚้–“ๅšๅ‡บ่ฒข็ป็š„ๆฏไธ€ๅ€‹ไบบ! :tada::+1: + +่ฉฒ้ …็›ฎ้ตๅฎˆ่ฒข็ป่€…็ด„ๅฎš [code of conduct](CODE_OF_CONDUCT.md)ใ€‚ +ๆˆ‘ๅ€‘ๅธŒๆœ›่ฒข็ป่€…่ƒฝ้ตๅฎˆๆญค็ด„ๅฎšใ€‚ๅฆ‚ๆžœๆœ‰็™ผ็พไปปไฝ•ไธ่ขซๆŽฅๅ—็š„่กŒ็‚บ๏ผŒ่ซ‹ๅ›žๅ ฑ่‡ณelectron@github.com(PS:่ซ‹็”จ่‹ฑ่ชž)ใ€‚ + +ไธ‹ๅœจๆ˜ฏไธ€ไบ›็”จๆ–ผๆ”น้€ฒElectron็š„ๆŒ‡ๅ—ใ€‚ +้€™ไบ›ๅชๆ˜ฏๆŒ‡ๅฐŽๆ–น้‡๏ผŒ่€Œไธๆ˜ฏ่ฆๅ‰‡๏ผŒๅšๅ‡บไฝ ่ช็‚บๆœ€้ฉๅˆ็š„ๅˆคๆ–ท๏ผŒไธฆ้šจๆ™‚ +ๅœจ pull request ไธญๆๅ‡บๅฐ่ฉฒๆ–‡ไปถ็š„ๆ›ดๆ”นใ€‚ + +## ๆไบค Issues + +* ไฝ ๅฏไปฅๅœจๆญคๅ‰ตๅปบไธ€ๅ€‹ issue [here](https://github.com/electron/electron/issues/new)๏ผŒ +ไฝ†ๅœจๆญคไน‹ๅ‰๏ผŒ่ซ‹้–ฑ่ฎ€ไปฅไธ‹ๆณจๆ„ไบ‹้ …๏ผŒๅ…ถไธญๆ‡‰ๅŒ…ๅซ็›กๅฏ่ƒฝๅคš็š„็ดฐ็ฏ€ใ€‚ +ๅฆ‚ๆžœๅฏไปฅ็š„่ฉฑ๏ผŒ่ซ‹ๅŒ…ๆ‹ฌ: + * ไฝ ๆ‰€ไฝฟ็”จ็š„ Electron ็‰ˆๆœฌ + * ไฝ ๆ‰€ไฝฟ็”จ็š„็ณป็ตฑ + * ๅฆ‚ๆžœ้ฉ็”จ๏ผŒ่ซ‹ๅŒ…ๆ‹ฌ:ไฝ ๅšไบ†ไป€้บผๆ™‚็™ผ็”Ÿไบ†ๅ•้กŒ๏ผŒไปฅๅŠไฝ ๆ‰€้ ๆœŸ็š„็ตๆžœใ€‚ +* ๅ…ถไป–ๆœ‰ๅŠฉๆ–ผ่งฃๆฑบไฝ ็š„ issue ็š„้ธ้ …: + * ๆˆชๅœ–ๅ’Œๅ‹•ๆ…‹GIF + * ็ต‚็ซฏๆฉŸๅ’Œ้–‹็™ผๅทฅๅ…ทไธญ็š„้Œฏ่ชค่จŠๆฏๆˆ–่ญฆๅ‘Šใ€‚ + * ๅŸท่กŒ [cursory search](https://github.com/electron/electron/issues?utf8=โœ“&q=is%3Aissue+) + ๆชขๆŸฅๆ˜ฏๅฆๅทฒๅญ˜ๅœจ้กžไผผๅ•้กŒ + +## ๆไบค Pull Requests + +* ๅฏไปฅ็š„่ฉฑ๏ผŒๅœจ pull request ๅŒ…ๅซๆˆชๅœ–ๅ’Œๅ‹•ๆ…‹GIFใ€‚ +* ้ตๅฎˆ JavaScript, C++, and Python [coding style defined in docs](/docs/development/coding-style.md). +* ไฝฟ็”จ [Markdown](https://daringfireball.net/projects/markdown) ๆ’ฐๅฏซๆ–‡ไปถใ€‚ + ่ซ‹ๅƒ่€ƒ [Documentation Styleguide](/docs/styleguide.md). +* ไฝฟ็”จ็ฐกๅ–ฎๆ˜Ž็žญ็š„ๆไบค่จŠๆฏใ€‚่ซ‹ๅƒ่€ƒ [Commit Message Styleguide](#git-commit-messages). + +## ๆ–‡ไปถๆจฃๅผ + +### ้€š็”จไปฃ็ขผ + +* ไปฅ็ฉบ่กŒๅšๆ–‡ไปถ็ตๅฐพใ€‚ +* ๆŒ‰็…งไปฅไธ‹้ †ๅบ่ผ‰ๅ…ฅๆจก็ต„: + * ๆทปๅŠ  Node Modules (ๅƒ่€ƒ `path`) + * ๆทปๅŠ  Electron Modules (ๅƒ่€ƒ `ipc`, `app`) + * ๆœฌๅœฐๆจก็ต„(ไฝฟ็”จ็›ธๅฐ่ทฏๅพ‘) +* ๆŒ‰็…งไปฅไธ‹็š„้ †ๅบๆŽ’ๅบ้กžๅˆฅ(class)็š„ๅฑฌๆ€ง: + * ้กžๅˆฅ็š„ๆ–นๆณ•ๅ’Œๅฑฌๆ€ง (ๆ–นๆณ•ไปฅ `@` ไฝœ็‚บ้–‹้ ญ) + * ๅฏฆ้ซ”(Instance)็š„ๆ–นๆณ•ๅ’Œๅฑฌๆ€ง +* ้ฟๅ…ไฝฟ็”จๅนณๅฐ็›ธไพไปฃ็ขผ: + * ไฝฟ็”จ `path.join()` ไพ†้€ฃๆŽฅๆช”ๆกˆๅ็จฑใ€‚ + * ็•ถ้œ€่ฆไฝฟ็”จ่‡จๆ™‚็›ฎ้Œ„ๆ™‚๏ผŒไฝฟ็”จ `os.tmpdir()` ่€Œไธๆ˜ฏ `/tmp` ใ€‚ +* ๅœจ function ็ตๅฐพไฝฟ็”จๆ˜Ž็ขบ็š„ `return` ใ€‚ + * ไธ่ฆไฝฟ็”จ `return null`, `return undefined`, `null`, ๆˆ– `undefined` + +### Git ๆไบค่จŠๆฏ (้‘‘ๆ–ผ้€ฒ่กŒGitๆไบคๆ™‚้œ€่ฆ่‹ฑๆ–‡ๆ›ธๅฏซ๏ผŒๆญค่™•ๆšซไธ็ฟป่ญฏ) + +* Use the present tense ("Add feature" not "Added feature") +* Use the imperative mood ("Move cursor to..." not "Moves cursor to...") +* Limit the first line to 72 characters or less +* Reference issues and pull requests liberally +* When only changing documentation, include `[ci skip]` in the commit description +* Consider starting the commit message with an applicable emoji: + * :art: `:art:` when improving the format/structure of the code + * :racehorse: `:racehorse:` when improving performance + * :non-potable_water: `:non-potable_water:` when plugging memory leaks + * :memo: `:memo:` when writing docs + * :penguin: `:penguin:` when fixing something on Linux + * :apple: `:apple:` when fixing something on macOS + * :checkered_flag: `:checkered_flag:` when fixing something on Windows + * :bug: `:bug:` when fixing a bug + * :fire: `:fire:` when removing code or files + * :green_heart: `:green_heart:` when fixing the CI build + * :white_check_mark: `:white_check_mark:` when adding tests + * :lock: `:lock:` when dealing with security + * :arrow_up: `:arrow_up:` when upgrading dependencies + * :arrow_down: `:arrow_down:` when downgrading dependencies + * :shirt: `:shirt:` when removing linter warnings diff --git a/docs-translations/zh-TW/project/README.md b/docs-translations/zh-TW/project/README.md new file mode 100644 index 0000000000..dae51010d1 --- /dev/null +++ b/docs-translations/zh-TW/project/README.md @@ -0,0 +1,77 @@ +[![Electron Logo](http://electron.atom.io/images/electron-logo.svg)](http://electron.atom.io/) + +[![Travis Build Status](https://travis-ci.org/electron/electron.svg?branch=master)](https://travis-ci.org/electron/electron) +[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/kvxe4byi7jcxbe26/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/electron) +[![devDependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron?type=dev) +[![Join the Electron Community on Slack](http://atom-slack.herokuapp.com/badge.svg)](http://atom-slack.herokuapp.com/) + +Electronๆก†ๆžถ่ฎ“ไฝ ๅฏไปฅ็”จJavaScript, HTML ๅ’Œ CSS ็ทจๅฏซ่ทจๅนณๅฐ็š„ๆ‡‰็”จ็จ‹ๅผใ€‚ +ๅฎƒๆ˜ฏๅŸบๆ–ผ[Node.js](https://nodejs.org/)ๅ’Œ[Chromium](http://www.chromium.org)๏ผŒ +ไธฆไธ”่ขซ[Atom editor](https://github.com/atom/atom)ๅŠ่จฑๅคšๅ…ถไป–็š„[apps](http://electron.atom.io/apps)ๆ‰€ไฝฟ็”จใ€‚ + +่ซ‹้—œๆณจ[@ElectronJS](https://twitter.com/electronjs)็š„Twitterไปฅ็ฒๅพ—้‡่ฆๅ…ฌๅ‘Šใ€‚ + +่ฉฒ้ …็›ฎ้ตๅฎˆ่ฒข็ป่€…็ด„ๅฎš [code of conduct](CODE_OF_CONDUCT.md)ใ€‚ +ๆˆ‘ๅ€‘ๅธŒๆœ›่ฒข็ป่€…่ƒฝ้ตๅฎˆๆญค็ด„ๅฎšใ€‚ๅฆ‚ๆžœๆœ‰็™ผ็พไปปไฝ•ไธ่ขซๆŽฅๅ—็š„่กŒ็‚บ๏ผŒ่ซ‹ๅ›žๅ ฑ่‡ณelectron@github.com(PS:่ซ‹็”จ่‹ฑ่ชž)ใ€‚ + +## ไธ‹่ผ‰ + +้ ็ทจ่ญฏ็š„ไบŒ้€ฒไฝๆช”ๅ’Œdebug symbols็‰ˆๅฏไปฅๅœจ[releases](https://github.com/electron/electron/releases)ไธญๆ‰พๅˆฐ๏ผŒ +ๅ…ถไธญๅŒ…ๅซLinux, Windows ๅ’Œ macOS็‰ˆ็š„Electronใ€‚ + +ไฝ ไนŸๅฏไปฅ็”จ[`npm`](https://docs.npmjs.com/)ๅฎ‰่ฃ้ ็ทจ่ญฏ็š„ไบŒ้€ฒไฝๆช”: + +```sh +# ๅœจ $PATH ๅ…จๅŸŸๅฎ‰่ฃ `electron` +npm install electron -g + +# ๅฎ‰่ฃ็‚บ้–‹็™ผไพ่ณด +npm install electron --save-dev +``` + +### ้กๅƒ็ถฒ็ซ™ + +- [ไธญๅœ‹](https://npm.taobao.org/mirrors/electron) + +## ๆ–‡ไปถ + +้–‹็™ผๆŒ‡ๅ—ๅ’ŒAPIๆ–‡ไปถไฝๆ–ผ +[docs](https://github.com/electron/electron/tree/master/docs)ใ€‚ +ๅฎƒไนŸๅŒ…ๆ‹ฌๅฆ‚ไฝ•็ทจ่ญฏ็œ‹ๆ”น้€ฒElectronใ€‚ + +## ็ฟป่ญฏ็‰ˆๆ–‡ไปถ + +- [่‘ก่„็‰™่ชž๏ผๅทด่ฅฟ](https://github.com/electron/electron/tree/master/docs-translations/pt-BR) +- [้Ÿ“่ชž](https://github.com/electron/electron/tree/master/docs-translations/ko-KR) +- [ๆ—ฅ่ชž](https://github.com/electron/electron/tree/master/docs-translations/jp) +- [่ฅฟ็ญ็‰™่ชž](https://github.com/electron/electron/tree/master/docs-translations/es) +- [็ฐก้ซ”ไธญๆ–‡](https://github.com/electron/electron/tree/master/docs-translations/zh-CN) +- [ๆญฃ้ซ”ไธญๆ–‡](https://github.com/electron/electron/tree/master/docs-translations/zh-TW) +- [ๅœŸ่€ณๅ…ถ](https://github.com/electron/electron/tree/master/docs-translations/tr-TR) +- [็ƒๅ…‹่˜ญ](https://github.com/electron/electron/tree/master/docs-translations/uk-UA) +- [ไฟ„่ชž](https://github.com/electron/electron/tree/master/docs-translations/ru-RU) +- [ๆณ•่ชž](https://github.com/electron/electron/tree/master/docs-translations/fr-FR) + +## ๅฟซ้€Ÿ้–‹ๅง‹ + +Clone ไธฆไฝฟ็”จ [`electron/electron-quick-start`](https://github.com/electron/electron-quick-start) +้€™ๅ€‹repo๏ผŒไปฅไฝฟ็”จ่ผ•้‡ๅŒ–็š„Electronใ€‚ + +## ็คพ็พค + +ไฝ ๅฏไปฅๅœจไปฅไธ‹ไฝ็ฝฎๆๅ•ไธฆๅ’Œ็คพ็พคๆˆๅ“กไบ’ๅ‹•: +- [`electron`](http://discuss.atom.io/c/electron) Atom่ซ–ๅฃ‡ไธŠ็š„ๅ…ถไธญไธ€ๅ€ +- `#atom-shell` Freenode็š„่Šๅคฉ้ ป้“ +- [`Atom`](http://atom-slack.herokuapp.com/) SlackไธŠ็š„้ ป้“ +- [`electron-br`](https://electron-br.slack.com) *(่‘ก่„็‰™่ชž๏ผๅทด่ฅฟ)* +- [`electron-kr`](http://www.meetup.com/electron-kr/) *(้Ÿ“่ชž)* +- [`electron-jp`](https://electron-jp-slackin.herokuapp.com/) *(ๆ—ฅ่ชž)* +- [`electron-tr`](http://www.meetup.com/Electron-JS-Istanbul/) *(ๅœŸ่€ณๅ…ถ)* +- [`electron-id`](https://electron-id.slack.com) *(ๅฐๅบฆๅฐผ่ฅฟไบž)* + +ๅœจ [awesome-electron](https://github.com/sindresorhus/awesome-electron) +ๆŸฅ็œ‹็”ฑ็คพ็พค็ถญ่ญท็š„ๆธ…ๅ–ฎ๏ผŒๅŒ…ๆ‹ฌๅฏฆ็”จ็š„ๆ‡‰็”จ็จ‹ๅผใ€ๅทฅๅ…ทไปฅๅŠ่ณ‡ๆบใ€‚ + +## ๆ†‘่ญ‰ + +MIT ยฉ 2016 Github From 8fa3057e199d52ff421c6d4f9bb92fee528eb934 Mon Sep 17 00:00:00 2001 From: Zeke Sikelianos Date: Tue, 25 Oct 2016 23:48:48 -0700 Subject: [PATCH 122/148] update docs linter to add support for inline ENUM values --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2978869387..b60517dd5f 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "asar": "^0.11.0", "browserify": "^13.1.0", "electabul": "~0.0.4", - "electron-docs-linter": "^1.10.0", + "electron-docs-linter": "^1.11.0", "request": "*", "standard": "^8.4.0", "standard-markdown": "^2.1.1" From 6d92457095c9b45a169296aa8be31388158948ba Mon Sep 17 00:00:00 2001 From: "ali.ibrahim" Date: Wed, 26 Oct 2016 11:10:15 +0200 Subject: [PATCH 123/148] Fixing code review issues: refactoring emit methods using CustomEmit. --- atom/browser/api/atom_api_url_request.cc | 64 ++++++++---------------- atom/browser/api/atom_api_url_request.h | 4 ++ atom/common/api/event_emitter_caller.cc | 14 +++--- atom/common/api/event_emitter_caller.h | 31 ++++++++---- 4 files changed, 53 insertions(+), 60 deletions(-) diff --git a/atom/browser/api/atom_api_url_request.cc b/atom/browser/api/atom_api_url_request.cc index 465ee3e53c..fe60bbb128 100644 --- a/atom/browser/api/atom_api_url_request.cc +++ b/atom/browser/api/atom_api_url_request.cc @@ -6,6 +6,7 @@ #include #include "atom/browser/api/atom_api_session.h" #include "atom/browser/net/atom_url_request.h" +#include "atom/common/api/event_emitter_caller.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/net_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" @@ -52,43 +53,6 @@ struct Converter> { } // namespace mate -namespace { - -template -std::array, sizeof...(ArgTypes)> BuildArgsArray( - v8::Isolate* isolate, - ArgTypes... args) { - std::array, sizeof...(ArgTypes)> result = { - {mate::ConvertToV8(isolate, args)...}}; - return result; -} - -template -void EmitRequestEvent(v8::Isolate* isolate, - v8::Local object, - ArgTypes... args) { - v8::HandleScope handle_scope(isolate); - auto arguments = BuildArgsArray(isolate, args...); - v8::Local _emitRequestEvent; - if (mate::Dictionary(isolate, object) - .Get("_emitRequestEvent", &_emitRequestEvent)) - _emitRequestEvent->Call(object, arguments.size(), arguments.data()); -} - -template -void EmitResponseEvent(v8::Isolate* isolate, - v8::Local object, - ArgTypes... args) { - v8::HandleScope handle_scope(isolate); - auto arguments = BuildArgsArray(isolate, args...); - v8::Local _emitResponseEvent; - if (mate::Dictionary(isolate, object) - .Get("_emitResponseEvent", &_emitResponseEvent)) - _emitResponseEvent->Call(object, arguments.size(), arguments.data()); -} - -} // namespace - namespace atom { namespace api { @@ -249,7 +213,7 @@ bool URLRequest::Write(scoped_refptr buffer, if (is_last) { request_state_.SetFlag(RequestStateFlags::kFinished); - EmitRequestEvent(isolate(), GetWrapper(), true, "finish"); + EmitRequestEvent(true, "finish"); } DCHECK(atom_request_); @@ -273,10 +237,10 @@ void URLRequest::Cancel() { // Really cancel if it was started. atom_request_->Cancel(); } - EmitRequestEvent(isolate(), GetWrapper(), true, "abort"); + EmitRequestEvent(true, "abort"); if (response_state_.Started() && !response_state_.Ended()) { - EmitResponseEvent(isolate(), GetWrapper(), true, "aborted"); + EmitResponseEvent(true, "aborted"); } Close(); } @@ -385,10 +349,10 @@ void URLRequest::OnError(const std::string& error, bool isRequestError) { auto error_object = v8::Exception::Error(mate::StringToV8(isolate(), error)); if (isRequestError) { request_state_.SetFlag(RequestStateFlags::kFailed); - EmitRequestEvent(isolate(), GetWrapper(), false, "error", error_object); + EmitRequestEvent(false, "error", error_object); } else { response_state_.SetFlag(ResponseStateFlags::kFailed); - EmitResponseEvent(isolate(), GetWrapper(), false, "error", error_object); + EmitResponseEvent(false, "error", error_object); } Close(); } @@ -431,9 +395,9 @@ void URLRequest::Close() { request_state_.SetFlag(RequestStateFlags::kClosed); if (response_state_.Started()) { // Emit a close event if we really have a response object. - EmitResponseEvent(isolate(), GetWrapper(), true, "close"); + EmitResponseEvent(true, "close"); } - EmitRequestEvent(isolate(), GetWrapper(), true, "close"); + EmitRequestEvent(true, "close"); } Unpin(); if (atom_request_) { @@ -454,6 +418,18 @@ void URLRequest::Unpin() { wrapper_.Reset(); } +template +void URLRequest::EmitRequestEvent(Args... args) { + v8::HandleScope handle_scope(isolate()); + mate::CustomEmit(isolate(), GetWrapper(), "_emitRequestEvent", args...); +} + +template +void URLRequest::EmitResponseEvent(Args... args) { + v8::HandleScope handle_scope(isolate()); + mate::CustomEmit(isolate(), GetWrapper(), "_emitResponseEvent", args...); +} + } // namespace api } // namespace atom diff --git a/atom/browser/api/atom_api_url_request.h b/atom/browser/api/atom_api_url_request.h index 8b2c327828..3aae14bb19 100644 --- a/atom/browser/api/atom_api_url_request.h +++ b/atom/browser/api/atom_api_url_request.h @@ -183,6 +183,10 @@ class URLRequest : public mate::EventEmitter { void Close(); void Pin(); void Unpin(); + template + void EmitRequestEvent(Args... args); + template + void EmitResponseEvent(Args... args); scoped_refptr atom_request_; RequestState request_state_; diff --git a/atom/common/api/event_emitter_caller.cc b/atom/common/api/event_emitter_caller.cc index 40448cad10..3fbb31c497 100644 --- a/atom/common/api/event_emitter_caller.cc +++ b/atom/common/api/event_emitter_caller.cc @@ -11,16 +11,16 @@ namespace mate { namespace internal { -v8::Local CallEmitWithArgs(v8::Isolate* isolate, - v8::Local obj, - ValueVector* args) { +v8::Local CallMethodWithArgs(v8::Isolate* isolate, + v8::Local obj, + const char* method, + ValueVector* args) { // Perform microtask checkpoint after running JavaScript. - v8::MicrotasksScope script_scope( - isolate, v8::MicrotasksScope::kRunMicrotasks); + v8::MicrotasksScope script_scope(isolate, + v8::MicrotasksScope::kRunMicrotasks); // Use node::MakeCallback to call the callback, and it will also run pending // tasks in Node.js. - return node::MakeCallback( - isolate, obj, "emit", args->size(), &args->front()); + return node::MakeCallback(isolate, obj, method, args->size(), &args->front()); } } // namespace internal diff --git a/atom/common/api/event_emitter_caller.h b/atom/common/api/event_emitter_caller.h index a2567da9d1..24917cbef6 100644 --- a/atom/common/api/event_emitter_caller.h +++ b/atom/common/api/event_emitter_caller.h @@ -15,37 +15,50 @@ namespace internal { using ValueVector = std::vector>; -v8::Local CallEmitWithArgs(v8::Isolate* isolate, - v8::Local obj, - ValueVector* args); +v8::Local CallMethodWithArgs(v8::Isolate* isolate, + v8::Local obj, + const char* method, + ValueVector* args); } // namespace internal // obj.emit.apply(obj, name, args...); // The caller is responsible of allocating a HandleScope. -template +template v8::Local EmitEvent(v8::Isolate* isolate, v8::Local obj, const StringType& name, const internal::ValueVector& args) { - internal::ValueVector concatenated_args = { StringToV8(isolate, name) }; + internal::ValueVector concatenated_args = {StringToV8(isolate, name)}; concatenated_args.reserve(1 + args.size()); concatenated_args.insert(concatenated_args.end(), args.begin(), args.end()); - return internal::CallEmitWithArgs(isolate, obj, &concatenated_args); + return internal::CallMethodWithArgs(isolate, obj, "emit", &concatenated_args); } // obj.emit(name, args...); // The caller is responsible of allocating a HandleScope. -template +template v8::Local EmitEvent(v8::Isolate* isolate, v8::Local obj, const StringType& name, const Args&... args) { internal::ValueVector converted_args = { - StringToV8(isolate, name), + StringToV8(isolate, name), ConvertToV8(isolate, args)..., + }; + return internal::CallMethodWithArgs(isolate, obj, "emit", &converted_args); +} + +// obj.custom_emit(args...) +template +v8::Local CustomEmit(v8::Isolate* isolate, + v8::Local object, + const char* custom_emit, + const Args&... args) { + internal::ValueVector converted_args = { ConvertToV8(isolate, args)..., }; - return internal::CallEmitWithArgs(isolate, obj, &converted_args); + return internal::CallMethodWithArgs(isolate, object, custom_emit, + &converted_args); } } // namespace mate From aeb774730b8df693a5d146897ab37a918bcf62c9 Mon Sep 17 00:00:00 2001 From: Will Tange Date: Wed, 26 Oct 2016 14:48:09 +0200 Subject: [PATCH 124/148] Link Accelerator docs to globalShortcut module Usage of Accelerators (i.e. `globalShortcut.register`) is now documented in the Accelerator docs themselves. --- docs/api/accelerator.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/docs/api/accelerator.md b/docs/api/accelerator.md index 1f760b4636..f90e409043 100644 --- a/docs/api/accelerator.md +++ b/docs/api/accelerator.md @@ -2,14 +2,30 @@ > Define keyboard shortcuts. -Accelerators can contain multiple modifiers and key codes, combined by -the `+` character. +Accelerators are Strings that can contain multiple modifiers and key codes, +combined by the `+` character, and are used to define keyboard shortcuts +throughout your application. Examples: * `CommandOrControl+A` * `CommandOrControl+Shift+Z` +Shortcuts are registered with the [`globalShortcut`](global-shortcut.md) module +using the [`register`](global-shortcut.md#globalshortcutregisteraccelerator-callback) +method, i.e. + +```javascript +const {app, globalShortcut} = require('electron') + +app.on('ready', () => { + // Register a 'CommandOrControl+Y' shortcut listener. + globalShortcut.register('CommandOrControl+Y', () => { + // Do stuff when Y and either Command/Control is pressed. + }) +}) +``` + ## Platform notice On Linux and Windows, the `Command` key does not have any effect so From 3e0d8841eaa4ebe72bb243b985731adceffc68a4 Mon Sep 17 00:00:00 2001 From: tinydew4 Date: Wed, 26 Oct 2016 15:36:06 +0000 Subject: [PATCH 125/148] Update the korean docs up to '02a7094' commit. --- docs-translations/ko-KR/api/browser-window.md | 252 +++++++++--------- docs-translations/ko-KR/api/clipboard.md | 13 + docs-translations/ko-KR/api/web-contents.md | 41 ++- docs-translations/ko-KR/api/web-frame.md | 10 +- 4 files changed, 166 insertions(+), 150 deletions(-) diff --git a/docs-translations/ko-KR/api/browser-window.md b/docs-translations/ko-KR/api/browser-window.md index cacd2d893b..e45983d084 100644 --- a/docs-translations/ko-KR/api/browser-window.md +++ b/docs-translations/ko-KR/api/browser-window.md @@ -118,50 +118,50 @@ child.once('ready-to-show', () => { * `width` Integer - ์œˆ๋„์šฐ์˜ ๊ฐ€๋กœ ๋„ˆ๋น„. ๊ธฐ๋ณธ๊ฐ’์€ `800`์ž…๋‹ˆ๋‹ค. * `height` Integer - ์œˆ๋„์šฐ์˜ ์„ธ๋กœ ๋†’์ด. ๊ธฐ๋ณธ๊ฐ’์€ `600`์ž…๋‹ˆ๋‹ค. -* `x` Integer (**required** y๊ฐ€ ์‚ฌ์šฉ๋˜๋ฉด) - ํ™”๋ฉด์„ ๊ธฐ์ค€์œผ๋กœ ์ฐฝ ์ขŒ์ธก์„ ์˜คํ”„์…‹ ํ•œ ์œ„์น˜. - ๊ธฐ๋ณธ๊ฐ’์€ `ํ™”๋ฉด์ค‘์•™`์ž…๋‹ˆ๋‹ค. -* `y` Integer (**required** x๊ฐ€ ์‚ฌ์šฉ๋˜๋ฉด) - ํ™”๋ฉด์„ ๊ธฐ์ค€์œผ๋กœ ์ฐฝ ์ƒ๋‹จ์„ ์˜คํ”„์…‹ ํ•œ ์œ„์น˜. - ๊ธฐ๋ณธ๊ฐ’์€ `ํ™”๋ฉด์ค‘์•™`์ž…๋‹ˆ๋‹ค. +* `x` Integer (**required** y๊ฐ€ ์‚ฌ์šฉ๋˜๋ฉด) - ํ™”๋ฉด์„ ๊ธฐ์ค€์œผ๋กœ ์ฐฝ ์ขŒ์ธก์„ ์˜คํ”„์…‹ ํ•œ + ์œ„์น˜. ๊ธฐ๋ณธ๊ฐ’์€ `ํ™”๋ฉด์ค‘์•™`์ž…๋‹ˆ๋‹ค. +* `y` Integer (**required** x๊ฐ€ ์‚ฌ์šฉ๋˜๋ฉด) - ํ™”๋ฉด์„ ๊ธฐ์ค€์œผ๋กœ ์ฐฝ ์ƒ๋‹จ์„ ์˜คํ”„์…‹ ํ•œ + ์œ„์น˜. ๊ธฐ๋ณธ๊ฐ’์€ `ํ™”๋ฉด์ค‘์•™`์ž…๋‹ˆ๋‹ค. * `useContentSize` Boolean - `width`์™€ `height`๋ฅผ ์›น ํŽ˜์ด์ง€์˜ ํฌ๊ธฐ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. - ์ด ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ์›น ํŽ˜์ด์ง€์˜ ํฌ๊ธฐ์— ์œˆ๋„์šฐ ํ”„๋ ˆ์ž„ ํฌ๊ธฐ๊ฐ€ ์ถ”๊ฐ€๋˜๋ฏ€๋กœ ์‹ค์ œ ์ฐฝ์€ ์กฐ๊ธˆ - ๋” ์ปค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. + ์ด ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๋ฉด ์›น ํŽ˜์ด์ง€์˜ ํฌ๊ธฐ์— ์œˆ๋„์šฐ ํ”„๋ ˆ์ž„ ํฌ๊ธฐ๊ฐ€ ์ถ”๊ฐ€๋˜๋ฏ€๋กœ ์‹ค์ œ + ์ฐฝ์€ ์กฐ๊ธˆ ๋” ์ปค์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. * `center` Boolean - ์œˆ๋„์šฐ๋ฅผ ํ™”๋ฉด ์ • ์ค‘์•™์— ์œ„์น˜์‹œํ‚ต๋‹ˆ๋‹ค. * `minWidth` Integer - ์œˆ๋„์šฐ์˜ ์ตœ์†Œ ๊ฐ€๋กœ ๋„ˆ๋น„. ๊ธฐ๋ณธ๊ฐ’์€ `0`์ž…๋‹ˆ๋‹ค. * `minHeight` Integer - ์œˆ๋„์šฐ์˜ ์ตœ์†Œ ์„ธ๋กœ ๋†’์ด. ๊ธฐ๋ณธ๊ฐ’์€ `0`์ž…๋‹ˆ๋‹ค. * `maxWidth` Integer - ์œˆ๋„์šฐ์˜ ์ตœ๋Œ€ ๊ฐ€๋กœ ๋„ˆ๋น„. ๊ธฐ๋ณธ๊ฐ’์€ `์ œํ•œ์—†์Œ`์ž…๋‹ˆ๋‹ค. * `maxHeight` Integer - ์œˆ๋„์šฐ์˜ ์ตœ๋Œ€ ์„ธ๋กœ ๋†’์ด. ๊ธฐ๋ณธ๊ฐ’์€ `์ œํ•œ์—†์Œ`์ž…๋‹ˆ๋‹ค. -* `resizable` Boolean - ์œˆ๋„์šฐ์˜ ํฌ๊ธฐ๋ฅผ ์žฌ์กฐ์ • ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. ๊ธฐ๋ณธ๊ฐ’์€ `true` - ์ž…๋‹ˆ๋‹ค. +* `resizable` Boolean - ์œˆ๋„์šฐ์˜ ํฌ๊ธฐ๋ฅผ ์žฌ์กฐ์ • ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. ๊ธฐ๋ณธ๊ฐ’์€ + `true` ์ž…๋‹ˆ๋‹ค. * `movable` Boolean - ์œˆ๋„์šฐ๋ฅผ ์ด๋™์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. Linux์—์„  ๊ตฌํ˜„๋˜์–ด์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true` ์ž…๋‹ˆ๋‹ค. -* `minimizable` Boolean - ์œˆ๋„์šฐ๋ฅผ ์ตœ์†Œํ™”์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. Linux์—์„  ๊ตฌํ˜„๋˜์–ด์žˆ์ง€ +* `minimizable` Boolean - ์œˆ๋„์šฐ๋ฅผ ์ตœ์†Œํ™”์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. Linux์—์„  + ๊ตฌํ˜„๋˜์–ด์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true` ์ž…๋‹ˆ๋‹ค. +* `maximizable` Boolean - ์œˆ๋„์šฐ๋ฅผ ์ตœ๋Œ€ํ™”์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. Linux์—์„  + ๊ตฌํ˜„๋˜์–ด์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true` ์ž…๋‹ˆ๋‹ค. +* `closable` Boolean - ์œˆ๋„์šฐ๋ฅผ ๋‹ซ์„ ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. Linux์—์„  ๊ตฌํ˜„๋˜์–ด์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true` ์ž…๋‹ˆ๋‹ค. -* `maximizable` Boolean - ์œˆ๋„์šฐ๋ฅผ ์ตœ๋Œ€ํ™”์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. Linux์—์„  ๊ตฌํ˜„๋˜์–ด์žˆ์ง€ - ์•Š์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true` ์ž…๋‹ˆ๋‹ค. -* `closable` Boolean - ์œˆ๋„์šฐ๋ฅผ ๋‹ซ์„ ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. Linux์—์„  ๊ตฌํ˜„๋˜์–ด์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. - ๊ธฐ๋ณธ๊ฐ’์€ `true` ์ž…๋‹ˆ๋‹ค. * `focusable` Boolean - ์œˆ๋„์šฐ๊ฐ€ ํฌ์ปค์Šค๋  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. Windows์—์„  `focusable: false`๋ฅผ ์„ค์ •ํ•จ์œผ๋กœ์จ ์•”์‹œ์ ์œผ๋กœ `skipTaskbar: true`๋„ ์„ค์ •๋ฉ๋‹ˆ๋‹ค. Linux์—์„  `focusable: false`๋ฅผ ์„ค์ •ํ•จ์œผ๋กœ์จ - ์œˆ๋„์šฐ๊ฐ€ wm๊ณผ ํ•จ๊ป˜ ๋ฐ˜์‘์„ ์ค‘์ง€ํ•˜๋ฉฐ ๋ชจ๋“  ์ž‘์—… ์˜์—ญ์—์„œ ์œˆ๋„์šฐ๊ฐ€ ์–ธ์ œ๋‚˜ ์ตœ์ƒ๋‹จ์— ์žˆ๊ฒŒ - ๋ฉ๋‹ˆ๋‹ค. + ์œˆ๋„์šฐ๊ฐ€ wm๊ณผ ํ•จ๊ป˜ ๋ฐ˜์‘์„ ์ค‘์ง€ํ•˜๋ฉฐ ๋ชจ๋“  ์ž‘์—… ์˜์—ญ์—์„œ ์œˆ๋„์šฐ๊ฐ€ ์–ธ์ œ๋‚˜ ์ตœ์ƒ๋‹จ์— + ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. * `alwaysOnTop` Boolean - ์œˆ๋„์šฐ์ด ์–ธ์ œ๋‚˜ ๋‹ค๋ฅธ ์ฐฝ๋“ค ์œ„์— ์œ ์ง€๋˜๋Š”์ง€ ์—ฌ๋ถ€. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. * `fullscreen` Boolean - ์œˆ๋„์šฐ์˜ ์ „์ฒดํ™”๋ฉด ํ™œ์„ฑํ™” ์—ฌ๋ถ€. ์ด ์†์„ฑ์„ ๋ช…์‹œ์ ์œผ๋กœ - `false`๋กœ ์ง€์ •ํ–ˆ์„ ๊ฒฝ์šฐ, macOS์—์„  ์ „์ฒดํ™”๋ฉด ๋ฒ„ํŠผ์ด ์ˆจ๊ฒจ์ง€๊ฑฐ๋‚˜ ๋น„ํ™œ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ - `false` ์ž…๋‹ˆ๋‹ค. -* `fullscreenable` Boolean - ์œˆ๋„์šฐ๊ฐ€ ์ „์ฒดํ™”๋ฉด ๋ชจ๋“œ๋กœ ์ „ํ™˜๋  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค. - ๋˜ํ•œ macOS์—์„ , ์ตœ๋Œ€ํ™”/์คŒ ๋ฒ„ํŠผ์ด ์ „์ฒดํ™”๋ฉด ๋ชจ๋“œ ๋˜๋Š” ์œˆ๋„์šฐ ์ตœ๋Œ€ํ™”๋ฅผ ์‹คํ–‰ํ• ์ง€ ์—ฌ๋ถ€๋„ - ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. -* `skipTaskbar` Boolean - ์ž‘์—…ํ‘œ์‹œ์ค„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„์ด์ฝ˜ ํ‘œ์‹œ ์Šคํ‚ต ์—ฌ๋ถ€. ๊ธฐ๋ณธ๊ฐ’์€ - `false`์ž…๋‹ˆ๋‹ค. + `false`๋กœ ์ง€์ •ํ–ˆ์„ ๊ฒฝ์šฐ, macOS์—์„  ์ „์ฒดํ™”๋ฉด ๋ฒ„ํŠผ์ด ์ˆจ๊ฒจ์ง€๊ฑฐ๋‚˜ ๋น„ํ™œ์„ฑ๋ฉ๋‹ˆ๋‹ค. + ๊ธฐ๋ณธ๊ฐ’์€ `false` ์ž…๋‹ˆ๋‹ค. +* `fullscreenable` Boolean - ์œˆ๋„์šฐ๊ฐ€ ์ „์ฒดํ™”๋ฉด ๋ชจ๋“œ๋กœ ์ „ํ™˜๋  ์ˆ˜ ์žˆ๋Š”์ง€ + ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค. ๋˜ํ•œ macOS์—์„ , ์ตœ๋Œ€ํ™”/์คŒ ๋ฒ„ํŠผ์ด ์ „์ฒดํ™”๋ฉด ๋ชจ๋“œ ๋˜๋Š” ์œˆ๋„์šฐ + ์ตœ๋Œ€ํ™”๋ฅผ ์‹คํ–‰ํ• ์ง€ ์—ฌ๋ถ€๋„ ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. +* `skipTaskbar` Boolean - ์ž‘์—…ํ‘œ์‹œ์ค„ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์•„์ด์ฝ˜ ํ‘œ์‹œ ์Šคํ‚ต ์—ฌ๋ถ€. + ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. * `kiosk` Boolean - Kiosk(ํ‚ค์˜ค์Šคํฌ) ๋ชจ๋“œ. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. * `title` String - ๊ธฐ๋ณธ ์œˆ๋„์šฐ ์ œ๋ชฉ. ๊ธฐ๋ณธ๊ฐ’์€ `"Electron"`์ž…๋‹ˆ๋‹ค. * `icon` [NativeImage](native-image.md) - ์œˆ๋„์šฐ ์•„์ด์ฝ˜, ์ƒ๋žตํ•˜๋ฉด ์‹คํ–‰ ํŒŒ์ผ์˜ ์•„์ด์ฝ˜์ด ๋Œ€์‹  ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. * `icon` [NativeImage](native-image.md) - ์œˆ๋„์šฐ ์•„์ด์ฝ˜. Windows์—์„  ๊ฐ€์žฅ ์ข‹์€ - ์‹œ๊ฐ์  ํšจ๊ณผ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด `ICO`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•˜๋ฉฐ, ๋˜ํ•œ undefined๋กœ ๋‚จ๊ฒจ๋‘๋ฉด - ์‹คํ–‰ ํŒŒ์ผ์˜ ์•„์ด์ฝ˜์ด ๋Œ€์‹  ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + ์‹œ๊ฐ์  ํšจ๊ณผ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด `ICO`๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•˜๋ฉฐ, ๋˜ํ•œ undefined๋กœ + ๋‚จ๊ฒจ๋‘๋ฉด ์‹คํ–‰ ํŒŒ์ผ์˜ ์•„์ด์ฝ˜์ด ๋Œ€์‹  ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. On Windows it is recommended to use `ICO` icons to get best visual effects, you can also leave it undefined so the executable's icon will be used. @@ -169,14 +169,15 @@ On Windows it is * `frame` Boolean - `false`๋กœ ์ง€์ •ํ•˜๋ฉด ์ฐฝ์„ [Frameless Window](frameless-window.md) ํ˜•ํƒœ๋กœ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. * `parent` BrowserWindow - ๋ถ€๋ชจ ์œˆ๋„์šฐ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๊ฐ’์€ `null`์ž…๋‹ˆ๋‹ค. -* `modal` Boolean - ์ด ์œˆ๋„์šฐ๊ฐ€ ๋ชจ๋‹ฌ ์œˆ๋„์šฐ์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ์˜ต์…˜์€ ์ž์‹ - ์œˆ๋„์šฐ์—์„œ๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. +* `modal` Boolean - ์ด ์œˆ๋„์šฐ๊ฐ€ ๋ชจ๋‹ฌ ์œˆ๋„์šฐ์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์ด ์˜ต์…˜์€ + ์ž์‹ ์œˆ๋„์šฐ์—์„œ๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. * `acceptFirstMouse` Boolean - ์œˆ๋„์šฐ๊ฐ€ ๋น„ํ™œ์„ฑํ™” ์ƒํƒœ์ผ ๋•Œ ๋‚ด๋ถ€ ์ฝ˜ํ…์ธ  ํด๋ฆญ ์‹œ - ํ™œ์„ฑํ™” ๋˜๋Š” ๋™์‹œ์— ๋‹จ์ผ mouse-down ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ์ง€ ์—ฌ๋ถ€. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. -* `disableAutoHideCursor` Boolean - ํƒ€์ดํ•‘์ค‘ ์ž๋™์œผ๋กœ ์ปค์„œ๋ฅผ ์ˆจ๊ธธ์ง€ ์—ฌ๋ถ€. ๊ธฐ๋ณธ๊ฐ’์€ - `false`์ž…๋‹ˆ๋‹ค. -* `autoHideMenuBar` Boolean - `Alt`๋ฅผ ๋ˆ„๋ฅด์ง€ ์•Š๋Š” ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฉ”๋‰ด๋ฐ”๋ฅผ ์ˆจ๊ธธ์ง€ - ์—ฌ๋ถ€. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. + ํ™œ์„ฑํ™” ๋˜๋Š” ๋™์‹œ์— ๋‹จ์ผ mouse-down ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ์ง€ ์—ฌ๋ถ€. ๊ธฐ๋ณธ๊ฐ’์€ `false` + ์ž…๋‹ˆ๋‹ค. +* `disableAutoHideCursor` Boolean - ํƒ€์ดํ•‘์ค‘ ์ž๋™์œผ๋กœ ์ปค์„œ๋ฅผ ์ˆจ๊ธธ์ง€ ์—ฌ๋ถ€. + ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. +* `autoHideMenuBar` Boolean - `Alt`๋ฅผ ๋ˆ„๋ฅด์ง€ ์•Š๋Š” ํ•œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ฉ”๋‰ด๋ฐ”๋ฅผ + ์ˆจ๊ธธ์ง€ ์—ฌ๋ถ€. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. * `enableLargerThanScreen` Boolean - ์œˆ๋„์šฐ ํฌ๊ธฐ๊ฐ€ ํ™”๋ฉด ํฌ๊ธฐ๋ณด๋‹ค ํฌ๊ฒŒ ์žฌ์กฐ์ • ๋  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. * `backgroundColor` String - `#66CD00` ์™€ `#FFF`, `#80FFFFFF` (์•ŒํŒŒ ์ง€์›๋จ) ๊ฐ™์ด @@ -189,19 +190,91 @@ On Windows it is `false`์ž…๋‹ˆ๋‹ค. * `type` String - ํŠน์ • ํ”Œ๋žซํผ์—๋งŒ ์ ์šฉ๋˜๋Š” ์œˆ๋„์šฐ์˜ ์ข…๋ฅ˜๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ ์ผ๋ฐ˜ ์œˆ๋„์šฐ ์ž…๋‹ˆ๋‹ค. ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ฐฝ์˜ ์ข…๋ฅ˜๋Š” ์•„๋ž˜๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. -* `standardWindow` Boolean - macOS์˜ ํ‘œ์ค€ ์œˆ๋„์šฐ๋ฅผ ํ…์Šค์ณ ์œˆ๋„์šฐ ๋Œ€์‹  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. - ๊ธฐ๋ณธ ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. -* `titleBarStyle` String, macOS - ์œˆ๋„์šฐ ํƒ€์ดํ‹€ ๋ฐ” ์Šคํƒ€์ผ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ์‚ฌํ•ญ์€ - ์•„๋ž˜๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. -* `thickFrame` Boolean - Windows์—์„œ ํ…Œ๋‘๋ฆฌ ์—†๋Š” ์œˆ๋„์šฐ๋ฅผ ์œ„ํ•ด ํ‘œ์ค€ ์œˆ๋„์šฐ ํ”„๋ ˆ์ž„์„ - ์ถ”๊ฐ€ํ•˜๋Š” `WS_THICKFRAME` ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. `false`๋กœ ์ง€์ •ํ•˜๋ฉด ์œˆ๋„์šฐ์˜ ๊ทธ๋ฆผ์ž์™€ - ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. -* `webPreferences` Object - ์›น ํŽ˜์ด์ง€ ๊ธฐ๋Šฅ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์†์„ฑ์€ - ์•„๋ž˜๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. +* `standardWindow` Boolean - macOS์˜ ํ‘œ์ค€ ์œˆ๋„์šฐ๋ฅผ ํ…์Šค์ณ ์œˆ๋„์šฐ ๋Œ€์‹  + ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. +* `titleBarStyle` String, macOS - ์œˆ๋„์šฐ ํƒ€์ดํ‹€ ๋ฐ” ์Šคํƒ€์ผ์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ + `default` ์ž…๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•œ ๊ฐ’์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: + * `default` - ํ‘œ์ค€ Mac ํšŒ์ƒ‰ ๋ถˆํˆฌ๋ช… ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + * `hidden` - ํƒ€์ดํ‹€ ๋ฐ”๋ฅผ ์ˆจ๊ธฐ๊ณ  ์ฝ˜ํ…์ธ  ์ „์ฒด๋ฅผ ์œˆ๋„์šฐ ํฌ๊ธฐ์— ๋งž์ถฅ๋‹ˆ๋‹ค. + ํƒ€์ดํ‹€ ๋ฐ”๋Š” ์—†์–ด์ง€์ง€๋งŒ ํ‘œ์ค€ ์ฐฝ ์ปจํŠธ๋กค ("์‹ ํ˜ธ๋“ฑ ๋ฒ„ํŠผ")์€ ์™ผ์ชฝ ์ƒ๋‹จ์— + ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. + * `hidden-inset` - `hidden` ํƒ€์ดํ‹€ ๋ฐ” ์†์„ฑ๊ณผ ํ•จ๊ป˜ ์‹ ํ˜ธ๋“ฑ ๋ฒ„ํŠผ์ด ์œˆ๋„์šฐ + ๋ชจ์„œ๋ฆฌ๋กœ๋ถ€ํ„ฐ ์•ฝ๊ฐ„ ๋” ์•ˆ์ชฝ์œผ๋กœ ๋“ค์–ด๊ฐ€๋„๋กํ•ฉ๋‹ˆ๋‹ค. 10.9 Mavericks์—์„  ์ง€์›๋˜์ง€ + ์•Š๊ณ  `hidden`์œผ๋กœ ํด๋ฐฑํ•ฉ๋‹ˆ๋‹ค. +* `thickFrame` Boolean - Windows์—์„œ ํ…Œ๋‘๋ฆฌ ์—†๋Š” ์œˆ๋„์šฐ๋ฅผ ์œ„ํ•ด ํ‘œ์ค€ ์œˆ๋„์šฐ + ํ”„๋ ˆ์ž„์„ ์ถ”๊ฐ€ํ•˜๋Š” `WS_THICKFRAME` ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. `false`๋กœ ์ง€์ •ํ•˜๋ฉด + ์œˆ๋„์šฐ์˜ ๊ทธ๋ฆผ์ž์™€ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. +* `webPreferences` Object - ์›น ํŽ˜์ด์ง€ ๊ธฐ๋Šฅ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. + * `nodeIntegration` Boolean - node(node.js) ํ†ตํ•ฉ ์—ฌ๋ถ€. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. + * `preload` String - ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ง€์ •ํ•˜๋ฉด ํŽ˜์ด์ง€ ๋‚ด์˜ ๋‹ค๋ฅธ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ž‘๋™ํ•˜๊ธฐ + ์ „์— ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ง€์ •ํ•œ ์Šคํฌ๋ฆฝํŠธ๋Š” node ํ†ตํ•ฉ ํ™œ์„ฑํ™” ์—ฌ๋ถ€์— ์ƒ๊ด€์—†์ด + ์–ธ์ œ๋‚˜ ๋ชจ๋“  node API์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์†์„ฑ์˜ ์Šคํฌ๋ฆฝํŠธ ๊ฒฝ๋กœ๋Š” ์ ˆ๋Œ€ + ๊ฒฝ๋กœ๋กœ ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. node ํ†ตํ•ฉ์ด ๋น„ํ™œ์„ฑํ™”๋˜์–ด์žˆ์„ ๊ฒฝ์šฐ, ๋ฏธ๋ฆฌ ๋กœ๋“œ๋˜๋Š” + ์Šคํฌ๋ฆฝํŠธ๋Š” node์˜ ์ „์—ญ ์‹ฌ๋ณผ๋“ค์„ ๋‹ค์‹œ ์ „์—ญ ๋ฒ”์œ„๋กœ ๋‹ค์‹œ ํฌํ•จ ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + [์—ฌ๊ธฐ](process.md#event-loaded)์˜ ์˜ˆ์‹œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. + * `session` [Session](session.md#class-session) - ํŽ˜์ด์ง€์—์„œ ์‚ฌ์šฉํ•  ์„ธ์…˜์„ + ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. Session ๊ฐ์ฒด๋ฅผ ์ง์ ‘์ ์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ๋Œ€์‹ , ํŒŒํ‹ฐ์…˜ ๋ฌธ์ž์—ด์„ ๋ฐ›๋Š” + `partition` ์˜ต์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. `session`๊ณผ `partition`์ด ๊ฐ™์ด + ์ œ๊ณต๋˜์—ˆ์„ ๊ฒฝ์šฐ `session`์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ ๊ธฐ๋ณธ ์„ธ์…˜์ž…๋‹ˆ๋‹ค. + * `partition` String - ํŽ˜์ด์ง€์—์„œ ์‚ฌ์šฉํ•  ์„ธ์…˜์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ `partition` + ์ด `persist:`๋กœ ์‹œ์ž‘ํ•˜๋ฉด ํŽ˜์ด์ง€๋Š” ์ง€์†์„ฑ ์„ธ์…˜์„ ์‚ฌ์šฉํ•˜๋ฉฐ ๋‹ค๋ฅธ ๋ชจ๋“  ์•ฑ ๋‚ด์˜ + ํŽ˜์ด์ง€์—์„œ ๊ฐ™์€ `partition`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ `persist:` ์ ‘๋‘์–ด๋กœ + ์‹œ์ž‘ํ•˜์ง€ ์•Š์œผ๋ฉด ํŽ˜์ด์ง€๋Š” ์ธ-๋ฉ”๋ชจ๋ฆฌ ์„ธ์…˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€์—์„œ ๊ฐ™์€ + `partition`์„ ์ง€์ •ํ•˜๋ฉด ๊ฐ™์€ ์„ธ์…˜์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. `partition`์„ + ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ธฐ๋ณธ ์„ธ์…˜์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. + * `zoomFactor` Number - ํŽ˜์ด์ง€์˜ ๊ธฐ๋ณธ ์คŒ ๊ฐ’์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `300%`๋ฅผ + ํ‘œํ˜„ํ•˜๋ ค๋ฉด `3.0`์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `1.0`์ž…๋‹ˆ๋‹ค. + * `javascript` Boolean - ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. + * `webSecurity` Boolean - `false`๋กœ ์ง€์ •ํ•˜๋ฉด same-origin ์ •์ฑ…์„ ๋น„ํ™œ์„ฑํ™” + ํ•ฉ๋‹ˆ๋‹ค. (์ด ์†์„ฑ์€ ๋ณดํ†ต ์‚ฌ๋žŒ๋“ค์— ์˜ํ•ด ์›น ์‚ฌ์ดํŠธ๋ฅผ ํ…Œ์ŠคํŠธํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค) + ๊ทธ๋ฆฌ๊ณ  `allowDisplayingInsecureContent`์™€ `allowRunningInsecureContent` ๋‘ + ์†์„ฑ์„ ์‚ฌ์šฉ์ž๊ฐ€ `true`๋กœ ์ง€์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ `true`๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ + `true`์ž…๋‹ˆ๋‹ค. + * `allowDisplayingInsecureContent` Boolean - https ํŽ˜์ด์ง€์—์„œ http URL์—์„œ + ๋กœ๋“œํ•œ ์ด๋ฏธ์ง€ ๊ฐ™์€ ๋ฆฌ์†Œ์Šค๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false` + ์ž…๋‹ˆ๋‹ค. + * `allowRunningInsecureContent` Boolean - https ํŽ˜์ด์ง€์—์„œ http URL์—์„œ ๋กœ๋“œํ•œ + JavaScript์™€ CSS ๋˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ + `false`์ž…๋‹ˆ๋‹ค. + * `images` Boolean - ์ด๋ฏธ์ง€ ์ง€์›์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. + * `textAreasAreResizable` Boolean - HTML TextArea ์š”์†Œ์˜ ํฌ๊ธฐ๋ฅผ ์žฌ์กฐ์ •์„ + ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. + * `webgl` Boolean - WebGL ์ง€์›์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. + * `webaudio` Boolean - WebAudio ์ง€์›์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. + * `plugins` Boolean - ํ”Œ๋Ÿฌ๊ทธ์ธ ํ™œ์„ฑํ™” ์—ฌ๋ถ€๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. + * `experimentalFeatures` Boolean - Chrome์˜ ์‹คํ—˜์ ์ธ ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. + ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. + * `experimentalCanvasFeatures` Boolean - Chrome์˜ ์‹คํ—˜์ ์ธ ์บ”๋ฒ„์Šค(canvas) + ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. + * `directWrite` Boolean - Windows์—์„œ ํฐํŠธ ๋ Œ๋”๋ง์„ ์œ„ํ•ด DirectWrite๋ฅผ + ์‚ฌ์šฉํ•˜๋Š”์ง€๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. + * `scrollBounce` Boolean - macOS์—์„œ ์Šคํฌ๋กค ํŠ•๊ธฐ๊ธฐ ํšจ๊ณผ (ํƒ„์„ฑ ๋ฐด๋”ฉ)๋ฅผ ํ™œ์„ฑํ™” + ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. + * `blinkFeatures` String - ํ™œ์„ฑํ™” ํ•  `CSSVariables,KeyboardEventKey`๊ฐ™์ด `,`๋กœ + ๊ตฌ๋ถ„๋œ ๊ธฐ๋Šฅ ๋ฌธ์ž์—ด๋“ค์˜ ๋ฆฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค. [RuntimeEnabledFeatures.in][blink-feature-string] + ํŒŒ์ผ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + * `disableBlinkFeatures` String - ๋น„ํ™œ์„ฑํ™” ํ•  `CSSVariables,KeyboardEventKey`๊ฐ™์ด + `,`๋กœ ๊ตฌ๋ถ„๋œ ๊ธฐ๋Šฅ ๋ฌธ์ž์—ด๋“ค์˜ ๋ฆฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค. [RuntimeEnabledFeatures.in][blink-feature-string] + ํŒŒ์ผ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + * `defaultFontFamily` Object - font-family์˜ ๊ธฐ๋ณธ ํฐํŠธ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. + * `standard` String - ๊ธฐ๋ณธ๊ฐ’ `Times New Roman`. + * `serif` String - ๊ธฐ๋ณธ๊ฐ’ `Times New Roman`. + * `sansSerif` String - ๊ธฐ๋ณธ๊ฐ’ `Arial`. + * `monospace` String - ๊ธฐ๋ณธ๊ฐ’ `Courier New`. + * `defaultFontSize` Integer - ๊ธฐ๋ณธ๊ฐ’ `16`. + * `defaultMonospaceFontSize` Integer - ๊ธฐ๋ณธ๊ฐ’ `13`. + * `minimumFontSize` Integer - ๊ธฐ๋ณธ๊ฐ’ `0`. + * `defaultEncoding` String - ๊ธฐ๋ณธ๊ฐ’ `ISO-8859-1`. + * `backgroundThrottling` Boolean - ํŽ˜์ด์ง€๊ฐ€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ƒํƒœ์— ์ง„์ž…ํ•  ๋•Œ + ์• ๋‹ˆ๋ฉ”์ด์…˜๊ณผ ํƒ€์ด๋จธ์— ์Šค๋กœํ‹€์„ ์ ์šฉํ• ์ง€ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. + * `offscreen` Boolean - ๋ธŒ๋ผ์šฐ์ € ์œˆ๋„์šฐ์— ์˜คํ”„ ์Šคํฌ๋ฆฐ ๋žœ๋”๋ง์„ ์ ์šฉํ• ์ง€ ์—ฌ๋ถ€๋ฅผ + ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. + * `sandbox` Boolean - Chromium ์šด์˜์ฒด์ œ ์ˆ˜์ค€์˜ ์ƒŒ๋“œ๋ฐ•์Šค ํ™œ์„ฑํ™” ์—ฌ๋ถ€. -`minWidth`/`maxWidth`/`minHeight`/`maxHeight`๋ฅผ ํ†ตํ•ด ์ตœ์†Œ ๋˜๋Š” ์ตœ๋Œ€ ์œˆ๋„์šฐ ํฌ๊ธฐ๋ฅผ -์ง€์ •ํ•œ ๊ฒฝ์šฐ, ์ด๋Š” ์‚ฌ์šฉ์ž๋งŒ์„ ์ œ์•ฝํ•˜๋ฉฐ, `setBounds`/`setSize` ๋˜๋Š” `BrowserWindow`์˜ -์ƒ์„ฑ์ž์—์„œ ํฌ๊ธฐ ์ œ์•ฝ์„ ๋”ฐ๋ฅด์ง€ ์•Š๋Š” ์œˆ๋„์šฐ ํฌ๊ธฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์€ ๋ง‰์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. +`minWidth`/`maxWidth`/`minHeight`/`maxHeight`๋ฅผ ํ†ตํ•ด ์ตœ์†Œ ๋˜๋Š” ์ตœ๋Œ€ ์œˆ๋„์šฐ +ํฌ๊ธฐ๋ฅผ ์ง€์ •ํ•œ ๊ฒฝ์šฐ, ์ด๋Š” ์‚ฌ์šฉ์ž๋งŒ์„ ์ œ์•ฝํ•˜๋ฉฐ, `setBounds`/`setSize` ๋˜๋Š” +`BrowserWindow`์˜ ์ƒ์„ฑ์ž์—์„œ ํฌ๊ธฐ ์ œ์•ฝ์„ ๋”ฐ๋ฅด์ง€ ์•Š๋Š” ์œˆ๋„์šฐ ํฌ๊ธฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์€ +๋ง‰์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. `type` ์†์„ฑ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ’๊ณผ ๋™์ž‘์€ ๋‹ค์Œ๊ณผ ๊ฐ™์œผ๋ฉฐ, ํ”Œ๋žซํผ์— ๋”ฐ๋ผ ๋‹ค๋ฆ…๋‹ˆ๋‹ค: @@ -211,86 +284,11 @@ On Windows it is * `textured`๋Š” ์ฐฝ์— ๋ฉ”ํƒˆ ๊ทธ๋ผ๋””์–ธํŠธ ์™ธ๊ด€(`NSTexturedBackgroundWindowMask`)์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค. * `desktop`์€ ๋ฐ์Šคํฌํƒ‘ ๋ฐฐ๊ฒฝ ๋ ˆ๋ฒจ(`kCGDesktopWindowLevel - 1`)์— ์œˆ๋„์šฐ๋ฅผ - ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง„ ์œˆ๋„์šฐ๋Š” ํฌ์ปค์Šค, ํ‚ค๋ณด๋“œ, ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ๋ฅผ ๋ฐ›์„ - ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํŽธ๋ฒ•์œผ๋กœ `globalShortcut`์„ ํ†ตํ•ด ํ‚ค ์ž…๋ ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. + ๋ฐฐ์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ฐธ๊ณ ๋กœ ์ด๋ ‡๊ฒŒ ๋งŒ๋“ค์–ด์ง„ ์œˆ๋„์šฐ๋Š” ํฌ์ปค์Šค, ํ‚ค๋ณด๋“œ, ๋งˆ์šฐ์Šค ์ด๋ฒคํŠธ๋ฅผ + ๋ฐ›์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ํŽธ๋ฒ•์œผ๋กœ `globalShortcut`์„ ํ†ตํ•ด ํ‚ค ์ž…๋ ฅ์„ ๋ฐ›์„ ์ˆ˜ + ์žˆ์Šต๋‹ˆ๋‹ค. * Windows์˜ ๊ฒฝ์šฐ, ๊ฐ€๋Šฅํ•œ ํƒ€์ž…์œผ๋ก  `toolbar`๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. -`titleBarStyle`์˜ ์†์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค: - -* `default` ๋˜๋Š” ๋ฏธ์ง€์ •: ํ‘œ์ค€ Mac ํšŒ์ƒ‰ ๋ถˆํˆฌ๋ช… ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. -* `hidden`: ํƒ€์ดํ‹€ ๋ฐ”๋ฅผ ์ˆจ๊ธฐ๊ณ  ์ฝ˜ํ…์ธ  ์ „์ฒด๋ฅผ ์œˆ๋„์šฐ ํฌ๊ธฐ์— ๋งž์ถฅ๋‹ˆ๋‹ค. - ํƒ€์ดํ‹€ ๋ฐ”๋Š” ์—†์–ด์ง€์ง€๋งŒ ํ‘œ์ค€ ์ฐฝ ์ปจํŠธ๋กค ("์‹ ํ˜ธ๋“ฑ ๋ฒ„ํŠผ")์€ ์™ผ์ชฝ ์ƒ๋‹จ์— ์œ ์ง€๋ฉ๋‹ˆ๋‹ค. -* `hidden-inset`: `hidden` ํƒ€์ดํ‹€ ๋ฐ” ์†์„ฑ๊ณผ ํ•จ๊ป˜ ์‹ ํ˜ธ๋“ฑ ๋ฒ„ํŠผ์ด ์œˆ๋„์šฐ ๋ชจ์„œ๋ฆฌ๋กœ๋ถ€ํ„ฐ - ์•ฝ๊ฐ„ ๋” ์•ˆ์ชฝ์œผ๋กœ ๋“ค์–ด๊ฐ€๋„๋กํ•ฉ๋‹ˆ๋‹ค. 10.9 Mavericks์—์„  ์ง€์›๋˜์ง€ ์•Š๊ณ  `hidden`์œผ๋กœ - ํด๋ฐฑํ•ฉ๋‹ˆ๋‹ค. - -`webPreferences` ์†์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์†์„ฑ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: - -* `nodeIntegration` Boolean - node(node.js) ํ†ตํ•ฉ ์—ฌ๋ถ€. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. -* `preload` String - ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ง€์ •ํ•˜๋ฉด ํŽ˜์ด์ง€ ๋‚ด์˜ ๋‹ค๋ฅธ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ž‘๋™ํ•˜๊ธฐ ์ „์— - ๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์ง€์ •ํ•œ ์Šคํฌ๋ฆฝํŠธ๋Š” node ํ†ตํ•ฉ ํ™œ์„ฑํ™” ์—ฌ๋ถ€์— ์ƒ๊ด€์—†์ด ์–ธ์ œ๋‚˜ ๋ชจ๋“  - node API์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์†์„ฑ์˜ ์Šคํฌ๋ฆฝํŠธ ๊ฒฝ๋กœ๋Š” ์ ˆ๋Œ€ ๊ฒฝ๋กœ๋กœ ์ง€์ •ํ•ด์•ผ - ํ•ฉ๋‹ˆ๋‹ค. node ํ†ตํ•ฉ์ด ๋น„ํ™œ์„ฑํ™”๋˜์–ด์žˆ์„ ๊ฒฝ์šฐ, preload ์Šคํฌ๋ฆฝํŠธ๋Š” node์˜ global - ์‹ฌ๋ณผ๋“ค์„ ๋‹ค์‹œ global ์Šค์ฝ”ํ”„๋กœ ๋‹ค์‹œ ํฌํ•จ ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - [์—ฌ๊ธฐ](process.md#event-loaded)์˜ ์˜ˆ์‹œ๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. -* `session` [Session](session.md#class-session) - ํŽ˜์ด์ง€์—์„œ ์‚ฌ์šฉํ•  ์„ธ์…˜์„ - ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. Session ๊ฐ์ฒด๋ฅผ ์ง์ ‘์ ์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ๋Œ€์‹ , ํŒŒํ‹ฐ์…˜ ๋ฌธ์ž์—ด์„ ๋ฐ›๋Š” - `partition` ์˜ต์…˜์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. `session`๊ณผ `partition`์ด ๊ฐ™์ด - ์ œ๊ณต๋˜์—ˆ์„ ๊ฒฝ์šฐ `session`์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ ๊ธฐ๋ณธ ์„ธ์…˜์ž…๋‹ˆ๋‹ค. - * `partition` String - ํŽ˜์ด์ง€์—์„œ ์‚ฌ์šฉํ•  ์„ธ์…˜์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ `partition`์ด - `persist:`๋กœ ์‹œ์ž‘ํ•˜๋ฉด ํŽ˜์ด์ง€๋Š” ์ง€์†์„ฑ ์„ธ์…˜์„ ์‚ฌ์šฉํ•˜๋ฉฐ ๋‹ค๋ฅธ ๋ชจ๋“  ์•ฑ ๋‚ด์˜ - ํŽ˜์ด์ง€์—์„œ ๊ฐ™์€ `partition`์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ `persist:` ์ ‘๋‘์–ด๋กœ - ์‹œ์ž‘ํ•˜์ง€ ์•Š์œผ๋ฉด ํŽ˜์ด์ง€๋Š” ์ธ-๋ฉ”๋ชจ๋ฆฌ ์„ธ์…˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€์—์„œ ๊ฐ™์€ - `partition`์„ ์ง€์ •ํ•˜๋ฉด ๊ฐ™์€ ์„ธ์…˜์„ ๊ณต์œ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. `partition`์„ ์ง€์ •ํ•˜์ง€ - ์•Š์œผ๋ฉด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ธฐ๋ณธ ์„ธ์…˜์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. -* `zoomFactor` Number - ํŽ˜์ด์ง€์˜ ๊ธฐ๋ณธ ์คŒ ๊ฐ’์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด `300%`๋ฅผ - ํ‘œํ˜„ํ•˜๋ ค๋ฉด `3.0`์œผ๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `1.0`์ž…๋‹ˆ๋‹ค. -* `javascript` Boolean - ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. -* `webSecurity` Boolean - `false`๋กœ ์ง€์ •ํ•˜๋ฉด same-origin ์ •์ฑ…์„ ๋น„ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. - (์ด ์†์„ฑ์€ ๋ณดํ†ต ์‚ฌ๋žŒ๋“ค์— ์˜ํ•ด ์›น ์‚ฌ์ดํŠธ๋ฅผ ํ…Œ์ŠคํŠธํ•  ๋•Œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค) ๊ทธ๋ฆฌ๊ณ  - `allowDisplayingInsecureContent`์™€ `allowRunningInsecureContent` ๋‘ ์†์„ฑ์„ - ์‚ฌ์šฉ์ž๊ฐ€ `true`๋กœ ์ง€์ •๋˜์ง€ ์•Š์€ ๊ฒฝ์šฐ `true`๋กœ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ - `true`์ž…๋‹ˆ๋‹ค. -* `allowDisplayingInsecureContent` Boolean - https ํŽ˜์ด์ง€์—์„œ http URL์—์„œ - ๋กœ๋“œํ•œ ์ด๋ฏธ์ง€ ๊ฐ™์€ ๋ฆฌ์†Œ์Šค๋ฅผ ํ‘œ์‹œํ•  ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. -* `allowRunningInsecureContent` Boolean - https ํŽ˜์ด์ง€์—์„œ http URL์—์„œ ๋กœ๋“œํ•œ - JavaScript์™€ CSS ๋˜๋Š” ํ”Œ๋Ÿฌ๊ทธ์ธ์„ ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ์žˆ๋„๋ก ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ - `false`์ž…๋‹ˆ๋‹ค. -* `images` Boolean - ์ด๋ฏธ์ง€ ์ง€์›์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. -* `textAreasAreResizable` Boolean - HTML TextArea ์š”์†Œ์˜ ํฌ๊ธฐ๋ฅผ ์žฌ์กฐ์ •์„ - ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. -* `webgl` Boolean - WebGL ์ง€์›์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. -* `webaudio` Boolean - WebAudio ์ง€์›์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. -* `plugins` Boolean - ํ”Œ๋Ÿฌ๊ทธ์ธ ํ™œ์„ฑํ™” ์—ฌ๋ถ€๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. -* `experimentalFeatures` Boolean - Chrome์˜ ์‹คํ—˜์ ์ธ ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. - ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. -* `experimentalCanvasFeatures` Boolean - Chrome์˜ ์‹คํ—˜์ ์ธ ์บ”๋ฒ„์Šค(canvas) ๊ธฐ๋Šฅ์„ - ํ™œ์„ฑํ™”ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. -* `directWrite` Boolean - Windows์—์„œ ํฐํŠธ ๋ Œ๋”๋ง์„ ์œ„ํ•ด DirectWrite๋ฅผ - ์‚ฌ์šฉํ•˜๋Š”์ง€๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. -* `scrollBounce` Boolean - macOS์—์„œ ์Šคํฌ๋กค ํŠ•๊ธฐ๊ธฐ ํšจ๊ณผ (ํƒ„์„ฑ ๋ฐด๋”ฉ)๋ฅผ ํ™œ์„ฑํ™” ํ•ฉ๋‹ˆ๋‹ค. - ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. -* `blinkFeatures` String - ํ™œ์„ฑํ™” ํ•  `CSSVariables,KeyboardEventKey`๊ฐ™์ด `,`๋กœ - ๊ตฌ๋ถ„๋œ ๊ธฐ๋Šฅ ๋ฌธ์ž์—ด๋“ค์˜ ๋ฆฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค. [RuntimeEnabledFeatures.in][blink-feature-string] - ํŒŒ์ผ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -* `disableBlinkFeatures` String - ๋น„ํ™œ์„ฑํ™” ํ•  `CSSVariables,KeyboardEventKey`๊ฐ™์ด - `,`๋กœ ๊ตฌ๋ถ„๋œ ๊ธฐ๋Šฅ ๋ฌธ์ž์—ด๋“ค์˜ ๋ฆฌ์ŠคํŠธ์ž…๋‹ˆ๋‹ค. [RuntimeEnabledFeatures.in][blink-feature-string] - ํŒŒ์ผ์—์„œ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. -* `defaultFontFamily` Object - font-family์˜ ๊ธฐ๋ณธ ํฐํŠธ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. - * `standard` String - ๊ธฐ๋ณธ๊ฐ’ `Times New Roman`. - * `serif` String - ๊ธฐ๋ณธ๊ฐ’ `Times New Roman`. - * `sansSerif` String - ๊ธฐ๋ณธ๊ฐ’ `Arial`. - * `monospace` String - ๊ธฐ๋ณธ๊ฐ’ `Courier New`. -* `defaultFontSize` Integer - ๊ธฐ๋ณธ๊ฐ’ `16`. -* `defaultMonospaceFontSize` Integer - ๊ธฐ๋ณธ๊ฐ’ `13`. -* `minimumFontSize` Integer - ๊ธฐ๋ณธ๊ฐ’ `0`. -* `defaultEncoding` String - ๊ธฐ๋ณธ๊ฐ’ `ISO-8859-1`. -* `backgroundThrottling` Boolean - ํŽ˜์ด์ง€๊ฐ€ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ƒํƒœ์— ์ง„์ž…ํ•  ๋•Œ ์• ๋‹ˆ๋ฉ”์ด์…˜๊ณผ - ํƒ€์ด๋จธ์— ์Šค๋กœํ‹€์„ ์ ์šฉํ• ์ง€ ์—ฌ๋ถ€์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `true`์ž…๋‹ˆ๋‹ค. -* `offscreen` Boolean - ๋ธŒ๋ผ์šฐ์ € ์œˆ๋„์šฐ์— ์˜คํ”„ ์Šคํฌ๋ฆฐ ๋žœ๋”๋ง์„ ์ ์šฉํ• ์ง€ ์—ฌ๋ถ€๋ฅผ - ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ `false`์ž…๋‹ˆ๋‹ค. -* `sandbox` Boolean - Chromium ์šด์˜์ฒด์ œ ์ˆ˜์ค€์˜ ์ƒŒ๋“œ๋ฐ•์Šค ํ™œ์„ฑํ™” ์—ฌ๋ถ€. - ### Instance Events `new BrowserWindow`๋กœ ์ƒ์„ฑ๋œ ๊ฐ์ฒด๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค: @@ -654,6 +652,17 @@ Returns `Boolean` - ์œˆ๋„์šฐ๊ฐ€ ์ „์ฒดํ™”๋ฉด ๋ชจ๋“œ์ธ์ง€ ์—ฌ๋ถ€. ํฌ๊ธฐ๋Š” ๊ด€์—ฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ์ € ์ „์ฒด ์ฝ˜ํ…์ธ  ๋ทฐ ๋‚ด์— ์žˆ๋Š” ๋ชจ๋“  ์—‘์ŠคํŠธ๋ผ ๋„ˆ๋น„, ๋†’์ด ์˜์—ญ์ด ํ•ฉํ•ด์ง‘๋‹ˆ๋‹ค. +#### `win.previewFile(path[, displayName])` _macOS_ + +* `path` String - QuickLook ์œผ๋กœ ๋ฏธ๋ฆฌ ๋ณผ ํŒŒ์ผ์— ๋Œ€ํ•œ ์ ˆ๋Œ€ ๊ฒฝ๋กœ. Quick Look ์ด + ์—ด๊ธฐ ์œ„ํ•œ ํŒŒ์ผ์˜ ์ปจํ…์ธ  ํ˜•์‹์„ ๊ฒฐ์ •ํ•˜๋Š”๋ฐ ๊ฒฝ๋กœ์˜ ํŒŒ์ผ๋ช…๊ณผ ํ™•์žฅ์ž๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ + ๋•Œ๋ฌธ์— ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค. +* `displayName` String (Optional) - Quick Look ๋ชจ๋‹ฌ ๋ทฐ์— ํ‘œ์‹œ๋˜๋Š” ํŒŒ์ผ์˜ ์ด๋ฆ„. + ์ด๊ฒƒ์€ ์ˆœ์ „ํžˆ ๋ณด์—ฌ์ฃผ๋Š” ์šฉ๋„์ด๋ฉฐ ํŒŒ์ผ์˜ ์ปจํ…์ธ  ํ˜•์‹์— ์˜ํ–ฅ์„ ์ฃผ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. + ๊ธฐ๋ณธ๊ฐ’์€ `path` ์ž…๋‹ˆ๋‹ค. + +์ฃผ์–ด์ง„ ๊ฒฝ๋กœ์˜ ํŒŒ์ผ์„ ๋ฏธ๋ฆฌ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด [Quick Look][quick-look] ์„ ์‚ฌ์šฉํ•˜์„ธ์š”. + #### `win.setBounds(bounds[, animate])` * `bounds` [Rectangle](structures/rectangle.md) @@ -1168,3 +1177,4 @@ Returns `BrowserWindow[]` - ๋ชจ๋“  ์ž์‹ ์œˆ๋„์šฐ. [blink-feature-string]: https://cs.chromium.org/chromium/src/third_party/WebKit/Source/platform/RuntimeEnabledFeatures.in [window-levels]: https://developer.apple.com/reference/appkit/nswindow/1664726-window_levels +[quick-look]: https://en.wikipedia.org/wiki/Quick_Look diff --git a/docs-translations/ko-KR/api/clipboard.md b/docs-translations/ko-KR/api/clipboard.md index 890b2349df..a689bca002 100644 --- a/docs-translations/ko-KR/api/clipboard.md +++ b/docs-translations/ko-KR/api/clipboard.md @@ -105,6 +105,19 @@ clipboard.write({ }) ``` +### `clipboard.readFindText()` _macOS_ + +Returns `String` - FindPasteboard ์˜ ํ…์ŠคํŠธ. ์ด ๋ฉ”์†Œ๋“œ๋Š” ๋ Œ๋”๋Ÿฌ ํ”„๋กœ์„ธ์Šค์—์„œ +ํ˜ธ์ถœ๋˜์—ˆ์„ ๋–„ ๋™๊ธฐ IPC ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์บ์‹œ๋œ ๊ฐ’์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ํ™œ์„ฑํ™”๋  ๋•Œ +๋งˆ๋‹ค FindPasteboard ์—์„œ ๋‹ค์‹œ ์ฝ์Šต๋‹ˆ๋‹ค. + +### `clipboard.writeFindText(text)` _macOS_ + +* `text` String + +`text` ๋ฅผ FindPasteboard ์— ์ผ๋ฐ˜ ํ…์ŠคํŠธ๋กœ ์”๋‹ˆ๋‹ค. ์ด ๋ฉ”์†Œ๋“œ๋Š” ๋ Œ๋”๋Ÿฌ +ํ”„๋กœ์„ธ์Šค์—์„œ ํ˜ธ์ถœ๋˜์—ˆ์„ ๋–„ ๋™๊ธฐ IPC ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. + ### `clipboard.clear([type])` * `type` String (optional) diff --git a/docs-translations/ko-KR/api/web-contents.md b/docs-translations/ko-KR/api/web-contents.md index b788afddb3..f95daf9e2c 100644 --- a/docs-translations/ko-KR/api/web-contents.md +++ b/docs-translations/ko-KR/api/web-contents.md @@ -391,31 +391,24 @@ Returns: ์ข…๋ฅ˜. ๊ฐ’์€ `none`, `plainText`, `password`, `other` ์ค‘ ํ•œ ๊ฐ€์ง€๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. * `menuSourceType` String - ์ปจํ…์ŠคํŠธ ๋ฉ”๋‰ด๋ฅผ ํ˜ธ์ถœํ•œ ์ž…๋ ฅ ์†Œ์Šค. ๊ฐ’์€ `none`, `mouse`, `keyboard`, `touch`, `touchMenu` ์ค‘ ํ•œ ๊ฐ€์ง€๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. - * `mediaFlags` Object - ์ปจํ…์ŠคํŠธ ๋ฉ”๋‰ด๊ฐ€ ํ˜ธ์ถœ๋œ ๋ฏธ๋””์–ด ์š”์†Œ์— ๋Œ€ํ•œ ํ”Œ๋ž˜๊ทธ. ์ž์„ธํ•œ - ์‚ฌํ•ญ์€ ์•„๋ž˜๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. + * `mediaFlags` Object - ์ปจํ…์ŠคํŠธ ๋ฉ”๋‰ด๊ฐ€ ํ˜ธ์ถœ๋œ ๋ฏธ๋””์–ด ์š”์†Œ์— ๋Œ€ํ•œ ํ”Œ๋ž˜๊ทธ. + * `inError` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด๊ฐ€ ํฌ๋ž˜์‹œ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€. + * `isPaused` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด๊ฐ€ ์ผ์‹œ์ค‘์ง€๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€. + * `isMuted` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด๊ฐ€ ์Œ์†Œ๊ฑฐ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€. + * `hasAudio` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด๊ฐ€ ์˜ค๋””์˜ค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. + * `isLooping` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด๊ฐ€ ๋ฃจํ”„์ค‘์ธ์ง€ ์—ฌ๋ถ€. + * `isControlsVisible` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด์˜ ์ปจํŠธ๋กค์ด ๋ณด์ด๋Š”์ง€ ์—ฌ๋ถ€. + * `canToggleControls` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด์˜ ์ปจํŠธ๋กค์„ ํ† ๊ธ€ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. + * `canRotate` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด๋ฅผ ๋Œ๋ฆด ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. * `editFlags` Object - ์ด ํ”Œ๋ž˜๊ทธ๋Š” ๋ Œ๋”๋Ÿฌ๊ฐ€ ์–ด๋–ค ํ–‰๋™์„ ์ดํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ - ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. ์ž์„ธํ•œ ์‚ฌํ•ญ์€ ์•„๋ž˜๋ฅผ ์ฐธ๊ณ ํ•˜์„ธ์š”. - -`mediaFlags`๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค: - -* `inError` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด๊ฐ€ ํฌ๋ž˜์‹œ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€. -* `isPaused` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด๊ฐ€ ์ผ์‹œ์ค‘์ง€๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€. -* `isMuted` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด๊ฐ€ ์Œ์†Œ๊ฑฐ๋˜์—ˆ๋Š”์ง€ ์—ฌ๋ถ€. -* `hasAudio` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด๊ฐ€ ์˜ค๋””์˜ค๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. -* `isLooping` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด๊ฐ€ ๋ฃจํ”„์ค‘์ธ์ง€ ์—ฌ๋ถ€. -* `isControlsVisible` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด์˜ ์ปจํŠธ๋กค์ด ๋ณด์ด๋Š”์ง€ ์—ฌ๋ถ€. -* `canToggleControls` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด์˜ ์ปจํŠธ๋กค์„ ํ† ๊ธ€ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. -* `canRotate` Boolean - ๋ฏธ๋””์–ด ๊ฐ์ฒด๋ฅผ ๋Œ๋ฆด ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. - -`editFlags`๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค: - -* `canUndo` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ์‹คํ–‰ ์ทจ์†Œํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. -* `canRedo` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ๋‹ค์‹œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. -* `canCut` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ์ž˜๋ผ๋‚ด๊ธฐ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. -* `canCopy` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ๋ณต์‚ฌ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. -* `canPaste` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ๋ถ™์—ฌ๋„ฃ๊ธฐ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. -* `canDelete` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ์‚ญ์ œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. -* `canSelectAll` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ๋ชจ๋‘ ์„ ํƒ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. + ํ‘œ์‹œํ•ฉ๋‹ˆ๋‹ค. + * `canUndo` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ์‹คํ–‰ ์ทจ์†Œํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. + * `canRedo` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ๋‹ค์‹œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. + * `canCut` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ์ž˜๋ผ๋‚ด๊ธฐ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. + * `canCopy` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ๋ณต์‚ฌ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. + * `canPaste` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ๋ถ™์—ฌ๋„ฃ๊ธฐ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. + * `canDelete` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ์‚ญ์ œ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. + * `canSelectAll` Boolean - ๋ Œ๋”๋Ÿฌ์—์„œ ๋ชจ๋‘ ์„ ํƒ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์—ฌ๋ถ€. ์ƒˆ๋กœ์šด ์ปจํ…์ŠคํŠธ ๋ฉ”๋‰ด์˜ ์ œ์–ด๊ฐ€ ํ•„์š”ํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค. diff --git a/docs-translations/ko-KR/api/web-frame.md b/docs-translations/ko-KR/api/web-frame.md index 7c88d176d9..b3362d962a 100644 --- a/docs-translations/ko-KR/api/web-frame.md +++ b/docs-translations/ko-KR/api/web-frame.md @@ -85,11 +85,11 @@ webFrame.setSpellCheckProvider('en-US', true, { * `scheme` String * `options` Object(optional) - * `secure` (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. - * `bypassCSP` (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. - * `allowServiceWorkers` (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. - * `supportFetchAPI` (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. - * `corsEnabled` (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. + * `secure` Boolean - (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. + * `bypassCSP` Boolean - (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. + * `allowServiceWorkers` Boolean - (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. + * `supportFetchAPI` Boolean - (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. + * `corsEnabled` Boolean - (optional) ๊ธฐ๋ณธ๊ฐ’ ์ฐธ. `scheme`๋ฅผ ๋ณด์•ˆ๋œ ์Šคํ‚ด์œผ๋กœ ๋“ฑ๋กํ•ฉ๋‹ˆ๋‹ค. ๋ฆฌ์†Œ์Šค์— ๋Œ€ํ•ด ๋ณด์•ˆ ์ •์ฑ…์„ ์šฐํšŒํ•˜๋ฉฐ, ServiceWorker์˜ ๋“ฑ๋ก๊ณผ fetch API๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. From fbe4394bbd3936f22b658a856320ecc130578f20 Mon Sep 17 00:00:00 2001 From: tinydew4 Date: Wed, 26 Oct 2016 15:40:45 +0000 Subject: [PATCH 126/148] Clean unnecessary sentences on web-contents.md --- docs/api/web-contents.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/api/web-contents.md b/docs/api/web-contents.md index 74b54da4bf..96e3eee7df 100644 --- a/docs/api/web-contents.md +++ b/docs/api/web-contents.md @@ -398,7 +398,7 @@ Returns: * `menuSourceType` String - Input source that invoked the context menu. Can be `none`, `mouse`, `keyboard`, `touch`, `touchMenu`. * `mediaFlags` Object - The flags for the media element the context menu was - invoked on. See more about this below. + invoked on. * `inError` Boolean - Whether the media element has crashed. * `isPaused` Boolean - Whether the media element is paused. * `isMuted` Boolean - Whether the media element is muted. @@ -409,8 +409,8 @@ Returns: * `canToggleControls` Boolean - Whether the media element's controls are toggleable. * `canRotate` Boolean - Whether the media element can be rotated. - * `editFlags` Object - These flags indicate whether the renderer believes it is - able to perform the corresponding action. See more about this below. + * `editFlags` Object - These flags indicate whether the renderer believes it + is able to perform the corresponding action. * `canUndo` Boolean - Whether the renderer believes it can undo. * `canRedo` Boolean - Whether the renderer believes it can redo. * `canCut` Boolean - Whether the renderer believes it can cut. From 29470dd018cbd9cc0523407b8eccebd4807adb7b Mon Sep 17 00:00:00 2001 From: Christian Engvall Date: Wed, 26 Oct 2016 21:33:48 +0200 Subject: [PATCH 127/148] Adding documentation about hidden-inset --- docs/api/frameless-window.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/docs/api/frameless-window.md b/docs/api/frameless-window.md index 6395a33dc7..cab93bc7ba 100644 --- a/docs/api/frameless-window.md +++ b/docs/api/frameless-window.md @@ -27,12 +27,24 @@ both the titlebar and window controls, you may want to have the title bar hidden and your content extend to the full window size, yet still preserve the window controls ("traffic lights") for standard window actions. You can do so by specifying the new `titleBarStyle` option: +#### Hidden +Results in a hidden title bar and a full size content window, yet the title bar still has the standard window controls (โ€œtraffic lightsโ€) in the top left. ```javascript const {BrowserWindow} = require('electron') let win = new BrowserWindow({titleBarStyle: 'hidden'}) win.show() ``` +#### Hidden-inset +Results in a hidden title bar with an alternative look where the traffic light buttons are slightly more inset from the window edge. + +```javascript +const {BrowserWindow} = require('electron') +let win = new BrowserWindow({titleBarStyle: 'hidden-inset'}) +win.show() +``` + + ## Transparent window From a2b3abbf47f2adc8f945f3e12ce6f756670d03ca Mon Sep 17 00:00:00 2001 From: liusi Date: Thu, 27 Oct 2016 17:42:43 +0800 Subject: [PATCH 128/148] incorrect position when restored from maximize-on-top-drag under Windows #7630 --- atom/browser/native_window_views.cc | 1 - atom/browser/native_window_views.h | 16 -------- atom/browser/native_window_views_win.cc | 51 +++++++------------------ 3 files changed, 13 insertions(+), 55 deletions(-) diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index d2f2077151..b830c9a7ac 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -327,7 +327,6 @@ NativeWindowViews::NativeWindowViews( last_window_state_ = ui::SHOW_STATE_FULLSCREEN; else last_window_state_ = ui::SHOW_STATE_NORMAL; - last_normal_bounds_ = GetBounds(); #endif } diff --git a/atom/browser/native_window_views.h b/atom/browser/native_window_views.h index caaf64ba71..379dc4ceaa 100644 --- a/atom/browser/native_window_views.h +++ b/atom/browser/native_window_views.h @@ -211,22 +211,6 @@ class NativeWindowViews : public NativeWindow, ui::WindowShowState last_window_state_; - // There's an issue with restore on Windows, that sometimes causes the Window - // to receive the wrong size (#2498). To circumvent that, we keep tabs on the - // size of the window while in the normal state (not maximized, minimized or - // fullscreen), so we restore it correctly. - gfx::Rect last_normal_bounds_; - - // last_normal_bounds_ may or may not require update on WM_MOVE. When a - // window is maximized, it is moved (WM_MOVE) to maximum size first and then - // sized (WM_SIZE). In this case, last_normal_bounds_ should not update. We - // keep last_normal_bounds_candidate_ as a candidate which will become valid - // last_normal_bounds_ if the moves are consecutive with no WM_SIZE event in - // between. - gfx::Rect last_normal_bounds_candidate_; - - bool consecutive_moves_; - // In charge of running taskbar related APIs. TaskbarHost taskbar_host_; diff --git a/atom/browser/native_window_views_win.cc b/atom/browser/native_window_views_win.cc index 85230addb0..d6f57b6aea 100644 --- a/atom/browser/native_window_views_win.cc +++ b/atom/browser/native_window_views_win.cc @@ -125,7 +125,6 @@ bool NativeWindowViews::PreHandleMSG( return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param)); return false; case WM_SIZE: { - consecutive_moves_ = false; // Handle window state change. HandleSizeEvent(w_param, l_param); return false; @@ -135,15 +134,6 @@ bool NativeWindowViews::PreHandleMSG( ::GetWindowRect(GetAcceleratedWidget(), (LPRECT)l_param); return false; } - case WM_MOVE: { - if (last_window_state_ == ui::SHOW_STATE_NORMAL) { - if (consecutive_moves_) - last_normal_bounds_ = last_normal_bounds_candidate_; - last_normal_bounds_candidate_ = GetBounds(); - consecutive_moves_ = true; - } - return false; - } default: return false; } @@ -162,35 +152,20 @@ void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) { NotifyWindowMinimize(); break; case SIZE_RESTORED: - if (last_window_state_ == ui::SHOW_STATE_NORMAL) { - // Window was resized so we save it's new size. - last_normal_bounds_ = GetBounds(); - } else { - switch (last_window_state_) { - case ui::SHOW_STATE_MAXIMIZED: + switch (last_window_state_) { + case ui::SHOW_STATE_MAXIMIZED: + last_window_state_ = ui::SHOW_STATE_NORMAL; + NotifyWindowUnmaximize(); + break; + case ui::SHOW_STATE_MINIMIZED: + if (IsFullscreen()) { + last_window_state_ = ui::SHOW_STATE_FULLSCREEN; + NotifyWindowEnterFullScreen(); + } else { last_window_state_ = ui::SHOW_STATE_NORMAL; - - // When the window is restored we resize it to the previous known - // normal size. - SetBounds(last_normal_bounds_, false); - - NotifyWindowUnmaximize(); - break; - case ui::SHOW_STATE_MINIMIZED: - if (IsFullscreen()) { - last_window_state_ = ui::SHOW_STATE_FULLSCREEN; - NotifyWindowEnterFullScreen(); - } else { - last_window_state_ = ui::SHOW_STATE_NORMAL; - - // When the window is restored we resize it to the previous known - // normal size. - SetBounds(last_normal_bounds_, false); - - NotifyWindowRestore(); - } - break; - } + NotifyWindowRestore(); + } + break; } break; } From 933e013e7e1841d475daab00acb3680ce0cb394d Mon Sep 17 00:00:00 2001 From: Vitalie Lazu Date: Thu, 27 Oct 2016 14:58:16 +0300 Subject: [PATCH 129/148] Fixed typo --- docs-translations/ru-RU/tutorial/application-distribution.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs-translations/ru-RU/tutorial/application-distribution.md b/docs-translations/ru-RU/tutorial/application-distribution.md index 7659523cae..5ef6c1591b 100644 --- a/docs-translations/ru-RU/tutorial/application-distribution.md +++ b/docs-translations/ru-RU/tutorial/application-distribution.md @@ -52,7 +52,7 @@ electron/resources/ โ””โ”€โ”€ app.asar ``` -ะ‘ะพะปัŒัˆะต ะดะตั‚ะฐะปะตะน ะผะพะถะฝะพ ะฝะฐะนั‚ะธ ะฒ [ะธะฝัั‚ัƒั€ะบั†ะธะธ ะฟะพ ัƒะฟะฐะบะพะฒะบะต ะฟั€ะธะปะพะถะตะฝะธั](application-packaging.md). +ะ‘ะพะปัŒัˆะต ะดะตั‚ะฐะปะตะน ะผะพะถะฝะพ ะฝะฐะนั‚ะธ ะฒ [ะธะฝัั‚ั€ัƒะบั†ะธะธ ะฟะพ ัƒะฟะฐะบะพะฒะบะต ะฟั€ะธะปะพะถะตะฝะธั](application-packaging.md). ## ะ ะตะฑั€ะตะฝะดะธั€ะพะฒะฐะฝะธะต ัะบะฐั‡ะฐะฝะฝั‹ั… ะธัะฟะพะปะฝัะตะผั‹ั… ั„ะฐะนะปะพะฒ From c8263a9a1852648af79d64fb0d3c75bd457517a7 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 27 Oct 2016 10:41:43 -0700 Subject: [PATCH 130/148] Add newlines and backticks --- docs/api/frameless-window.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/api/frameless-window.md b/docs/api/frameless-window.md index cab93bc7ba..7eeedae658 100644 --- a/docs/api/frameless-window.md +++ b/docs/api/frameless-window.md @@ -27,7 +27,9 @@ both the titlebar and window controls, you may want to have the title bar hidden and your content extend to the full window size, yet still preserve the window controls ("traffic lights") for standard window actions. You can do so by specifying the new `titleBarStyle` option: -#### Hidden + +#### `hidden` + Results in a hidden title bar and a full size content window, yet the title bar still has the standard window controls (โ€œtraffic lightsโ€) in the top left. ```javascript @@ -35,7 +37,9 @@ const {BrowserWindow} = require('electron') let win = new BrowserWindow({titleBarStyle: 'hidden'}) win.show() ``` -#### Hidden-inset + +#### `hidden-inset` + Results in a hidden title bar with an alternative look where the traffic light buttons are slightly more inset from the window edge. ```javascript From d9f3355dea00380e1e9123157d836a15eb7905cc Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 27 Oct 2016 10:42:31 -0700 Subject: [PATCH 131/148] Remove excess newlines --- docs/api/frameless-window.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/api/frameless-window.md b/docs/api/frameless-window.md index 7eeedae658..3ef5cdc93e 100644 --- a/docs/api/frameless-window.md +++ b/docs/api/frameless-window.md @@ -48,8 +48,6 @@ let win = new BrowserWindow({titleBarStyle: 'hidden-inset'}) win.show() ``` - - ## Transparent window By setting the `transparent` option to `true`, you can also make the frameless From d50cabddc044ff524be0df4cd520b9fd54dba813 Mon Sep 17 00:00:00 2001 From: tinydew4 Date: Fri, 28 Oct 2016 08:42:57 +0000 Subject: [PATCH 132/148] [ko] Update the korean docs up to '2006d64' commit. --- docs-translations/ko-KR/api/accelerator.md | 18 +++++++++++++++++- .../ko-KR/api/frameless-window.md | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/docs-translations/ko-KR/api/accelerator.md b/docs-translations/ko-KR/api/accelerator.md index a606608a6a..51401143cb 100644 --- a/docs-translations/ko-KR/api/accelerator.md +++ b/docs-translations/ko-KR/api/accelerator.md @@ -2,13 +2,29 @@ > ํ‚ค๋ณด๋“œ ๋‹จ์ถ•ํ‚ค๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. -Accelerator๋Š” `+` ๋ฌธ์ž๋ฅผ ํ†ตํ•ด ์—ฌ๋Ÿฌ ํ˜ผํ•ฉํ‚ค์™€ ํ‚ค์ฝ”๋“œ๋ฅผ ๊ฒฐํ•ฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. +Accelerator ๋Š” `+` ๋ฌธ์ž๋กœ ๊ฒฐํ•ฉ๋œ ์—ฌ๋Ÿฌ ์ˆ˜์‹์–ด์™€ ํ‚ค ์ฝ”๋“œ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋Š” +๋ฌธ์ž์—ด์ž…๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ํ‚ค๋ณด๋“œ ๋‹จ์ถ•ํ‚ค๋ฅผ ์ •์˜ํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์˜ˆ์‹œ: * `CommandOrControl+A` * `CommandOrControl+Shift+Z` +๋‹จ์ถ•ํ‚ค๋Š” [`globalShortcut`](global-shortcut.md) ๋ชจ๋“ˆ์˜ +[`register`](global-shortcut.md#globalshortcutregisteraccelerator-callback) +๋ฉ”์†Œ๋“œ๋กœ ๋“ฑ๋ก๋ฉ๋‹ˆ๋‹ค. ์˜ˆ์‹œ: + +```javascript +const {app, globalShortcut} = require('electron') + +app.on('ready', () => { + // '์ปค๋งจ๋“œ ๋˜๋Š” ์ปจํŠธ๋กค+Y' ๋‹จ์ถ•ํ‚ค ๋ฆฌ์Šค๋„ˆ ๋“ฑ๋ก. + globalShortcut.register('CommandOrControl+Y', () => { + // ์ปค๋งจ๋“œ/์ปจํŠธ๋กค๊ณผ Y ๊ฐ€ ๋ˆŒ๋ ธ์„ ๋•Œ ํ•  ๋™์ž‘. + }) +}) +``` + ## ํ”Œ๋žซํผ์— ๊ด€๋ จํ•˜์—ฌ ์ฃผ์˜ํ•  ์  Linux์™€ Windows์—์„œ๋Š” `Command`ํ‚ค๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹ ์— diff --git a/docs-translations/ko-KR/api/frameless-window.md b/docs-translations/ko-KR/api/frameless-window.md index 8df016e6a0..0d27fd4abd 100644 --- a/docs-translations/ko-KR/api/frameless-window.md +++ b/docs-translations/ko-KR/api/frameless-window.md @@ -24,8 +24,26 @@ macOS 10.9 Mavericks ์ดํ›„์˜ ์ตœ์‹  ๋ฒ„์ „๋ถ€ํ„ฐ๋Š” ํ…Œ๋‘๋ฆฌ๊ฐ€ ์—†๋Š” ์ฐฝ์„ ๋น„ํ™œ์„ฑํ™”ํ•˜๋Š” ๋Œ€์‹  ์ƒˆ๋กœ์šด `titleBarStyle` ์˜ต์…˜์„ ํ†ตํ•ด ์ œ๋ชฉ๋งŒ ์ˆจ๊ธฐ๊ณ  ์ฐฝ ๊ตฌ์„ฑ ์š”์†Œ ("์‹ ํ˜ธ๋“ฑ ๋ฒ„ํŠผ")์˜ ๊ธฐ๋Šฅ๊ณผ ์ฐฝ ํฌ๊ธฐ๋ฅผ ๊ทธ๋Œ€๋กœ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค: +#### `hidden` + +์ œ๋ชฉ ํ‘œ์‹œ์ค„์„ ์ˆจ๊ธฐ๊ณ  ์ปจํ…์ธ  ์ฐฝ์„ ์ „์ฒด ํฌ๊ธฐ๋กœ ํ•ฉ๋‹ˆ๋‹ค. ์ œ๋ชฉ ํ‘œ์‹œ์ค„์€ ์—ฌ์ „ํžˆ ์™ผ์ชฝ +์ƒ๋‹จ์— ํ‘œ์ค€ ์ฐฝ ์ปจํŠธ๋กค (โ€œ์‹ ํ˜ธ๋“ฑโ€) ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. + ```javascript +const {BrowserWindow} = require('electron') let win = new BrowserWindow({titleBarStyle: 'hidden'}) +win.show() +``` + +#### `hidden-inset` + +์ œ๋ชฉ ํ‘œ์‹œ์ค„์„ ์ˆจ๊ธฐ๊ณ  ์ฐฝ ๊ฐ€์žฅ์ž๋ฆฌ์— ์•ฝ๊ฐ„ ๋” ๋“ค์–ด๊ฐ„ ์‹ ํ˜ธ๋“ฑ ๋ฒ„ํŠผ ๋ชจ์–‘์œผ๋กœ +๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค. + +```javascript +const {BrowserWindow} = require('electron') +let win = new BrowserWindow({titleBarStyle: 'hidden-inset'}) +win.show() ``` ## ํˆฌ๋ช…ํ•œ ์ฐฝ ๋งŒ๋“ค๊ธฐ From 4b0b875d6f8077200e15f0a50452ddd10ba1d163 Mon Sep 17 00:00:00 2001 From: Julian Engel Date: Fri, 28 Oct 2016 18:04:51 +0300 Subject: [PATCH 133/148] Added example usage for the default port According to Issue ##7756 I added the example usage. --- docs/tutorial/debugging-main-process.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/tutorial/debugging-main-process.md b/docs/tutorial/debugging-main-process.md index 9bd8d219c6..5458c1b2c2 100644 --- a/docs/tutorial/debugging-main-process.md +++ b/docs/tutorial/debugging-main-process.md @@ -16,6 +16,12 @@ Electron will listen for V8 debugger protocol messages on the specified `port`, an external debugger will need to connect on this port. The default `port` is `5858`. +An example debug command on the default port: + +``` +$ node_modules/.bin/electron --debug=5859 . +# main process runs... +``` ### `--debug-brk=[port]` Like `--debug` but pauses execution on the first line of JavaScript. From a0772dbbe9957474e4a9397d256f624deb9f2706 Mon Sep 17 00:00:00 2001 From: Ian Olsen Date: Fri, 28 Oct 2016 14:32:48 -0700 Subject: [PATCH 134/148] fix link to Mac debug instructions --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index 8e0ed98c55..1a5c4ce7cb 100644 --- a/docs/README.md +++ b/docs/README.md @@ -96,7 +96,7 @@ an issue: * [Build Instructions (macOS)](development/build-instructions-osx.md) * [Build Instructions (Windows)](development/build-instructions-windows.md) * [Build Instructions (Linux)](development/build-instructions-linux.md) -* [Debug Instructions (macOS)](development/debug-instructions-macos.md) +* [Debug Instructions (macOS)](development/debugging-instructions-macos.md) * [Debug Instructions (Windows)](development/debug-instructions-windows.md) * [Setting Up Symbol Server in debugger](development/setting-up-symbol-server.md) * [Documentation Styleguide](styleguide.md) From f613d8d0d0791399a8641f4a009196dd469fb177 Mon Sep 17 00:00:00 2001 From: Laurent Le Van Date: Sat, 29 Oct 2016 18:10:57 +0300 Subject: [PATCH 135/148] [docs-translations\fr-FR]Add of the tutorial folder and create supported-platforms.md in French --- .../fr-FR/tutorial/supported-platforms.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs-translations/fr-FR/tutorial/supported-platforms.md diff --git a/docs-translations/fr-FR/tutorial/supported-platforms.md b/docs-translations/fr-FR/tutorial/supported-platforms.md new file mode 100644 index 0000000000..930ae647e2 --- /dev/null +++ b/docs-translations/fr-FR/tutorial/supported-platforms.md @@ -0,0 +1,27 @@ +# Plateformes supportรฉes + +Les plateformes suivantes sont supportรฉes par Electron: + +### macOS + +Seulement les binaires en 64bit sont fournis sur macOS, et la version minimale de macOS suportรฉe est macOS 10.9. + +### Windows + +Windows 7 et suivants sont supportรฉs, les systรจmes d'exploitation plus ancien de sont pas supportรฉ +(et ne marchent pas). + +Les binaires `ia32` (`x86`) et `x64` (`amd64`) sont fournis pour Windows. +Veuillez noter que la version `ARM` de Windows n'est pas supportรฉ ร  ce jour. + +### Linux + +Les binaires prรฉcompilรฉs `ia32` (`i686`) et `x64` (`amd64`) d'Electron sont compilรฉs sous +Ubuntu 12.04, le binaire `arm` est compilรฉ ร  partir d'une version ARM v7 hard-float ABI et +NEON pour Debian Wheezy. + +Le binaire prรฉcompilรฉ peut tourner sur une distribution si la distribution contient les librairies liรฉes ร  Electron, sur la plateforme de compilation. Donc il est ganranti de pouvoir le faire marcher seulement sur Ubuntu 12.04, mais les plateformes suivantes sont aussi vรฉrifiรฉes comme capable de faire marcher la version prรฉcompilรฉ des binaires d'Electron : + +* Ubuntu 12.04 et suivantes +* Fedora 21 +* Debian 8 From b376c2993790ecaf6ae89582542787af88566abc Mon Sep 17 00:00:00 2001 From: Laurent Le Van Date: Sun, 30 Oct 2016 14:22:35 +0200 Subject: [PATCH 136/148] [docs-translations/fr-FR]Correct some typos (double space deletion and 'de' to 'ne') in supported-platforms.md --- docs-translations/fr-FR/tutorial/supported-platforms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs-translations/fr-FR/tutorial/supported-platforms.md b/docs-translations/fr-FR/tutorial/supported-platforms.md index 930ae647e2..23168642a1 100644 --- a/docs-translations/fr-FR/tutorial/supported-platforms.md +++ b/docs-translations/fr-FR/tutorial/supported-platforms.md @@ -4,11 +4,11 @@ Les plateformes suivantes sont supportรฉes par Electron: ### macOS -Seulement les binaires en 64bit sont fournis sur macOS, et la version minimale de macOS suportรฉe est macOS 10.9. +Seulement les binaires en 64bit sont fournis sur macOS, et la version minimale de macOS suportรฉe est macOS 10.9. ### Windows -Windows 7 et suivants sont supportรฉs, les systรจmes d'exploitation plus ancien de sont pas supportรฉ +Windows 7 et suivants sont supportรฉs, les systรจmes d'exploitation plus ancien ne sont pas supportรฉ (et ne marchent pas). Les binaires `ia32` (`x86`) et `x64` (`amd64`) sont fournis pour Windows. From 4ee308fcc277d3443c3b65edb4a648d595411ce1 Mon Sep 17 00:00:00 2001 From: Samuel Attard Date: Mon, 31 Oct 2016 12:43:57 +1100 Subject: [PATCH 137/148] Quick fix up of net docs --- docs/api/net.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/api/net.md b/docs/api/net.md index d14fe3dc02..2669c749b7 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -74,7 +74,7 @@ interface and it is therefore an [EventEmitter](https://nodejs.org/api/events.ht ### `new ClientRequest(options)` -* `options` Object or String - If `options` is a String, it is interpreted as +* `options` (Object | String) - If `options` is a String, it is interpreted as the request URL. If it is an object, it is expected to fully specify an HTTP request via the following properties: @@ -225,11 +225,12 @@ before first write. Trying to call it after the first write will throw an error. #### `request.write(chunk[, encoding][, callback])` -* `chunk` String or Buffer - A chunk of the request body's data. If it is a +* `chunk` (String | Buffer) - A chunk of the request body's data. If it is a string, it is converted into a Buffer using the specified encoding. * `encoding` String (optional) - Used to convert string chunks into Buffer objects. Defaults to 'utf-8'. -* `callback` Function (optional) - Called after the write operation ends. +* `callback` Function (optional) - Called after the write operation ends. + `callback` is essentially a dummy function introduced in the purpose of keeping similarity with the Node.js API. It is called asynchronously in the next tick after `chunk` content have been delivered to the Chromium networking layer. @@ -242,7 +243,7 @@ it is not allowed to add or remove a custom header. #### `request.end([chunk][, encoding][, callback])` -* `chunk` String or Buffer (optional) +* `chunk` (String | Buffer) (optional) * `encoding` String (optional) * `callback` Function (optional) From dda3fcef91381d31459cd7cdf157eb5c42b201b2 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 28 Oct 2016 10:34:11 -0700 Subject: [PATCH 138/148] Add failing spec for notification permission crash --- .../pages/permissions/notification.html | 10 ++++++++++ spec/webview-spec.js | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 spec/fixtures/pages/permissions/notification.html diff --git a/spec/fixtures/pages/permissions/notification.html b/spec/fixtures/pages/permissions/notification.html new file mode 100644 index 0000000000..264fc9faf8 --- /dev/null +++ b/spec/fixtures/pages/permissions/notification.html @@ -0,0 +1,10 @@ + diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 059fc72288..01fbfe8953 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -946,6 +946,24 @@ describe(' tag', function () { setUpRequestHandler(webview, 'openExternal', done) document.body.appendChild(webview) }) + + it('emits when using Notification.requestPermission', function (done) { + webview.addEventListener('ipc-message', function (e) { + assert.equal(e.channel, 'message') + assert.deepEqual(e.args, ['granted']) + done() + }) + webview.src = 'file://' + fixtures + '/pages/permissions/notification.html' + webview.partition = 'permissionTest' + webview.setAttribute('nodeintegration', 'on') + session.fromPartition(webview.partition).setPermissionRequestHandler(function (webContents, permission, callback) { + if (webContents.getId() === webview.getId()) { + assert.equal(permission, 'notifications') + callback(true) + } + }) + document.body.appendChild(webview) + }) }) describe('.getWebContents', function () { From 611614c649ede3d13e01df9cef6b6e6d621ce7b9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 28 Oct 2016 11:14:14 -0700 Subject: [PATCH 139/148] Use equal/deepEqual for channel/args asserts --- spec/webview-spec.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 01fbfe8953..0e166d3382 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -903,8 +903,8 @@ describe(' tag', function () { it('emits when using navigator.getUserMedia api', function (done) { webview.addEventListener('ipc-message', function (e) { - assert(e.channel, 'message') - assert(e.args, ['PermissionDeniedError']) + assert.equal(e.channel, 'message') + assert.deepEqual(e.args, ['PermissionDeniedError']) done() }) webview.src = 'file://' + fixtures + '/pages/permissions/media.html' @@ -916,8 +916,8 @@ describe(' tag', function () { it('emits when using navigator.geolocation api', function (done) { webview.addEventListener('ipc-message', function (e) { - assert(e.channel, 'message') - assert(e.args, ['ERROR(1): User denied Geolocation']) + assert.equal(e.channel, 'message') + assert.deepEqual(e.args, ['User denied Geolocation']) done() }) webview.src = 'file://' + fixtures + '/pages/permissions/geolocation.html' @@ -929,8 +929,8 @@ describe(' tag', function () { it('emits when using navigator.requestMIDIAccess api', function (done) { webview.addEventListener('ipc-message', function (e) { - assert(e.channel, 'message') - assert(e.args, ['SecurityError']) + assert.equal(e.channel, 'message') + assert.deepEqual(e.args, ['SecurityError']) done() }) webview.src = 'file://' + fixtures + '/pages/permissions/midi.html' From 078c924760d6524360d0d206fbec033e9fea57b0 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 28 Oct 2016 11:54:06 -0700 Subject: [PATCH 140/148] Upgrade brightray for notification crash fix --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index a55f26ec2f..148277c597 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit a55f26ec2f53ccd961381234c941564b4fd4403f +Subproject commit 148277c5972b60fbfa839d80d227119bd3f65604 From 3f8e173452fd6f5384de230dee5df346c9b30c22 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Fri, 28 Oct 2016 14:53:02 -0700 Subject: [PATCH 141/148] Call callback asynchronously to match original issue --- spec/webview-spec.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/webview-spec.js b/spec/webview-spec.js index 0e166d3382..d1acbeb80c 100644 --- a/spec/webview-spec.js +++ b/spec/webview-spec.js @@ -959,7 +959,9 @@ describe(' tag', function () { session.fromPartition(webview.partition).setPermissionRequestHandler(function (webContents, permission, callback) { if (webContents.getId() === webview.getId()) { assert.equal(permission, 'notifications') - callback(true) + setTimeout(function () { + callback(true) + }, 10) } }) document.body.appendChild(webview) From 651b0c0f825ae4b67fc83c3ae19c283ae1f2711c Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Mon, 31 Oct 2016 08:59:26 -0700 Subject: [PATCH 142/148] fixed a couple of typos --- docs/api/net.md | 2 +- lib/browser/api/net.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/net.md b/docs/api/net.md index d14fe3dc02..01954dd97e 100644 --- a/docs/api/net.md +++ b/docs/api/net.md @@ -136,7 +136,7 @@ Emitted when an authenticating proxy is asking for user credentials. The `callback` function is expected to be called back with user credentials: -* `usrename` String +* `username` String * `password` String ```JavaScript diff --git a/lib/browser/api/net.js b/lib/browser/api/net.js index e8b6f2a473..e128bc3b05 100644 --- a/lib/browser/api/net.js +++ b/lib/browser/api/net.js @@ -203,7 +203,7 @@ class ClientRequest extends EventEmitter { urlRequest.on('login', (event, authInfo, callback) => { this.emit('login', authInfo, (username, password) => { - // If null or undefined usrename/password, force to empty string. + // If null or undefined username/password, force to empty string. if (username === null || username === undefined) { username = '' } From 53ff706cd2b78e9c61af5be4b5f2c0f39f9c55a9 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 31 Oct 2016 09:02:18 -0700 Subject: [PATCH 143/148] Upgrade brigthray for notification crash fix --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 148277c597..bb35b4ada1 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 148277c5972b60fbfa839d80d227119bd3f65604 +Subproject commit bb35b4ada1ab9285251087656a9fdef488796509 From 7c48dd54e1461e1d1255dcc8f99c9f14f81ff51d Mon Sep 17 00:00:00 2001 From: DaLun Date: Mon, 31 Oct 2016 11:21:43 -0500 Subject: [PATCH 144/148] ZH_TW docs api/structures/cookie add (#7793) * Update cookie.md * Update cookie.md * Update task.md * ZH_TW docs /structures/cookie add * Fix a word && add new docs * Update task.md * Update cookie.md --- docs-translations/zh-TW/api/structures/cookie.md | 11 +++++++++++ docs-translations/zh-TW/api/structures/task.md | 8 ++++++++ 2 files changed, 19 insertions(+) create mode 100644 docs-translations/zh-TW/api/structures/cookie.md create mode 100644 docs-translations/zh-TW/api/structures/task.md diff --git a/docs-translations/zh-TW/api/structures/cookie.md b/docs-translations/zh-TW/api/structures/cookie.md new file mode 100644 index 0000000000..0358cf1642 --- /dev/null +++ b/docs-translations/zh-TW/api/structures/cookie.md @@ -0,0 +1,11 @@ +# Cookie ็‰ฉไปถ + +* `name` ๅญ—ไธฒ - cookie ็š„ๅๅญ—ใ€‚ +* `value` ๅญ—ไธฒ - cookie ็š„ๅ€ผใ€‚ +* `domain` ๅญ—ไธฒ - cookie ็š„ๅŸŸๅใ€‚ +* `hostOnly` ๅญ—ไธฒ - cookie ๆ˜ฏๅฆ็‚บ Host-Only.ใ€‚ +* `path` ๅญ—ไธฒ - cookie ็š„่ทฏๅพ‘ใ€‚ +* `secure` ๅธƒๆž— - cookie ็š„็ถฒๅŸŸๆ˜ฏๅฆๅฎ‰ๅ…จ ๏ผˆhttps)ใ€‚ +* `httpOnly` ๅธƒๆž— - cookie ๆ˜ฏๅฆๅช่ƒฝ้‹่กŒๅœจ HTTPใ€‚ +* `session` ๅธƒๆž— - cookie ็‚บ ็ŸญๆœŸ session ๆˆ–่€… ้•ทๆœŸ cookie๏ผŒ่‹ฅๆ˜ฏ้•ทๆœŸ cookie ๅพ—ๅŒ…ๅซไธ€ๅ€‹ๆˆชๆญขๆ—ฅๆœŸใ€‚ +* `expirationDate` ้›™็ฒพๅบฆๆตฎ้ปžๆ•ธ (ๅฏ้ธ) - cookie ็š„ๆˆชๆญขๆ—ฅๆœŸ๏ผŒ็•ถ `session` ่จญๅฎš็‚บ ๆ™‚ๅฏ็”จ๏ผŒๅ€ผ็‚บ UNIXๆ™‚้–“ใ€‚ diff --git a/docs-translations/zh-TW/api/structures/task.md b/docs-translations/zh-TW/api/structures/task.md new file mode 100644 index 0000000000..e9d58e3cf1 --- /dev/null +++ b/docs-translations/zh-TW/api/structures/task.md @@ -0,0 +1,8 @@ +# Task ็‰ฉไปถ + +* `program` ๅญ—ไธฒ - ็จ‹ๅผๅŸท่กŒ็š„่ทฏๅพ‘๏ผŒ้€šๅธธไฝ ๆ‡‰่ฉฒๆŒ‡ๅฎš `process.execPath`๏ผŒๆญคๅ€ผ็‚บ็•ถๅ‰็จ‹ๅผๅŸท่กŒ็š„่ทฏๅพ‘ใ€‚ +* `arguments` ๅญ—ไธฒ - `program` ๅœจๅ‘ฝไปคๅˆ—ไธ‹ๅŸท่กŒ็š„้™„ๅŠ ๅƒๆ•ธใ€‚ +* `title` ๅญ—ไธฒ - JumpList ๅ…ง้กฏ็คบ็š„ๆจ™้กŒใ€‚ +* `description` ๅญ—ไธฒ - ้—œๆ–ผๆญค็‰ฉไปถ็š„ๆ่ฟฐใ€‚ +* `iconPath` ๅญ—ไธฒ - ๆญค็‰ฉไปถ็š„ icon ่ทฏๅพ‘๏ผŒ่ขซ้กฏ็คบๅœจ JumpList ไธญ๏ผŒ้€šๅธธไฝ ๅฏไปฅๆŒ‡ๅฎš `process.execPath`ๅŽป้กฏ็คบ็•ถๅ‰็‰ฉไปถ็š„ icon ใ€‚ +* `iconIndex` ๆ•ธๅญ— - icon ็š„็ดขๅผ•๏ผŒๅฆ‚ๆžœไธ€ๅ€‹ๆช”ๆกˆๅŒ…็”ฑๅ…ฉๅ€‹ๆˆ–ไปฅไธŠ็š„็š„ icon, ่จญๅฎšๆญคๅ€ผๅŽปๆŒ‡ๅฎš icon, ๅฆ‚ๆžœๆช”ๆกˆๅ…งๅชๆœ‰ไธ€ๅ€‹ icon, ๆญคๅ€ผ็‚บ 0 ใ€‚ From 651a2d4399c7d3c894f6683d8bf8f2fe05a5f0eb Mon Sep 17 00:00:00 2001 From: DaLun Date: Mon, 31 Oct 2016 11:21:56 -0500 Subject: [PATCH 145/148] ZH_TW docs update (#7797) * Update cookie.md * Update cookie.md * Update task.md * ZH_TW docs /structures/cookie add * Fix a word && add new docs * Update task.md * Update cookie.md * new update --- docs-translations/zh-TW/api/structures/certificate.md | 9 +++++++++ .../zh-TW/api/structures/memory-usage-details.md | 8 ++++++++ 2 files changed, 17 insertions(+) create mode 100644 docs-translations/zh-TW/api/structures/certificate.md create mode 100644 docs-translations/zh-TW/api/structures/memory-usage-details.md diff --git a/docs-translations/zh-TW/api/structures/certificate.md b/docs-translations/zh-TW/api/structures/certificate.md new file mode 100644 index 0000000000..e1a65e271f --- /dev/null +++ b/docs-translations/zh-TW/api/structures/certificate.md @@ -0,0 +1,9 @@ +# Certificate ็‰ฉไปถ ๏ผˆๆ†‘่ญ‰๏ผ‰ + +* `data` ๅญ—ไธฒ - PEM ๅŠ ๅฏ†่ณ‡ๆ–™ใ€‚ +* `issuerName` ๅญ—ไธฒ - ๆ†‘่ญ‰็™ผ่กŒ่€…็š„ๅๅญ—ใ€‚ +* `subjectName` ๅญ—ไธฒ - ๆ†‘่ญ‰ไฝฟ็”จ่€…็š„ๅๅญ—ใ€‚ +* `serialNumber` ๅญ—ไธฒ - ๆ†‘่ญ‰ๅบ่™Ÿใ€‚ +* `validStart` ๆ•ธๅญ— - ๆ†‘่ญ‰้–‹ๅง‹ๆ—ฅๆœŸ๏ผŒๅ€ผ็‚บ UNIX ๆ™‚้–“ใ€‚ +* `validExpiry` ๆ•ธๅญ— - ๆ†‘่ญ‰็ตๆŸๆ—ฅๆœŸ๏ผŒๅ€ผ็‚บ UNIX ๆ™‚้–“ใ€‚ +* `fingerprint` ๅญ—ไธฒ - ๆ†‘่ญ‰ๆŒ‡็ด‹ใ€‚ diff --git a/docs-translations/zh-TW/api/structures/memory-usage-details.md b/docs-translations/zh-TW/api/structures/memory-usage-details.md new file mode 100644 index 0000000000..b19eb41329 --- /dev/null +++ b/docs-translations/zh-TW/api/structures/memory-usage-details.md @@ -0,0 +1,8 @@ +# MemoryUsageDetails ็‰ฉไปถ + +* `count` ๆ•ธๅญ— +* `size` ๆ•ธๅญ— +* `liveSize` ๆ•ธๅญ— +* `decodedSize` ๆ•ธๅญ— +* `purgedSize` ๆ•ธๅญ— +* `purgeableSize` ๆ•ธๅญ— From 48eaee0c0e4f987fdd4078336647ba66b53a8617 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 31 Oct 2016 09:27:42 -0700 Subject: [PATCH 146/148] Match example to node inspector doc --- docs/tutorial/debugging-main-process.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/tutorial/debugging-main-process.md b/docs/tutorial/debugging-main-process.md index 5458c1b2c2..fb5759e499 100644 --- a/docs/tutorial/debugging-main-process.md +++ b/docs/tutorial/debugging-main-process.md @@ -16,12 +16,10 @@ Electron will listen for V8 debugger protocol messages on the specified `port`, an external debugger will need to connect on this port. The default `port` is `5858`. -An example debug command on the default port: +```shell +electron --debug=5858 your/app +``` -``` -$ node_modules/.bin/electron --debug=5859 . -# main process runs... -``` ### `--debug-brk=[port]` Like `--debug` but pauses execution on the first line of JavaScript. From e9a2792b5580524d5192ee218bb7d8cb3fc023cd Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 31 Oct 2016 11:34:53 -0700 Subject: [PATCH 147/148] Format URL passed to BrowserWindow.loadURL --- docs/tutorial/quick-start.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/tutorial/quick-start.md b/docs/tutorial/quick-start.md index 682016e45b..d95957a48c 100644 --- a/docs/tutorial/quick-start.md +++ b/docs/tutorial/quick-start.md @@ -81,6 +81,8 @@ example being: ```javascript const {app, BrowserWindow} = require('electron') +const path = require('path') +const url = require('url') // Keep a global reference of the window object, if you don't, the window will // be closed automatically when the JavaScript object is garbage collected. @@ -91,7 +93,11 @@ function createWindow () { win = new BrowserWindow({width: 800, height: 600}) // and load the index.html of the app. - win.loadURL(`file://${__dirname}/index.html`) + win.loadURL(url.format({ + pathname: path.join(__dirname, 'index.html'), + protocol: 'file:', + slashes: true + })) // Open the DevTools. win.webContents.openDevTools() @@ -225,8 +231,10 @@ repository. $ git clone https://github.com/electron/electron-quick-start # Go into the repository $ cd electron-quick-start -# Install dependencies and run the app -$ npm install && npm start +# Install dependencies +$ npm install +# Run the app +$ npm start ``` For more example apps, see the From 038718717c5babee042d6cd12e17f6d21372ea45 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Mon, 31 Oct 2016 12:40:49 -0700 Subject: [PATCH 148/148] Add initial ready-to-show spec --- spec/api-browser-window-spec.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spec/api-browser-window-spec.js b/spec/api-browser-window-spec.js index ae99be6808..e268af969d 100644 --- a/spec/api-browser-window-spec.js +++ b/spec/api-browser-window-spec.js @@ -118,6 +118,13 @@ describe('browser-window module', function () { w.loadURL('about:blank') }) + it('should emit ready-to-show event', function (done) { + w.on('ready-to-show', function () { + done() + }) + w.loadURL('about:blank') + }) + it('should emit did-get-response-details event', function (done) { // expected {fileName: resourceType} pairs var expectedResources = {