Compare commits

...

35 Commits

Author SHA1 Message Date
Electron Bot
b15a3ee2be Bump v3.0.0-nightly.20180904 2018-09-04 17:16:17 -07:00
Shelley Vohr
7b043ac554 chore: add release-artifact-cleanup script (#14447) 2018-09-04 11:36:48 -07:00
trop[bot]
89a6f1efbb feat: add getUploadProgress API to the net API (#14446) 2018-09-04 12:26:50 -05:00
trop[bot]
ce592a5705 feat: allow setting window shape (backport: 3-0-x) (#14445)
* feat: allow setting window shape

This binds Widget::SetShape, an API that already exists in Chromium (for
Windows and Linux). It's a more reliable method of having some parts of
your window be "click-through" than the current `setIgnoreMouseEvents`
API, which messes around with the `WS_EX_LAYERED` window style on
Windows, causing strange bugs and incompatibility with hardware
acceleration.

* update docs
2018-09-04 09:22:11 -07:00
trop[bot]
12087b74e8 feat: allow some features during beta (backport: 3-0-x) (#14449)
* feat: allow all nonbreaking changes during beta

Changes the version policy: currently only nonbreaking bug/security
fixes are allowed during beta. This change would allow all nonbreaking
changes, e.g. new features, during beta.

* refactor: clarify criteria for changes during beta

* Update electron-versioning.md
2018-09-04 11:12:30 -05:00
trop[bot]
d365078022 fix: webview.focus() should move page focus to webview (#14428) 2018-09-03 13:26:41 +10:00
trop[bot]
3dbd84c224 docs: add notes on OOPIF webview's behaviors (#14409) 2018-08-31 14:48:38 -07:00
trop[bot]
2e479ff799 fix: use flexbox to style webview (backport: 3-0-x) (#14408)
* fix: use flexbox to style webview

* docs: remove notes on browserplugin based webview
2018-08-31 14:48:08 -07:00
trop[bot]
a341ae450a fix: allow Tray with title only (without icon) on Mac (#14384) 2018-09-01 08:49:56 +12:00
Roller Bot
0aec308681 chore: bump libcc (3-0-x) (#14391)
* chore: bump libcc submodule to dc2e7ebd2867d4329ebe7b6849e89cf3dc0afa8e

* chore: bump libcc in DEPS to dc2e7ebd2867d4329ebe7b6849e89cf3dc0afa8e
2018-08-31 10:38:56 -07:00
Samuel Attard
8e9c5b8338 chore: fix bootstrap script on 3-0-x (#14361) 2018-08-29 09:55:54 -07:00
trop[bot]
6bc1e37156 docs: keyboard listeners no longer work on webview (#14372) 2018-08-29 19:26:33 +09:00
Electron Bot
7da7dd85e3 Bump v3.0.0-beta.8 2018-08-28 23:04:31 -07:00
trop[bot]
ccf8a797dc fix: use OS process handle to clear object registry (#14364)
RenderProcessHost switch can happen between ipc calls when
speculative process are invvolved, which will lead to deletion
of entries on current context. Use OS process handles to
uniquely associate a destruction handler for a render process.
2018-08-28 22:55:42 -07:00
Milan Burda
3301e05f33 fix: don't expose desktopCapturer in sandboxed renderers if the feature is disabled (#14345) 2018-08-28 19:51:07 -05:00
trop[bot]
b1c22ba531 fix: emit focus/blur events for webview (backport: 3-0-x) (#14359)
* fix: emit focus/blur events for webview

* test: webview can emit focus event
2018-08-28 13:38:11 -05:00
trop[bot]
873f39b159 fix: crash when tray is destroyed (#14357)
Release the view of status item before destroying it,
gives chance to perform cleanup on the view.
2018-08-28 13:37:38 -05:00
trop[bot]
11864e9e08 fix: create persistent channel ID store when cookie store is persistent (#14358) 2018-08-28 13:37:09 -05:00
trop[bot]
c8a21dbb92 fix: don't crash on tray.setContextMenu(null) (#14331) 2018-08-27 13:27:41 -07:00
trop[bot]
97058837e7 fix: dont parse arguments after a -- in the inspector (#14333) 2018-08-27 14:44:53 -05:00
trop[bot]
ff539c1d61 fix: don't expose view APIs when not enabled (#14321) 2018-08-27 13:00:19 +09:00
trop[bot]
9237d40e09 fix: issue 10962, crash when open devtool (backport: 3-0-x) (#14303)
* fix: crash when opening devtool (#10962)

* fix: fixed linting issues
2018-08-25 12:23:06 -07:00
Shelley Vohr
4721dc0856 fix: opt into location services once device service has been started (backport: 3-0-x) (#14289)
* fix: opt into location services once device service has been started (#14253)

* fix: opt into location services once device service has been started

* refactor: provide fake location provider to mock geolocation reponses

* chore: add spec for navigator.geolocation api using fake location provider

* fix conflict
2018-08-24 08:23:15 -07:00
Electron Bot
1f7fd985dd Bump v3.0.0-nightly.20180823 2018-08-23 21:23:48 -07:00
Roller Bot
d432e420ae chore: bump libcc (3-0-x) (#14280)
* chore: bump libcc submodule to 7165af0ca9863529f28e493568ae3d105eddcdef

* chore: bump libcc in DEPS to 7165af0ca9863529f28e493568ae3d105eddcdef
2018-08-23 21:12:09 -07:00
trop[bot]
635c3f53d8 fix: add method and referrer properties to app login event (backport: 3-0-x) (#14277)
* refactor: remove brightray/network_delegate.{cc|h}

* refactor: respond to http requests through network delegate
2018-08-23 20:47:16 +09:00
trop[bot]
ba703deee2 Print error when removed webview attribute is used (backport: 3-0-x) (#14274)
* chore: print error when removed webview attribute is used

* docs: document removed webview features
2018-08-23 15:42:08 +09:00
Electron Bot
b03178105d Bump v3.0.0-beta.7 2018-08-22 11:13:36 -07:00
Samuel Attard
ef0a6d9a1c fix: inheritance of webPreferences sub properties 2018-08-22 12:19:11 -05:00
trop[bot]
4c7af6a429 fix: notify request context shutdown on IO before cleanup (#14092) 2018-08-22 08:24:56 -07:00
trop[bot]
d1886c5d22 ci: add better logging around request failures for releasing (#14245) 2018-08-21 13:31:44 -07:00
trop[bot]
c558dc2d7d chore: retry for the meta dumper a few times (#14243) 2018-08-21 13:31:13 -07:00
Electron Bot
be68cfd4ea Bump v3.0.0-nightly.20180821 2018-08-21 12:07:19 -07:00
Samuel Attard
115a15c356 Revert "Bump v3.0.0-nightly.20180821"
This reverts commit d4fb904450.
2018-08-21 11:45:21 -07:00
Electron Bot
d4fb904450 Bump v3.0.0-nightly.20180821 2018-08-21 11:16:44 -07:00
93 changed files with 1526 additions and 1035 deletions

View File

@@ -27,6 +27,12 @@ declare_args() {
enable_desktop_capturer = true
enable_run_as_node = true
enable_osr = true
# Provide a fake location provider for mocking
# the geolocation responses. Disable it if you
# need to test with chromium's location provider.
# Should not be enabled for release build.
enable_fake_location_provider = !is_official_build
}
filenames_gypi = exec_script(
@@ -312,6 +318,13 @@ static_library("electron_lib") {
sources = filenames_gypi.lib_sources
set_sources_assignment_filter(sources_assignment_filter)
if (enable_fake_location_provider) {
defines += [
"OVERRIDE_LOCATION_PROVIDER"
]
sources += filenames_gypi.lib_sources_location_provider
}
if (enable_run_as_node) {
sources += [
"atom/app/node_main.cc",

2
DEPS
View File

@@ -2,7 +2,7 @@ vars = {
'chromium_version':
'63.0.3239.150',
'libchromiumcontent_revision':
'92dc0accfae5cd133fa2a6758ae6b3ff4ff7e569',
'dc2e7ebd2867d4329ebe7b6849e89cf3dc0afa8e',
'node_version':
'v9.7.0-33-g538a5023af',
'native_mate_revision':

View File

@@ -667,17 +667,17 @@ void App::OnNewWindowForTab() {
}
#endif
void App::OnLogin(LoginHandler* login_handler,
void App::OnLogin(scoped_refptr<LoginHandler> login_handler,
const base::DictionaryValue& request_details) {
v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate());
bool prevent_default = false;
content::WebContents* web_contents = login_handler->GetWebContents();
if (web_contents) {
prevent_default =
Emit("login", WebContents::CreateFrom(isolate(), web_contents),
request_details, login_handler->auth_info(),
base::Bind(&PassLoginInformation, WrapRefCounted(login_handler)));
prevent_default = Emit(
"login", WebContents::CreateFrom(isolate(), web_contents),
request_details, login_handler->auth_info(),
base::Bind(&PassLoginInformation, base::RetainedRef(login_handler)));
}
// Default behavior is to always cancel the auth.

View File

@@ -98,7 +98,7 @@ class App : public AtomBrowserClient::Delegate,
void OnActivate(bool has_visible_windows) override;
void OnWillFinishLaunching() override;
void OnFinishLaunching(const base::DictionaryValue& launch_info) override;
void OnLogin(LoginHandler* login_handler,
void OnLogin(scoped_refptr<LoginHandler> login_handler,
const base::DictionaryValue& request_details) override;
void OnAccessibilitySupportChanged() override;
void OnPreMainMessageLoopRun() override;

View File

@@ -5,6 +5,7 @@
#include "atom/browser/api/atom_api_cookies.h"
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/request_context_delegate.h"
#include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/gurl_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
@@ -253,9 +254,10 @@ void SetCookieOnIO(scoped_refptr<net::URLRequestContextGetter> getter,
Cookies::Cookies(v8::Isolate* isolate, AtomBrowserContext* browser_context)
: browser_context_(browser_context) {
Init(isolate);
auto subscription = browser_context->RegisterCookieChangeCallback(
base::Bind(&Cookies::OnCookieChanged, base::Unretained(this)));
browser_context->set_cookie_change_subscription(std::move(subscription));
cookie_change_subscription_ =
browser_context->GetRequestContextDelegate()
->RegisterCookieChangeCallback(
base::Bind(&Cookies::OnCookieChanged, base::Unretained(this)));
}
Cookies::~Cookies() {}

View File

@@ -9,7 +9,7 @@
#include "atom/browser/api/trackable_object.h"
#include "atom/browser/net/cookie_details.h"
#include "base/callback.h"
#include "base/callback_list.h"
#include "native_mate/handle.h"
#include "net/cookies/canonical_cookie.h"
@@ -59,6 +59,8 @@ class Cookies : public mate::TrackableObject<Cookies> {
void OnCookieChanged(const CookieDetails*);
private:
std::unique_ptr<base::CallbackList<void(const CookieDetails*)>::Subscription>
cookie_change_subscription_;
scoped_refptr<AtomBrowserContext> browser_context_;
DISALLOW_COPY_AND_ASSIGN(Cookies);

View File

@@ -78,13 +78,13 @@ class Protocol : public mate::TrackableObject<Protocol> {
net::URLRequest* request,
net::NetworkDelegate* network_delegate) const override {
RequestJob* request_job = new RequestJob(request, network_delegate);
request_job->SetHandlerInfo(isolate_, request_context_.get(), handler_);
request_job->SetHandlerInfo(isolate_, request_context_, handler_);
return request_job;
}
private:
v8::Isolate* isolate_;
scoped_refptr<net::URLRequestContextGetter> request_context_;
net::URLRequestContextGetter* request_context_;
Protocol::Handler handler_;
DISALLOW_COPY_AND_ASSIGN(CustomProtocolHandler);

View File

@@ -244,7 +244,7 @@ class ResolveProxyHelper {
: callback_(callback),
original_thread_(base::ThreadTaskRunnerHandle::Get()) {
scoped_refptr<net::URLRequestContextGetter> context_getter =
browser_context->url_request_context_getter();
browser_context->GetRequestContext();
context_getter->GetNetworkTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(&ResolveProxyHelper::ResolveProxy,
base::Unretained(this), context_getter, url));
@@ -453,15 +453,6 @@ void SetDevToolsNetworkEmulationClientIdInIO(
network_delegate->SetDevToolsNetworkEmulationClientId(client_id);
}
// Clear protocol handlers in IO thread.
void ClearJobFactoryInIO(
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter) {
auto* job_factory = static_cast<AtomURLRequestJobFactory*>(
request_context_getter->job_factory());
if (job_factory)
job_factory->Clear();
}
void DestroyGlobalHandle(v8::Isolate* isolate,
const v8::Global<v8::Value>& global_handle) {
v8::Locker locker(isolate);
@@ -495,10 +486,6 @@ Session::Session(v8::Isolate* isolate, AtomBrowserContext* browser_context)
}
Session::~Session() {
auto* getter = browser_context_->GetRequestContext();
content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
base::BindOnce(ClearJobFactoryInIO, base::RetainedRef(getter)));
content::BrowserContext::GetDownloadManager(browser_context())
->RemoveObserver(this);
DestroyGlobalHandle(isolate(), cookies_);
@@ -597,10 +584,9 @@ void Session::EnableNetworkEmulation(const mate::Dictionary& options) {
devtools_network_emulation_client_id_, std::move(conditions));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
&SetDevToolsNetworkEmulationClientIdInIO,
base::RetainedRef(browser_context_->url_request_context_getter()),
devtools_network_emulation_client_id_));
base::BindOnce(&SetDevToolsNetworkEmulationClientIdInIO,
base::RetainedRef(browser_context_->GetRequestContext()),
devtools_network_emulation_client_id_));
}
void Session::DisableNetworkEmulation() {
@@ -609,10 +595,9 @@ void Session::DisableNetworkEmulation() {
devtools_network_emulation_client_id_, std::move(conditions));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(
&SetDevToolsNetworkEmulationClientIdInIO,
base::RetainedRef(browser_context_->url_request_context_getter()),
std::string()));
base::BindOnce(&SetDevToolsNetworkEmulationClientIdInIO,
base::RetainedRef(browser_context_->GetRequestContext()),
std::string()));
}
void Session::SetCertVerifyProc(v8::Local<v8::Value> val,

View File

@@ -571,6 +571,10 @@ double TopLevelWindow::GetOpacity() {
return window_->GetOpacity();
}
void TopLevelWindow::SetShape(const std::vector<gfx::Rect>& rects) {
window_->widget()->SetShape(std::make_unique<std::vector<gfx::Rect>>(rects));
}
void TopLevelWindow::SetRepresentedFilename(const std::string& filename) {
window_->SetRepresentedFilename(filename);
}
@@ -993,6 +997,7 @@ void TopLevelWindow::BuildPrototype(v8::Isolate* isolate,
.SetMethod("hasShadow", &TopLevelWindow::HasShadow)
.SetMethod("setOpacity", &TopLevelWindow::SetOpacity)
.SetMethod("getOpacity", &TopLevelWindow::GetOpacity)
.SetMethod("setShape", &TopLevelWindow::SetShape)
.SetMethod("setRepresentedFilename",
&TopLevelWindow::SetRepresentedFilename)
.SetMethod("getRepresentedFilename",

View File

@@ -146,6 +146,7 @@ class TopLevelWindow : public mate::TrackableObject<TopLevelWindow>,
bool HasShadow();
void SetOpacity(const double opacity);
double GetOpacity();
void SetShape(const std::vector<gfx::Rect>& rects);
void SetRepresentedFilename(const std::string& filename);
std::string GetRepresentedFilename();
void SetDocumentEdited(bool edited);

View File

@@ -210,7 +210,7 @@ void Tray::PopUpContextMenu(mate::Arguments* args) {
void Tray::SetContextMenu(v8::Isolate* isolate, mate::Handle<Menu> menu) {
menu_.Reset(isolate, menu.ToV8());
tray_icon_->SetContextMenu(menu->model());
tray_icon_->SetContextMenu(menu.IsEmpty() ? nullptr : menu->model());
}
gfx::Rect Tray::GetBounds() {

View File

@@ -125,6 +125,18 @@ bool URLRequest::ResponseState::Failed() const {
return IsFlagSet(ResponseStateFlags::kFailed);
}
mate::Dictionary URLRequest::GetUploadProgress(v8::Isolate* isolate) {
mate::Dictionary progress = mate::Dictionary::CreateEmpty(isolate);
if (atom_request_) {
progress.Set("active", true);
atom_request_->GetUploadProgress(&progress);
} else {
progress.Set("active", false);
}
return progress;
}
URLRequest::URLRequest(v8::Isolate* isolate, v8::Local<v8::Object> wrapper) {
InitWith(isolate, wrapper);
}
@@ -183,6 +195,7 @@ void URLRequest::BuildPrototype(v8::Isolate* isolate,
.SetMethod("setChunkedUpload", &URLRequest::SetChunkedUpload)
.SetMethod("followRedirect", &URLRequest::FollowRedirect)
.SetMethod("_setLoadFlags", &URLRequest::SetLoadFlags)
.SetMethod("getUploadProgress", &URLRequest::GetUploadProgress)
.SetProperty("notStarted", &URLRequest::NotStarted)
.SetProperty("finished", &URLRequest::Finished)
// Response APi

View File

@@ -112,6 +112,7 @@ class URLRequest : public mate::EventEmitter<URLRequest> {
void OnResponseData(scoped_refptr<const net::IOBufferWithSize> data);
void OnResponseCompleted();
void OnError(const std::string& error, bool isRequestError);
mate::Dictionary GetUploadProgress(v8::Isolate* isolate);
protected:
explicit URLRequest(v8::Isolate* isolate, v8::Local<v8::Object> wrapper);

View File

@@ -766,7 +766,8 @@ void WebContents::RenderViewCreated(content::RenderViewHost* render_view_host) {
}
void WebContents::RenderViewDeleted(content::RenderViewHost* render_view_host) {
Emit("render-view-deleted", render_view_host->GetProcess()->GetID());
Emit("render-view-deleted", render_view_host->GetProcess()->GetID(),
base::GetProcId(render_view_host->GetProcess()->GetHandle()));
}
void WebContents::RenderProcessGone(base::TerminationStatus status) {
@@ -1722,10 +1723,6 @@ void WebContents::OnCursorChange(const content::WebCursor& cursor) {
}
}
void WebContents::SetSize(v8::Local<v8::Value>) {
// TODO(zcbenz): Remove this method in 4.0.
}
bool WebContents::IsGuest() const {
return type_ == WEB_VIEW;
}
@@ -2022,7 +2019,6 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
.SetMethod("beginFrameSubscription", &WebContents::BeginFrameSubscription)
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
.SetMethod("startDrag", &WebContents::StartDrag)
.SetMethod("setSize", &WebContents::SetSize)
.SetMethod("isGuest", &WebContents::IsGuest)
.SetMethod("attachToIframe", &WebContents::AttachToIframe)
.SetMethod("isOffscreen", &WebContents::IsOffScreen)

View File

@@ -198,7 +198,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
void CapturePage(mate::Arguments* args);
// Methods for creating <webview>.
void SetSize(v8::Local<v8::Value>);
bool IsGuest() const;
void AttachToIframe(content::WebContents* embedder_web_contents,
int embedder_frame_id);

View File

@@ -95,7 +95,7 @@ void WebRequest::SetListener(Method method, Event type, mate::Arguments* args) {
}
brightray::URLRequestContextGetter* url_request_context_getter =
browser_context_->url_request_context_getter();
browser_context_->GetRequestContext();
if (!url_request_context_getter)
return;
BrowserThread::PostTask(

View File

@@ -17,7 +17,6 @@
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
#include "atom/browser/atom_speech_recognition_manager_delegate.h"
#include "atom/browser/child_web_contents_tracker.h"
#include "atom/browser/login_handler.h"
#include "atom/browser/native_window.h"
#include "atom/browser/session_preferences.h"
#include "atom/browser/web_contents_permission_helper.h"
@@ -46,6 +45,7 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/web_preferences.h"
#include "device/geolocation/public/cpp/location_provider.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "ppapi/host/ppapi_host.h"
#include "services/network/public/cpp/resource_request_body.h"
@@ -62,6 +62,10 @@
#include "net/ssl/client_cert_store.h"
#endif
#if defined(OVERRIDE_LOCATION_PROVIDER)
#include "atom/browser/fake_location_provider.h"
#endif // defined(OVERRIDE_LOCATION_PROVIDER)
using content::BrowserThread;
namespace atom {
@@ -495,17 +499,13 @@ std::unique_ptr<net::ClientCertStore> AtomBrowserClient::CreateClientCertStore(
#endif
}
content::ResourceDispatcherHostLoginDelegate*
AtomBrowserClient::CreateLoginDelegate(
net::AuthChallengeInfo* auth_info,
content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
bool is_main_frame,
const GURL& url,
bool first_auth_attempt,
const base::Callback<void(const base::Optional<net::AuthCredentials>&)>&
auth_required_callback) {
return new LoginHandler(auth_info, web_contents_getter, url,
auth_required_callback);
std::unique_ptr<device::LocationProvider>
AtomBrowserClient::OverrideSystemLocationProvider() {
#if defined(OVERRIDE_LOCATION_PROVIDER)
return std::make_unique<FakeLocationProvider>();
#else
return nullptr;
#endif
}
brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(

View File

@@ -106,14 +106,8 @@ class AtomBrowserClient : public brightray::BrowserClient,
void SiteInstanceDeleting(content::SiteInstance* site_instance) override;
std::unique_ptr<net::ClientCertStore> CreateClientCertStore(
content::ResourceContext* resource_context) override;
content::ResourceDispatcherHostLoginDelegate* CreateLoginDelegate(
net::AuthChallengeInfo* auth_info,
content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
bool is_main_frame,
const GURL& url,
bool first_auth_attempt,
const base::Callback<void(const base::Optional<net::AuthCredentials>&)>&
auth_required_callback) override;
std::unique_ptr<device::LocationProvider> OverrideSystemLocationProvider()
override;
// brightray::BrowserClient:
brightray::BrowserMainParts* OverrideCreateBrowserMainParts(

View File

@@ -4,59 +4,30 @@
#include "atom/browser/atom_browser_context.h"
#include "atom/browser/api/atom_api_protocol.h"
#include "atom/browser/atom_blob_reader.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/atom_download_manager_delegate.h"
#include "atom/browser/atom_permission_manager.h"
#include "atom/browser/browser.h"
#include "atom/browser/net/about_protocol_handler.h"
#include "atom/browser/net/asar/asar_protocol_handler.h"
#include "atom/browser/net/atom_cert_verifier.h"
#include "atom/browser/net/atom_network_delegate.h"
#include "atom/browser/net/atom_url_request_job_factory.h"
#include "atom/browser/net/cookie_details.h"
#include "atom/browser/net/http_protocol_handler.h"
#include "atom/browser/request_context_delegate.h"
#include "atom/browser/web_view_manager.h"
#include "atom/common/atom_version.h"
#include "atom/common/chrome_version.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/memory/ptr_util.h"
#include "base/path_service.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/task_scheduler/post_task.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_registry_simple.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/user_agent.h"
#include "net/ftp/ftp_network_layer.h"
#include "net/url_request/data_protocol_handler.h"
#include "net/url_request/ftp_protocol_handler.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_intercepting_job_factory.h"
#include "url/url_constants.h"
using content::BrowserThread;
namespace atom {
namespace {
class NoCacheBackend : public net::HttpCache::BackendFactory {
int CreateBackend(net::NetLog* net_log,
std::unique_ptr<disk_cache::Backend>* backend,
const net::CompletionCallback& callback) override {
return net::ERR_FAILED;
}
};
std::string RemoveWhitespace(const std::string& str) {
std::string trimmed;
if (base::RemoveChars(str, " ", &trimmed))
@@ -70,7 +41,8 @@ std::string RemoveWhitespace(const std::string& str) {
AtomBrowserContext::AtomBrowserContext(const std::string& partition,
bool in_memory,
const base::DictionaryValue& options)
: brightray::BrowserContext(partition, in_memory) {
: brightray::BrowserContext(partition, in_memory),
url_request_context_getter_(nullptr) {
// Construct user agent string.
Browser* browser = Browser::Get();
std::string name = RemoveWhitespace(browser->GetName());
@@ -86,87 +58,24 @@ AtomBrowserContext::AtomBrowserContext(const std::string& partition,
user_agent_ = content::BuildUserAgentFromProduct(user_agent);
// Read options.
use_cache_ = true;
options.GetBoolean("cache", &use_cache_);
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
bool use_cache = !command_line->HasSwitch(switches::kDisableHttpCache);
options.GetBoolean("cache", &use_cache);
request_context_delegate_.reset(new RequestContextDelegate(use_cache));
// Initialize Pref Registry in brightray.
InitPrefs();
}
AtomBrowserContext::~AtomBrowserContext() {}
AtomBrowserContext::~AtomBrowserContext() {
url_request_context_getter_->set_delegate(nullptr);
}
void AtomBrowserContext::SetUserAgent(const std::string& user_agent) {
user_agent_ = user_agent;
}
std::unique_ptr<base::CallbackList<void(const CookieDetails*)>::Subscription>
AtomBrowserContext::RegisterCookieChangeCallback(
const base::Callback<void(const CookieDetails*)>& cb) {
return cookie_change_sub_list_.Add(cb);
}
std::unique_ptr<net::NetworkDelegate>
AtomBrowserContext::CreateNetworkDelegate() {
return std::make_unique<AtomNetworkDelegate>();
}
std::string AtomBrowserContext::GetUserAgent() {
return user_agent_;
}
std::unique_ptr<net::URLRequestJobFactory>
AtomBrowserContext::CreateURLRequestJobFactory(
content::ProtocolHandlerMap* protocol_handlers) {
std::unique_ptr<AtomURLRequestJobFactory> job_factory(
new AtomURLRequestJobFactory);
for (auto& it : *protocol_handlers) {
job_factory->SetProtocolHandler(it.first,
base::WrapUnique(it.second.release()));
}
protocol_handlers->clear();
job_factory->SetProtocolHandler(url::kAboutScheme,
base::WrapUnique(new AboutProtocolHandler));
job_factory->SetProtocolHandler(
url::kDataScheme, base::WrapUnique(new net::DataProtocolHandler));
job_factory->SetProtocolHandler(
url::kFileScheme,
base::WrapUnique(
new asar::AsarProtocolHandler(base::CreateTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}))));
job_factory->SetProtocolHandler(
url::kHttpScheme,
base::WrapUnique(new HttpProtocolHandler(url::kHttpScheme)));
job_factory->SetProtocolHandler(
url::kHttpsScheme,
base::WrapUnique(new HttpProtocolHandler(url::kHttpsScheme)));
job_factory->SetProtocolHandler(
url::kWsScheme,
base::WrapUnique(new HttpProtocolHandler(url::kWsScheme)));
job_factory->SetProtocolHandler(
url::kWssScheme,
base::WrapUnique(new HttpProtocolHandler(url::kWssScheme)));
auto* host_resolver =
url_request_context_getter()->GetURLRequestContext()->host_resolver();
job_factory->SetProtocolHandler(
url::kFtpScheme, net::FtpProtocolHandler::Create(host_resolver));
return std::move(job_factory);
}
net::HttpCache::BackendFactory*
AtomBrowserContext::CreateHttpCacheBackendFactory(
const base::FilePath& base_path) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (!use_cache_ || command_line->HasSwitch(switches::kDisableHttpCache))
return new NoCacheBackend;
else
return brightray::BrowserContext::CreateHttpCacheBackendFactory(base_path);
}
content::DownloadManagerDelegate*
AtomBrowserContext::GetDownloadManagerDelegate() {
if (!download_manager_delegate_.get()) {
@@ -189,26 +98,6 @@ content::PermissionManager* AtomBrowserContext::GetPermissionManager() {
return permission_manager_.get();
}
std::unique_ptr<net::CertVerifier> AtomBrowserContext::CreateCertVerifier(
brightray::RequireCTDelegate* ct_delegate) {
return base::WrapUnique(new AtomCertVerifier(ct_delegate));
}
std::vector<std::string> AtomBrowserContext::GetCookieableSchemes() {
auto default_schemes = brightray::BrowserContext::GetCookieableSchemes();
const auto& standard_schemes = atom::api::GetStandardSchemes();
default_schemes.insert(default_schemes.end(), standard_schemes.begin(),
standard_schemes.end());
return default_schemes;
}
void AtomBrowserContext::NotifyCookieChange(const net::CanonicalCookie& cookie,
bool removed,
net::CookieChangeCause cause) {
CookieDetails cookie_details(&cookie, removed, cause);
cookie_change_sub_list_.Notify(&cookie_details);
}
void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) {
pref_registry->RegisterFilePathPref(prefs::kSelectFileLastDirectory,
base::FilePath());
@@ -219,6 +108,16 @@ void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) {
pref_registry->RegisterDictionaryPref(prefs::kDevToolsFileSystemPaths);
}
std::string AtomBrowserContext::GetUserAgent() const {
return user_agent_;
}
void AtomBrowserContext::OnMainRequestContextCreated(
brightray::URLRequestContextGetter* getter) {
getter->set_delegate(request_context_delegate_.get());
url_request_context_getter_ = getter;
}
AtomBlobReader* AtomBrowserContext::GetBlobReader() {
if (!blob_reader_.get()) {
content::ChromeBlobStorageContext* blob_context =

View File

@@ -8,17 +8,15 @@
#include <string>
#include <vector>
#include "base/callback_list.h"
#include "brightray/browser/browser_context.h"
namespace atom {
class AtomBlobReader;
class AtomDownloadManagerDelegate;
class AtomNetworkDelegate;
class AtomPermissionManager;
class RequestContextDelegate;
class WebViewManager;
struct CookieDetails;
class AtomBrowserContext : public brightray::BrowserContext {
public:
@@ -31,24 +29,7 @@ class AtomBrowserContext : public brightray::BrowserContext {
const base::DictionaryValue& options = base::DictionaryValue());
void SetUserAgent(const std::string& user_agent);
// Register callbacks that needs to notified on any cookie store changes.
std::unique_ptr<base::CallbackList<void(const CookieDetails*)>::Subscription>
RegisterCookieChangeCallback(
const base::Callback<void(const CookieDetails*)>& cb);
// brightray::URLRequestContextGetter::Delegate:
std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate() override;
std::string GetUserAgent() override;
std::unique_ptr<net::URLRequestJobFactory> CreateURLRequestJobFactory(
content::ProtocolHandlerMap* protocol_handlers) override;
net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory(
const base::FilePath& base_path) override;
std::unique_ptr<net::CertVerifier> CreateCertVerifier(
brightray::RequireCTDelegate* ct_delegate) override;
std::vector<std::string> GetCookieableSchemes() override;
void NotifyCookieChange(const net::CanonicalCookie& cookie,
bool removed,
net::CookieChangeCause cause) override;
AtomBlobReader* GetBlobReader();
// content::BrowserContext:
content::DownloadManagerDelegate* GetDownloadManagerDelegate() override;
@@ -57,14 +38,12 @@ class AtomBrowserContext : public brightray::BrowserContext {
// brightray::BrowserContext:
void RegisterPrefs(PrefRegistrySimple* pref_registry) override;
std::string GetUserAgent() const override;
void OnMainRequestContextCreated(
brightray::URLRequestContextGetter* getter) override;
AtomBlobReader* GetBlobReader();
void set_cookie_change_subscription(
std::unique_ptr<
base::CallbackList<void(const CookieDetails*)>::Subscription>
subscription) {
cookie_change_subscription_.swap(subscription);
RequestContextDelegate* GetRequestContextDelegate() const {
return request_context_delegate_.get();
}
protected:
@@ -74,16 +53,14 @@ class AtomBrowserContext : public brightray::BrowserContext {
~AtomBrowserContext() override;
private:
brightray::URLRequestContextGetter* url_request_context_getter_;
std::unique_ptr<AtomDownloadManagerDelegate> download_manager_delegate_;
std::unique_ptr<WebViewManager> guest_manager_;
std::unique_ptr<AtomPermissionManager> permission_manager_;
std::unique_ptr<AtomBlobReader> blob_reader_;
std::unique_ptr<RequestContextDelegate> request_context_delegate_;
std::string user_agent_;
bool use_cache_;
base::CallbackList<void(const CookieDetails*)> cookie_change_sub_list_;
std::unique_ptr<base::CallbackList<void(const CookieDetails*)>::Subscription>
cookie_change_subscription_;
DISALLOW_COPY_AND_ASSIGN(AtomBrowserContext);
};

View File

@@ -237,9 +237,6 @@ void AtomBrowserMainParts::PostMainMessageLoopStart() {
#if defined(OS_POSIX)
HandleShutdownSignals();
#endif
// TODO(deepak1556): Enable this optionally based on response
// from AtomPermissionManager.
GetGeolocationControl()->UserDidOptIntoLocationServices();
}
void AtomBrowserMainParts::PostMainMessageLoopRun() {

View File

@@ -54,6 +54,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
// Returns a closure that can be used to remove |callback| from the list.
void RegisterDestructionCallback(base::OnceClosure callback);
// Returns the connection to GeolocationControl which can be
// used to enable the location services once per client.
device::mojom::GeolocationControl* GetGeolocationControl();
Browser* browser() { return browser_.get(); }
protected:
@@ -87,8 +91,6 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
std::unique_ptr<brightray::ViewsDelegate> views_delegate_;
#endif
device::mojom::GeolocationControl* GetGeolocationControl();
// A fake BrowserProcess object that used to feed the source code from chrome.
std::unique_ptr<BrowserProcess> fake_browser_process_;

View File

@@ -7,6 +7,7 @@
#include <vector>
#include "atom/browser/atom_browser_client.h"
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/web_contents_preferences.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/permission_type.h"
@@ -43,6 +44,7 @@ class AtomPermissionManager::PendingRequest {
const StatusesCallback& callback)
: render_process_id_(render_frame_host->GetProcess()->GetID()),
callback_(callback),
permissions_(permissions),
results_(permissions.size(), blink::mojom::PermissionStatus::DENIED),
remaining_results_(permissions.size()) {}
@@ -50,6 +52,18 @@ class AtomPermissionManager::PendingRequest {
blink::mojom::PermissionStatus status) {
DCHECK(!IsComplete());
if (status == blink::mojom::PermissionStatus::GRANTED) {
const auto permission = permissions_[permission_id];
if (permission == content::PermissionType::MIDI_SYSEX) {
content::ChildProcessSecurityPolicy::GetInstance()
->GrantSendMidiSysExMessage(render_process_id_);
} else if (permission == content::PermissionType::GEOLOCATION) {
AtomBrowserMainParts::Get()
->GetGeolocationControl()
->UserDidOptIntoLocationServices();
}
}
results_[permission_id] = status;
--remaining_results_;
}
@@ -63,6 +77,7 @@ class AtomPermissionManager::PendingRequest {
private:
int render_process_id_;
const StatusesCallback callback_;
std::vector<content::PermissionType> permissions_;
std::vector<blink::mojom::PermissionStatus> results_;
size_t remaining_results_;
};
@@ -139,6 +154,10 @@ int AtomPermissionManager::RequestPermissionsWithDetails(
content::ChildProcessSecurityPolicy::GetInstance()
->GrantSendMidiSysExMessage(
render_frame_host->GetProcess()->GetID());
} else if (permission == content::PermissionType::GEOLOCATION) {
AtomBrowserMainParts::Get()
->GetGeolocationControl()
->UserDidOptIntoLocationServices();
}
statuses.push_back(blink::mojom::PermissionStatus::GRANTED);
}
@@ -153,10 +172,6 @@ int AtomPermissionManager::RequestPermissionsWithDetails(
for (size_t i = 0; i < permissions.size(); ++i) {
auto permission = permissions[i];
if (permission == content::PermissionType::MIDI_SYSEX) {
content::ChildProcessSecurityPolicy::GetInstance()
->GrantSendMidiSysExMessage(render_frame_host->GetProcess()->GetID());
}
const auto callback =
base::Bind(&AtomPermissionManager::OnPermissionResponse,
base::Unretained(this), request_id, i);
@@ -186,7 +201,6 @@ void AtomPermissionManager::OnPermissionResponse(
}
}
void AtomPermissionManager::ResetPermission(content::PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin) {}

View File

@@ -8,6 +8,7 @@
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/browser/browser_observer.h"
#include "atom/browser/login_handler.h"
#include "atom/browser/native_window.h"
#include "atom/browser/window_list.h"
#include "base/files/file_util.h"
@@ -164,7 +165,7 @@ void Browser::OnAccessibilitySupportChanged() {
}
void Browser::RequestLogin(
LoginHandler* login_handler,
scoped_refptr<LoginHandler> login_handler,
std::unique_ptr<base::DictionaryValue> request_details) {
for (BrowserObserver& observer : observers_)
observer.OnLogin(login_handler, *(request_details.get()));

View File

@@ -33,7 +33,6 @@ class Image;
namespace atom {
class AtomMenuModel;
class LoginHandler;
// This class is used for control application-wide operations.
class Browser : public WindowListObserver {
@@ -229,7 +228,7 @@ class Browser : public WindowListObserver {
void OnAccessibilitySupportChanged();
// Request basic auth login.
void RequestLogin(LoginHandler* login_handler,
void RequestLogin(scoped_refptr<LoginHandler> login_handler,
std::unique_ptr<base::DictionaryValue> request_details);
void PreMainMessageLoopRun();

View File

@@ -7,6 +7,8 @@
#include <string>
#include "atom/browser/login_handler.h"
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
namespace base {
@@ -15,8 +17,6 @@ class DictionaryValue;
namespace atom {
class LoginHandler;
class BrowserObserver {
public:
// The browser is about to close all windows.
@@ -49,7 +49,7 @@ class BrowserObserver {
virtual void OnFinishLaunching(const base::DictionaryValue& launch_info) {}
// The browser requests HTTP login.
virtual void OnLogin(LoginHandler* login_handler,
virtual void OnLogin(scoped_refptr<LoginHandler> login_handler,
const base::DictionaryValue& request_details) {}
// The browser's accessibility suppport has changed.

View File

@@ -0,0 +1,44 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/fake_location_provider.h"
#include "base/callback.h"
#include "base/time/time.h"
namespace atom {
FakeLocationProvider::FakeLocationProvider() {
position_.latitude = 10;
position_.longitude = -10;
position_.accuracy = 1;
position_.error_code =
device::mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE;
}
FakeLocationProvider::~FakeLocationProvider() = default;
void FakeLocationProvider::SetUpdateCallback(
const LocationProviderUpdateCallback& callback) {
callback_ = callback;
}
void FakeLocationProvider::StartProvider(bool high_accuracy) {}
void FakeLocationProvider::StopProvider() {}
const device::mojom::Geoposition& FakeLocationProvider::GetPosition() {
return position_;
}
void FakeLocationProvider::OnPermissionGranted() {
if (!callback_.is_null()) {
// Check device::ValidateGeoPosition for range of values.
position_.error_code = device::mojom::Geoposition::ErrorCode::NONE;
position_.timestamp = base::Time::Now();
callback_.Run(this, position_);
}
}
} // namespace atom

View File

@@ -0,0 +1,36 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_FAKE_LOCATION_PROVIDER_H_
#define ATOM_BROWSER_FAKE_LOCATION_PROVIDER_H_
#include "base/macros.h"
#include "device/geolocation/public/cpp/location_provider.h"
#include "services/device/public/mojom/geoposition.mojom.h"
namespace atom {
class FakeLocationProvider : public device::LocationProvider {
public:
FakeLocationProvider();
~FakeLocationProvider() override;
// LocationProvider Implementation:
void SetUpdateCallback(
const LocationProviderUpdateCallback& callback) override;
void StartProvider(bool high_accuracy) override;
void StopProvider() override;
const device::mojom::Geoposition& GetPosition() override;
void OnPermissionGranted() override;
private:
device::mojom::Geoposition position_;
LocationProviderUpdateCallback callback_;
DISALLOW_COPY_AND_ASSIGN(FakeLocationProvider);
};
} // namespace atom
#endif // ATOM_BROWSER_FAKE_LOCATION_PROVIDER_H_

View File

@@ -5,6 +5,7 @@
#include "atom/browser/login_handler.h"
#include "atom/browser/browser.h"
#include "atom/common/native_mate_converters/net_converter.h"
#include "base/values.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/web_contents.h"
@@ -15,78 +16,75 @@ using content::BrowserThread;
namespace atom {
LoginHandler::LoginHandler(
net::AuthChallengeInfo* auth_info,
content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
const GURL& url,
const base::Callback<void(const base::Optional<net::AuthCredentials>&)>&
auth_required_callback)
: auth_info_(auth_info),
web_contents_getter_(web_contents_getter),
auth_required_callback_(auth_required_callback) {
// Fill request details on IO thread.
// TODO(deepak1556): Fill in method and referrer details to
// avoid breaking the app login event.
net::URLRequest* request,
const net::AuthChallengeInfo& auth_info,
const net::NetworkDelegate::AuthCallback& callback,
net::AuthCredentials* credentials,
const content::ResourceRequestInfo* resource_request_info)
: credentials_(credentials),
auth_info_(auth_info),
auth_callback_(std::move(callback)),
weak_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::unique_ptr<base::DictionaryValue> request_details(
new base::DictionaryValue);
request_details->SetKey("url", base::Value(url.spec()));
FillRequestDetails(request_details.get(), request);
web_contents_getter_ =
resource_request_info->GetWebContentsGetterForRequest();
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindOnce(&Browser::RequestLogin, base::Unretained(Browser::Get()),
base::RetainedRef(WrapRefCounted(this)),
std::move(request_details)));
base::RetainedRef(this), std::move(request_details)));
}
LoginHandler::~LoginHandler() {}
void LoginHandler::Login(const base::string16& username,
const base::string16& password) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&LoginHandler::DoLogin, weak_factory_.GetWeakPtr(),
username, password));
}
void LoginHandler::CancelAuth() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&LoginHandler::DoCancelAuth, weak_factory_.GetWeakPtr()));
}
void LoginHandler::NotifyRequestDestroyed() {
auth_callback_.Reset();
credentials_ = nullptr;
weak_factory_.InvalidateWeakPtrs();
}
content::WebContents* LoginHandler::GetWebContents() const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return web_contents_getter_.Run();
}
void LoginHandler::Login(const base::string16& username,
const base::string16& password) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (TestAndSetAuthHandled())
return;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&LoginHandler::DoLogin, this, username, password));
}
void LoginHandler::CancelAuth() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (TestAndSetAuthHandled())
return;
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::BindOnce(&LoginHandler::DoCancelAuth, this));
}
void LoginHandler::OnRequestCancelled() {
TestAndSetAuthHandled();
auth_required_callback_.Reset();
}
// Marks authentication as handled and returns the previous handled state.
bool LoginHandler::TestAndSetAuthHandled() {
base::AutoLock lock(handled_auth_lock_);
bool was_handled = handled_auth_;
handled_auth_ = true;
return was_handled;
}
void LoginHandler::DoCancelAuth() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!auth_required_callback_.is_null())
std::move(auth_required_callback_).Run(base::nullopt);
if (!auth_callback_.is_null())
std::move(auth_callback_)
.Run(net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_CANCEL_AUTH);
}
void LoginHandler::DoLogin(const base::string16& username,
const base::string16& password) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!auth_required_callback_.is_null()) {
std::move(auth_required_callback_)
.Run(net::AuthCredentials(username, password));
if (!auth_callback_.is_null()) {
credentials_->Set(username, password);
std::move(auth_callback_)
.Run(net::NetworkDelegate::AUTH_REQUIRED_RESPONSE_SET_AUTH);
}
}

View File

@@ -6,72 +6,65 @@
#define ATOM_BROWSER_LOGIN_HANDLER_H_
#include "base/callback.h"
#include "base/optional.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "base/synchronization/lock.h"
#include "content/public/browser/resource_dispatcher_host_login_delegate.h"
#include "content/public/browser/resource_request_info.h"
#include "net/base/network_delegate.h"
namespace content {
class WebContents;
}
namespace net {
class AuthChallengeInfo;
class AuthCredentials;
} // namespace net
namespace atom {
// Handles the HTTP basic auth, must be created on IO thread.
class LoginHandler : public content::ResourceDispatcherHostLoginDelegate {
class LoginHandler : public base::RefCountedThreadSafe<LoginHandler> {
public:
LoginHandler(
net::AuthChallengeInfo* auth_info,
content::ResourceRequestInfo::WebContentsGetter web_contents_getter,
const GURL& url,
const base::Callback<void(const base::Optional<net::AuthCredentials>&)>&
auth_required_callback);
LoginHandler(net::URLRequest* request,
const net::AuthChallengeInfo& auth_info,
const net::NetworkDelegate::AuthCallback& callback,
net::AuthCredentials* credentials,
const content::ResourceRequestInfo* resource_request_info);
// The auth is cancelled, must be called on UI thread.
void CancelAuth();
// The URLRequest associated with the auth is destroyed.
void NotifyRequestDestroyed();
// Login with |username| and |password|, must be called on UI thread.
void Login(const base::string16& username, const base::string16& password);
// Returns the WebContents associated with the request, must be called on UI
// thread.
content::WebContents* GetWebContents() const;
// The auth is cancelled, must be called on UI thread.
void CancelAuth();
// Login with |username| and |password|, must be called on UI thread.
void Login(const base::string16& username, const base::string16& password);
const net::AuthChallengeInfo* auth_info() const { return auth_info_.get(); }
protected:
~LoginHandler() override;
// content::ResourceDispatcherHostLoginDelegate:
void OnRequestCancelled() override;
const net::AuthChallengeInfo* auth_info() const { return &auth_info_; }
private:
friend class base::RefCountedThreadSafe<LoginHandler>;
friend class base::DeleteHelper<LoginHandler>;
~LoginHandler();
// Must be called on IO thread.
void DoCancelAuth();
void DoLogin(const base::string16& username, const base::string16& password);
// Marks authentication as handled and returns the previous handled
// state.
bool TestAndSetAuthHandled();
// True if we've handled auth (Login or CancelAuth has been called).
bool handled_auth_ = false;
mutable base::Lock handled_auth_lock_;
// Credentials to be used for the auth.
net::AuthCredentials* credentials_;
// Who/where/what asked for the authentication.
scoped_refptr<net::AuthChallengeInfo> auth_info_;
const net::AuthChallengeInfo& auth_info_;
// WebContents associated with the login request.
content::ResourceRequestInfo::WebContentsGetter web_contents_getter_;
base::Callback<void(const base::Optional<net::AuthCredentials>&)>
auth_required_callback_;
// Called with preferred value of net::NetworkDelegate::AuthRequiredResponse.
net::NetworkDelegate::AuthCallback auth_callback_;
base::WeakPtrFactory<LoginHandler> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(LoginHandler);
};

View File

@@ -7,11 +7,17 @@
#include <utility>
#include "atom/browser/api/atom_api_web_contents.h"
#include "atom/browser/login_handler.h"
#include "atom/common/native_mate_converters/net_converter.h"
#include "atom/common/options_switches.h"
#include "base/command_line.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/resource_request_info.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request.h"
#include "services/network/throttling/throttling_network_transaction.h"
@@ -231,7 +237,15 @@ AtomNetworkDelegate::ResponseListenerInfo::ResponseListenerInfo(
AtomNetworkDelegate::ResponseListenerInfo::ResponseListenerInfo() = default;
AtomNetworkDelegate::ResponseListenerInfo::~ResponseListenerInfo() = default;
AtomNetworkDelegate::AtomNetworkDelegate() {}
AtomNetworkDelegate::AtomNetworkDelegate() {
auto* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kIgnoreConnectionsLimit)) {
std::string value =
command_line->GetSwitchValueASCII(switches::kIgnoreConnectionsLimit);
ignore_connections_limit_domains_ = base::SplitString(
value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
}
}
AtomNetworkDelegate::~AtomNetworkDelegate() {}
@@ -262,9 +276,17 @@ int AtomNetworkDelegate::OnBeforeURLRequest(
net::URLRequest* request,
const net::CompletionCallback& callback,
GURL* new_url) {
if (!base::ContainsKey(response_listeners_, kOnBeforeRequest))
return brightray::NetworkDelegate::OnBeforeURLRequest(request, callback,
new_url);
if (!base::ContainsKey(response_listeners_, kOnBeforeRequest)) {
for (const auto& domain : ignore_connections_limit_domains_) {
if (request->url().DomainIs(domain)) {
// Allow unlimited concurrent connections.
request->SetPriority(net::MAXIMUM_PRIORITY);
request->SetLoadFlags(request->load_flags() | net::LOAD_IGNORE_LIMITS);
break;
}
}
return net::OK;
}
return HandleResponseEvent(kOnBeforeRequest, request, callback, new_url);
}
@@ -278,8 +300,7 @@ int AtomNetworkDelegate::OnBeforeStartTransaction(
kDevToolsEmulateNetworkConditionsClientId,
client_id_);
if (!base::ContainsKey(response_listeners_, kOnBeforeSendHeaders))
return brightray::NetworkDelegate::OnBeforeStartTransaction(
request, callback, headers);
return net::OK;
return HandleResponseEvent(kOnBeforeSendHeaders, request, callback, headers,
*headers);
@@ -288,10 +309,8 @@ int AtomNetworkDelegate::OnBeforeStartTransaction(
void AtomNetworkDelegate::OnStartTransaction(
net::URLRequest* request,
const net::HttpRequestHeaders& headers) {
if (!base::ContainsKey(simple_listeners_, kOnSendHeaders)) {
brightray::NetworkDelegate::OnStartTransaction(request, headers);
if (!base::ContainsKey(simple_listeners_, kOnSendHeaders))
return;
}
HandleSimpleEvent(kOnSendHeaders, request, headers);
}
@@ -303,8 +322,7 @@ int AtomNetworkDelegate::OnHeadersReceived(
scoped_refptr<net::HttpResponseHeaders>* override,
GURL* allowed) {
if (!base::ContainsKey(response_listeners_, kOnHeadersReceived))
return brightray::NetworkDelegate::OnHeadersReceived(
request, callback, original, override, allowed);
return net::OK;
return HandleResponseEvent(
kOnHeadersReceived, request, callback,
@@ -313,10 +331,8 @@ int AtomNetworkDelegate::OnHeadersReceived(
void AtomNetworkDelegate::OnBeforeRedirect(net::URLRequest* request,
const GURL& new_location) {
if (!base::ContainsKey(simple_listeners_, kOnBeforeRedirect)) {
brightray::NetworkDelegate::OnBeforeRedirect(request, new_location);
if (!base::ContainsKey(simple_listeners_, kOnBeforeRedirect))
return;
}
HandleSimpleEvent(kOnBeforeRedirect, request, new_location,
request->response_headers(), request->GetSocketAddress(),
@@ -325,10 +341,8 @@ void AtomNetworkDelegate::OnBeforeRedirect(net::URLRequest* request,
void AtomNetworkDelegate::OnResponseStarted(net::URLRequest* request,
int net_error) {
if (!base::ContainsKey(simple_listeners_, kOnResponseStarted)) {
brightray::NetworkDelegate::OnResponseStarted(request, net_error);
if (!base::ContainsKey(simple_listeners_, kOnResponseStarted))
return;
}
if (request->status().status() != net::URLRequestStatus::SUCCESS)
return;
@@ -346,33 +360,109 @@ void AtomNetworkDelegate::OnCompleted(net::URLRequest* request, bool started) {
// Error event.
OnErrorOccurred(request, started);
return;
} else if (request->response_headers() &&
net::HttpResponseHeaders::IsRedirectResponseCode(
request->response_headers()->response_code())) {
}
if (request->response_headers() &&
net::HttpResponseHeaders::IsRedirectResponseCode(
request->response_headers()->response_code())) {
// Redirect event.
brightray::NetworkDelegate::OnCompleted(request, started);
return;
}
if (!base::ContainsKey(simple_listeners_, kOnCompleted)) {
brightray::NetworkDelegate::OnCompleted(request, started);
if (!base::ContainsKey(simple_listeners_, kOnCompleted))
return;
}
HandleSimpleEvent(kOnCompleted, request, request->response_headers(),
request->was_cached());
}
void AtomNetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) {
const auto& it = login_handler_map_.find(request->identifier());
if (it != login_handler_map_.end()) {
it->second->NotifyRequestDestroyed();
it->second = nullptr;
login_handler_map_.erase(it);
}
callbacks_.erase(request->identifier());
}
net::NetworkDelegate::AuthRequiredResponse AtomNetworkDelegate::OnAuthRequired(
net::URLRequest* request,
const net::AuthChallengeInfo& auth_info,
const AuthCallback& callback,
net::AuthCredentials* credentials) {
auto* resource_request_info =
content::ResourceRequestInfo::ForRequest(request);
if (!resource_request_info)
return AUTH_REQUIRED_RESPONSE_NO_ACTION;
login_handler_map_.emplace(
request->identifier(),
new LoginHandler(request, auth_info, std::move(callback), credentials,
resource_request_info));
return AUTH_REQUIRED_RESPONSE_IO_PENDING;
}
bool AtomNetworkDelegate::OnCanGetCookies(const net::URLRequest& request,
const net::CookieList& cookie_list) {
return true;
}
bool AtomNetworkDelegate::OnCanSetCookie(
const net::URLRequest& request,
const net::CanonicalCookie& cookie_line,
net::CookieOptions* options) {
return true;
}
bool AtomNetworkDelegate::OnCanAccessFile(
const net::URLRequest& request,
const base::FilePath& original_path,
const base::FilePath& absolute_path) const {
return true;
}
bool AtomNetworkDelegate::OnCanEnablePrivacyMode(
const GURL& url,
const GURL& first_party_for_cookies) const {
return false;
}
bool AtomNetworkDelegate::OnAreExperimentalCookieFeaturesEnabled() const {
return true;
}
bool AtomNetworkDelegate::OnCancelURLRequestWithPolicyViolatingReferrerHeader(
const net::URLRequest& request,
const GURL& target_url,
const GURL& referrer_url) const {
return false;
}
// TODO(deepak1556) : Enable after hooking into the reporting service
// https://crbug.com/704259
bool AtomNetworkDelegate::OnCanQueueReportingReport(
const url::Origin& origin) const {
return false;
}
void AtomNetworkDelegate::OnCanSendReportingReports(
std::set<url::Origin> origins,
base::OnceCallback<void(std::set<url::Origin>)> result_callback) const {}
bool AtomNetworkDelegate::OnCanSetReportingClient(const url::Origin& origin,
const GURL& endpoint) const {
return false;
}
bool AtomNetworkDelegate::OnCanUseReportingClient(const url::Origin& origin,
const GURL& endpoint) const {
return false;
}
void AtomNetworkDelegate::OnErrorOccurred(net::URLRequest* request,
bool started) {
if (!base::ContainsKey(simple_listeners_, kOnErrorOccurred)) {
brightray::NetworkDelegate::OnCompleted(request, started);
if (!base::ContainsKey(simple_listeners_, kOnErrorOccurred))
return;
}
HandleSimpleEvent(kOnErrorOccurred, request, request->was_cached(),
request->status());

View File

@@ -8,14 +8,14 @@
#include <map>
#include <set>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/synchronization/lock.h"
#include "base/values.h"
#include "brightray/browser/network_delegate.h"
#include "content/public/browser/resource_request_info.h"
#include "extensions/common/url_pattern.h"
#include "net/base/net_errors.h"
#include "net/base/network_delegate.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
@@ -27,7 +27,9 @@ using URLPatterns = std::set<URLPattern>;
const char* ResourceTypeToString(content::ResourceType type);
class AtomNetworkDelegate : public brightray::NetworkDelegate {
class LoginHandler;
class AtomNetworkDelegate : public net::NetworkDelegate {
public:
using ResponseCallback = base::Callback<void(const base::DictionaryValue&)>;
using SimpleListener = base::Callback<void(const base::DictionaryValue&)>;
@@ -86,6 +88,10 @@ class AtomNetworkDelegate : public brightray::NetworkDelegate {
int OnBeforeStartTransaction(net::URLRequest* request,
const net::CompletionCallback& callback,
net::HttpRequestHeaders* headers) override;
void OnBeforeSendHeaders(net::URLRequest* request,
const net::ProxyInfo& proxy_info,
const net::ProxyRetryInfoMap& proxy_retry_info,
net::HttpRequestHeaders* headers) override {}
void OnStartTransaction(net::URLRequest* request,
const net::HttpRequestHeaders& headers) override;
int OnHeadersReceived(
@@ -97,8 +103,43 @@ class AtomNetworkDelegate : public brightray::NetworkDelegate {
void OnBeforeRedirect(net::URLRequest* request,
const GURL& new_location) override;
void OnResponseStarted(net::URLRequest* request, int net_error) override;
void OnNetworkBytesReceived(net::URLRequest* request,
int64_t bytes_read) override {}
void OnNetworkBytesSent(net::URLRequest* request,
int64_t bytes_sent) override {}
void OnCompleted(net::URLRequest* request, bool started) override;
void OnURLRequestDestroyed(net::URLRequest* request) override;
void OnPACScriptError(int line_number, const base::string16& error) override {
}
AuthRequiredResponse OnAuthRequired(
net::URLRequest* request,
const net::AuthChallengeInfo& auth_info,
const AuthCallback& callback,
net::AuthCredentials* credentials) override;
bool OnCanGetCookies(const net::URLRequest& request,
const net::CookieList& cookie_list) override;
bool OnCanSetCookie(const net::URLRequest& request,
const net::CanonicalCookie& cookie_line,
net::CookieOptions* options) override;
bool OnCanAccessFile(const net::URLRequest& request,
const base::FilePath& original_path,
const base::FilePath& absolute_path) const override;
bool OnCanEnablePrivacyMode(
const GURL& url,
const GURL& first_party_for_cookies) const override;
bool OnAreExperimentalCookieFeaturesEnabled() const override;
bool OnCancelURLRequestWithPolicyViolatingReferrerHeader(
const net::URLRequest& request,
const GURL& target_url,
const GURL& referrer_url) const override;
bool OnCanQueueReportingReport(const url::Origin& origin) const override;
void OnCanSendReportingReports(std::set<url::Origin> origins,
base::OnceCallback<void(std::set<url::Origin>)>
result_callback) const override;
bool OnCanSetReportingClient(const url::Origin& origin,
const GURL& endpoint) const override;
bool OnCanUseReportingClient(const url::Origin& origin,
const GURL& endpoint) const override;
private:
void OnErrorOccurred(net::URLRequest* request, bool started);
@@ -124,9 +165,11 @@ class AtomNetworkDelegate : public brightray::NetworkDelegate {
T out,
const base::DictionaryValue& response);
std::map<uint64_t, scoped_refptr<LoginHandler>> login_handler_map_;
std::map<SimpleEvent, SimpleListenerInfo> simple_listeners_;
std::map<ResponseEvent, ResponseListenerInfo> response_listeners_;
std::map<uint64_t, net::CompletionCallback> callbacks_;
std::vector<std::string> ignore_connections_limit_domains_;
// Client id for devtools network emulation.
std::string client_id_;

View File

@@ -70,11 +70,8 @@ scoped_refptr<AtomURLRequest> AtomURLRequest::Create(
return nullptr;
}
scoped_refptr<brightray::URLRequestContextGetter> request_context_getter(
browser_context->url_request_context_getter());
browser_context->GetRequestContext());
DCHECK(request_context_getter);
if (!request_context_getter) {
return nullptr;
}
scoped_refptr<AtomURLRequest> atom_url_request(new AtomURLRequest(delegate));
if (content::BrowserThread::PostTask(
content::BrowserThread::IO, FROM_HERE,
@@ -504,4 +501,16 @@ void AtomURLRequest::InformDelegateErrorOccured(const std::string& error,
delegate_->OnError(error, isRequestError);
}
void AtomURLRequest::GetUploadProgress(mate::Dictionary* progress) const {
net::UploadProgress upload_progress;
if (request_) {
progress->Set("started", true);
upload_progress = request_->GetUploadProgress();
} else {
progress->Set("started", false);
}
progress->Set("current", upload_progress.position());
progress->Set("total", upload_progress.size());
}
} // namespace atom

View File

@@ -43,6 +43,7 @@ class AtomURLRequest : public base::RefCountedThreadSafe<AtomURLRequest>,
void PassLoginInformation(const base::string16& username,
const base::string16& password) const;
void SetLoadFlags(int flags) const;
void GetUploadProgress(mate::Dictionary* progress) const;
protected:
// Overrides of net::URLRequest::Delegate

View File

@@ -9,6 +9,7 @@
#include "atom/browser/api/atom_api_session.h"
#include "atom/browser/atom_browser_context.h"
#include "base/guid.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "native_mate/dictionary.h"
@@ -93,16 +94,15 @@ void URLRequestFetchJob::BeforeStartInUI(v8::Isolate* isolate,
if (options.Get("session", &val)) {
if (val->IsNull()) {
// We have to create the URLRequestContextGetter on UI thread.
url_request_context_getter_ = new brightray::URLRequestContextGetter(
this, nullptr, base::FilePath(), true,
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO), nullptr,
content::URLRequestInterceptorScopedVector());
custom_browser_context_ =
AtomBrowserContext::From(base::GenerateGUID(), true);
url_request_context_getter_ =
custom_browser_context_->GetRequestContext();
} else {
mate::Handle<api::Session> session;
if (mate::ConvertFromV8(isolate, val, &session) && !session.IsEmpty()) {
AtomBrowserContext* browser_context = session->browser_context();
url_request_context_getter_ =
browser_context->url_request_context_getter();
url_request_context_getter_ = browser_context->GetRequestContext();
}
}
}

View File

@@ -8,16 +8,17 @@
#include <string>
#include "atom/browser/net/js_asker.h"
#include "brightray/browser/url_request_context_getter.h"
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_read_observer.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request_context_getter.h"
namespace atom {
class AtomBrowserContext;
class URLRequestFetchJob : public JsAsker<net::URLRequestJob>,
public net::URLFetcherDelegate,
public brightray::URLRequestContextGetter::Delegate {
public net::URLFetcherDelegate {
public:
URLRequestFetchJob(net::URLRequest*, net::NetworkDelegate*);
~URLRequestFetchJob() override;
@@ -51,6 +52,7 @@ class URLRequestFetchJob : public JsAsker<net::URLRequestJob>,
void ClearPendingBuffer();
void ClearWriteBuffer();
scoped_refptr<AtomBrowserContext> custom_browser_context_;
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
std::unique_ptr<net::URLFetcher> fetcher_;
std::unique_ptr<net::HttpResponseInfo> response_info_;

View File

@@ -4,6 +4,8 @@
#include "atom/browser/node_debugger.h"
#include <string>
#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
#include "libplatform/libplatform.h"
@@ -25,10 +27,15 @@ void NodeDebugger::Start(node::MultiIsolatePlatform* platform) {
node::DebugOptions options;
for (auto& arg : base::CommandLine::ForCurrentProcess()->argv()) {
#if defined(OS_WIN)
options.ParseOption("Electron", base::UTF16ToUTF8(arg));
const std::string nice_arg = base::UTF16ToUTF8(arg);
#else
options.ParseOption("Electron", arg);
const std::string& nice_arg = arg;
#endif
// Stop handling arguments after a "--" to be consistent with Chromium
if (nice_arg == "--")
break;
options.ParseOption("Electron", nice_arg);
}
// Set process._debugWaitConnect if --inspect-brk was specified to stop

View File

@@ -0,0 +1,163 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/request_context_delegate.h"
#include "atom/browser/api/atom_api_protocol.h"
#include "atom/browser/net/about_protocol_handler.h"
#include "atom/browser/net/asar/asar_protocol_handler.h"
#include "atom/browser/net/atom_cert_verifier.h"
#include "atom/browser/net/atom_network_delegate.h"
#include "atom/browser/net/atom_url_request_job_factory.h"
#include "atom/browser/net/cookie_details.h"
#include "atom/browser/net/http_protocol_handler.h"
#include "atom/common/options_switches.h"
#include "base/strings/string_number_conversions.h"
#include "base/task_scheduler/post_task.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/url_constants.h"
#include "net/ftp/ftp_network_layer.h"
#include "net/url_request/data_protocol_handler.h"
#include "net/url_request/ftp_protocol_handler.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_intercepting_job_factory.h"
#include "url/url_constants.h"
using content::BrowserThread;
namespace atom {
namespace {
class NoCacheBackend : public net::HttpCache::BackendFactory {
int CreateBackend(net::NetLog* net_log,
std::unique_ptr<disk_cache::Backend>* backend,
const net::CompletionCallback& callback) override {
return net::ERR_FAILED;
}
};
} // namespace
RequestContextDelegate::RequestContextDelegate(bool use_cache)
: use_cache_(use_cache), weak_factory_(this) {}
RequestContextDelegate::~RequestContextDelegate() {}
std::unique_ptr<base::CallbackList<void(const CookieDetails*)>::Subscription>
RequestContextDelegate::RegisterCookieChangeCallback(
const base::Callback<void(const CookieDetails*)>& cb) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return cookie_change_sub_list_.Add(cb);
}
void RequestContextDelegate::NotifyCookieChange(
const net::CanonicalCookie& cookie,
net::CookieChangeCause cause) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
CookieDetails cookie_details(
&cookie, !(cause == net::CookieChangeCause::INSERTED), cause);
cookie_change_sub_list_.Notify(&cookie_details);
}
std::unique_ptr<net::NetworkDelegate>
RequestContextDelegate::CreateNetworkDelegate() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return std::make_unique<AtomNetworkDelegate>();
}
std::unique_ptr<net::URLRequestJobFactory>
RequestContextDelegate::CreateURLRequestJobFactory(
net::URLRequestContext* url_request_context,
content::ProtocolHandlerMap* protocol_handlers) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::unique_ptr<AtomURLRequestJobFactory> job_factory(
new AtomURLRequestJobFactory);
for (auto& it : *protocol_handlers) {
job_factory->SetProtocolHandler(it.first,
base::WrapUnique(it.second.release()));
}
protocol_handlers->clear();
job_factory->SetProtocolHandler(url::kAboutScheme,
base::WrapUnique(new AboutProtocolHandler));
job_factory->SetProtocolHandler(
url::kDataScheme, base::WrapUnique(new net::DataProtocolHandler));
job_factory->SetProtocolHandler(
url::kFileScheme,
base::WrapUnique(
new asar::AsarProtocolHandler(base::CreateTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}))));
job_factory->SetProtocolHandler(
url::kHttpScheme,
base::WrapUnique(new HttpProtocolHandler(url::kHttpScheme)));
job_factory->SetProtocolHandler(
url::kHttpsScheme,
base::WrapUnique(new HttpProtocolHandler(url::kHttpsScheme)));
job_factory->SetProtocolHandler(
url::kWsScheme,
base::WrapUnique(new HttpProtocolHandler(url::kWsScheme)));
job_factory->SetProtocolHandler(
url::kWssScheme,
base::WrapUnique(new HttpProtocolHandler(url::kWssScheme)));
auto* host_resolver = url_request_context->host_resolver();
job_factory->SetProtocolHandler(
url::kFtpScheme, net::FtpProtocolHandler::Create(host_resolver));
return std::move(job_factory);
}
net::HttpCache::BackendFactory*
RequestContextDelegate::CreateHttpCacheBackendFactory(
const base::FilePath& base_path) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (!use_cache_) {
return new NoCacheBackend;
} else {
int max_size = 0;
base::StringToInt(
command_line->GetSwitchValueASCII(switches::kDiskCacheSize), &max_size);
base::FilePath cache_path = base_path.Append(FILE_PATH_LITERAL("Cache"));
return new net::HttpCache::DefaultBackend(
net::DISK_CACHE, net::CACHE_BACKEND_DEFAULT, cache_path, max_size);
}
}
std::unique_ptr<net::CertVerifier> RequestContextDelegate::CreateCertVerifier(
brightray::RequireCTDelegate* ct_delegate) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
return std::make_unique<AtomCertVerifier>(ct_delegate);
}
void RequestContextDelegate::GetCookieableSchemes(
std::vector<std::string>* cookie_schemes) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
const auto& standard_schemes = atom::api::GetStandardSchemes();
cookie_schemes->insert(cookie_schemes->end(), standard_schemes.begin(),
standard_schemes.end());
}
void RequestContextDelegate::OnCookieChanged(const net::CanonicalCookie& cookie,
net::CookieChangeCause cause) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::BindRepeating(&RequestContextDelegate::NotifyCookieChange,
weak_factory_.GetWeakPtr(), cookie, cause));
}
} // namespace atom

View File

@@ -0,0 +1,58 @@
// Copyright (c) 2018 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_REQUEST_CONTEXT_DELEGATE_H_
#define ATOM_BROWSER_REQUEST_CONTEXT_DELEGATE_H_
#include <string>
#include <vector>
#include "base/callback_list.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "brightray/browser/url_request_context_getter.h"
namespace atom {
struct CookieDetails;
class RequestContextDelegate
: public brightray::URLRequestContextGetter::Delegate {
public:
explicit RequestContextDelegate(bool use_cache);
~RequestContextDelegate() override;
// Register callbacks that needs to notified on any cookie store changes.
std::unique_ptr<base::CallbackList<void(const CookieDetails*)>::Subscription>
RegisterCookieChangeCallback(
const base::Callback<void(const CookieDetails*)>& cb);
protected:
std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate() override;
std::unique_ptr<net::URLRequestJobFactory> CreateURLRequestJobFactory(
net::URLRequestContext* url_request_context,
content::ProtocolHandlerMap* protocol_handlers) override;
net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory(
const base::FilePath& base_path) override;
std::unique_ptr<net::CertVerifier> CreateCertVerifier(
brightray::RequireCTDelegate* ct_delegate) override;
void GetCookieableSchemes(std::vector<std::string>* cookie_schemes) override;
void OnCookieChanged(const net::CanonicalCookie& cookie,
net::CookieChangeCause cause) override;
private:
void NotifyCookieChange(const net::CanonicalCookie& cookie,
net::CookieChangeCause cause);
base::CallbackList<void(const CookieDetails*)> cookie_change_sub_list_;
bool use_cache_ = true;
base::WeakPtrFactory<RequestContextDelegate> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RequestContextDelegate);
};
} // namespace atom
#endif // ATOM_BROWSER_REQUEST_CONTEXT_DELEGATE_H_

View File

@@ -56,8 +56,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 3,0,0,6
PRODUCTVERSION 3,0,0,6
FILEVERSION 3,0,0,20180904
PRODUCTVERSION 3,0,0,20180904
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L

View File

@@ -41,9 +41,15 @@ const CGFloat kVerticalTitleMargin = 2;
@implementation StatusItemView
- (id)initWithImage:(NSImage*)image icon:(atom::TrayIconCocoa*)icon {
image_.reset([image copy]);
- (void)dealloc {
trayIcon_ = nil;
menuController_ = nil;
[super dealloc];
}
- (id)initWithIcon:(atom::TrayIconCocoa*)icon {
trayIcon_ = icon;
menuController_ = nil;
highlight_mode_ = atom::TrayIcon::HighlightMode::SELECTION;
ignoreDoubleClickEvents_ = NO;
forceHighlight_ = NO;
@@ -89,6 +95,7 @@ const CGFloat kVerticalTitleMargin = 2;
trackingArea_.reset();
}
[[NSStatusBar systemStatusBar] removeStatusItem:statusItem_];
[statusItem_ setView:nil];
statusItem_.reset();
}
@@ -156,6 +163,8 @@ const CGFloat kVerticalTitleMargin = 2;
// The width of the icon.
- (CGFloat)iconWidth {
if (!image_ && title_)
return kHorizontalMargin;
CGFloat thickness = [[NSStatusBar systemStatusBar] thickness];
CGFloat imageHeight = [image_ size].height;
CGFloat imageWidth = [image_ size].width;
@@ -424,7 +433,9 @@ const CGFloat kVerticalTitleMargin = 2;
namespace atom {
TrayIconCocoa::TrayIconCocoa() {}
TrayIconCocoa::TrayIconCocoa() {
status_item_view_.reset([[StatusItemView alloc] initWithIcon:this]);
}
TrayIconCocoa::~TrayIconCocoa() {
[status_item_view_ removeItem];
@@ -433,12 +444,7 @@ TrayIconCocoa::~TrayIconCocoa() {
}
void TrayIconCocoa::SetImage(const gfx::Image& image) {
if (status_item_view_) {
[status_item_view_ setImage:image.AsNSImage()];
} else {
status_item_view_.reset(
[[StatusItemView alloc] initWithImage:image.AsNSImage() icon:this]);
}
[status_item_view_ setImage:image.IsEmpty() ? nil : image.AsNSImage()];
}
void TrayIconCocoa::SetPressedImage(const gfx::Image& image) {
@@ -474,11 +480,18 @@ void TrayIconCocoa::SetContextMenu(AtomMenuModel* menu_model) {
// Substribe to MenuClosed event.
if (menu_model_)
menu_model_->RemoveObserver(this);
menu_model->AddObserver(this);
// Create native menu.
menu_.reset([[AtomMenuController alloc] initWithModel:menu_model
useDefaultAccelerator:NO]);
menu_model_ = menu_model;
if (menu_model) {
menu_model->AddObserver(this);
// Create native menu.
menu_.reset([[AtomMenuController alloc] initWithModel:menu_model
useDefaultAccelerator:NO]);
} else {
menu_.reset();
}
[status_item_view_ setMenuController:menu_.get()];
}

View File

@@ -31,6 +31,22 @@ bool IsPDFViewerEnabled() {
#endif
}
bool IsFakeLocationProviderEnabled() {
#if defined(OVERRIDE_LOCATION_PROVIDER)
return true;
#else
return false;
#endif
}
bool IsViewApiEnabled() {
#if defined(ENABLE_VIEW_API)
return true;
#else
return false;
#endif
}
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
@@ -39,6 +55,9 @@ void Initialize(v8::Local<v8::Object> exports,
dict.SetMethod("isDesktopCapturerEnabled", &IsDesktopCapturerEnabled);
dict.SetMethod("isOffscreenRenderingEnabled", &IsOffscreenRenderingEnabled);
dict.SetMethod("isPDFViewerEnabled", &IsPDFViewerEnabled);
dict.SetMethod("isFakeLocationProviderEnabled",
&IsFakeLocationProviderEnabled);
dict.SetMethod("isViewApiEnabled", &IsViewApiEnabled);
}
} // namespace

View File

@@ -8,7 +8,7 @@
#define ATOM_MAJOR_VERSION 3
#define ATOM_MINOR_VERSION 0
#define ATOM_PATCH_VERSION 0
#define ATOM_PRE_RELEASE_VERSION -beta.6
#define ATOM_PRE_RELEASE_VERSION -nightly.20180904
#ifndef ATOM_STRINGIFY
#define ATOM_STRINGIFY(n) ATOM_STRINGIFY_HELPER(n)

View File

@@ -211,6 +211,7 @@ void NodeBindings::Initialize() {
// Init node.
// (we assume node::Init would not modify the parameters under embedded mode).
// NOTE: If you change this line, please ping @codebytere or @MarshallOfSound
node::Init(nullptr, nullptr, nullptr, nullptr);
#if defined(OS_WIN)

View File

@@ -215,6 +215,12 @@ const char kWidevineCdmPath[] = "widevine-cdm-path";
// Widevine CDM version.
const char kWidevineCdmVersion[] = "widevine-cdm-version";
// Forces the maximum disk space to be used by the disk cache, in bytes.
const char kDiskCacheSize[] = "disk-cache-size";
// Ignore the limit of 6 connections per host.
const char kIgnoreConnectionsLimit[] = "ignore-connections-limit";
} // namespace switches
} // namespace atom

View File

@@ -112,6 +112,9 @@ extern const char kWebviewTag[];
extern const char kWidevineCdmPath[];
extern const char kWidevineCdmVersion[];
extern const char kDiskCacheSize[];
extern const char kIgnoreConnectionsLimit[];
} // namespace switches
} // namespace atom

View File

@@ -16,7 +16,7 @@
#include "atom/renderer/content_settings_observer.h"
#include "atom/renderer/preferences_manager.h"
#include "base/command_line.h"
#include "base/process/process_handle.h"
#include "base/process/process.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "chrome/renderer/media/chrome_key_systems.h"
@@ -94,7 +94,8 @@ void RendererClientBase::DidCreateScriptContext(
content::RenderFrame* render_frame) {
// global.setHidden("contextId", `${processId}-${++nextContextId}`)
std::string context_id = base::StringPrintf(
"%" CrPRIdPid "-%d", base::GetCurrentProcId(), ++next_context_id_);
"%" CrPRIdPid "-%d", base::GetProcId(base::Process::Current().Handle()),
++next_context_id_);
v8::Isolate* isolate = context->GetIsolate();
v8::Local<v8::String> key = mate::StringToSymbol(isolate, "contextId");
v8::Local<v8::Private> private_key = v8::Private::ForApi(isolate, key);

View File

@@ -36,6 +36,7 @@ static_library("brightray") {
"//components/prefs",
"//content/public/browser",
"//content/shell:resources",
"//net:extras",
"//net:net_with_v8",
"//skia",
"//ui/views",

View File

@@ -112,6 +112,7 @@
'libraries': [
# Following libraries are always linked statically.
'<(libchromiumcontent_dir)/libbase_static.a',
'<(libchromiumcontent_dir)/libextras.a',
'<(libchromiumcontent_dir)/libgtkui.a',
'<(libchromiumcontent_dir)/libhttp_server.a',
'<(libchromiumcontent_dir)/libdevice_service.a',
@@ -206,6 +207,7 @@
'libraries': [
# Following libraries are always linked statically.
'<(libchromiumcontent_dir)/libbase_static.a',
'<(libchromiumcontent_dir)/libextras.a',
'<(libchromiumcontent_dir)/libhttp_server.a',
'<(libchromiumcontent_dir)/libdevice_service.a',
'<(libchromiumcontent_dir)/libdom_keycode_converter.a',
@@ -342,6 +344,7 @@
'-ldxgi.lib',
# Following libs are always linked statically.
'<(libchromiumcontent_dir)/base_static.lib',
'<(libchromiumcontent_dir)/extras.lib',
'<(libchromiumcontent_dir)/sandbox.lib',
'<(libchromiumcontent_dir)/sandbox_helper_win.lib',
'<(libchromiumcontent_dir)/http_server.lib',

View File

@@ -11,7 +11,6 @@
#include "brightray/browser/brightray_paths.h"
#include "brightray/browser/browser_client.h"
#include "brightray/browser/inspectable_web_contents_impl.h"
#include "brightray/browser/network_delegate.h"
#include "brightray/browser/special_storage_policy.h"
#include "brightray/browser/zoom_level_delegate.h"
#include "brightray/common/application_info.h"
@@ -20,7 +19,6 @@
#include "components/prefs/pref_service.h"
#include "components/prefs/pref_service_factory.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/storage_partition.h"
#include "net/base/escape.h"
@@ -37,25 +35,10 @@ std::string MakePartitionName(const std::string& input) {
} // namespace
class BrowserContext::ResourceContext : public content::ResourceContext {
public:
ResourceContext() : getter_(nullptr) {}
void set_url_request_context_getter(URLRequestContextGetter* getter) {
getter_ = getter;
}
private:
net::HostResolver* GetHostResolver() override {
return getter_->host_resolver();
}
net::URLRequestContext* GetRequestContext() override {
return getter_->GetURLRequestContext();
}
URLRequestContextGetter* getter_;
};
// static
void BrowserContextDeleter::Destruct(const BrowserContext* browser_context) {
browser_context->OnDestruct();
}
// static
BrowserContext::BrowserContextMap BrowserContext::browser_context_map_;
@@ -72,7 +55,6 @@ scoped_refptr<BrowserContext> BrowserContext::Get(const std::string& partition,
BrowserContext::BrowserContext(const std::string& partition, bool in_memory)
: in_memory_(in_memory),
resource_context_(new ResourceContext),
storage_policy_(new SpecialStoragePolicy),
weak_factory_(this) {
if (!PathService::Get(DIR_USER_DATA, &path_)) {
@@ -88,6 +70,8 @@ BrowserContext::BrowserContext(const std::string& partition, bool in_memory)
content::BrowserContext::Initialize(this, path_);
io_handle_ = new URLRequestContextGetter::Handle(GetWeakPtr());
browser_context_map_[PartitionKey(partition, in_memory)] = GetWeakPtr();
}
@@ -95,13 +79,14 @@ BrowserContext::~BrowserContext() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
NotifyWillBeDestroyed(this);
ShutdownStoragePartitions();
if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE,
resource_context_.release());
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&URLRequestContextGetter::NotifyContextShutdownOnIO,
base::RetainedRef(url_request_getter_)));
io_handle_->ShutdownOnUIThread();
}
void BrowserContext::OnDestruct() const {
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
delete this;
} else {
BrowserThread::DeleteSoon(BrowserThread::UI, FROM_HERE, this);
}
}
@@ -135,17 +120,10 @@ URLRequestContextGetter* BrowserContext::GetRequestContext() {
net::URLRequestContextGetter* BrowserContext::CreateRequestContext(
content::ProtocolHandlerMap* protocol_handlers,
content::URLRequestInterceptorScopedVector protocol_interceptors) {
DCHECK(!url_request_getter_.get());
url_request_getter_ = new URLRequestContextGetter(
this, static_cast<NetLog*>(BrowserClient::Get()->GetNetLog()), GetPath(),
in_memory_, BrowserThread::GetTaskRunnerForThread(BrowserThread::IO),
protocol_handlers, std::move(protocol_interceptors));
resource_context_->set_url_request_context_getter(url_request_getter_.get());
return url_request_getter_.get();
}
std::unique_ptr<net::NetworkDelegate> BrowserContext::CreateNetworkDelegate() {
return std::make_unique<NetworkDelegate>();
return io_handle_
->CreateMainRequestContextGetter(protocol_handlers,
std::move(protocol_interceptors))
.get();
}
std::string BrowserContext::GetMediaDeviceIDSalt() {
@@ -171,7 +149,7 @@ bool BrowserContext::IsOffTheRecord() const {
}
content::ResourceContext* BrowserContext::GetResourceContext() {
return resource_context_.get();
return io_handle_->GetResourceContext();
}
content::DownloadManagerDelegate* BrowserContext::GetDownloadManagerDelegate() {
@@ -214,17 +192,19 @@ BrowserContext::CreateRequestContextForStoragePartition(
bool in_memory,
content::ProtocolHandlerMap* protocol_handlers,
content::URLRequestInterceptorScopedVector request_interceptors) {
NOTREACHED();
return nullptr;
}
net::URLRequestContextGetter* BrowserContext::CreateMediaRequestContext() {
return url_request_getter_.get();
return io_handle_->GetMainRequestContextGetter().get();
}
net::URLRequestContextGetter*
BrowserContext::CreateMediaRequestContextForStoragePartition(
const base::FilePath& partition_path,
bool in_memory) {
NOTREACHED();
return nullptr;
}

View File

@@ -23,9 +23,15 @@ class SpecialStoragePolicy;
namespace brightray {
class BrowserContext : public base::RefCounted<BrowserContext>,
public content::BrowserContext,
public brightray::URLRequestContextGetter::Delegate {
class BrowserContext;
struct BrowserContextDeleter {
static void Destruct(const BrowserContext* browser_context);
};
class BrowserContext
: public base::RefCountedThreadSafe<BrowserContext, BrowserContextDeleter>,
public content::BrowserContext {
public:
// Get the BrowserContext according to its |partition| and |in_memory|,
// empty pointer when be returned when there is no matching BrowserContext.
@@ -66,14 +72,14 @@ class BrowserContext : public base::RefCounted<BrowserContext>,
const base::FilePath& partition_path,
bool in_memory) override;
std::string GetMediaDeviceIDSalt() override;
URLRequestContextGetter* url_request_context_getter() const {
return url_request_getter_.get();
}
base::FilePath GetPath() const override;
void InitPrefs();
PrefService* prefs() { return prefs_.get(); }
virtual std::string GetUserAgent() const = 0;
virtual void OnMainRequestContextCreated(URLRequestContextGetter* getter) {}
protected:
BrowserContext(const std::string& partition, bool in_memory);
~BrowserContext() override;
@@ -81,16 +87,14 @@ class BrowserContext : public base::RefCounted<BrowserContext>,
// Subclasses should override this to register custom preferences.
virtual void RegisterPrefs(PrefRegistrySimple* pref_registry) {}
// URLRequestContextGetter::Delegate:
std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate() override;
base::FilePath GetPath() const override;
private:
friend class base::RefCounted<BrowserContext>;
class ResourceContext;
friend class base::RefCountedThreadSafe<BrowserContext,
BrowserContextDeleter>;
friend class base::DeleteHelper<BrowserContext>;
friend struct BrowserContextDeleter;
void RegisterInternalPrefs(PrefRegistrySimple* pref_registry);
void OnDestruct() const;
// partition_id => browser_context
struct PartitionKey {
@@ -117,11 +121,12 @@ class BrowserContext : public base::RefCounted<BrowserContext>,
base::FilePath path_;
bool in_memory_;
std::unique_ptr<ResourceContext> resource_context_;
scoped_refptr<URLRequestContextGetter> url_request_getter_;
scoped_refptr<storage::SpecialStoragePolicy> storage_policy_;
std::unique_ptr<PrefService> prefs_;
std::unique_ptr<MediaDeviceIDSalt> media_device_id_salt_;
// Self-destructing class responsible for creating URLRequestContextGetter
// on the UI thread and deletes itself on the IO thread.
URLRequestContextGetter::Handle* io_handle_;
base::WeakPtrFactory<BrowserContext> weak_factory_;

View File

@@ -484,7 +484,7 @@ void InspectableWebContentsImpl::LoadNetworkResource(
net::URLFetcher* fetcher =
(net::URLFetcher::Create(gurl, net::URLFetcher::GET, this)).release();
pending_requests_[fetcher] = callback;
fetcher->SetRequestContext(browser_context->url_request_context_getter());
fetcher->SetRequestContext(browser_context->GetRequestContext());
fetcher->SetExtraRequestHeaders(headers);
fetcher->SaveResponseWithWriter(
std::unique_ptr<net::URLFetcherResponseWriter>(
@@ -735,6 +735,8 @@ void InspectableWebContentsImpl::WebContentsDestroyed() {
for (const auto& pair : pending_requests_)
delete pair.first;
pending_requests_.clear();
if (view_ && view_->GetDelegate())
view_->GetDelegate()->DevToolsClosed();
}

View File

@@ -1,161 +0,0 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.
#include "brightray/browser/network_delegate.h"
#include <string>
#include <vector>
#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/url_request/url_request.h"
namespace brightray {
namespace {
// Ignore the limit of 6 connections per host.
const char kIgnoreConnectionsLimit[] = "ignore-connections-limit";
} // namespace
NetworkDelegate::NetworkDelegate() {
auto* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(kIgnoreConnectionsLimit)) {
std::string value =
command_line->GetSwitchValueASCII(kIgnoreConnectionsLimit);
ignore_connections_limit_domains_ = base::SplitString(
value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
}
}
NetworkDelegate::~NetworkDelegate() {}
int NetworkDelegate::OnBeforeURLRequest(net::URLRequest* request,
const net::CompletionCallback& callback,
GURL* new_url) {
for (const auto& domain : ignore_connections_limit_domains_) {
if (request->url().DomainIs(domain)) {
// Allow unlimited concurrent connections.
request->SetPriority(net::MAXIMUM_PRIORITY);
request->SetLoadFlags(request->load_flags() | net::LOAD_IGNORE_LIMITS);
break;
}
}
return net::OK;
}
int NetworkDelegate::OnBeforeStartTransaction(
net::URLRequest* request,
const net::CompletionCallback& callback,
net::HttpRequestHeaders* headers) {
return net::OK;
}
void NetworkDelegate::OnStartTransaction(
net::URLRequest* request,
const net::HttpRequestHeaders& headers) {}
void NetworkDelegate::OnBeforeSendHeaders(
net::URLRequest* request,
const net::ProxyInfo& proxy_info,
const net::ProxyRetryInfoMap& proxy_retry_info,
net::HttpRequestHeaders* headers) {}
int NetworkDelegate::OnHeadersReceived(
net::URLRequest* request,
const net::CompletionCallback& callback,
const net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
GURL* allowed_unsafe_redirect_url) {
return net::OK;
}
void NetworkDelegate::OnBeforeRedirect(net::URLRequest* request,
const GURL& new_location) {}
void NetworkDelegate::OnResponseStarted(net::URLRequest* request,
int net_error) {}
void NetworkDelegate::OnNetworkBytesReceived(net::URLRequest* request,
int64_t bytes_read) {}
void NetworkDelegate::OnNetworkBytesSent(net::URLRequest* request,
int64_t bytes_sent) {}
void NetworkDelegate::OnCompleted(net::URLRequest* request, bool started) {}
void NetworkDelegate::OnURLRequestDestroyed(net::URLRequest* request) {}
void NetworkDelegate::OnPACScriptError(int line_number,
const base::string16& error) {}
NetworkDelegate::AuthRequiredResponse NetworkDelegate::OnAuthRequired(
net::URLRequest* request,
const net::AuthChallengeInfo& auth_info,
const AuthCallback& callback,
net::AuthCredentials* credentials) {
return AUTH_REQUIRED_RESPONSE_NO_ACTION;
}
bool NetworkDelegate::OnCanGetCookies(const net::URLRequest& request,
const net::CookieList& cookie_list) {
return true;
}
bool NetworkDelegate::OnCanSetCookie(const net::URLRequest& request,
const net::CanonicalCookie& cookie_line,
net::CookieOptions* options) {
return true;
}
bool NetworkDelegate::OnCanAccessFile(
const net::URLRequest& request,
const base::FilePath& original_path,
const base::FilePath& absolute_path) const {
return true;
}
bool NetworkDelegate::OnCanEnablePrivacyMode(
const GURL& url,
const GURL& first_party_for_cookies) const {
return false;
}
bool NetworkDelegate::OnAreExperimentalCookieFeaturesEnabled() const {
return true;
}
bool NetworkDelegate::OnCancelURLRequestWithPolicyViolatingReferrerHeader(
const net::URLRequest& request,
const GURL& target_url,
const GURL& referrer_url) const {
return false;
}
// TODO(deepak1556) : Enable after hooking into the reporting service
// https://crbug.com/704259
bool NetworkDelegate::OnCanQueueReportingReport(
const url::Origin& origin) const {
return false;
}
void NetworkDelegate::OnCanSendReportingReports(
std::set<url::Origin> origins,
base::OnceCallback<void(std::set<url::Origin>)> result_callback) const {}
bool NetworkDelegate::OnCanSetReportingClient(const url::Origin& origin,
const GURL& endpoint) const {
return false;
}
bool NetworkDelegate::OnCanUseReportingClient(const url::Origin& origin,
const GURL& endpoint) const {
return false;
}
} // namespace brightray

View File

@@ -1,88 +0,0 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE-CHROMIUM file.
#ifndef BRIGHTRAY_BROWSER_NETWORK_DELEGATE_H_
#define BRIGHTRAY_BROWSER_NETWORK_DELEGATE_H_
#include <set>
#include <string>
#include <vector>
#include "net/base/network_delegate.h"
namespace brightray {
class NetworkDelegate : public net::NetworkDelegate {
public:
NetworkDelegate();
~NetworkDelegate() override;
protected:
int OnBeforeURLRequest(net::URLRequest* request,
const net::CompletionCallback& callback,
GURL* new_url) override;
int OnBeforeStartTransaction(net::URLRequest* request,
const net::CompletionCallback& callback,
net::HttpRequestHeaders* headers) override;
void OnBeforeSendHeaders(net::URLRequest* request,
const net::ProxyInfo& proxy_info,
const net::ProxyRetryInfoMap& proxy_retry_info,
net::HttpRequestHeaders* headers) override;
void OnStartTransaction(net::URLRequest* request,
const net::HttpRequestHeaders& headers) override;
int OnHeadersReceived(
net::URLRequest* request,
const net::CompletionCallback& callback,
const net::HttpResponseHeaders* original_response_headers,
scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
GURL* allowed_unsafe_redirect_url) override;
void OnBeforeRedirect(net::URLRequest* request,
const GURL& new_location) override;
void OnResponseStarted(net::URLRequest* request, int net_error) override;
void OnNetworkBytesReceived(net::URLRequest* request,
int64_t bytes_read) override;
void OnNetworkBytesSent(net::URLRequest* request,
int64_t bytes_sent) override;
void OnCompleted(net::URLRequest* request, bool started) override;
void OnURLRequestDestroyed(net::URLRequest* request) override;
void OnPACScriptError(int line_number, const base::string16& error) override;
AuthRequiredResponse OnAuthRequired(
net::URLRequest* request,
const net::AuthChallengeInfo& auth_info,
const AuthCallback& callback,
net::AuthCredentials* credentials) override;
bool OnCanGetCookies(const net::URLRequest& request,
const net::CookieList& cookie_list) override;
bool OnCanSetCookie(const net::URLRequest& request,
const net::CanonicalCookie& cookie_line,
net::CookieOptions* options) override;
bool OnCanAccessFile(const net::URLRequest& request,
const base::FilePath& original_path,
const base::FilePath& absolute_path) const override;
bool OnCanEnablePrivacyMode(
const GURL& url,
const GURL& first_party_for_cookies) const override;
bool OnAreExperimentalCookieFeaturesEnabled() const override;
bool OnCancelURLRequestWithPolicyViolatingReferrerHeader(
const net::URLRequest& request,
const GURL& target_url,
const GURL& referrer_url) const override;
bool OnCanQueueReportingReport(const url::Origin& origin) const override;
void OnCanSendReportingReports(std::set<url::Origin> origins,
base::OnceCallback<void(std::set<url::Origin>)>
result_callback) const override;
bool OnCanSetReportingClient(const url::Origin& origin,
const GURL& endpoint) const override;
bool OnCanUseReportingClient(const url::Origin& origin,
const GURL& endpoint) const override;
private:
std::vector<std::string> ignore_connections_limit_domains_;
DISALLOW_COPY_AND_ASSIGN(NetworkDelegate);
};
} // namespace brightray
#endif // BRIGHTRAY_BROWSER_NETWORK_DELEGATE_H_

View File

@@ -12,14 +12,15 @@
#include "base/strings/string_util.h"
#include "base/task_scheduler/post_task.h"
#include "brightray/browser/browser_client.h"
#include "brightray/browser/browser_context.h"
#include "brightray/browser/net/require_ct_delegate.h"
#include "brightray/browser/net_log.h"
#include "brightray/browser/network_delegate.h"
#include "brightray/common/switches.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cookie_store_factory.h"
#include "content/public/browser/devtools_network_transaction_factory.h"
#include "content/public/browser/resource_context.h"
#include "net/base/host_mapping_rules.h"
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_known_logs.h"
@@ -29,6 +30,7 @@
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_store.h"
#include "net/dns/mapped_host_resolver.h"
#include "net/extras/sqlite/sqlite_channel_id_store.h"
#include "net/http/http_auth_filter.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_auth_preferences.h"
@@ -58,83 +60,107 @@ using content::BrowserThread;
namespace brightray {
std::string URLRequestContextGetter::Delegate::GetUserAgent() {
return base::EmptyString();
}
class ResourceContext : public content::ResourceContext {
public:
ResourceContext() = default;
~ResourceContext() override = default;
std::unique_ptr<net::NetworkDelegate>
URLRequestContextGetter::Delegate::CreateNetworkDelegate() {
return nullptr;
}
std::unique_ptr<net::URLRequestJobFactory>
URLRequestContextGetter::Delegate::CreateURLRequestJobFactory(
content::ProtocolHandlerMap* protocol_handlers) {
std::unique_ptr<net::URLRequestJobFactoryImpl> job_factory(
new net::URLRequestJobFactoryImpl);
for (auto& it : *protocol_handlers) {
job_factory->SetProtocolHandler(it.first,
base::WrapUnique(it.second.release()));
net::HostResolver* GetHostResolver() override {
if (request_context_)
return request_context_->host_resolver();
return nullptr;
}
protocol_handlers->clear();
job_factory->SetProtocolHandler(
url::kDataScheme, base::WrapUnique(new net::DataProtocolHandler));
job_factory->SetProtocolHandler(
url::kFileScheme,
base::WrapUnique(
new net::FileProtocolHandler(base::CreateTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}))));
net::URLRequestContext* GetRequestContext() override {
return request_context_;
}
return std::move(job_factory);
private:
friend class URLRequestContextGetter;
net::URLRequestContext* request_context_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ResourceContext);
};
URLRequestContextGetter::Handle::Handle(
base::WeakPtr<BrowserContext> browser_context)
: resource_context_(new ResourceContext),
browser_context_(browser_context),
initialized_(false) {}
URLRequestContextGetter::Handle::~Handle() {}
content::ResourceContext* URLRequestContextGetter::Handle::GetResourceContext()
const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
LazyInitialize();
return resource_context_.get();
}
net::HttpCache::BackendFactory*
URLRequestContextGetter::Delegate::CreateHttpCacheBackendFactory(
const base::FilePath& base_path) {
auto* command_line = base::CommandLine::ForCurrentProcess();
int max_size = 0;
base::StringToInt(command_line->GetSwitchValueASCII(switches::kDiskCacheSize),
&max_size);
base::FilePath cache_path = base_path.Append(FILE_PATH_LITERAL("Cache"));
return new net::HttpCache::DefaultBackend(
net::DISK_CACHE, net::CACHE_BACKEND_DEFAULT, cache_path, max_size);
scoped_refptr<URLRequestContextGetter>
URLRequestContextGetter::Handle::CreateMainRequestContextGetter(
content::ProtocolHandlerMap* protocol_handlers,
content::URLRequestInterceptorScopedVector protocol_interceptors) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!main_request_context_getter_.get());
main_request_context_getter_ = new URLRequestContextGetter(
BrowserClient::Get()->GetNetLog(), resource_context_.get(),
browser_context_->IsOffTheRecord(), browser_context_->GetUserAgent(),
browser_context_->GetPath(), protocol_handlers,
std::move(protocol_interceptors));
browser_context_->OnMainRequestContextCreated(
main_request_context_getter_.get());
return main_request_context_getter_;
}
std::unique_ptr<net::CertVerifier>
URLRequestContextGetter::Delegate::CreateCertVerifier(
RequireCTDelegate* ct_delegate) {
return net::CertVerifier::CreateDefault();
scoped_refptr<URLRequestContextGetter>
URLRequestContextGetter::Handle::GetMainRequestContextGetter() const {
return main_request_context_getter_;
}
net::SSLConfigService*
URLRequestContextGetter::Delegate::CreateSSLConfigService() {
return new net::SSLConfigServiceDefaults;
void URLRequestContextGetter::Handle::LazyInitialize() const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (initialized_)
return;
initialized_ = true;
content::BrowserContext::EnsureResourceContextInitialized(
browser_context_.get());
}
std::vector<std::string>
URLRequestContextGetter::Delegate::GetCookieableSchemes() {
return {"http", "https", "ws", "wss"};
void URLRequestContextGetter::Handle::ShutdownOnUIThread() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (main_request_context_getter_.get()) {
if (BrowserThread::IsThreadInitialized(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::BindOnce(&URLRequestContextGetter::NotifyContextShuttingDown,
base::RetainedRef(main_request_context_getter_),
std::move(resource_context_)));
}
}
if (!BrowserThread::DeleteSoon(BrowserThread::IO, FROM_HERE, this))
delete this;
}
URLRequestContextGetter::URLRequestContextGetter(
Delegate* delegate,
NetLog* net_log,
const base::FilePath& base_path,
ResourceContext* resource_context,
bool in_memory,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const std::string& user_agent,
const base::FilePath& base_path,
content::ProtocolHandlerMap* protocol_handlers,
content::URLRequestInterceptorScopedVector protocol_interceptors)
: delegate_(delegate),
: job_factory_(nullptr),
delegate_(nullptr),
net_log_(net_log),
resource_context_(resource_context),
protocol_interceptors_(std::move(protocol_interceptors)),
base_path_(base_path),
in_memory_(in_memory),
io_task_runner_(io_task_runner),
protocol_interceptors_(std::move(protocol_interceptors)),
job_factory_(nullptr),
user_agent_(user_agent),
context_shutting_down_(false) {
// Must first be created on the UI thread.
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -142,48 +168,30 @@ URLRequestContextGetter::URLRequestContextGetter(
if (protocol_handlers)
std::swap(protocol_handlers_, *protocol_handlers);
if (delegate_)
user_agent_ = delegate_->GetUserAgent();
// We must create the proxy config service on the UI loop on Linux because it
// must synchronously run on the glib message loop. This will be passed to
// the URLRequestContextStorage on the IO thread in GetURLRequestContext().
proxy_config_service_ =
net::ProxyResolutionService::CreateSystemProxyConfigService(
io_task_runner_);
BrowserThread::GetTaskRunnerForThread(BrowserThread::IO));
}
URLRequestContextGetter::~URLRequestContextGetter() {}
void URLRequestContextGetter::NotifyContextShutdownOnIO() {
void URLRequestContextGetter::NotifyContextShuttingDown(
std::unique_ptr<ResourceContext> resource_context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
context_shutting_down_ = true;
cookie_change_sub_.reset();
resource_context.reset();
net::URLRequestContextGetter::NotifyContextShuttingDown();
url_request_context_.reset();
storage_.reset();
http_network_session_.reset();
http_auth_preferences_.reset();
host_mapping_rules_.reset();
url_request_context_.reset();
storage_.reset();
ct_delegate_.reset();
net::URLRequestContextGetter::NotifyContextShuttingDown();
}
void URLRequestContextGetter::OnCookieChanged(
const net::CanonicalCookie& cookie,
net::CookieChangeCause cause) {
DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
if (!delegate_ || context_shutting_down_)
return;
content::BrowserThread::PostTask(
content::BrowserThread::UI, FROM_HERE,
base::BindOnce(&Delegate::NotifyCookieChange, base::Unretained(delegate_),
cookie, !(cause == net::CookieChangeCause::INSERTED),
cause));
}
net::HostResolver* URLRequestContextGetter::host_resolver() {
return url_request_context_->host_resolver();
}
net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext() {
@@ -208,28 +216,46 @@ net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext() {
storage_->set_network_delegate(delegate_->CreateNetworkDelegate());
std::unique_ptr<net::CookieStore> cookie_store;
scoped_refptr<net::SQLiteChannelIDStore> channel_id_db;
// Create a single task runner to use with the CookieStore and
// ChannelIDStore.
scoped_refptr<base::SequencedTaskRunner> cookie_background_task_runner =
base::CreateSequencedTaskRunnerWithTraits(
{base::MayBlock(), base::TaskPriority::BACKGROUND,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
auto cookie_path = in_memory_
? base::FilePath()
: base_path_.Append(FILE_PATH_LITERAL("Cookies"));
std::unique_ptr<net::CookieStore> cookie_store =
content::CreateCookieStore(content::CookieStoreConfig(
cookie_path, false, false, nullptr));
storage_->set_cookie_store(std::move(cookie_store));
if (!in_memory_) {
channel_id_db = new net::SQLiteChannelIDStore(
base_path_.Append(FILE_PATH_LITERAL("Origin Bound Certs")),
cookie_background_task_runner);
}
std::unique_ptr<net::ChannelIDService> channel_id_service(
new net::ChannelIDService(
new net::DefaultChannelIDStore(channel_id_db.get())));
content::CookieStoreConfig cookie_config(cookie_path, false, false,
nullptr);
cookie_config.channel_id_service = channel_id_service.get();
cookie_config.background_task_runner = cookie_background_task_runner;
cookie_store = content::CreateCookieStore(cookie_config);
cookie_store->SetChannelIDServiceID(channel_id_service->GetUniqueID());
// Set custom schemes that can accept cookies.
net::CookieMonster* cookie_monster =
static_cast<net::CookieMonster*>(url_request_context_->cookie_store());
cookie_monster->SetCookieableSchemes(delegate_->GetCookieableSchemes());
static_cast<net::CookieMonster*>(cookie_store.get());
std::vector<std::string> cookie_schemes({"http", "https", "ws", "wss"});
delegate_->GetCookieableSchemes(&cookie_schemes);
cookie_monster->SetCookieableSchemes(cookie_schemes);
// Cookie store will outlive notifier by order of declaration
// in the header.
cookie_change_sub_ =
url_request_context_->cookie_store()
->GetChangeDispatcher()
.AddCallbackForAllChanges(
base::Bind(&URLRequestContextGetter::OnCookieChanged, this));
storage_->set_channel_id_service(std::make_unique<net::ChannelIDService>(
new net::DefaultChannelIDStore(nullptr)));
cookie_store->GetChangeDispatcher().AddCallbackForAllChanges(
base::Bind(&URLRequestContextGetter::OnCookieChanged,
base::RetainedRef(this)));
storage_->set_cookie_store(std::move(cookie_store));
storage_->set_channel_id_service(std::move(channel_id_service));
storage_->set_http_user_agent_settings(
base::WrapUnique(new net::StaticHttpUserAgentSettings(
@@ -307,7 +333,7 @@ net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext() {
storage_->set_transport_security_state(std::move(transport_security_state));
storage_->set_cert_verifier(
delegate_->CreateCertVerifier(ct_delegate_.get()));
storage_->set_ssl_config_service(delegate_->CreateSSLConfigService());
storage_->set_ssl_config_service(new net::SSLConfigServiceDefaults());
storage_->set_http_auth_handler_factory(std::move(auth_handler_factory));
std::unique_ptr<net::HttpServerProperties> server_properties(
new net::HttpServerPropertiesImpl);
@@ -360,7 +386,8 @@ net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext() {
std::move(backend), false));
std::unique_ptr<net::URLRequestJobFactory> job_factory =
delegate_->CreateURLRequestJobFactory(&protocol_handlers_);
delegate_->CreateURLRequestJobFactory(url_request_context_.get(),
&protocol_handlers_);
job_factory_ = job_factory.get();
// Set up interceptors in the reverse order.
@@ -378,6 +405,9 @@ net::URLRequestContext* URLRequestContextGetter::GetURLRequestContext() {
storage_->set_job_factory(std::move(top_job_factory));
}
if (resource_context_)
resource_context_->request_context_ = url_request_context_.get();
return url_request_context_.get();
}
@@ -386,4 +416,11 @@ URLRequestContextGetter::GetNetworkTaskRunner() const {
return BrowserThread::GetTaskRunnerForThread(BrowserThread::IO);
}
void URLRequestContextGetter::OnCookieChanged(
const net::CanonicalCookie& cookie,
net::CookieChangeCause cause) const {
if (delegate_)
delegate_->OnCookieChanged(cookie, cause);
}
} // namespace brightray

View File

@@ -22,10 +22,6 @@
#include "base/debug/leak_tracker.h"
#endif
namespace base {
class MessageLoop;
}
namespace net {
class HostMappingRules;
class HostResolver;
@@ -38,6 +34,8 @@ class URLRequestJobFactory;
namespace brightray {
class BrowserContext;
class ResourceContext;
class RequireCTDelegate;
class NetLog;
@@ -48,55 +46,76 @@ class URLRequestContextGetter : public net::URLRequestContextGetter {
Delegate() {}
virtual ~Delegate() {}
virtual std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate();
virtual std::string GetUserAgent();
virtual std::unique_ptr<net::NetworkDelegate> CreateNetworkDelegate() = 0;
virtual std::unique_ptr<net::URLRequestJobFactory>
CreateURLRequestJobFactory(content::ProtocolHandlerMap* protocol_handlers);
CreateURLRequestJobFactory(
net::URLRequestContext* url_request_context,
content::ProtocolHandlerMap* protocol_handlers) = 0;
virtual net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory(
const base::FilePath& base_path);
const base::FilePath& base_path) = 0;
virtual std::unique_ptr<net::CertVerifier> CreateCertVerifier(
RequireCTDelegate* ct_delegate);
virtual net::SSLConfigService* CreateSSLConfigService();
virtual std::vector<std::string> GetCookieableSchemes();
virtual void NotifyCookieChange(const net::CanonicalCookie& cookie,
bool removed,
net::CookieChangeCause cause) {}
RequireCTDelegate* ct_delegate) = 0;
virtual void GetCookieableSchemes(
std::vector<std::string>* cookie_schemes) {}
virtual void OnCookieChanged(const net::CanonicalCookie& cookie,
net::CookieChangeCause cause) {}
};
URLRequestContextGetter(
Delegate* delegate,
NetLog* net_log,
const base::FilePath& base_path,
ResourceContext* resource_context,
bool in_memory,
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
const std::string& user_agent,
const base::FilePath& base_path,
content::ProtocolHandlerMap* protocol_handlers,
content::URLRequestInterceptorScopedVector protocol_interceptors);
// net::CookieChangeDispatcher::CookieChangedCallback implementation.
void OnCookieChanged(const net::CanonicalCookie& cookie,
net::CookieChangeCause cause);
// net::URLRequestContextGetter:
net::URLRequestContext* GetURLRequestContext() override;
scoped_refptr<base::SingleThreadTaskRunner> GetNetworkTaskRunner()
const override;
net::HostResolver* host_resolver();
net::URLRequestJobFactory* job_factory() const { return job_factory_; }
void set_delegate(Delegate* delegate) { delegate_ = delegate; }
void NotifyContextShutdownOnIO();
// Discard reference to URLRequestContext and inform observers to
// shutdown. Must be called only on IO thread.
void NotifyContextShuttingDown(std::unique_ptr<ResourceContext>);
private:
friend class BrowserContext;
// Responsible for destroying URLRequestContextGetter
// on the IO thread.
class Handle {
public:
explicit Handle(base::WeakPtr<BrowserContext> browser_context);
~Handle();
scoped_refptr<URLRequestContextGetter> CreateMainRequestContextGetter(
content::ProtocolHandlerMap* protocol_handlers,
content::URLRequestInterceptorScopedVector protocol_interceptors);
content::ResourceContext* GetResourceContext() const;
scoped_refptr<URLRequestContextGetter> GetMainRequestContextGetter() const;
void ShutdownOnUIThread();
private:
void LazyInitialize() const;
scoped_refptr<URLRequestContextGetter> main_request_context_getter_;
std::unique_ptr<ResourceContext> resource_context_;
base::WeakPtr<BrowserContext> browser_context_;
mutable bool initialized_;
DISALLOW_COPY_AND_ASSIGN(Handle);
};
~URLRequestContextGetter() override;
Delegate* delegate_;
NetLog* net_log_;
base::FilePath base_path_;
bool in_memory_;
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
std::string user_agent_;
// net::CookieChangeDispatcher::CookieChangedCallback implementation.
void OnCookieChanged(const net::CanonicalCookie& cookie,
net::CookieChangeCause cause) const;
#if DCHECK_IS_ON()
base::debug::LeakTracker<URLRequestContextGetter> leak_tracker_;
@@ -110,11 +129,16 @@ class URLRequestContextGetter : public net::URLRequestContextGetter {
std::unique_ptr<net::HttpAuthPreferences> http_auth_preferences_;
std::unique_ptr<net::HttpNetworkSession> http_network_session_;
std::unique_ptr<net::CookieChangeSubscription> cookie_change_sub_;
net::URLRequestJobFactory* job_factory_;
Delegate* delegate_;
NetLog* net_log_;
ResourceContext* resource_context_;
content::ProtocolHandlerMap protocol_handlers_;
content::URLRequestInterceptorScopedVector protocol_interceptors_;
net::URLRequestJobFactory* job_factory_; // weak ref
base::FilePath base_path_;
bool in_memory_;
std::string user_agent_;
bool context_shutting_down_;
DISALLOW_COPY_AND_ASSIGN(URLRequestContextGetter);

View File

@@ -50,9 +50,6 @@ const char kAuthServerWhitelist[] = "auth-server-whitelist";
const char kAuthNegotiateDelegateWhitelist[] =
"auth-negotiate-delegate-whitelist";
// Forces the maximum disk space to be used by the disk cache, in bytes.
const char kDiskCacheSize[] = "disk-cache-size";
} // namespace switches
} // namespace brightray

View File

@@ -17,7 +17,6 @@ extern const char kProxyPacUrl[];
extern const char kDisableHttp2[];
extern const char kAuthServerWhitelist[];
extern const char kAuthNegotiateDelegateWhitelist[];
extern const char kDiskCacheSize[];
} // namespace switches

View File

@@ -51,8 +51,6 @@
'browser/net/require_ct_delegate.h',
'browser/net_log.cc',
'browser/net_log.h',
'browser/network_delegate.cc',
'browser/network_delegate.h',
'browser/notification_delegate.h',
'browser/notification_presenter.cc',
'browser/notification_presenter.h',

View File

@@ -182,6 +182,10 @@ tray.setHighlightMode('off')
webContents.openDevTools({detach: true})
// Replace with
webContents.openDevTools({mode: 'detach'})
// Removed
webContents.setSize(options)
// There is no replacement for this API
```
## `webFrame`
@@ -198,6 +202,22 @@ webFrame.registerURLSchemeAsPrivileged('app', {secure: true})
protocol.registerStandardSchemes(['app'], {secure: true})
```
## `<webview>`
```js
// Removed
webview.setAttribute('disableguestresize', '')
// There is no replacement for this API
// Removed
webview.setAttribute('guestinstance', instanceId)
// There is no replacement for this API
// Keyboard listeners no longer work on webview tag
webview.onkeydown = () => { /* handler */ }
webview.onkeyup = () => { /* handler */ }
```
## Node Headers URL
This is the URL specified as `disturl` in a `.npmrc` file or as the `--dist-url`

View File

@@ -1264,6 +1264,17 @@ Sets the opacity of the window. On Linux does nothing.
Returns `Number` - between 0.0 (fully transparent) and 1.0 (fully opaque)
#### `win.setShape(rects)` _Windows_ _Linux_ _Experimental_
* `rects` [Rectangle[]](structures/rectangle.md) - Sets a shape on the window.
Passing an empty list reverts the window to being rectangular.
Setting a window shape determines the area within the window where the system
permits drawing and user interaction. Outside of the given region, no pixels
will be drawn and no mouse events will be registered. Mouse events outside of
the region will not be received by that window, but will fall through to
whatever is behind the window.
#### `win.setThumbarButtons(buttons)` _Windows_
* `buttons` [ThumbarButton[]](structures/thumbar-button.md)

View File

@@ -215,3 +215,17 @@ response object,it will emit the `aborted` event.
#### `request.followRedirect()`
Continues any deferred redirection request when the redirection mode is `manual`.
#### `request.getUploadProgress()`
Returns `Object`:
* `active` Boolean - Whether the request is currently active. If this is false
no other properties will be set
* `started` Boolean - Whether the upload has started. If this is false both
`current` and `total` will be set to 0.
* `current` Integer - The number of bytes that have been uploaded so far
* `total` Integer - The number of bytes that will be uploaded this request
You can use this method in conjunction with `POST` requests to get the progress
of a file upload or other data transfer.

View File

@@ -275,7 +275,7 @@ The `position` is only available on Windows, and it is (0, 0) by default.
#### `tray.setContextMenu(menu)`
* `menu` Menu
* `menu` Menu | null
Sets the context menu for this icon.

View File

@@ -1381,23 +1381,6 @@ win.webContents.on('did-finish-load', () => {
Shows pop-up dictionary that searches the selected word on the page.
#### `contents.setSize(options)`
Set the size of the page. This is only supported for `<webview>` guest contents.
* `options` Object
* `enableAutoSize` Boolean (optional) - true to make the webview container automatically
resize within the bounds specified by the attributes normal, min and max.
* `normal` [Size](structures/size.md) (optional) - Normal size of the page. This can be used in
combination with the [`disableguestresize`](webview-tag.md#disableguestresize)
attribute to manually resize the webview guest contents.
* `min` [Size](structures/size.md) (optional) - Minimum size of the page. This can be used in
combination with the [`disableguestresize`](webview-tag.md#disableguestresize)
attribute to manually resize the webview guest contents.
* `max` [Size](structures/size.md) (optional) - Maximium size of the page. This can be used in
combination with the [`disableguestresize`](webview-tag.md#disableguestresize)
attribute to manually resize the webview guest contents.
#### `contents.isOffscreen()`
Returns `Boolean` - Indicates whether *offscreen rendering* is enabled.

View File

@@ -62,33 +62,28 @@ and displays a "loading..." message during the load time:
</script>
```
## Internal implementation
Under the hood `webview` is implemented with [Out-of-Process iframes (OOPIFs)](https://www.chromium.org/developers/design-documents/oop-iframes).
The `webview` tag is essentially a custom element using shadow DOM to wrap an
`iframe` element inside it.
So the behavior of `webview` is very similar to a cross-domain `iframe`, as
examples:
* When clicking into a `webview`, the page focus will move from the embedder
frame to `webview`.
* You can not add keyboard event listeners to `webview`.
* All reactions between the embedder frame and `webview` are asynchronous.
## CSS Styling Notes
Please note that the `webview` tag's style uses `display:flex;` internally to
ensure the child `object` element fills the full height and width of its `webview`
container when used with traditional and flexbox layouts (since v0.36.11). Please
do not overwrite the default `display:flex;` CSS property, unless specifying
ensure the child `iframe` element fills the full height and width of its `webview`
container when used with traditional and flexbox layouts. Please do not
overwrite the default `display:flex;` CSS property, unless specifying
`display:inline-flex;` for inline layout.
`webview` has issues being hidden using the `hidden` attribute or using
`display: none;`. It can cause unusual rendering behaviour within its child
`browserplugin` object and the web page is reloaded when the `webview` is
un-hidden. The recommended approach is to hide the `webview` using
`visibility: hidden`.
```html
<style>
webview {
display:inline-flex;
width:640px;
height:480px;
}
webview.hide {
visibility: hidden;
}
</style>
```
## Tag Attributes
The `webview` tag has the following attributes:
@@ -244,59 +239,6 @@ A list of strings which specifies the blink features to be disabled separated by
The full list of supported feature strings can be found in the
[RuntimeEnabledFeatures.json5][runtime-enabled-features] file.
### `guestinstance`
```html
<webview src="https://www.github.com/" guestinstance="3"></webview>
```
A value that links the webview to a specific webContents. When a webview
first loads a new webContents is created and this attribute is set to its
instance identifier. Setting this attribute on a new or existing webview
connects it to the existing webContents that currently renders in a different
webview.
The existing webview will see the `destroy` event and will then create a new
webContents when a new url is loaded.
### `disableguestresize`
```html
<webview src="https://www.github.com/" disableguestresize></webview>
```
When this attribute is present the `webview` contents will be prevented from
resizing when the `webview` element itself is resized.
This can be used in combination with
[`webContents.setSize`](web-contents.md#contentssetsizeoptions) to manually
resize the webview contents in reaction to a window size change. This can
make resizing faster compared to relying on the webview element bounds to
automatically resize the contents.
```javascript
const {webContents} = require('electron')
// We assume that `win` points to a `BrowserWindow` instance containing a
// `<webview>` with `disableguestresize`.
win.on('resize', () => {
const [width, height] = win.getContentSize()
for (let wc of webContents.getAllWebContents()) {
// Check if `wc` belongs to a webview in the `win` window.
if (wc.hostWebContents &&
wc.hostWebContents.id === win.webContents.id) {
wc.setSize({
normal: {
width: width,
height: height
}
})
}
}
})
```
## Methods
The `webview` tag has the following methods:

View File

@@ -77,15 +77,20 @@ Whatever you choose, you will periodically have to bump the version in your `pac
The process is as follows:
1. All new major and minor releases lines begin with a `-beta.N` tag for `N >= 1`. At that point, the feature set is **locked**. That release line admits no further features, and focuses only on security and stability.
e.g. `2.0.0-beta.1`.
2. Bug fixes, regression fixes, and security patches can be admitted. Upon doing so, a new beta is released incrementing `N`.
e.g. `2.0.0-beta.2`
3. If a particular beta release is _generally regarded_ as stable, it will be re-released as a stable build, changing only the version information.
e.g. `2.0.0`.
4. If future bug fixes or security patches need to be made once a release is stable, they are applied and the _patch_ version is incremented accordingly
1. All new major and minor releases lines begin with a beta series indicated by semver prerelease tags of `beta.N`, e.g. `2.0.0-beta.1`. After the first beta, subsequent beta releases must meet all of the following conditions:
1. The change is backwards API-compatible (deprecations are allowed)
2. The risk to meeting our stability timeline must be low.
2. If allowed changes need to be made once a release is beta, they are applied and the prerelease tag is incremented, e.g. `2.0.0-beta.2`.
3. If a particular beta release is _generally regarded_ as stable, it will be re-released as a stable build, changing only the version information. e.g. `2.0.0`. After the first stable, all changes must be backwards-compatible bug or security fixes.
4. If future bug fixes or security patches need to be made once a release is stable, they are applied and the _patch_ version is incremented
e.g. `2.0.1`.
Specifically, the above means:
1. Admitting non-breaking-API changes early in the beta cycle is okay, even if those changes have the potential to cause moderate side-affects
2. Admitting feature-flagged changes, that do not otherwise alter existing code paths, at most points in the beta cycle is okay. Users can explicitly enable those flags in their apps.
3. Admitting features of any sort very late in the beta cycle is 👎 without a very good reason.
For each major and minor bump, you should expect to see something like the following:
```text
@@ -125,12 +130,7 @@ Feature flags are a common practice in Chromium, and are well-established in the
* it is enabled/disabled either at runtime, or build-time; we do not support the concept of a request-scoped feature flag
* it completely segments new and old code paths; refactoring old code to support a new feature _violates_ the feature-flag contract
* feature flags are eventually removed after the soft-branch is merged
We reconcile flagged code with our versioning strategy as follows:
1. we do not consider iterating on feature-flagged code in a stability branch; even judicious use of feature flags is not without risk
2. you may break API contracts in feature-flagged code without bumping the major version. Flagged code does not adhere to semver
* feature flags are eventually removed after the feature is released
# Semantic Commits

View File

@@ -4,7 +4,7 @@
'product_name%': 'Electron',
'company_name%': 'GitHub, Inc',
'company_abbr%': 'github',
'version%': '3.0.0-beta.6',
'version%': '3.0.0-nightly.20180904',
'js2c_input_dir': '<(SHARED_INTERMEDIATE_DIR)/js2c',
},
'includes': [
@@ -340,6 +340,16 @@
'link_settings': {
'libraries': [ '<@(libchromiumcontent_v8_libraries)' ],
},
'sources': [
'<@(lib_sources_location_provider)',
],
'defines': [
# Enable fake location provider to mock geolocation
# responses in component build. Should not be enabled
# for release build. If you need to test with chromium's
# location provider, remove this definition.
'OVERRIDE_LOCATION_PROVIDER',
],
}],
['OS=="win"', {
'sources': [

View File

@@ -306,6 +306,8 @@
'atom/browser/relauncher.h',
'atom/browser/render_process_preferences.cc',
'atom/browser/render_process_preferences.h',
'atom/browser/request_context_delegate.cc',
'atom/browser/request_context_delegate.h',
'atom/browser/session_preferences.cc',
'atom/browser/session_preferences.h',
'atom/browser/ui/accelerator_util.cc',
@@ -695,6 +697,10 @@
'chromium_src/chrome/utility/printing_handler_win.cc',
'chromium_src/chrome/utility/printing_handler_win.h',
],
'lib_sources_location_provider': [
'atom/browser/fake_location_provider.cc',
'atom/browser/fake_location_provider.h',
],
'framework_sources': [
'atom/app/atom_library_main.h',
'atom/app/atom_library_main.mm',

View File

@@ -1,9 +1,9 @@
const features = process.atomBinding('features')
// Browser side modules, please sort alphabetically.
module.exports = [
{name: 'app', file: 'app'},
{name: 'autoUpdater', file: 'auto-updater'},
{name: 'BoxLayout', file: 'box-layout'},
{name: 'Button', file: 'button'},
{name: 'BrowserView', file: 'browser-view'},
{name: 'BrowserWindow', file: 'browser-window'},
{name: 'contentTracing', file: 'content-tracing'},
@@ -11,8 +11,6 @@ module.exports = [
{name: 'globalShortcut', file: 'global-shortcut'},
{name: 'ipcMain', file: 'ipc-main'},
{name: 'inAppPurchase', file: 'in-app-purchase'},
{name: 'LabelButton', file: 'label-button'},
{name: 'LayoutManager', file: 'layout-manager'},
{name: 'Menu', file: 'menu'},
{name: 'MenuItem', file: 'menu-item'},
{name: 'net', file: 'net'},
@@ -24,7 +22,6 @@ module.exports = [
{name: 'screen', file: 'screen'},
{name: 'session', file: 'session'},
{name: 'systemPreferences', file: 'system-preferences'},
{name: 'TextField', file: 'text-field'},
{name: 'TopLevelWindow', file: 'top-level-window'},
{name: 'TouchBar', file: 'touch-bar'},
{name: 'Tray', file: 'tray'},
@@ -34,3 +31,13 @@ module.exports = [
// The internal modules, invisible unless you know their names.
{name: 'NavigationController', file: 'navigation-controller', private: true}
]
if (features.isViewApiEnabled()) {
module.exports.push(
{name: 'BoxLayout', file: 'box-layout'},
{name: 'Button', file: 'button'},
{name: 'LabelButton', file: 'label-button'},
{name: 'LayoutManager', file: 'layout-manager'},
{name: 'TextField', file: 'text-field'}
)
}

View File

@@ -352,6 +352,10 @@ class ClientRequest extends EventEmitter {
abort () {
this.urlRequest.cancel()
}
getUploadProgress () {
return this.urlRequest.getUploadProgress()
}
}
function writeAfterEndNT (self, error, callback) {

View File

@@ -264,6 +264,12 @@ WebContents.prototype.getZoomFactor = function (callback) {
})
}
// TODO(zcbenz): Remove the stub in 4.0.
WebContents.prototype.setSize = function () {
console.error('The WebContents.setSize method has been removed, see',
'https://github.com/electron/electron/issues/14120 for more.')
}
// Add JavaScript wrappers for WebContents class.
WebContents.prototype._init = function () {
// The navigation controller.

View File

@@ -26,6 +26,7 @@ const supportedWebViewEvents = [
'did-navigate',
'did-frame-navigate',
'did-navigate-in-page',
'focus-change',
'close',
'crashed',
'gpu-crashed',
@@ -322,6 +323,10 @@ ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_ATTACH_GUEST', function (event, embedder
attachGuest(event, embedderFrameId, elementInstanceId, guestInstanceId, params)
})
ipcMain.on('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', function (event, focus, guestInstanceId) {
event.sender.emit('focus-change', {}, focus, guestInstanceId)
})
// Returns WebContents from its guest id.
const getGuest = function (guestInstanceId) {
const guestInstance = guestInstances[guestInstanceId]

View File

@@ -27,11 +27,11 @@ const mergeOptions = function (child, parent, visited) {
for (const key in parent) {
if (key === 'isBrowserView') continue
if (!hasProp.call(parent, key)) continue
if (key in child) continue
if (key in child && key !== 'webPreferences') continue
const value = parent[key]
if (typeof value === 'object') {
child[key] = mergeOptions({}, value, visited)
child[key] = mergeOptions(child[key] || {}, value, visited)
} else {
child[key] = value
}

View File

@@ -98,9 +98,10 @@ class ObjectsRegistry {
// Private: Clear the storage when renderer process is destoryed.
registerDeleteListener (webContents, contextId) {
const processId = webContents.getProcessId()
const listener = (event, deletedProcessId) => {
if (deletedProcessId === processId) {
// contextId => ${OSProcessId}-${contextCount}
const OSProcessId = contextId.split('-')[0]
const listener = (event, deletedProcessId, deletedOSProcessId) => {
if (deletedOSProcessId && deletedOSProcessId.toString() === OSProcessId) {
webContents.removeListener('render-view-deleted', listener)
this.clear(webContents, contextId)
}

View File

@@ -25,6 +25,7 @@ var v8Util = process.atomBinding('v8_util')
v8Util.setHiddenValue(global, 'ipc', new events.EventEmitter())
// Use electron module after everything is ready.
const {ipcRenderer} = require('electron')
const {
warnAboutNodeWithRemoteContent,
@@ -184,3 +185,15 @@ window.addEventListener('load', function loadHandler () {
window.removeEventListener('load', loadHandler)
})
// Report focus/blur events of webview to browser.
// Note that while Chromium content APIs have observer for focus/blur, they
// unfortunately do not work for webview.
if (process.guestInstanceId) {
window.addEventListener('focus', () => {
ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', true, process.guestInstanceId)
})
window.addEventListener('blur', () => {
ipcRenderer.send('ELECTRON_GUEST_VIEW_MANAGER_FOCUS_CHANGE', false, process.guestInstanceId)
})
}

View File

@@ -24,6 +24,7 @@ const WEB_VIEW_EVENTS = {
'did-navigate': ['url', 'httpResponseCode', 'httpStatusText'],
'did-frame-navigate': ['url', 'httpResponseCode', 'httpStatusText', 'isMainFrame', 'frameProcessId', 'frameRoutingId'],
'did-navigate-in-page': ['url', 'isMainFrame', 'frameProcessId', 'frameRoutingId'],
'focus-change': ['focus', 'guestInstanceId'],
'close': [],
'crashed': [],
'gpu-crashed': [],
@@ -55,6 +56,8 @@ const dispatchEvent = function (webView, eventName, eventKey, ...args) {
webView.dispatchEvent(domEvent)
if (eventName === 'load-commit') {
webView.onLoadCommit(domEvent)
} else if (eventName === 'focus-change') {
webView.onFocusChange(domEvent)
}
}

View File

@@ -16,6 +16,13 @@ const getNextId = function () {
return ++nextId
}
// A list of removed attributes from 3.0.
const removedAttributes = [
'autoresize',
'disableguestresize',
'guestinstance'
]
// Represents the internal state of the WebView node.
class WebViewImpl {
constructor (webviewNode) {
@@ -23,22 +30,38 @@ class WebViewImpl {
v8Util.setHiddenValue(this.webviewNode, 'internal', this)
this.elementAttached = false
this.beforeFirstNavigation = true
this.hasFocus = false
// Check for removed attributes.
for (const attributeName of removedAttributes) {
if (this.webviewNode.hasAttribute(attributeName)) {
this.reportRemovedAttribute(attributeName)
}
}
// on* Event handlers.
this.on = {}
// Create internal iframe element.
this.internalElement = this.createInternalElement()
const shadowRoot = this.webviewNode.attachShadow({mode: 'open'})
shadowRoot.innerHTML = '<!DOCTYPE html><style type="text/css">:host { display: flex; }</style>'
this.setupWebViewAttributes()
this.setupFocusPropagation()
this.viewInstanceId = getNextId()
shadowRoot.appendChild(this.internalElement)
// Provide access to contentWindow.
Object.defineProperty(this.webviewNode, 'contentWindow', {
get: () => {
return this.internalElement.contentWindow
},
enumerable: true
})
}
createInternalElement () {
const iframeElement = document.createElement('iframe')
iframeElement.style.width = '100%'
iframeElement.style.height = '100%'
iframeElement.style.flex = '1 1 auto'
iframeElement.style.border = '0'
v8Util.setHiddenValue(iframeElement, 'internal', this)
return iframeElement
@@ -76,32 +99,17 @@ class WebViewImpl {
})
}
setupFocusPropagation () {
if (!this.webviewNode.hasAttribute('tabIndex')) {
// <webview> needs a tabIndex in order to be focusable.
// TODO(fsamuel): It would be nice to avoid exposing a tabIndex attribute
// to allow <webview> to be focusable.
// See http://crbug.com/231664.
this.webviewNode.setAttribute('tabIndex', -1)
}
// Focus the BrowserPlugin when the <webview> takes focus.
this.webviewNode.addEventListener('focus', () => {
this.internalElement.focus()
})
// Blur the BrowserPlugin when the <webview> loses focus.
this.webviewNode.addEventListener('blur', () => {
this.internalElement.blur()
})
}
// This observer monitors mutations to attributes of the <webview> and
// updates the BrowserPlugin properties accordingly. In turn, updating
// a BrowserPlugin property will update the corresponding BrowserPlugin
// attribute, if necessary. See BrowserPlugin::UpdateDOMAttribute for more
// details.
handleWebviewAttributeMutation (attributeName, oldValue, newValue) {
if (removedAttributes.includes(attributeName)) {
this.reportRemovedAttribute(attributeName)
return
}
if (!this.attributes[attributeName] || this.attributes[attributeName].ignoreMutation) {
return
}
@@ -165,6 +173,15 @@ class WebViewImpl {
}
}
// Emits focus/blur events.
onFocusChange () {
const hasFocus = document.activeElement === this.webviewNode
if (hasFocus !== this.hasFocus) {
this.hasFocus = hasFocus
this.dispatchEvent(new Event(hasFocus ? 'focus' : 'blur'))
}
}
onAttach (storagePartitionId) {
return this.attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue(storagePartitionId)
}
@@ -197,6 +214,12 @@ class WebViewImpl {
// even documented.
this.resizeObserver = new ResizeObserver(this.onElementResize.bind(this)).observe(this.internalElement)
}
// TODO(zcbenz): Remove the warning in 4.0.
reportRemovedAttribute (attributeName) {
console.error(`The "${attributeName}" attribute has been removed from the <webview> tag,`,
'see https://github.com/electron/electron/issues/14120 for more.')
}
}
// Registers <webview> custom element.
@@ -343,6 +366,11 @@ const registerWebViewElement = function () {
return internal.webContents
}
// Focusing the webview should move page focus to the underlying iframe.
proto.focus = function () {
this.contentWindow.focus()
}
window.WebView = webFrame.registerEmbedderCustomElement('webview', {
prototype: proto
})

View File

@@ -1,48 +1,17 @@
Object.defineProperties(exports, {
ipcRenderer: {
enumerable: true,
get: function () {
return require('../ipc-renderer')
}
},
remote: {
enumerable: true,
get: function () {
return require('../../../renderer/api/remote')
}
},
webFrame: {
enumerable: true,
get: function () {
return require('../../../renderer/api/web-frame')
}
},
crashReporter: {
enumerable: true,
get: function () {
return require('../../../common/api/crash-reporter')
}
},
CallbacksRegistry: {
get: function () {
return require('../../../common/api/callbacks-registry')
}
},
isPromise: {
get: function () {
return require('../../../common/api/is-promise')
}
},
// XXX(alexeykuzmin): It won't be available if the Desktop Capturer
// was disabled during build time.
desktopCapturer: {
get: function () {
return require('../../../renderer/api/desktop-capturer')
}
},
nativeImage: {
get: function () {
return require('../../../common/api/native-image')
}
const moduleList = require('../module-list')
for (const {
name,
load,
enabled = true,
private: isPrivate = false
} of moduleList) {
if (!enabled) {
continue
}
})
Object.defineProperty(exports, name, {
enumerable: !isPrivate,
get: load
})
}

View File

@@ -0,0 +1,39 @@
const features = process.atomBinding('features')
module.exports = [
{
name: 'CallbacksRegistry',
load: () => require('../../common/api/callbacks-registry'),
private: true
},
{
name: 'crashReporter',
load: () => require('../../common/api/crash-reporter')
},
{
name: 'desktopCapturer',
load: () => require('../../renderer/api/desktop-capturer'),
enabled: features.isDesktopCapturerEnabled()
},
{
name: 'ipcRenderer',
load: () => require('./ipc-renderer')
},
{
name: 'isPromise',
load: () => require('../../common/api/is-promise'),
private: true
},
{
name: 'nativeImage',
load: () => require('../../common/api/native-image')
},
{
name: 'remote',
load: () => require('../../renderer/api/remote')
},
{
name: 'webFrame',
load: () => require('../../renderer/api/web-frame')
}
]

View File

@@ -1,10 +1,12 @@
/* eslint no-eval: "off" */
/* global binding, Buffer */
const events = require('events')
const electron = require('electron')
process.atomBinding = require('../common/atom-binding-setup')(binding.get, 'renderer')
// The electron module depends on process.atomBinding
const electron = require('electron')
const v8Util = process.atomBinding('v8_util')
// Expose browserify Buffer as a hidden value. This is used by C++ code to
// deserialize Buffer instances sent from browser process.

2
package-lock.json generated
View File

@@ -1,6 +1,6 @@
{
"name": "electron",
"version": "3.0.0-nightly.20180818",
"version": "3.0.0-beta.8",
"lockfileVersion": 1,
"requires": true,
"dependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "electron",
"version": "3.0.0-beta.6",
"version": "3.0.0-nightly.20180904",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {

View File

@@ -169,8 +169,6 @@ def setup_libchromiumcontent(is_dev, target_arch, url,
mkdir_p(target_dir)
else:
mkdir_p(DOWNLOAD_DIR)
if is_verbose_mode():
args += ['-v']
if is_dev:
subprocess.check_call([sys.executable, script] + args)
else:

View File

@@ -34,8 +34,13 @@ async function makeRequest (requestOptions, parseResponse) {
resolve(body)
}
} else {
console.error('Error occurred while requesting:', requestOptions.url)
if (parseResponse) {
console.log('Error: ', `(status ${res.statusCode})`, err || JSON.parse(res.body), requestOptions)
try {
console.log('Error: ', `(status ${res.statusCode})`, err || JSON.parse(res.body), requestOptions)
} catch (err) {
console.log('Error: ', `(status ${res.statusCode})`, err || res.body, requestOptions)
}
} else {
console.log('Error: ', `(status ${res.statusCode})`, err || res.body, requestOptions)
}

View File

@@ -0,0 +1,108 @@
#!/usr/bin/env node
if (!process.env.CI) require('dotenv-safe').load()
require('colors')
const args = require('minimist')(process.argv.slice(2), {
boolean: ['tag']
})
const { execSync } = require('child_process')
const { GitProcess } = require('dugite')
const GitHub = require('github')
const path = require('path')
const github = new GitHub()
const gitDir = path.resolve(__dirname, '..')
github.authenticate({
type: 'token',
token: process.env.ELECTRON_GITHUB_TOKEN
})
function getLastBumpCommit (tag) {
const data = execSync(`git log -n1 --grep "Bump ${tag}" --format="format:{hash: %H, message: '%s'}"`)
return JSON.parse(data)
}
async function getCurrentBranch (gitDir) {
const gitArgs = ['rev-parse', '--abbrev-ref', 'HEAD']
const branchDetails = await GitProcess.exec(gitArgs, gitDir)
if (branchDetails.exitCode === 0) {
return branchDetails.stdout.trim()
}
const error = GitProcess.parseError(branchDetails.stderr)
console.error(`Couldn't get current branch: `, error)
process.exit(1)
}
async function revertBumpCommit (tag) {
const branch = getCurrentBranch()
const commitToRevert = getLastBumpCommit(tag).hash
await GitProcess.exec(['revert', commitToRevert], gitDir)
const pushDetails = await GitProcess.exec(['push', 'origin', `HEAD:${branch}`, '--follow-tags'], gitDir)
if (pushDetails.exitCode === 0) {
console.log(`Successfully reverted release commit.`)
} else {
const error = GitProcess.parseError(pushDetails.stderr)
console.error(`Failed to push release commit: `, error)
process.exit(1)
}
}
async function deleteDraft (tag, targetRepo) {
try {
const result = await github.repos.getReleaseByTag({
owner: 'electron',
repo: targetRepo,
tag
})
if (!result.draft) {
console.log(`Published releases cannot be deleted.`)
process.exit(1)
} else {
await github.repos.deleteRelease({
owner: 'electron',
repo: targetRepo,
release_id: result.id
})
}
console.log(`Successfully deleted draft with tag ${tag} from ${targetRepo}`)
} catch (err) {
console.error(`Couldn't delete draft with tag ${tag} from ${targetRepo}: `, err)
process.exit(1)
}
}
async function deleteTag (tag, targetRepo) {
try {
await github.gitdata.deleteReference({
owner: 'electron',
repo: targetRepo,
ref: tag
})
console.log(`Successfully deleted tag ${tag} from ${targetRepo}`)
} catch (err) {
console.log(`Couldn't delete tag ${tag} from ${targetRepo}: `, err)
process.exit(1)
}
}
async function cleanReleaseArtifacts () {
const tag = args.tag
const lastBumpCommit = getLastBumpCommit().message
if (lastBumpCommit.indexOf('nightly' > 0)) {
await deleteDraft(tag, 'nightlies')
await deleteTag(tag, 'nightlies')
} else {
await deleteDraft(tag, 'electron')
}
await deleteTag(tag, 'electron')
await revertBumpCommit(tag)
console.log('Failed release artifact cleanup complete')
}
cleanReleaseArtifacts()

View File

@@ -15,6 +15,21 @@ BASE_URL = 'https://electron-metadumper.herokuapp.com/?version='
version = sys.argv[1]
authToken = os.getenv('META_DUMPER_AUTH_HEADER')
def get_content(retry_count = 5):
try:
request = urllib2.Request(
BASE_URL + version,
headers={"Authorization" : authToken}
)
return urllib2.urlopen(
request
).read()
except Exception as e:
if retry_count == 0:
raise e
return get_content(retry_count - 1)
def main():
if not authToken or authToken == "":
raise Exception("Please set META_DUMPER_AUTH_HEADER")
@@ -23,14 +38,7 @@ def main():
safe_mkdir(OUT_DIR)
index_json = os.path.relpath(os.path.join(OUT_DIR, 'index.json'))
request = urllib2.Request(
BASE_URL + version,
headers={"Authorization" : authToken}
)
new_content = urllib2.urlopen(
request
).read()
new_content = get_content()
with open(index_json, "w") as f:
f.write(new_content)

View File

@@ -893,6 +893,17 @@ describe('BrowserWindow module', () => {
})
})
describe('BrowserWindow.setShape(rects)', () => {
it('allows setting shape', () => {
assert.doesNotThrow(() => {
w.setShape([])
w.setShape([{x: 0, y: 0, width: 100, height: 100}])
w.setShape([{x: 0, y: 0, width: 100, height: 100}, {x: 0, y: 200, width: 1000, height: 100}])
w.setShape([])
})
})
})
describe('"useContentSize" option', () => {
it('make window created with content size when used', () => {
w.destroy()

47
spec/api-tray-spec.js Normal file
View File

@@ -0,0 +1,47 @@
const {remote} = require('electron')
const {Menu, Tray, nativeImage} = remote
describe('tray module', () => {
let tray
beforeEach(() => {
tray = new Tray(nativeImage.createEmpty())
})
afterEach(() => {
tray.destroy()
tray = null
})
describe('tray.setContextMenu', () => {
it('accepts menu instance', () => {
tray.setContextMenu(new Menu())
})
it('accepts null', () => {
tray.setContextMenu(null)
})
})
describe('tray.setImage', () => {
it('accepts empty image', () => {
tray.setImage(nativeImage.createEmpty())
})
})
describe('tray.setPressedImage', () => {
it('accepts empty image', () => {
tray.setPressedImage(nativeImage.createEmpty())
})
})
describe('tray.setTitle', () => {
it('accepts non-empty string', () => {
tray.setTitle('Hello World!')
})
it('accepts empty string', () => {
tray.setTitle('')
})
})
})

View File

@@ -226,6 +226,47 @@ describe('chromium feature', () => {
})
})
describe('navigator.geolocation', () => {
before(function () {
if (!features.isFakeLocationProviderEnabled()) {
return this.skip()
}
})
it('returns position when permission is granted', (done) => {
navigator.geolocation.getCurrentPosition((position) => {
assert(position.timestamp)
done()
}, (error) => {
done(error)
})
})
it('returns error when permission is denied', (done) => {
w = new BrowserWindow({
show: false,
webPreferences: {
partition: 'geolocation-spec'
}
})
w.webContents.on('ipc-message', (event, args) => {
if (args[0] === 'success') {
done()
} else {
done('unexpected response from geolocation api')
}
})
w.webContents.session.setPermissionRequestHandler((wc, permission, callback) => {
if (permission === 'geolocation') {
callback(false)
} else {
callback(true)
}
})
w.loadURL(`file://${fixtures}/pages/geolocation/index.html`)
})
})
describe('window.open', () => {
it('returns a BrowserWindowProxy object', () => {
const b = window.open('about:blank', '', 'show=no')

View File

@@ -17,7 +17,7 @@
}
// This should trigger a dereference and a remote getURL call should fail
contents.emit('render-view-deleted', {}, contents.getProcessId())
contents.emit('render-view-deleted', {}, '', contents.getOSProcessId())
try {
contents.getURL()
ipcRenderer.send('error-message', 'No error thrown')

View File

@@ -0,0 +1,12 @@
<script>
const ipcRenderer = require('electron').ipcRenderer;
navigator.geolocation.getCurrentPosition((position) => {
ipcRenderer.send(position);
}, (error) => {
if (error) {
ipcRenderer.send('success')
} else {
ipcRenderer.send('unexpected error')
}
})
</script>

View File

@@ -1283,6 +1283,20 @@ describe('<webview> tag', function () {
expect(secondResizeEvent.newWidth).to.equal(newWidth)
expect(secondResizeEvent.newHeight).to.equal(newHeight)
})
it('emits focus event', async () => {
const domReadySignal = waitForEvent(webview, 'dom-ready')
webview.src = `file://${fixtures}/pages/a.html`
document.body.appendChild(webview)
await domReadySignal
// If this test fails, check if webview.focus() still works.
const focusSignal = waitForEvent(webview, 'focus')
webview.focus()
await focusSignal
})
})
describe('zoom behavior', () => {