commit
4d302956d3
74 changed files with 1000 additions and 418 deletions
|
@ -15,7 +15,7 @@ Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
|
|||
announcements.
|
||||
|
||||
This project adheres to the [Contributor Covenant 1.2](http://contributor-covenant.org/version/1/2/0).
|
||||
By participating, you are expected to uphold this code. Please report
|
||||
By participating, you are expected to uphold this code. Please report
|
||||
unacceptable behavior to atom@github.com.
|
||||
|
||||
## Downloads
|
||||
|
@ -55,12 +55,12 @@ contains documents describing how to build and contribute to Electron.
|
|||
|
||||
## Community
|
||||
|
||||
You can ask questions and interact with the community in the following
|
||||
You can ask questions and interact with the community in the following
|
||||
locations:
|
||||
- [`electron`](http://discuss.atom.io/category/electron) category on the Atom
|
||||
- [`electron`](http://discuss.atom.io/category/electron) category on the Atom
|
||||
forums
|
||||
- `#atom-shell` channel on Freenode
|
||||
- [`Atom`](http://atom-slack.herokuapp.com/) channel on Slack
|
||||
|
||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
Check out [awesome-electron](https://github.com/sindresorhus/awesome-electron)
|
||||
for a community maintained list of useful example apps, tools and resources.
|
||||
|
|
2
atom.gyp
2
atom.gyp
|
@ -4,7 +4,7 @@
|
|||
'product_name%': 'Electron',
|
||||
'company_name%': 'GitHub, Inc',
|
||||
'company_abbr%': 'github',
|
||||
'version%': '0.33.1',
|
||||
'version%': '0.33.6',
|
||||
},
|
||||
'includes': [
|
||||
'filenames.gypi',
|
||||
|
|
|
@ -27,10 +27,10 @@ AtomMainDelegate::~AtomMainDelegate() {
|
|||
}
|
||||
|
||||
bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
||||
// Disable logging out to debug.log on Windows
|
||||
logging::LoggingSettings settings;
|
||||
#if defined(OS_WIN)
|
||||
#if defined(DEBUG)
|
||||
// Print logging to debug.log on Windows
|
||||
settings.logging_dest = logging::LOG_TO_ALL;
|
||||
settings.log_file = L"debug.log";
|
||||
settings.lock_log = logging::LOCK_LOG_FILE;
|
||||
|
@ -41,6 +41,12 @@ bool AtomMainDelegate::BasicStartupComplete(int* exit_code) {
|
|||
#else // defined(OS_WIN)
|
||||
settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG;
|
||||
#endif // !defined(OS_WIN)
|
||||
|
||||
// Only enable logging when --enable-logging is specified.
|
||||
auto command_line = base::CommandLine::ForCurrentProcess();
|
||||
if (!command_line->HasSwitch(switches::kEnableLogging))
|
||||
settings.logging_dest = logging::LOG_NONE;
|
||||
|
||||
logging::InitLogging(settings);
|
||||
|
||||
// Logging with pid and timestamp.
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include "base/prefs/pref_service.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/thread_task_runner_handle.h"
|
||||
#include "brightray/browser/net/devtools_network_conditions.h"
|
||||
#include "brightray/browser/net/devtools_network_controller.h"
|
||||
#include "chrome/common/pref_names.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/storage_partition.h"
|
||||
|
@ -294,6 +296,43 @@ void Session::SetDownloadPath(const base::FilePath& path) {
|
|||
prefs::kDownloadDefaultDirectory, path);
|
||||
}
|
||||
|
||||
void Session::EnableNetworkEmulation(const mate::Dictionary& options) {
|
||||
scoped_ptr<brightray::DevToolsNetworkConditions> conditions;
|
||||
bool offline = false;
|
||||
double latency, download_throughput, upload_throughput;
|
||||
if (options.Get("offline", &offline) && offline) {
|
||||
conditions.reset(new brightray::DevToolsNetworkConditions(offline));
|
||||
} else {
|
||||
options.Get("latency", &latency);
|
||||
options.Get("downloadThroughput", &download_throughput);
|
||||
options.Get("uploadThroughput", &upload_throughput);
|
||||
conditions.reset(
|
||||
new brightray::DevToolsNetworkConditions(false,
|
||||
latency,
|
||||
download_throughput,
|
||||
upload_throughput));
|
||||
}
|
||||
auto controller = browser_context_->GetDevToolsNetworkController();
|
||||
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&brightray::DevToolsNetworkController::SetNetworkState,
|
||||
base::Unretained(controller),
|
||||
std::string(),
|
||||
base::Passed(&conditions)));
|
||||
}
|
||||
|
||||
void Session::DisableNetworkEmulation() {
|
||||
scoped_ptr<brightray::DevToolsNetworkConditions> conditions(
|
||||
new brightray::DevToolsNetworkConditions(false));
|
||||
auto controller = browser_context_->GetDevToolsNetworkController();
|
||||
|
||||
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
||||
base::Bind(&brightray::DevToolsNetworkController::SetNetworkState,
|
||||
base::Unretained(controller),
|
||||
std::string(),
|
||||
base::Passed(&conditions)));
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Session::Cookies(v8::Isolate* isolate) {
|
||||
if (cookies_.IsEmpty()) {
|
||||
auto handle = atom::api::Cookies::Create(isolate, browser_context());
|
||||
|
@ -310,6 +349,8 @@ mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder(
|
|||
.SetMethod("clearStorageData", &Session::ClearStorageData)
|
||||
.SetMethod("setProxy", &Session::SetProxy)
|
||||
.SetMethod("setDownloadPath", &Session::SetDownloadPath)
|
||||
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
|
||||
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
|
||||
.SetProperty("cookies", &Session::Cookies);
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ class FilePath;
|
|||
|
||||
namespace mate {
|
||||
class Arguments;
|
||||
class Dictionary;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
@ -65,6 +66,8 @@ class Session: public mate::TrackableObject<Session>,
|
|||
void ClearStorageData(mate::Arguments* args);
|
||||
void SetProxy(const std::string& proxy, const base::Closure& callback);
|
||||
void SetDownloadPath(const base::FilePath& path);
|
||||
void EnableNetworkEmulation(const mate::Dictionary& options);
|
||||
void DisableNetworkEmulation();
|
||||
v8::Local<v8::Value> Cookies(v8::Isolate* isolate);
|
||||
|
||||
// Cached object for cookies API.
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <set>
|
||||
|
||||
#include "atom/browser/api/atom_api_session.h"
|
||||
#include "atom/browser/api/atom_api_window.h"
|
||||
#include "atom/browser/atom_browser_client.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
|
@ -26,6 +27,7 @@
|
|||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "brightray/browser/inspectable_web_contents.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view.h"
|
||||
#include "chrome/browser/printing/print_view_manager_basic.h"
|
||||
#include "chrome/browser/printing/print_preview_message_handler.h"
|
||||
#include "content/common/view_messages.h"
|
||||
|
@ -228,6 +230,8 @@ WebContents::WebContents(v8::Isolate* isolate,
|
|||
AttachAsUserData(web_contents);
|
||||
InitWithWebContents(web_contents);
|
||||
|
||||
managed_web_contents()->GetView()->SetDelegate(this);
|
||||
|
||||
// Save the preferences in C++.
|
||||
base::DictionaryValue web_preferences;
|
||||
mate::ConvertFromV8(isolate, options.GetHandle(), &web_preferences);
|
||||
|
@ -491,6 +495,33 @@ void WebContents::DidUpdateFaviconURL(
|
|||
Emit("page-favicon-updated", unique_urls);
|
||||
}
|
||||
|
||||
void WebContents::DevToolsFocused() {
|
||||
Emit("devtools-focused");
|
||||
}
|
||||
|
||||
void WebContents::DevToolsOpened() {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto handle = WebContents::CreateFrom(
|
||||
isolate(), managed_web_contents()->GetDevToolsWebContents());
|
||||
devtools_web_contents_.Reset(isolate(), handle.ToV8());
|
||||
|
||||
// Inherit owner window in devtools.
|
||||
if (owner_window())
|
||||
handle->SetOwnerWindow(managed_web_contents()->GetDevToolsWebContents(),
|
||||
owner_window());
|
||||
|
||||
Emit("devtools-opened");
|
||||
}
|
||||
|
||||
void WebContents::DevToolsClosed() {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
devtools_web_contents_.Reset();
|
||||
|
||||
Emit("devtools-closed");
|
||||
}
|
||||
|
||||
bool WebContents::OnMessageReceived(const IPC::Message& message) {
|
||||
bool handled = true;
|
||||
IPC_BEGIN_MESSAGE_MAP(WebContents, message)
|
||||
|
@ -698,10 +729,6 @@ void WebContents::InspectServiceWorker() {
|
|||
}
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::Session(v8::Isolate* isolate) {
|
||||
return v8::Local<v8::Value>::New(isolate, session_);
|
||||
}
|
||||
|
||||
void WebContents::HasServiceWorker(
|
||||
const base::Callback<void(bool)>& callback) {
|
||||
auto context = GetServiceWorkerContext(web_contents());
|
||||
|
@ -893,6 +920,24 @@ v8::Local<v8::Value> WebContents::GetWebPreferences(v8::Isolate* isolate) {
|
|||
return mate::ConvertToV8(isolate, *web_preferences->web_preferences());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::GetOwnerBrowserWindow() {
|
||||
if (owner_window())
|
||||
return Window::From(isolate(), owner_window());
|
||||
else
|
||||
return v8::Null(isolate());
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::Session(v8::Isolate* isolate) {
|
||||
return v8::Local<v8::Value>::New(isolate, session_);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::DevToolsWebContents(v8::Isolate* isolate) {
|
||||
if (devtools_web_contents_.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
else
|
||||
return v8::Local<v8::Value>::New(isolate, devtools_web_contents_);
|
||||
}
|
||||
|
||||
mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) {
|
||||
if (template_.IsEmpty())
|
||||
|
@ -949,6 +994,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
|||
.SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency)
|
||||
.SetMethod("isGuest", &WebContents::IsGuest)
|
||||
.SetMethod("getWebPreferences", &WebContents::GetWebPreferences)
|
||||
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
|
||||
.SetMethod("hasServiceWorker", &WebContents::HasServiceWorker)
|
||||
.SetMethod("unregisterServiceWorker",
|
||||
&WebContents::UnregisterServiceWorker)
|
||||
|
@ -957,7 +1003,9 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
|||
.SetMethod("_printToPDF", &WebContents::PrintToPDF)
|
||||
.SetMethod("addWorkSpace", &WebContents::AddWorkSpace)
|
||||
.SetMethod("removeWorkSpace", &WebContents::RemoveWorkSpace)
|
||||
.SetProperty("session", &WebContents::Session)
|
||||
.SetProperty("session", &WebContents::Session, true)
|
||||
.SetProperty("devToolsWebContents",
|
||||
&WebContents::DevToolsWebContents, true)
|
||||
.Build());
|
||||
|
||||
return mate::ObjectTemplateBuilder(
|
||||
|
|
|
@ -83,7 +83,6 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
|||
void DisableDeviceEmulation();
|
||||
void InspectElement(int x, int y);
|
||||
void InspectServiceWorker();
|
||||
v8::Local<v8::Value> Session(v8::Isolate* isolate);
|
||||
void HasServiceWorker(const base::Callback<void(bool)>&);
|
||||
void UnregisterServiceWorker(const base::Callback<void(bool)>&);
|
||||
void SetAudioMuted(bool muted);
|
||||
|
@ -135,6 +134,13 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
|||
// Returns the web preferences of current WebContents.
|
||||
v8::Local<v8::Value> GetWebPreferences(v8::Isolate* isolate);
|
||||
|
||||
// Returns the owner window.
|
||||
v8::Local<v8::Value> GetOwnerBrowserWindow();
|
||||
|
||||
// Properties.
|
||||
v8::Local<v8::Value> Session(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
|
||||
|
||||
protected:
|
||||
explicit WebContents(content::WebContents* web_contents);
|
||||
WebContents(v8::Isolate* isolate, const mate::Dictionary& options);
|
||||
|
@ -218,6 +224,11 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
|||
void PluginCrashed(const base::FilePath& plugin_path,
|
||||
base::ProcessId plugin_pid) override;
|
||||
|
||||
// brightray::InspectableWebContentsViewDelegate:
|
||||
void DevToolsFocused() override;
|
||||
void DevToolsOpened() override;
|
||||
void DevToolsClosed() override;
|
||||
|
||||
private:
|
||||
enum Type {
|
||||
BROWSER_WINDOW, // Used by BrowserWindow.
|
||||
|
@ -237,6 +248,7 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
|||
IPC::Message* message);
|
||||
|
||||
v8::Global<v8::Value> session_;
|
||||
v8::Global<v8::Value> devtools_web_contents_;
|
||||
|
||||
scoped_ptr<WebViewGuestDelegate> guest_delegate_;
|
||||
|
||||
|
|
|
@ -92,6 +92,7 @@ Window::Window(v8::Isolate* isolate, const mate::Dictionary& options) {
|
|||
web_contents->SetOwnerWindow(window_.get());
|
||||
window_->InitFromOptions(options);
|
||||
window_->AddObserver(this);
|
||||
AttachAsUserData(window_.get());
|
||||
}
|
||||
|
||||
Window::~Window() {
|
||||
|
@ -184,28 +185,6 @@ void Window::OnRendererResponsive() {
|
|||
Emit("responsive");
|
||||
}
|
||||
|
||||
void Window::OnDevToolsFocus() {
|
||||
Emit("devtools-focused");
|
||||
}
|
||||
|
||||
void Window::OnDevToolsOpened() {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
auto handle = WebContents::CreateFrom(
|
||||
isolate(), api_web_contents_->GetDevToolsWebContents());
|
||||
devtools_web_contents_.Reset(isolate(), handle.ToV8());
|
||||
|
||||
Emit("devtools-opened");
|
||||
}
|
||||
|
||||
void Window::OnDevToolsClosed() {
|
||||
v8::Locker locker(isolate());
|
||||
v8::HandleScope handle_scope(isolate());
|
||||
devtools_web_contents_.Reset();
|
||||
|
||||
Emit("devtools-closed");
|
||||
}
|
||||
|
||||
void Window::OnExecuteWindowsCommand(const std::string& command_name) {
|
||||
Emit("app-command", command_name);
|
||||
}
|
||||
|
@ -540,13 +519,6 @@ v8::Local<v8::Value> Window::WebContents(v8::Isolate* isolate) {
|
|||
return v8::Local<v8::Value>::New(isolate, web_contents_);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> Window::DevToolsWebContents(v8::Isolate* isolate) {
|
||||
if (devtools_web_contents_.IsEmpty())
|
||||
return v8::Null(isolate);
|
||||
else
|
||||
return v8::Local<v8::Value>::New(isolate, devtools_web_contents_);
|
||||
}
|
||||
|
||||
// static
|
||||
void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> prototype) {
|
||||
|
@ -618,8 +590,17 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
|||
&Window::ShowDefinitionForSelection)
|
||||
#endif
|
||||
.SetProperty("id", &Window::ID, true)
|
||||
.SetProperty("webContents", &Window::WebContents, true)
|
||||
.SetProperty("devToolsWebContents", &Window::DevToolsWebContents, true);
|
||||
.SetProperty("webContents", &Window::WebContents, true);
|
||||
}
|
||||
|
||||
// static
|
||||
v8::Local<v8::Value> Window::From(v8::Isolate* isolate,
|
||||
NativeWindow* native_window) {
|
||||
auto existing = TrackableObject::FromWrappedClass(isolate, native_window);
|
||||
if (existing)
|
||||
return existing->GetWrapper(isolate);
|
||||
else
|
||||
return v8::Null(isolate);
|
||||
}
|
||||
|
||||
} // namespace api
|
||||
|
|
|
@ -43,6 +43,10 @@ class Window : public mate::TrackableObject<Window>,
|
|||
static void BuildPrototype(v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> prototype);
|
||||
|
||||
// Returns the BrowserWindow object from |native_window|.
|
||||
static v8::Local<v8::Value> From(v8::Isolate* isolate,
|
||||
NativeWindow* native_window);
|
||||
|
||||
NativeWindow* window() const { return window_.get(); }
|
||||
|
||||
protected:
|
||||
|
@ -69,9 +73,6 @@ class Window : public mate::TrackableObject<Window>,
|
|||
void OnWindowLeaveHtmlFullScreen() override;
|
||||
void OnRendererUnresponsive() override;
|
||||
void OnRendererResponsive() override;
|
||||
void OnDevToolsFocus() override;
|
||||
void OnDevToolsOpened() override;
|
||||
void OnDevToolsClosed() override;
|
||||
void OnExecuteWindowsCommand(const std::string& command_name) override;
|
||||
|
||||
// mate::Wrappable:
|
||||
|
@ -150,10 +151,8 @@ class Window : public mate::TrackableObject<Window>,
|
|||
|
||||
int32_t ID() const;
|
||||
v8::Local<v8::Value> WebContents(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> DevToolsWebContents(v8::Isolate* isolate);
|
||||
|
||||
v8::Global<v8::Value> web_contents_;
|
||||
v8::Global<v8::Value> devtools_web_contents_;
|
||||
v8::Global<v8::Value> menu_;
|
||||
|
||||
api::WebContents* api_web_contents_;
|
||||
|
|
|
@ -48,6 +48,15 @@ BrowserWindow::_init = ->
|
|||
# Notify the creation of the window.
|
||||
app.emit 'browser-window-created', {}, this
|
||||
|
||||
# Be compatible with old APIs.
|
||||
@webContents.on 'devtools-focused', => @emit 'devtools-focused'
|
||||
@webContents.on 'devtools-opened', => @emit 'devtools-opened'
|
||||
@webContents.on 'devtools-closed', => @emit 'devtools-closed'
|
||||
Object.defineProperty this, 'devToolsWebContents',
|
||||
enumerable: true,
|
||||
configurable: false,
|
||||
get: -> @webContents.devToolsWebContents
|
||||
|
||||
BrowserWindow.getFocusedWindow = ->
|
||||
windows = BrowserWindow.getAllWindows()
|
||||
return window for window in windows when window.isFocused()
|
||||
|
|
|
@ -79,7 +79,11 @@ Menu::_init = ->
|
|||
v8Util.setHiddenValue group[0], 'checked', true unless checked
|
||||
|
||||
Menu::popup = (window, x, y) ->
|
||||
throw new TypeError('Invalid window') unless window?.constructor is BrowserWindow
|
||||
unless window?.constructor is BrowserWindow
|
||||
# Shift.
|
||||
y = x
|
||||
x = window
|
||||
window = BrowserWindow.getFocusedWindow()
|
||||
if x? and y?
|
||||
@_popupAt(window, x, y)
|
||||
else
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
#include "atom/browser/atom_quota_permission_context.h"
|
||||
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
|
||||
#include "atom/browser/atom_speech_recognition_manager_delegate.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
|
@ -30,6 +31,7 @@
|
|||
#include "content/public/browser/client_certificate_delegate.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/resource_dispatcher_host.h"
|
||||
#include "content/public/browser/site_instance.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/common/web_preferences.h"
|
||||
|
@ -226,6 +228,13 @@ void AtomBrowserClient::SelectClientCertificate(
|
|||
delegate.Pass());
|
||||
}
|
||||
|
||||
void AtomBrowserClient::ResourceDispatcherHostCreated() {
|
||||
resource_dispatcher_host_delegate_.reset(
|
||||
new AtomResourceDispatcherHostDelegate);
|
||||
content::ResourceDispatcherHost::Get()->SetDelegate(
|
||||
resource_dispatcher_host_delegate_.get());
|
||||
}
|
||||
|
||||
brightray::BrowserMainParts* AtomBrowserClient::OverrideCreateBrowserMainParts(
|
||||
const content::MainFunctionParams&) {
|
||||
v8::V8::Initialize(); // Init V8 before creating main parts.
|
||||
|
|
|
@ -23,6 +23,8 @@ class SSLCertRequestInfo;
|
|||
|
||||
namespace atom {
|
||||
|
||||
class AtomResourceDispatcherHostDelegate;
|
||||
|
||||
class AtomBrowserClient : public brightray::BrowserClient,
|
||||
public content::RenderProcessHostObserver {
|
||||
public:
|
||||
|
@ -56,6 +58,7 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
|||
content::WebContents* web_contents,
|
||||
net::SSLCertRequestInfo* cert_request_info,
|
||||
scoped_ptr<content::ClientCertificateDelegate> delegate) override;
|
||||
void ResourceDispatcherHostCreated() override;
|
||||
|
||||
// brightray::BrowserClient:
|
||||
brightray::BrowserMainParts* OverrideCreateBrowserMainParts(
|
||||
|
@ -68,6 +71,9 @@ class AtomBrowserClient : public brightray::BrowserClient,
|
|||
// pending_render_process => current_render_process.
|
||||
std::map<int, int> pending_processes_;
|
||||
|
||||
scoped_ptr<AtomResourceDispatcherHostDelegate>
|
||||
resource_dispatcher_host_delegate_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AtomBrowserClient);
|
||||
};
|
||||
|
||||
|
|
|
@ -52,13 +52,16 @@ void AtomBrowserMainParts::RegisterDestructionCallback(
|
|||
destruction_callbacks_.push_back(callback);
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::PreEarlyInitialization() {
|
||||
brightray::BrowserMainParts::PreEarlyInitialization();
|
||||
#if defined(OS_POSIX)
|
||||
HandleSIGCHLD();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::PostEarlyInitialization() {
|
||||
brightray::BrowserMainParts::PostEarlyInitialization();
|
||||
|
||||
#if defined(USE_X11)
|
||||
SetDPIFromGSettings();
|
||||
#endif
|
||||
|
||||
{
|
||||
// Temporary set the bridge_task_runner_ as current thread's task runner,
|
||||
// so we can fool gin::PerIsolateData to use it as its task runner, instead
|
||||
|
@ -116,6 +119,13 @@ void AtomBrowserMainParts::PreMainMessageLoopRun() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::PostMainMessageLoopStart() {
|
||||
brightray::BrowserMainParts::PostMainMessageLoopStart();
|
||||
#if defined(OS_POSIX)
|
||||
HandleShutdownSignals();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::PostMainMessageLoopRun() {
|
||||
brightray::BrowserMainParts::PostMainMessageLoopRun();
|
||||
|
||||
|
|
|
@ -39,8 +39,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
|||
|
||||
protected:
|
||||
// content::BrowserMainParts:
|
||||
void PreEarlyInitialization() override;
|
||||
void PostEarlyInitialization() override;
|
||||
void PreMainMessageLoopRun() override;
|
||||
void PostMainMessageLoopStart() override;
|
||||
void PostMainMessageLoopRun() override;
|
||||
#if defined(OS_MACOSX)
|
||||
void PreMainMessageLoopStart() override;
|
||||
|
@ -48,8 +50,10 @@ class AtomBrowserMainParts : public brightray::BrowserMainParts {
|
|||
#endif
|
||||
|
||||
private:
|
||||
#if defined(USE_X11)
|
||||
void SetDPIFromGSettings();
|
||||
#if defined(OS_POSIX)
|
||||
// Set signal handlers.
|
||||
void HandleSIGCHLD();
|
||||
void HandleShutdownSignals();
|
||||
#endif
|
||||
|
||||
// A fake BrowserProcess object that used to feed the source code from chrome.
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
// Copyright (c) 2014 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "ui/gfx/switches.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
const char* kInterfaceSchema = "org.gnome.desktop.interface";
|
||||
const char* kScaleFactor = "scaling-factor";
|
||||
|
||||
bool SchemaExists(const char* schema_name) {
|
||||
const gchar* const* schemas = g_settings_list_schemas();
|
||||
while (*schemas) {
|
||||
if (strcmp(schema_name, static_cast<const char*>(*schemas)) == 0)
|
||||
return true;
|
||||
schemas++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KeyExists(GSettings* client, const char* key) {
|
||||
gchar** keys = g_settings_list_keys(client);
|
||||
if (!keys)
|
||||
return false;
|
||||
|
||||
gchar** iter = keys;
|
||||
while (*iter) {
|
||||
if (strcmp(*iter, key) == 0)
|
||||
break;
|
||||
iter++;
|
||||
}
|
||||
|
||||
bool exists = *iter != NULL;
|
||||
g_strfreev(keys);
|
||||
return exists;
|
||||
}
|
||||
|
||||
void GetDPIFromGSettings(guint* scale_factor) {
|
||||
GSettings* client = nullptr;
|
||||
if (!SchemaExists(kInterfaceSchema) ||
|
||||
!(client = g_settings_new(kInterfaceSchema))) {
|
||||
VLOG(1) << "Cannot create gsettings client.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (KeyExists(client, kScaleFactor))
|
||||
*scale_factor = g_settings_get_uint(client, kScaleFactor);
|
||||
|
||||
g_object_unref(client);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void AtomBrowserMainParts::SetDPIFromGSettings() {
|
||||
guint scale_factor = 1;
|
||||
GetDPIFromGSettings(&scale_factor);
|
||||
if (scale_factor == 0)
|
||||
scale_factor = 1;
|
||||
|
||||
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
|
||||
switches::kForceDeviceScaleFactor, base::UintToString(scale_factor));
|
||||
}
|
||||
|
||||
} // namespace atom
|
225
atom/browser/atom_browser_main_parts_posix.cc
Normal file
225
atom/browser/atom_browser_main_parts_posix.cc
Normal file
|
@ -0,0 +1,225 @@
|
|||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Most code came from: chrome/browser/chrome_browser_main_posix.cc.
|
||||
|
||||
#include "atom/browser/atom_browser_main_parts.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <sys/resource.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
#include "base/posix/eintr_wrapper.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
|
||||
// See comment in |PreEarlyInitialization()|, where sigaction is called.
|
||||
void SIGCHLDHandler(int signal) {
|
||||
}
|
||||
|
||||
// The OSX fork() implementation can crash in the child process before
|
||||
// fork() returns. In that case, the shutdown pipe will still be
|
||||
// shared with the parent process. To prevent child crashes from
|
||||
// causing parent shutdowns, |g_pipe_pid| is the pid for the process
|
||||
// which registered |g_shutdown_pipe_write_fd|.
|
||||
// See <http://crbug.com/175341>.
|
||||
pid_t g_pipe_pid = -1;
|
||||
int g_shutdown_pipe_write_fd = -1;
|
||||
int g_shutdown_pipe_read_fd = -1;
|
||||
|
||||
// Common code between SIG{HUP, INT, TERM}Handler.
|
||||
void GracefulShutdownHandler(int signal) {
|
||||
// Reinstall the default handler. We had one shot at graceful shutdown.
|
||||
struct sigaction action;
|
||||
memset(&action, 0, sizeof(action));
|
||||
action.sa_handler = SIG_DFL;
|
||||
RAW_CHECK(sigaction(signal, &action, NULL) == 0);
|
||||
|
||||
RAW_CHECK(g_pipe_pid == getpid());
|
||||
RAW_CHECK(g_shutdown_pipe_write_fd != -1);
|
||||
RAW_CHECK(g_shutdown_pipe_read_fd != -1);
|
||||
size_t bytes_written = 0;
|
||||
do {
|
||||
int rv = HANDLE_EINTR(
|
||||
write(g_shutdown_pipe_write_fd,
|
||||
reinterpret_cast<const char*>(&signal) + bytes_written,
|
||||
sizeof(signal) - bytes_written));
|
||||
RAW_CHECK(rv >= 0);
|
||||
bytes_written += rv;
|
||||
} while (bytes_written < sizeof(signal));
|
||||
}
|
||||
|
||||
// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
|
||||
void SIGHUPHandler(int signal) {
|
||||
RAW_CHECK(signal == SIGHUP);
|
||||
GracefulShutdownHandler(signal);
|
||||
}
|
||||
|
||||
// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
|
||||
void SIGINTHandler(int signal) {
|
||||
RAW_CHECK(signal == SIGINT);
|
||||
GracefulShutdownHandler(signal);
|
||||
}
|
||||
|
||||
// See comment in |PostMainMessageLoopStart()|, where sigaction is called.
|
||||
void SIGTERMHandler(int signal) {
|
||||
RAW_CHECK(signal == SIGTERM);
|
||||
GracefulShutdownHandler(signal);
|
||||
}
|
||||
|
||||
class ShutdownDetector : public base::PlatformThread::Delegate {
|
||||
public:
|
||||
explicit ShutdownDetector(int shutdown_fd);
|
||||
|
||||
void ThreadMain() override;
|
||||
|
||||
private:
|
||||
const int shutdown_fd_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(ShutdownDetector);
|
||||
};
|
||||
|
||||
ShutdownDetector::ShutdownDetector(int shutdown_fd)
|
||||
: shutdown_fd_(shutdown_fd) {
|
||||
CHECK_NE(shutdown_fd_, -1);
|
||||
}
|
||||
|
||||
// These functions are used to help us diagnose crash dumps that happen
|
||||
// during the shutdown process.
|
||||
NOINLINE void ShutdownFDReadError() {
|
||||
// Ensure function isn't optimized away.
|
||||
asm("");
|
||||
sleep(UINT_MAX);
|
||||
}
|
||||
|
||||
NOINLINE void ShutdownFDClosedError() {
|
||||
// Ensure function isn't optimized away.
|
||||
asm("");
|
||||
sleep(UINT_MAX);
|
||||
}
|
||||
|
||||
NOINLINE void ExitPosted() {
|
||||
// Ensure function isn't optimized away.
|
||||
asm("");
|
||||
sleep(UINT_MAX);
|
||||
}
|
||||
|
||||
void ShutdownDetector::ThreadMain() {
|
||||
base::PlatformThread::SetName("CrShutdownDetector");
|
||||
|
||||
int signal;
|
||||
size_t bytes_read = 0;
|
||||
ssize_t ret;
|
||||
do {
|
||||
ret = HANDLE_EINTR(
|
||||
read(shutdown_fd_,
|
||||
reinterpret_cast<char*>(&signal) + bytes_read,
|
||||
sizeof(signal) - bytes_read));
|
||||
if (ret < 0) {
|
||||
NOTREACHED() << "Unexpected error: " << strerror(errno);
|
||||
ShutdownFDReadError();
|
||||
break;
|
||||
} else if (ret == 0) {
|
||||
NOTREACHED() << "Unexpected closure of shutdown pipe.";
|
||||
ShutdownFDClosedError();
|
||||
break;
|
||||
}
|
||||
bytes_read += ret;
|
||||
} while (bytes_read < sizeof(signal));
|
||||
VLOG(1) << "Handling shutdown for signal " << signal << ".";
|
||||
base::Closure task =
|
||||
base::Bind(&Browser::Quit, base::Unretained(Browser::Get()));
|
||||
|
||||
if (!BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, task)) {
|
||||
// Without a UI thread to post the exit task to, there aren't many
|
||||
// options. Raise the signal again. The default handler will pick it up
|
||||
// and cause an ungraceful exit.
|
||||
RAW_LOG(WARNING, "No UI thread, exiting ungracefully.");
|
||||
kill(getpid(), signal);
|
||||
|
||||
// The signal may be handled on another thread. Give that a chance to
|
||||
// happen.
|
||||
sleep(3);
|
||||
|
||||
// We really should be dead by now. For whatever reason, we're not. Exit
|
||||
// immediately, with the exit status set to the signal number with bit 8
|
||||
// set. On the systems that we care about, this exit status is what is
|
||||
// normally used to indicate an exit by this signal's default handler.
|
||||
// This mechanism isn't a de jure standard, but even in the worst case, it
|
||||
// should at least result in an immediate exit.
|
||||
RAW_LOG(WARNING, "Still here, exiting really ungracefully.");
|
||||
_exit(signal | (1 << 7));
|
||||
}
|
||||
ExitPosted();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void AtomBrowserMainParts::HandleSIGCHLD() {
|
||||
// We need to accept SIGCHLD, even though our handler is a no-op because
|
||||
// otherwise we cannot wait on children. (According to POSIX 2001.)
|
||||
struct sigaction action;
|
||||
memset(&action, 0, sizeof(action));
|
||||
action.sa_handler = SIGCHLDHandler;
|
||||
CHECK_EQ(sigaction(SIGCHLD, &action, NULL), 0);
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::HandleShutdownSignals() {
|
||||
int pipefd[2];
|
||||
int ret = pipe(pipefd);
|
||||
if (ret < 0) {
|
||||
PLOG(DFATAL) << "Failed to create pipe";
|
||||
} else {
|
||||
g_pipe_pid = getpid();
|
||||
g_shutdown_pipe_read_fd = pipefd[0];
|
||||
g_shutdown_pipe_write_fd = pipefd[1];
|
||||
#if !defined(ADDRESS_SANITIZER) && !defined(KEEP_SHADOW_STACKS)
|
||||
const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 2;
|
||||
#else
|
||||
// ASan instrumentation and -finstrument-functions (used for keeping the
|
||||
// shadow stacks) bloat the stack frames, so we need to increase the stack
|
||||
// size to avoid hitting the guard page.
|
||||
const size_t kShutdownDetectorThreadStackSize = PTHREAD_STACK_MIN * 4;
|
||||
#endif
|
||||
// TODO(viettrungluu,willchan): crbug.com/29675 - This currently leaks, so
|
||||
// if you change this, you'll probably need to change the suppression.
|
||||
if (!base::PlatformThread::CreateNonJoinable(
|
||||
kShutdownDetectorThreadStackSize,
|
||||
new ShutdownDetector(g_shutdown_pipe_read_fd))) {
|
||||
LOG(DFATAL) << "Failed to create shutdown detector task.";
|
||||
}
|
||||
}
|
||||
// Setup signal handlers for shutdown AFTER shutdown pipe is setup because
|
||||
// it may be called right away after handler is set.
|
||||
|
||||
// If adding to this list of signal handlers, note the new signal probably
|
||||
// needs to be reset in child processes. See
|
||||
// base/process_util_posix.cc:LaunchProcess.
|
||||
|
||||
// We need to handle SIGTERM, because that is how many POSIX-based distros ask
|
||||
// processes to quit gracefully at shutdown time.
|
||||
struct sigaction action;
|
||||
memset(&action, 0, sizeof(action));
|
||||
action.sa_handler = SIGTERMHandler;
|
||||
CHECK_EQ(sigaction(SIGTERM, &action, NULL), 0);
|
||||
// Also handle SIGINT - when the user terminates the browser via Ctrl+C. If
|
||||
// the browser process is being debugged, GDB will catch the SIGINT first.
|
||||
action.sa_handler = SIGINTHandler;
|
||||
CHECK_EQ(sigaction(SIGINT, &action, NULL), 0);
|
||||
// And SIGHUP, for when the terminal disappears. On shutdown, many Linux
|
||||
// distros send SIGHUP, SIGTERM, and then SIGKILL.
|
||||
action.sa_handler = SIGHUPHandler;
|
||||
CHECK_EQ(sigaction(SIGHUP, &action, NULL), 0);
|
||||
}
|
||||
|
||||
} // namespace atom
|
32
atom/browser/atom_resource_dispatcher_host_delegate.cc
Normal file
32
atom/browser/atom_resource_dispatcher_host_delegate.cc
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "atom/browser/atom_resource_dispatcher_host_delegate.h"
|
||||
|
||||
#include "atom/common/platform_util.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "net/base/escape.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
|
||||
AtomResourceDispatcherHostDelegate::AtomResourceDispatcherHostDelegate() {
|
||||
}
|
||||
|
||||
bool AtomResourceDispatcherHostDelegate::HandleExternalProtocol(
|
||||
const GURL& url,
|
||||
int render_process_id,
|
||||
int render_view_id,
|
||||
bool is_main_frame,
|
||||
ui::PageTransition transition,
|
||||
bool has_user_gesture) {
|
||||
GURL escaped_url(net::EscapeExternalHandlerValue(url.spec()));
|
||||
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
||||
base::Bind(base::IgnoreResult(platform_util::OpenExternal), escaped_url));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace atom
|
28
atom/browser/atom_resource_dispatcher_host_delegate.h
Normal file
28
atom/browser/atom_resource_dispatcher_host_delegate.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Copyright (c) 2015 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
|
||||
#define ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
|
||||
|
||||
#include "content/public/browser/resource_dispatcher_host_delegate.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
class AtomResourceDispatcherHostDelegate
|
||||
: public content::ResourceDispatcherHostDelegate {
|
||||
public:
|
||||
AtomResourceDispatcherHostDelegate();
|
||||
|
||||
// content::ResourceDispatcherHostDelegate:
|
||||
bool HandleExternalProtocol(const GURL& url,
|
||||
int render_process_id,
|
||||
int render_view_id,
|
||||
bool is_main_frame,
|
||||
ui::PageTransition transition,
|
||||
bool has_user_gesture) override;
|
||||
};
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_ATOM_RESOURCE_DISPATCHER_HOST_DELEGATE_H_
|
|
@ -16,7 +16,8 @@ namespace atom {
|
|||
|
||||
Browser::Browser()
|
||||
: is_quiting_(false),
|
||||
is_ready_(false) {
|
||||
is_ready_(false),
|
||||
is_shutdown_(false) {
|
||||
WindowList::AddObserver(this);
|
||||
}
|
||||
|
||||
|
@ -30,6 +31,9 @@ Browser* Browser::Get() {
|
|||
}
|
||||
|
||||
void Browser::Quit() {
|
||||
if (is_quiting_)
|
||||
return;
|
||||
|
||||
is_quiting_ = HandleBeforeQuit();
|
||||
if (!is_quiting_)
|
||||
return;
|
||||
|
@ -42,9 +46,13 @@ void Browser::Quit() {
|
|||
}
|
||||
|
||||
void Browser::Shutdown() {
|
||||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnQuit());
|
||||
if (is_shutdown_)
|
||||
return;
|
||||
|
||||
is_shutdown_ = true;
|
||||
is_quiting_ = true;
|
||||
|
||||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnQuit());
|
||||
base::MessageLoop::current()->PostTask(
|
||||
FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
|
||||
}
|
||||
|
@ -121,6 +129,9 @@ void Browser::ClientCertificateSelector(
|
|||
}
|
||||
|
||||
void Browser::NotifyAndShutdown() {
|
||||
if (is_shutdown_)
|
||||
return;
|
||||
|
||||
bool prevent_default = false;
|
||||
FOR_EACH_OBSERVER(BrowserObserver, observers_, OnWillQuit(&prevent_default));
|
||||
|
||||
|
|
|
@ -159,6 +159,9 @@ class Browser : public WindowListObserver {
|
|||
// Whether "ready" event has been emitted.
|
||||
bool is_ready_;
|
||||
|
||||
// The browse is being shutdown.
|
||||
bool is_shutdown_;
|
||||
|
||||
std::string version_override_;
|
||||
std::string name_override_;
|
||||
|
||||
|
|
|
@ -21,6 +21,14 @@
|
|||
#include "content/public/browser/render_view_host.h"
|
||||
#include "storage/browser/fileapi/isolated_context.h"
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
#include "atom/browser/native_window_views.h"
|
||||
#endif
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include "atom/browser/browser.h"
|
||||
#endif
|
||||
|
||||
using content::BrowserThread;
|
||||
|
||||
namespace atom {
|
||||
|
@ -128,7 +136,11 @@ void CommonWebContentsDelegate::InitWithWebContents(
|
|||
}
|
||||
|
||||
void CommonWebContentsDelegate::SetOwnerWindow(NativeWindow* owner_window) {
|
||||
content::WebContents* web_contents = GetWebContents();
|
||||
SetOwnerWindow(GetWebContents(), owner_window);
|
||||
}
|
||||
|
||||
void CommonWebContentsDelegate::SetOwnerWindow(
|
||||
content::WebContents* web_contents, NativeWindow* owner_window) {
|
||||
owner_window_ = owner_window->GetWeakPtr();
|
||||
NativeWindowRelay* relay = new NativeWindowRelay(owner_window_);
|
||||
web_contents->SetUserData(relay->key, relay);
|
||||
|
@ -355,6 +367,23 @@ void CommonWebContentsDelegate::OnDevToolsAppendToFile(
|
|||
"DevToolsAPI.appendedToURL", &url_value, nullptr, nullptr);
|
||||
}
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
gfx::ImageSkia CommonWebContentsDelegate::GetDevToolsWindowIcon() {
|
||||
if (!owner_window())
|
||||
return gfx::ImageSkia();
|
||||
return static_cast<views::WidgetDelegate*>(static_cast<NativeWindowViews*>(
|
||||
owner_window()))->GetWindowAppIcon();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_X11)
|
||||
void CommonWebContentsDelegate::GetDevToolsWindowWMClass(
|
||||
std::string* name, std::string* class_name) {
|
||||
*class_name = Browser::Get()->GetName();
|
||||
*name = base::StringToLowerASCII(*class_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
void CommonWebContentsDelegate::SetHtmlApiFullscreen(bool enter_fullscreen) {
|
||||
// Window is already in fullscreen mode, save the state.
|
||||
if (enter_fullscreen && owner_window_->IsFullscreen()) {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "brightray/browser/default_web_contents_delegate.h"
|
||||
#include "brightray/browser/inspectable_web_contents_impl.h"
|
||||
#include "brightray/browser/inspectable_web_contents_delegate.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view_delegate.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
|
@ -21,7 +22,8 @@ class WebDialogHelper;
|
|||
|
||||
class CommonWebContentsDelegate
|
||||
: public brightray::DefaultWebContentsDelegate,
|
||||
public brightray::InspectableWebContentsDelegate {
|
||||
public brightray::InspectableWebContentsDelegate,
|
||||
public brightray::InspectableWebContentsViewDelegate {
|
||||
public:
|
||||
CommonWebContentsDelegate();
|
||||
virtual ~CommonWebContentsDelegate();
|
||||
|
@ -32,6 +34,8 @@ class CommonWebContentsDelegate
|
|||
|
||||
// Set the window as owner window.
|
||||
void SetOwnerWindow(NativeWindow* owner_window);
|
||||
void SetOwnerWindow(content::WebContents* web_contents,
|
||||
NativeWindow* owner_window);
|
||||
|
||||
// Destroy the managed InspectableWebContents object.
|
||||
void DestroyWebContents();
|
||||
|
@ -86,6 +90,15 @@ class CommonWebContentsDelegate
|
|||
void DevToolsRemoveFileSystem(
|
||||
const base::FilePath& file_system_path) override;
|
||||
|
||||
// brightray::InspectableWebContentsViewDelegate:
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
gfx::ImageSkia GetDevToolsWindowIcon() override;
|
||||
#endif
|
||||
#if defined(USE_X11)
|
||||
void GetDevToolsWindowWMClass(
|
||||
std::string* name, std::string* class_name) override;
|
||||
#endif
|
||||
|
||||
private:
|
||||
// Callback for when DevToolsSaveToFile has completed.
|
||||
void OnDevToolsSaveToFile(const std::string& url);
|
||||
|
|
|
@ -13,8 +13,8 @@ app.on('window-all-closed', function() {
|
|||
|
||||
// Parse command line options.
|
||||
var argv = process.argv.slice(1);
|
||||
var option = { file: null, help: null, version: null, webdriver: null };
|
||||
for (var i in argv) {
|
||||
var option = { file: null, help: null, version: null, webdriver: null, modules: [] };
|
||||
for (var i = 0; i < argv.length; i++) {
|
||||
if (argv[i] == '--version' || argv[i] == '-v') {
|
||||
option.version = true;
|
||||
break;
|
||||
|
@ -23,6 +23,9 @@ for (var i in argv) {
|
|||
break;
|
||||
} else if (argv[i] == '--test-type=webdriver') {
|
||||
option.webdriver = true;
|
||||
} else if (argv[i] == '--require' || argv[i] == '-r') {
|
||||
option.modules.push(argv[++i]);
|
||||
continue;
|
||||
} else if (argv[i][0] == '-') {
|
||||
continue;
|
||||
} else {
|
||||
|
@ -212,6 +215,10 @@ app.once('ready', function() {
|
|||
Menu.setApplicationMenu(menu);
|
||||
});
|
||||
|
||||
if (option.modules.length > 0) {
|
||||
require('module')._preloadModules(option.modules);
|
||||
}
|
||||
|
||||
// Start the specified app if there is one specified in command line, otherwise
|
||||
// start the default app.
|
||||
if (option.file && !option.webdriver) {
|
||||
|
@ -253,6 +260,7 @@ if (option.file && !option.webdriver) {
|
|||
helpMessage += "A path to an Electron application may be specified. The path must be to \n";
|
||||
helpMessage += "an index.js file or to a folder containing a package.json or index.js file.\n\n";
|
||||
helpMessage += "Options:\n";
|
||||
helpMessage += " -r, --require Module to preload (option can be repeated)";
|
||||
helpMessage += " -h, --help Print this usage message.\n";
|
||||
helpMessage += " -v, --version Print the version.";
|
||||
console.log(helpMessage);
|
||||
|
|
|
@ -7,14 +7,17 @@ Module = require 'module'
|
|||
# we need to restore it here.
|
||||
process.argv.splice 1, 1
|
||||
|
||||
# Clear search paths.
|
||||
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'reset-search-paths')
|
||||
|
||||
# Import common settings.
|
||||
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init')
|
||||
|
||||
# Add browser/api/lib to module search paths, which contains javascript part of
|
||||
# Electron's built-in libraries.
|
||||
globalPaths = Module.globalPaths
|
||||
globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
|
||||
|
||||
# Import common settings.
|
||||
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init')
|
||||
|
||||
if process.platform is 'win32'
|
||||
# Redirect node's console to use our own implementations, since node can not
|
||||
# handle console output when running as GUI program.
|
||||
|
@ -64,7 +67,9 @@ for packagePath in searchPaths
|
|||
catch e
|
||||
continue
|
||||
|
||||
throw new Error("Unable to find a valid app") unless packageJson?
|
||||
unless packageJson?
|
||||
process.nextTick -> process.exit 1
|
||||
throw new Error("Unable to find a valid app")
|
||||
|
||||
# Set application's version.
|
||||
app.setVersion packageJson.version if packageJson.version?
|
||||
|
|
|
@ -106,16 +106,9 @@ ipc.on 'ATOM_BROWSER_GLOBAL', (event, name) ->
|
|||
catch e
|
||||
event.returnValue = errorToMeta e
|
||||
|
||||
ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event, guestInstanceId) ->
|
||||
ipc.on 'ATOM_BROWSER_CURRENT_WINDOW', (event) ->
|
||||
try
|
||||
BrowserWindow = require 'browser-window'
|
||||
if guestInstanceId?
|
||||
guestViewManager = require './guest-view-manager'
|
||||
window = BrowserWindow.fromWebContents guestViewManager.getEmbedder(guestInstanceId)
|
||||
else
|
||||
window = BrowserWindow.fromWebContents event.sender
|
||||
window = BrowserWindow.fromDevToolsWebContents event.sender unless window?
|
||||
event.returnValue = valueToMeta event.sender, window
|
||||
event.returnValue = valueToMeta event.sender, event.sender.getOwnerBrowserWindow()
|
||||
catch e
|
||||
event.returnValue = errorToMeta e
|
||||
|
||||
|
|
|
@ -76,8 +76,6 @@ NativeWindow::NativeWindow(
|
|||
aspect_ratio_(0.0),
|
||||
inspectable_web_contents_(inspectable_web_contents),
|
||||
weak_factory_(this) {
|
||||
inspectable_web_contents->GetView()->SetDelegate(this);
|
||||
|
||||
options.Get(switches::kFrame, &has_frame_);
|
||||
options.Get(switches::kTransparent, &transparent_);
|
||||
options.Get(switches::kEnableLargerThanScreen, &enable_larger_than_screen_);
|
||||
|
@ -160,13 +158,8 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) {
|
|||
// Then show it.
|
||||
bool show = true;
|
||||
options.Get(switches::kShow, &show);
|
||||
if (show) {
|
||||
if (show)
|
||||
Show();
|
||||
} else {
|
||||
// When RenderView is created it sets to visible, this is to prevent
|
||||
// breaking the visibility API.
|
||||
web_contents()->WasHidden();
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindow::SetSize(const gfx::Size& size) {
|
||||
|
@ -418,18 +411,6 @@ void NativeWindow::NotifyWindowExecuteWindowsCommand(
|
|||
OnExecuteWindowsCommand(command));
|
||||
}
|
||||
|
||||
void NativeWindow::DevToolsFocused() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsFocus());
|
||||
}
|
||||
|
||||
void NativeWindow::DevToolsOpened() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsOpened());
|
||||
}
|
||||
|
||||
void NativeWindow::DevToolsClosed() {
|
||||
FOR_EACH_OBSERVER(NativeWindowObserver, observers_, OnDevToolsClosed());
|
||||
}
|
||||
|
||||
void NativeWindow::RenderViewCreated(
|
||||
content::RenderViewHost* render_view_host) {
|
||||
if (!transparent_)
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "brightray/browser/inspectable_web_contents_view_delegate.h"
|
||||
#include "base/supports_user_data.h"
|
||||
#include "content/public/browser/readback_types.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "content/public/browser/web_contents_user_data.h"
|
||||
|
@ -50,8 +50,8 @@ namespace atom {
|
|||
|
||||
struct DraggableRegion;
|
||||
|
||||
class NativeWindow : public content::WebContentsObserver,
|
||||
public brightray::InspectableWebContentsViewDelegate {
|
||||
class NativeWindow : public base::SupportsUserData,
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
using CapturePageCallback = base::Callback<void(const SkBitmap& bitmap)>;
|
||||
|
||||
|
@ -234,11 +234,6 @@ class NativeWindow : public content::WebContentsObserver,
|
|||
NativeWindow(brightray::InspectableWebContents* inspectable_web_contents,
|
||||
const mate::Dictionary& options);
|
||||
|
||||
// brightray::InspectableWebContentsViewDelegate:
|
||||
void DevToolsFocused() override;
|
||||
void DevToolsOpened() override;
|
||||
void DevToolsClosed() override;
|
||||
|
||||
// content::WebContentsObserver:
|
||||
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
|
||||
void BeforeUnloadDialogCancelled() override;
|
||||
|
|
|
@ -470,8 +470,6 @@ bool NativeWindowMac::IsFocused() {
|
|||
}
|
||||
|
||||
void NativeWindowMac::Show() {
|
||||
web_contents()->WasShown();
|
||||
|
||||
// This method is supposed to put focus on window, however if the app does not
|
||||
// have focus then "makeKeyAndOrderFront" will only show the window.
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
|
@ -480,13 +478,11 @@ void NativeWindowMac::Show() {
|
|||
}
|
||||
|
||||
void NativeWindowMac::ShowInactive() {
|
||||
web_contents()->WasShown();
|
||||
[window_ orderFrontRegardless];
|
||||
}
|
||||
|
||||
void NativeWindowMac::Hide() {
|
||||
[window_ orderOut:nil];
|
||||
web_contents()->WasHidden();
|
||||
}
|
||||
|
||||
bool NativeWindowMac::IsVisible() {
|
||||
|
|
|
@ -55,11 +55,6 @@ class NativeWindowObserver {
|
|||
virtual void OnWindowEnterHtmlFullScreen() {}
|
||||
virtual void OnWindowLeaveHtmlFullScreen() {}
|
||||
|
||||
// Redirect devtools events.
|
||||
virtual void OnDevToolsFocus() {}
|
||||
virtual void OnDevToolsOpened() {}
|
||||
virtual void OnDevToolsClosed() {}
|
||||
|
||||
// Called when renderer is hung.
|
||||
virtual void OnRendererUnresponsive() {}
|
||||
|
||||
|
|
|
@ -169,9 +169,6 @@ NativeWindowViews::NativeWindowViews(
|
|||
menu_bar_autohide_(false),
|
||||
menu_bar_visible_(false),
|
||||
menu_bar_alt_pressed_(false),
|
||||
#if defined(OS_WIN)
|
||||
is_minimized_(false),
|
||||
#endif
|
||||
keyboard_event_handler_(new views::UnhandledKeyboardEventHandler),
|
||||
use_content_size_(false),
|
||||
resizable_(true) {
|
||||
|
@ -228,6 +225,9 @@ NativeWindowViews::NativeWindowViews(
|
|||
|
||||
window_->Init(params);
|
||||
|
||||
bool fullscreen = false;
|
||||
options.Get(switches::kFullscreen, &fullscreen);
|
||||
|
||||
#if defined(USE_X11)
|
||||
// Start monitoring window states.
|
||||
window_state_watcher_.reset(new WindowStateWatcher(this));
|
||||
|
@ -253,8 +253,7 @@ NativeWindowViews::NativeWindowViews(
|
|||
}
|
||||
|
||||
// Before the window is mapped, there is no SHOW_FULLSCREEN_STATE.
|
||||
bool fullscreen = false;
|
||||
if (options.Get(switches::kFullscreen, & fullscreen) && fullscreen) {
|
||||
if (fullscreen) {
|
||||
state_atom_list.push_back(GetAtom("_NET_WM_STATE_FULLSCREEN"));
|
||||
}
|
||||
|
||||
|
@ -278,6 +277,14 @@ NativeWindowViews::NativeWindowViews(
|
|||
bounds = ContentBoundsToWindowBounds(bounds);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// Save initial window state.
|
||||
if (fullscreen)
|
||||
last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
|
||||
else
|
||||
last_window_state_ = ui::SHOW_STATE_NORMAL;
|
||||
|
||||
last_normal_size_ = gfx::Size(widget_size_);
|
||||
|
||||
if (!has_frame()) {
|
||||
// Set Window style so that we get a minimize and maximize animation when
|
||||
// frameless.
|
||||
|
@ -338,18 +345,15 @@ bool NativeWindowViews::IsFocused() {
|
|||
}
|
||||
|
||||
void NativeWindowViews::Show() {
|
||||
web_contents()->WasShown();
|
||||
window_->native_widget_private()->ShowWithWindowState(GetRestoredState());
|
||||
}
|
||||
|
||||
void NativeWindowViews::ShowInactive() {
|
||||
web_contents()->WasShown();
|
||||
window_->ShowInactive();
|
||||
}
|
||||
|
||||
void NativeWindowViews::Hide() {
|
||||
window_->Hide();
|
||||
web_contents()->WasHidden();
|
||||
}
|
||||
|
||||
bool NativeWindowViews::IsVisible() {
|
||||
|
@ -391,11 +395,16 @@ bool NativeWindowViews::IsMinimized() {
|
|||
void NativeWindowViews::SetFullScreen(bool fullscreen) {
|
||||
#if defined(OS_WIN)
|
||||
// There is no native fullscreen state on Windows.
|
||||
window_->SetFullscreen(fullscreen);
|
||||
if (fullscreen)
|
||||
if (fullscreen) {
|
||||
last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
|
||||
NotifyWindowEnterFullScreen();
|
||||
else
|
||||
} else {
|
||||
last_window_state_ = ui::SHOW_STATE_NORMAL;
|
||||
NotifyWindowLeaveFullScreen();
|
||||
}
|
||||
// We set the new value after notifying, so we can handle the size event
|
||||
// correctly.
|
||||
window_->SetFullscreen(fullscreen);
|
||||
#else
|
||||
if (IsVisible())
|
||||
window_->SetFullscreen(fullscreen);
|
||||
|
@ -807,51 +816,103 @@ void NativeWindowViews::OnWidgetMove() {
|
|||
|
||||
#if defined(OS_WIN)
|
||||
bool NativeWindowViews::ExecuteWindowsCommand(int command_id) {
|
||||
// Windows uses the 4 lower order bits of |command_id| for type-specific
|
||||
// information so we must exclude this when comparing.
|
||||
static const int sc_mask = 0xFFF0;
|
||||
if ((command_id & sc_mask) == SC_MINIMIZE) {
|
||||
NotifyWindowMinimize();
|
||||
is_minimized_ = true;
|
||||
} else if ((command_id & sc_mask) == SC_RESTORE) {
|
||||
if (is_minimized_)
|
||||
NotifyWindowRestore();
|
||||
else
|
||||
NotifyWindowUnmaximize();
|
||||
is_minimized_ = false;
|
||||
} else if ((command_id & sc_mask) == SC_MAXIMIZE) {
|
||||
NotifyWindowMaximize();
|
||||
} else {
|
||||
std::string command = AppCommandToString(command_id);
|
||||
NotifyWindowExecuteWindowsCommand(command);
|
||||
}
|
||||
std::string command = AppCommandToString(command_id);
|
||||
NotifyWindowExecuteWindowsCommand(command);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
gfx::ImageSkia NativeWindowViews::GetDevToolsWindowIcon() {
|
||||
return GetWindowAppIcon();
|
||||
}
|
||||
|
||||
#if defined(USE_X11)
|
||||
void NativeWindowViews::GetDevToolsWindowWMClass(
|
||||
std::string* name, std::string* class_name) {
|
||||
*class_name = Browser::Get()->GetName();
|
||||
*name = base::StringToLowerASCII(*class_name);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
bool NativeWindowViews::PreHandleMSG(
|
||||
UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) {
|
||||
// Handle thumbar button click message.
|
||||
if (message == WM_COMMAND && HIWORD(w_param) == THBN_CLICKED)
|
||||
return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param));
|
||||
else
|
||||
return false;
|
||||
switch (message) {
|
||||
case WM_COMMAND:
|
||||
// Handle thumbar button click message.
|
||||
if (HIWORD(w_param) == THBN_CLICKED)
|
||||
return taskbar_host_.HandleThumbarButtonEvent(LOWORD(w_param));
|
||||
return false;
|
||||
case WM_SIZE:
|
||||
// Handle window state change.
|
||||
HandleSizeEvent(w_param, l_param);
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowViews::HandleSizeEvent(WPARAM w_param, LPARAM l_param) {
|
||||
// Here we handle the WM_SIZE event in order to figure out what is the current
|
||||
// window state and notify the user accordingly.
|
||||
switch (w_param) {
|
||||
case SIZE_MAXIMIZED:
|
||||
last_window_state_ = ui::SHOW_STATE_MAXIMIZED;
|
||||
NotifyWindowMaximize();
|
||||
break;
|
||||
case SIZE_MINIMIZED:
|
||||
last_window_state_ = ui::SHOW_STATE_MINIMIZED;
|
||||
NotifyWindowMinimize();
|
||||
break;
|
||||
case SIZE_RESTORED:
|
||||
if (last_window_state_ == ui::SHOW_STATE_NORMAL) {
|
||||
// Window was resized so we save it's new size.
|
||||
last_normal_size_ = GetSize();
|
||||
} else {
|
||||
switch (last_window_state_) {
|
||||
case ui::SHOW_STATE_MAXIMIZED:
|
||||
last_window_state_ = ui::SHOW_STATE_NORMAL;
|
||||
|
||||
// When the window is restored we resize it to the previous known
|
||||
// normal size.
|
||||
NativeWindow::SetSize(last_normal_size_);
|
||||
|
||||
NotifyWindowUnmaximize();
|
||||
break;
|
||||
case ui::SHOW_STATE_MINIMIZED:
|
||||
if (IsFullscreen()) {
|
||||
last_window_state_ = ui::SHOW_STATE_FULLSCREEN;
|
||||
NotifyWindowEnterFullScreen();
|
||||
} else {
|
||||
last_window_state_ = ui::SHOW_STATE_NORMAL;
|
||||
|
||||
// When the window is restored we resize it to the previous known
|
||||
// normal size.
|
||||
NativeWindow::SetSize(last_normal_size_);
|
||||
|
||||
NotifyWindowRestore();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
gfx::Size NativeWindowViews::WindowSizeToFramelessSize(
|
||||
const gfx::Size& size) {
|
||||
if (size.width() == 0 && size.height() == 0)
|
||||
return size;
|
||||
|
||||
gfx::Rect window_bounds = gfx::Rect(size);
|
||||
if (use_content_size_) {
|
||||
if (menu_bar_ && menu_bar_visible_) {
|
||||
window_bounds.set_height(window_bounds.height() + kMenuBarHeight);
|
||||
}
|
||||
} else if (has_frame()) {
|
||||
#if defined(OS_WIN)
|
||||
gfx::Size frame_size = gfx::win::ScreenToDIPRect(
|
||||
window_->non_client_view()->GetWindowBoundsForClientBounds(
|
||||
gfx::Rect())).size();
|
||||
#else
|
||||
gfx::Size frame_size =
|
||||
window_->non_client_view()->GetWindowBoundsForClientBounds(
|
||||
gfx::Rect()).size();
|
||||
#endif
|
||||
window_bounds.set_height(window_bounds.height() - frame_size.height());
|
||||
window_bounds.set_width(window_bounds.width() - frame_size.width());
|
||||
}
|
||||
|
||||
return window_bounds.size();
|
||||
}
|
||||
|
||||
void NativeWindowViews::HandleKeyboardEvent(
|
||||
content::WebContents*,
|
||||
const content::NativeWebKeyboardEvent& event) {
|
||||
|
@ -883,9 +944,6 @@ void NativeWindowViews::HandleKeyboardEvent(
|
|||
// When a single Alt is pressed:
|
||||
menu_bar_alt_pressed_ = true;
|
||||
} else if (event.type == blink::WebInputEvent::KeyUp && IsAltKey(event) &&
|
||||
#if defined(USE_X11)
|
||||
event.modifiers == 0 &&
|
||||
#endif
|
||||
menu_bar_alt_pressed_) {
|
||||
// When a single Alt is released right after a Alt is pressed:
|
||||
menu_bar_alt_pressed_ = false;
|
||||
|
|
|
@ -94,6 +94,8 @@ class NativeWindowViews : public NativeWindow,
|
|||
|
||||
gfx::AcceleratedWidget GetAcceleratedWidget();
|
||||
|
||||
gfx::Size WindowSizeToFramelessSize(const gfx::Size& size);
|
||||
|
||||
views::Widget* widget() const { return window_.get(); }
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
@ -131,17 +133,12 @@ class NativeWindowViews : public NativeWindow,
|
|||
bool ExecuteWindowsCommand(int command_id) override;
|
||||
#endif
|
||||
|
||||
// brightray::InspectableWebContentsViewDelegate:
|
||||
gfx::ImageSkia GetDevToolsWindowIcon() override;
|
||||
#if defined(USE_X11)
|
||||
void GetDevToolsWindowWMClass(
|
||||
std::string* name, std::string* class_name) override;
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
// MessageHandlerDelegate:
|
||||
bool PreHandleMSG(
|
||||
UINT message, WPARAM w_param, LPARAM l_param, LRESULT* result) override;
|
||||
|
||||
void HandleSizeEvent(WPARAM w_param, LPARAM l_param);
|
||||
#endif
|
||||
|
||||
// NativeWindow:
|
||||
|
@ -178,9 +175,15 @@ class NativeWindowViews : public NativeWindow,
|
|||
#elif defined(OS_WIN)
|
||||
// Weak ref.
|
||||
AtomDesktopWindowTreeHostWin* atom_desktop_window_tree_host_win_;
|
||||
// Records window was whether restored from minimized state or maximized
|
||||
// state.
|
||||
bool is_minimized_;
|
||||
|
||||
ui::WindowShowState last_window_state_;
|
||||
|
||||
// There's an issue with restore on Windows, that sometimes causes the Window
|
||||
// to receive the wrong size (#2498). To circumvent that, we keep tabs on the
|
||||
// size of the window while in the normal state (not maximized, minimized or
|
||||
// fullscreen), so we restore it correctly.
|
||||
gfx::Size last_normal_size_;
|
||||
|
||||
// In charge of running taskbar related APIs.
|
||||
TaskbarHost taskbar_host_;
|
||||
#endif
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<key>CFBundleIconFile</key>
|
||||
<string>atom.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.33.1</string>
|
||||
<string>0.33.6</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.8.0</string>
|
||||
<key>NSMainNibFile</key>
|
||||
|
|
|
@ -56,8 +56,8 @@ END
|
|||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,33,1,0
|
||||
PRODUCTVERSION 0,33,1,0
|
||||
FILEVERSION 0,33,6,0
|
||||
PRODUCTVERSION 0,33,6,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
|
@ -74,12 +74,12 @@ BEGIN
|
|||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "0.33.1"
|
||||
VALUE "FileVersion", "0.33.6"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "0.33.1"
|
||||
VALUE "ProductVersion", "0.33.6"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
|
|
@ -79,6 +79,9 @@ class FileDialog {
|
|||
if (!title.empty())
|
||||
GetPtr()->SetTitle(base::UTF8ToUTF16(title).c_str());
|
||||
|
||||
if (!filterspec.empty())
|
||||
GetPtr()->SetDefaultExtension(filterspec.front().pszSpec);
|
||||
|
||||
SetDefaultFolder(default_path);
|
||||
}
|
||||
|
||||
|
|
|
@ -40,12 +40,14 @@ int WinFrameView::NonClientHitTest(const gfx::Point& point) {
|
|||
}
|
||||
|
||||
gfx::Size WinFrameView::GetMinimumSize() const {
|
||||
gfx::Size size = FramelessView::GetMinimumSize();
|
||||
gfx::Size size = window_->WindowSizeToFramelessSize(
|
||||
window_->GetMinimumSize());
|
||||
return gfx::win::DIPToScreenSize(size);
|
||||
}
|
||||
|
||||
gfx::Size WinFrameView::GetMaximumSize() const {
|
||||
gfx::Size size = FramelessView::GetMaximumSize();
|
||||
gfx::Size size = window_->WindowSizeToFramelessSize(
|
||||
window_->GetMaximumSize());
|
||||
return gfx::win::DIPToScreenSize(size);
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#include "base/environment.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "dbus/bus.h"
|
||||
#include "dbus/object_proxy.h"
|
||||
|
@ -50,6 +51,10 @@ void SetWindowType(::Window xwindow, const std::string& type) {
|
|||
}
|
||||
|
||||
bool ShouldUseGlobalMenuBar() {
|
||||
scoped_ptr<base::Environment> env(base::Environment::Create());
|
||||
if (env->HasVar("ELECTRON_FORCE_WINDOW_MENU_BAR"))
|
||||
return false;
|
||||
|
||||
dbus::Bus::Options options;
|
||||
scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#define ATOM_MAJOR_VERSION 0
|
||||
#define ATOM_MINOR_VERSION 33
|
||||
#define ATOM_PATCH_VERSION 1
|
||||
#define ATOM_PATCH_VERSION 6
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
|
|
@ -9,21 +9,8 @@ process.atomBinding = (name) ->
|
|||
catch e
|
||||
process.binding "atom_common_#{name}" if /No such module/.test e.message
|
||||
|
||||
# Global module search paths.
|
||||
globalPaths = Module.globalPaths
|
||||
|
||||
# Don't lookup modules in user-defined search paths, see http://git.io/vf8sF.
|
||||
homeDir =
|
||||
if process.platform is 'win32'
|
||||
process.env.USERPROFILE
|
||||
else
|
||||
process.env.HOME
|
||||
if homeDir # Node only add user-defined search paths when $HOME is defined.
|
||||
userModulePath = path.resolve homeDir, '.node_modules'
|
||||
globalPaths.splice globalPaths.indexOf(userModulePath), 2
|
||||
|
||||
# Add common/api/lib to module search paths.
|
||||
globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
|
||||
Module.globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
|
||||
|
||||
# setImmediate and process.nextTick makes use of uv_check and uv_prepare to
|
||||
# run the callbacks, however since we only run uv loop on requests, the
|
||||
|
|
29
atom/common/lib/reset-search-paths.coffee
Normal file
29
atom/common/lib/reset-search-paths.coffee
Normal file
|
@ -0,0 +1,29 @@
|
|||
path = require 'path'
|
||||
Module = require 'module'
|
||||
|
||||
# Clear Node's global search paths.
|
||||
Module.globalPaths.length = 0
|
||||
|
||||
# Clear current and parent(init.coffee)'s search paths.
|
||||
module.paths = []
|
||||
module.parent.paths = []
|
||||
|
||||
# Prevent Node from adding paths outside this app to search paths.
|
||||
Module._nodeModulePaths = (from) ->
|
||||
from = path.resolve from
|
||||
|
||||
# If "from" is outside the app then we do nothing.
|
||||
skipOutsidePaths = from.startsWith process.resourcesPath
|
||||
|
||||
# Following logoic is copied from module.js.
|
||||
splitRe = if process.platform is 'win32' then /[\/\\]/ else /\//
|
||||
paths = []
|
||||
|
||||
parts = from.split splitRe
|
||||
for part, tip in parts by -1
|
||||
continue if part is 'node_modules'
|
||||
dir = parts.slice(0, tip + 1).join path.sep
|
||||
break if skipOutsidePaths and not dir.startsWith process.resourcesPath
|
||||
paths.push path.join(dir, 'node_modules')
|
||||
|
||||
paths
|
|
@ -166,8 +166,8 @@ bool Converter<blink::WebKeyboardEvent>::FromV8(
|
|||
if (shifted)
|
||||
out->modifiers |= blink::WebInputEvent::ShiftKey;
|
||||
out->setKeyIdentifierFromWindowsKeyCode();
|
||||
if (out->type == blink::WebInputEvent::Char
|
||||
|| out->type == blink::WebInputEvent::RawKeyDown) {
|
||||
if (out->type == blink::WebInputEvent::Char ||
|
||||
out->type == blink::WebInputEvent::RawKeyDown) {
|
||||
out->text[0] = code;
|
||||
out->unmodifiedText[0] = code;
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ exports.require = (module) ->
|
|||
windowCache = null
|
||||
exports.getCurrentWindow = ->
|
||||
return windowCache if windowCache?
|
||||
meta = ipc.sendSync 'ATOM_BROWSER_CURRENT_WINDOW', process.guestInstanceId
|
||||
meta = ipc.sendSync 'ATOM_BROWSER_CURRENT_WINDOW'
|
||||
windowCache = metaToValue meta
|
||||
|
||||
# Get current WebContents object.
|
||||
|
|
|
@ -7,16 +7,16 @@ Module = require 'module'
|
|||
# atom-renderer.js, we need to restore it here.
|
||||
process.argv.splice 1, 1
|
||||
|
||||
# Clear search paths.
|
||||
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'reset-search-paths')
|
||||
|
||||
# Import common settings.
|
||||
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init')
|
||||
|
||||
# Add renderer/api/lib to require's search paths, which contains javascript part
|
||||
# of Atom's built-in libraries.
|
||||
globalPaths = Module.globalPaths
|
||||
globalPaths.push path.resolve(__dirname, '..', 'api', 'lib')
|
||||
# And also app.
|
||||
globalPaths.push path.join(process.resourcesPath, 'app')
|
||||
globalPaths.push path.join(process.resourcesPath, 'app.asar')
|
||||
|
||||
# Import common settings.
|
||||
require path.resolve(__dirname, '..', '..', 'common', 'lib', 'init')
|
||||
|
||||
# The global variable will be used by ipc for event dispatching
|
||||
v8Util = process.atomBinding 'v8_util'
|
||||
|
|
|
@ -44,7 +44,7 @@ createMenu = (x, y, items, document) ->
|
|||
showFileChooserDialog = (callback) ->
|
||||
remote = require 'remote'
|
||||
dialog = remote.require 'dialog'
|
||||
files = dialog.showOpenDialog remote.getCurrentWindow(), null
|
||||
files = dialog.showOpenDialog {}
|
||||
callback pathToHtml5FileObject files[0] if files?
|
||||
|
||||
pathToHtml5FileObject = (path) ->
|
||||
|
|
|
@ -122,3 +122,7 @@ window.history.go = (offset) -> sendHistoryOperation 'goToOffset', offset
|
|||
Object.defineProperty window.history, 'length',
|
||||
get: ->
|
||||
getHistoryOperation 'length'
|
||||
|
||||
# Make document.hidden return the correct value.
|
||||
Object.defineProperty document, 'hidden',
|
||||
get: -> !remote.getCurrentWindow().isVisible()
|
||||
|
|
|
@ -46,6 +46,7 @@ class WebViewImpl
|
|||
# that we don't end up allocating a second guest.
|
||||
if @guestInstanceId
|
||||
guestViewInternal.destroyGuest @guestInstanceId
|
||||
@webContents = null
|
||||
@guestInstanceId = undefined
|
||||
@beforeFirstNavigation = true
|
||||
@attributes[webViewConstants.ATTRIBUTE_PARTITION].validPartitionId = true
|
||||
|
@ -188,6 +189,7 @@ class WebViewImpl
|
|||
|
||||
attachWindow: (guestInstanceId) ->
|
||||
@guestInstanceId = guestInstanceId
|
||||
@webContents = remote.getGuestWebContents @guestInstanceId
|
||||
return true unless @internalInstanceId
|
||||
|
||||
guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildParams()
|
||||
|
@ -299,7 +301,7 @@ registerWebViewElement = ->
|
|||
createHandler = (m) ->
|
||||
(args...) ->
|
||||
internal = v8Util.getHiddenValue this, 'internal'
|
||||
remote.getGuestWebContents(internal.guestInstanceId)[m] args...
|
||||
internal.webContents[m] args...
|
||||
proto[m] = createHandler m for m in methods
|
||||
|
||||
window.WebView = webFrame.registerEmbedderCustomElement 'webview',
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
## 개발 가이드
|
||||
|
||||
* [지원하는 플랫폼](tutorial/supported-platforms.md)
|
||||
* [어플리케이션 배포](tutorial/application-distribution.md)
|
||||
* [어플리케이션 패키징](tutorial/application-packaging.md)
|
||||
* [네이티브 Node 모듈 사용하기](tutorial/using-native-node-modules.md)
|
||||
|
|
|
@ -84,13 +84,19 @@ Net log 이벤트를 활성화하고 `path`에 로그를 기록합니다.
|
|||
|
||||
## --ssl-version-fallback-min=`version`
|
||||
|
||||
Fallback SSL/TLS 최소 버전을 지정합니다. ("tls1", "tls1.1", "tls1.2")
|
||||
TLS fallback에서 사용할 SSL/TLS 최소 버전을 지정합니다. ("tls1", "tls1.1", "tls1.2")
|
||||
|
||||
## --enable-logging
|
||||
|
||||
Chromium의 로그를 콘솔에 출력합니다.
|
||||
|
||||
이 스위치는 어플리케이션이 로드되기 전에 파싱 되므로 `app.commandLine.appendSwitch`에서 사용할 수 없습니다.
|
||||
|
||||
## --v=`log_level`
|
||||
|
||||
기본 V-logging 최대 활성화 레벨을 지정합니다. 기본값은 0입니다. 기본적으로 양수를 레벨로 사용합니다.
|
||||
|
||||
`--v=-1`를 사용하면 로깅이 비활성화 됩니다.
|
||||
이 스위치는 `--enable-logging` 스위치를 같이 지정해야 작동합니다.
|
||||
|
||||
## --vmodule=`pattern`
|
||||
|
||||
|
@ -100,10 +106,4 @@ Fallback SSL/TLS 최소 버전을 지정합니다. ("tls1", "tls1.1", "tls1.2")
|
|||
또한 슬래시(`/`) 또는 백슬래시(`\`)를 포함하는 패턴은 지정한 경로에 대해 패턴을 테스트 합니다.
|
||||
예를 들어 `*/foo/bar/*=2` 표현식은 `foo/bar` 디렉터리 안의 모든 소스 코드의 로깅 레벨을 2로 지정합니다.
|
||||
|
||||
모든 크로미움과 관련된 로그를 비활성화하고 어플리케이션의 로그만 활성화 하려면 다음과 같이 코드를 작성하면 됩니다:
|
||||
|
||||
|
||||
```javascript
|
||||
app.commandLine.appendSwitch('v', -1);
|
||||
app.commandLine.appendSwitch('vmodule', 'console=0');
|
||||
```
|
||||
이 스위치는 `--enable-logging` 스위치를 같이 지정해야 작동합니다.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# MenuItem
|
||||
|
||||
`menu-item` 모듈은 어플리케이션 또는 컨텐츠 [`menu`](menu.md)에 아이템을 추가할 수 있도록 관련 클래스를 제공합니다.
|
||||
`menu-item` 모듈은 어플리케이션 또는 컨텍스트 [`menu`](menu.md)에 아이템을 추가할 수 있도록 관련 클래스를 제공합니다.
|
||||
|
||||
[`menu`](menu.md)에서 예제를 확인할 수 있습니다.
|
||||
|
||||
|
|
|
@ -229,11 +229,11 @@ Menu.setApplicationMenu(menu);
|
|||
|
||||
또한 `template`에는 다른 속성도 추가할 수 있으며 메뉴가 만들어질 때 해당 메뉴 아이템의 프로퍼티로 변환됩니다.
|
||||
|
||||
### `Menu.popup(browserWindow[, x, y])`
|
||||
### `Menu.popup([browserWindow, x, y])`
|
||||
|
||||
* `browserWindow` BrowserWindow
|
||||
* `browserWindow` BrowserWindow (optional)
|
||||
* `x` Number (optional)
|
||||
* `y` Number (만약 `x`를 지정했을 경우 `y`도 필수로 지정해야 합니다)
|
||||
* `y` Number (만약 `x`를 지정했을 경우 반드시 `y`도 지정해야 합니다)
|
||||
|
||||
메뉴를 `browserWindow` 내부 팝업으로 표시합니다.
|
||||
옵션으로 메뉴를 표시할 `(x,y)` 좌표를 지정할 수 있습니다.
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
`screen`은 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 상속 받았습니다.
|
||||
|
||||
**참고:** 랜더러 / DevTools에선 이미 DOM 속성이 `window.screen`을 가지고 있으므로 `screen = require('screen')` 형식으로 모듈을 사용할 수 없습니다.
|
||||
밑의 예제와 같이 `atomScreen` 같은 이름으로 모듈 이름을 대체하여 사용해야 합니다.
|
||||
아래의 예제와 같이 `electronScreen` 같은 이름으로 모듈 이름을 대체하여 사용해야 합니다.
|
||||
|
||||
다음 예제는 화면 전체를 채우는 윈도우 창을 생성합니다:
|
||||
|
||||
|
@ -17,8 +17,8 @@ var BrowserWindow = require('browser-window');
|
|||
var mainWindow;
|
||||
|
||||
app.on('ready', function() {
|
||||
var atomScreen = require('screen');
|
||||
var size = atomScreen.getPrimaryDisplay().workAreaSize;
|
||||
var electronScreen = require('screen');
|
||||
var size = electronScreen.getPrimaryDisplay().workAreaSize;
|
||||
mainWindow = new BrowserWindow({ width: size.width, height: size.height });
|
||||
});
|
||||
```
|
||||
|
@ -32,8 +32,8 @@ var BrowserWindow = require('browser-window');
|
|||
var mainWindow;
|
||||
|
||||
app.on('ready', function() {
|
||||
var atomScreen = require('screen');
|
||||
var displays = atomScreen.getAllDisplays();
|
||||
var electronScreen = require('screen');
|
||||
var displays = electronScreen.getAllDisplays();
|
||||
var externalDisplay = null;
|
||||
for (var i in displays) {
|
||||
if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) {
|
||||
|
|
|
@ -17,11 +17,7 @@ var session = win.webContents.session
|
|||
### Event: 'will-download'
|
||||
|
||||
* `event` Event
|
||||
* `item` Object
|
||||
* `url` String
|
||||
* `filename` String
|
||||
* `mimeType` String
|
||||
* `hasUserGesture` Boolean
|
||||
* `item` [DownloadItem](download-item.md)
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
|
||||
Electron의 `webContents`에서 `item`을 다운로드할 때 발생하는 이벤트입니다.
|
||||
|
@ -31,7 +27,7 @@ Electron의 `webContents`에서 `item`을 다운로드할 때 발생하는 이
|
|||
```javascript
|
||||
session.on('will-download', function(event, item, webContents) {
|
||||
event.preventDefault();
|
||||
require('request')(item.url, function(data) {
|
||||
require('request')(item.getUrl(), function(data) {
|
||||
require('fs').writeFileSync('/somewhere', data);
|
||||
});
|
||||
});
|
||||
|
@ -185,3 +181,29 @@ proxy-uri = [<proxy-scheme>"://"]<proxy-host>[":"<proxy-port>]
|
|||
* `path` String - 다운로드 위치
|
||||
|
||||
다운로드 저장 위치를 지정합니다. 기본 다운로드 위치는 각 어플리케이션 데이터 디렉터리의 `Downloads` 폴더입니다.
|
||||
|
||||
### `session.enableNetworkEmulation(options)`
|
||||
|
||||
* `options` Object
|
||||
* `offline` Boolean - 네트워크의 오프라인 상태 여부
|
||||
* `latency` Double - 밀리세컨드 단위의 RTT
|
||||
* `downloadThroughput` Double - Bps 단위의 다운로드 주기
|
||||
* `uploadThroughput` Double - Bps 단위의 업로드 주기
|
||||
|
||||
제공된 설정으로 `session`의 네트워크를 에뮬레이트합니다.
|
||||
|
||||
```javascript
|
||||
// 50kbps의 처리량과 함께 500ms의 레이턴시로 GPRS 연결을 에뮬레이트합니다.
|
||||
window.webContents.session.enableNetworkEmulation({
|
||||
latency: 500,
|
||||
downloadThroughput: 6400,
|
||||
uploadThroughput: 6400
|
||||
});
|
||||
|
||||
// 네트워크가 끊긴 상태를 에뮬레이트합니다.
|
||||
window.webContents.session.enableNetworkEmulation({offline: true});
|
||||
```
|
||||
|
||||
### `session.disableNetworkEmulation`
|
||||
|
||||
활성화된 `session`의 에뮬레이션을 비활성화합니다. 기본 네트워크 설정으로 돌아갑니다.
|
||||
|
|
|
@ -111,6 +111,7 @@ app.on('ready', function() {
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>헬로 월드!</title>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -126,31 +127,31 @@ app.on('ready', function() {
|
|||
앱을 작성한 후 [어플리케이션 배포](application-distribution.md) 가이드를 따라 앱을 패키징 하고 패키징한 앱을 실행할 수 있습니다.
|
||||
또한 Electron 실행파일을 다운로드 받아 바로 실행해 볼 수도 있습니다.
|
||||
|
||||
### electron-prebuilt
|
||||
### electron-prebuilt 사용
|
||||
|
||||
`npm`을 통해 `electron-prebuilt` 패키지를 전역에 설치하면 간단한 명령으로 앱을 실행할 수 있습니다.
|
||||
|
||||
앱 디렉터리 내에서 이렇게 실행합니다:
|
||||
앱 디렉터리 내에서 다음 명령으로 실행할 수 있습니다:
|
||||
|
||||
```bash
|
||||
electron .
|
||||
```
|
||||
|
||||
또는 앱 디렉터리 밖에서 앱 디렉터리를 입력해도 됩니다:
|
||||
또는 앱 디렉터리 밖에서 앱을 실행할 수도 있습니다:
|
||||
|
||||
```bash
|
||||
electron app
|
||||
```
|
||||
|
||||
npm 모듈을 로컬에 설치했다면 이렇게 실행할 수 있습니다:
|
||||
npm 모듈을 로컬에 설치했다면 다음 명령으로 실행할 수 있습니다:
|
||||
|
||||
```bash
|
||||
./node_modules/.bin/electron .
|
||||
```
|
||||
|
||||
### 임의로 다운로드 받은 Electron
|
||||
### 다운로드 받은 Electron 바이너리 사용
|
||||
|
||||
만약 Electron 바이너리를 임의로 다운로드 받았다면 다음과 같이 앱 디렉터리에 놓고 실행하면 됩니다.
|
||||
따로 Electron 바이너리를 다운로드 받았다면 다음 예시와 같이 실행하면 됩니다.
|
||||
|
||||
#### Windows
|
||||
|
||||
|
|
26
docs-translations/ko-KR/tutorial/supported-platforms.md
Normal file
26
docs-translations/ko-KR/tutorial/supported-platforms.md
Normal file
|
@ -0,0 +1,26 @@
|
|||
# 지원하는 플랫폼
|
||||
|
||||
Electron에선 다음과 같은 플랫폼을 지원합니다:
|
||||
|
||||
### OS X
|
||||
|
||||
OS X는 64비트 바이너리만 제공됩니다. 그리고 최소 OS X 지원 버전은 10.8입니다.
|
||||
|
||||
### Windows
|
||||
|
||||
Windows 7 이후 버전만 지원됩니다. Windows Vista에서도 작동할 수 있지만 아직 모든 작동 테스트가 완료되지 않았습니다.
|
||||
|
||||
윈도우용 바이너리는 `x86`과 `x64` 모두 제공됩니다. 그리고 `ARM` 버전 윈도우는 아직 지원하지 않습니다. (역주: 추후 지원할 가능성이 있습니다)
|
||||
|
||||
### Linux
|
||||
|
||||
Ubuntu 12.04 버전에서 빌드된 `ia32`(`i686`), `x64`(`amd64`) 바이너리가 제공됩니다.
|
||||
그리고 `arm` 버전 바이너리는 ARM v7 hard-float ABI와 Debian Wheezy용 NEON에 맞춰 제공됩니다.
|
||||
|
||||
미리 빌드된 바이너리가 배포판에서 작동할 수 있는지 여부는 Electron이 빌드된 플랫폼에서 링크된 라이브러리에 따라 달라집니다.
|
||||
그래서 현재 Linux 바이너리는 Ubuntu 12.04 버전만 정상적인 작동이 보장됩니다.
|
||||
하지만 다음 플랫폼들은 미리 빌드된 Electron 바이너리가 정상적으로 작동하는 것을 확인했습니다:
|
||||
|
||||
* Ubuntu 12.04 이후 버전
|
||||
* Fedora 21
|
||||
* Debian 8
|
|
@ -29,7 +29,20 @@ npm install --save-dev electron-rebuild
|
|||
node ./node_modules/.bin/electron-rebuild
|
||||
```
|
||||
|
||||
### node-gyp을 이용한 방법
|
||||
### `npm`을 이용한 방법
|
||||
|
||||
또한 `npm`을 통해 설치할 수도 있습니다.
|
||||
환경변수가 필요한 것을 제외하고 일반 Node 모듈을 설치하는 방법과 완전히 똑같습니다:
|
||||
|
||||
```bash
|
||||
export npm_config_disturl=https://atom.io/download/atom-shell
|
||||
export npm_config_target=0.33.1
|
||||
export npm_config_arch=x64
|
||||
export npm_config_runtime=electron
|
||||
HOME=~/.electron-gyp npm install module-name
|
||||
```
|
||||
|
||||
### `node-gyp`를 이용한 방법
|
||||
|
||||
Node 모듈을 `node-gyp`를 사용하여 Electron을 타겟으로 빌드할 때는 `node-gyp`에 헤더 다운로드 주소와 버전을 알려주어야 합니다:
|
||||
|
||||
|
@ -40,15 +53,3 @@ $ HOME=~/.electron-gyp node-gyp rebuild --target=0.29.1 --arch=x64 --dist-url=ht
|
|||
|
||||
`HOME=~/.electron-gyp`은 변경할 헤더의 위치를 찾습니다. `--target=0.29.1`은 Electron의 버전입니다.
|
||||
`--dist-url=...`은 헤더를 다운로드 하는 주소입니다. `--arch=x64`는 64비트 시스템을 타겟으로 빌드 한다는 것을 `node-gyp`에게 알려줍니다.
|
||||
|
||||
### npm을 이용한 방법
|
||||
|
||||
또한 `npm`을 통해 설치할 수도 있습니다.
|
||||
환경변수가 필요한 것을 제외하고 일반 Node 모듈을 설치하는 방법과 완전히 똑같습니다:
|
||||
|
||||
```bash
|
||||
export npm_config_disturl=https://atom.io/download/atom-shell
|
||||
export npm_config_target=0.29.1
|
||||
export npm_config_arch=x64
|
||||
HOME=~/.electron-gyp npm install module-name
|
||||
```
|
||||
|
|
|
@ -71,7 +71,7 @@ driver.quit();
|
|||
먼저, `chromedriver` 바이너리를 다운로드 받고 실행합니다:
|
||||
|
||||
```bash
|
||||
$ chromedriver --url-base=/wd/hub --port=9515
|
||||
$ chromedriver --url-base=wd/hub --port=9515
|
||||
Starting ChromeDriver (v2.10.291558) on port 9515
|
||||
Only local connections are allowed.
|
||||
```
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
## Guides
|
||||
|
||||
* [Supported Platforms](tutorial/supported-platforms.md)
|
||||
* [Application Distribution](tutorial/application-distribution.md)
|
||||
* [Application Packaging](tutorial/application-packaging.md)
|
||||
* [Using Native Node Modules](tutorial/using-native-node-modules.md)
|
||||
|
|
|
@ -197,12 +197,6 @@ You can request the following paths by the name:
|
|||
* `~/Library/Application Support` on OS X
|
||||
* `userData` The directory for storing your app's configuration files, which by
|
||||
default it is the `appData` directory appended with your app's name.
|
||||
* `cache` Per-user application cache directory, which by default points to:
|
||||
* `%APPDATA%` on Windows (which doesn't have a universal cache location)
|
||||
* `$XDG_CACHE_HOME` or `~/.cache` on Linux
|
||||
* `~/Library/Caches` on OS X
|
||||
* `userCache` The directory for placing your app's caches, by default it is the
|
||||
`cache` directory appended with your app's name.
|
||||
* `temp` Temporary directory.
|
||||
* `userDesktop` The current user's Desktop directory.
|
||||
* `exe` The current executable file.
|
||||
|
|
|
@ -24,14 +24,13 @@ You can also create a window without chrome by using
|
|||
[EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter).
|
||||
|
||||
It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
Properties `width` and `height` are required.
|
||||
|
||||
### `new BrowserWindow(options)`
|
||||
|
||||
`options` Object, properties:
|
||||
|
||||
* `width` Integer (**required**) - Window's width.
|
||||
* `height` Integer (**required**) - Window's height.
|
||||
* `width` Integer - Window's width.
|
||||
* `height` Integer - Window's height.
|
||||
* `x` Integer - Window's left offset from screen.
|
||||
* `y` Integer - Window's top offset from screen.
|
||||
* `use-content-size` Boolean - The `width` and `height` would be used as web
|
||||
|
@ -232,18 +231,6 @@ Emitted when the window enters full screen state triggered by html api.
|
|||
|
||||
Emitted when the window leaves full screen state triggered by html api.
|
||||
|
||||
### Event: 'devtools-opened'
|
||||
|
||||
Emitted when DevTools is opened.
|
||||
|
||||
### Event: 'devtools-closed'
|
||||
|
||||
Emitted when DevTools is closed.
|
||||
|
||||
### Event: 'devtools-focused'
|
||||
|
||||
Emitted when DevTools is focused / opened.
|
||||
|
||||
### Event: 'app-command':
|
||||
|
||||
Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx)
|
||||
|
@ -318,16 +305,6 @@ operations will be done via it.
|
|||
See the [`webContents` documentation](web-contents.md) for its methods and
|
||||
events.
|
||||
|
||||
**Note:** Users should never store this object because it may become `null`
|
||||
when the renderer process (web page) has crashed.
|
||||
|
||||
### `win.devToolsWebContents`
|
||||
|
||||
Get the `WebContents` of DevTools for this window.
|
||||
|
||||
**Note:** Users should never store this object because it may become `null`
|
||||
when the DevTools has been closed.
|
||||
|
||||
### `win.id`
|
||||
|
||||
The unique ID of this window.
|
||||
|
@ -596,41 +573,6 @@ bar will become grey when set to `true`.
|
|||
|
||||
Whether the window's document has been edited.
|
||||
|
||||
### `win.openDevTools([options])`
|
||||
|
||||
* `options` Object (optional). Properties:
|
||||
* `detach` Boolean - opens DevTools in a new window
|
||||
|
||||
Opens the developer tools.
|
||||
|
||||
### `win.closeDevTools()`
|
||||
|
||||
Closes the developer tools.
|
||||
|
||||
### `win.isDevToolsOpened()`
|
||||
|
||||
Returns whether the developer tools are opened.
|
||||
|
||||
### `win.toggleDevTools()`
|
||||
|
||||
Toggles the developer tools.
|
||||
|
||||
### `win.isDevToolsFocused()`
|
||||
|
||||
Returns whether the developer tools is focused.
|
||||
|
||||
### `win.inspectElement(x, y)`
|
||||
|
||||
* `x` Integer
|
||||
* `y` Integer
|
||||
|
||||
Starts inspecting element at position (`x`, `y`).
|
||||
|
||||
### `win.inspectServiceWorker()`
|
||||
|
||||
Opens the developer tools for the service worker context present in the web
|
||||
contents.
|
||||
|
||||
### `win.focusOnWebView()`
|
||||
|
||||
### `win.blurWebView()`
|
||||
|
|
|
@ -89,15 +89,21 @@ Enables net log events to be saved and writes them to `path`.
|
|||
|
||||
## --ssl-version-fallback-min=`version`
|
||||
|
||||
Set the minimum SSL/TLS version ("tls1", "tls1.1" or "tls1.2") that TLS
|
||||
Sets the minimum SSL/TLS version ("tls1", "tls1.1" or "tls1.2") that TLS
|
||||
fallback will accept.
|
||||
|
||||
## --enable-logging
|
||||
|
||||
Prints Chromium's logging into console.
|
||||
|
||||
This switch can not be used in `app.commandLine.appendSwitch` since it is parsed earlier than user's app is loaded.
|
||||
|
||||
## --v=`log_level`
|
||||
|
||||
Gives the default maximal active V-logging level; 0 is the default. Normally
|
||||
positive values are used for V-logging levels.
|
||||
|
||||
Passing `--v=-1` will disable logging.
|
||||
This switch only works when `--enable-logging` is also passed.
|
||||
|
||||
## --vmodule=`pattern`
|
||||
|
||||
|
@ -109,10 +115,4 @@ Any pattern containing a forward or backward slash will be tested against the
|
|||
whole pathname and not just the module. E.g. `*/foo/bar/*=2` would change the
|
||||
logging level for all code in the source files under a `foo/bar` directory.
|
||||
|
||||
To disable all chromium related logs and only enable your application logs you
|
||||
can do:
|
||||
|
||||
```javascript
|
||||
app.commandLine.appendSwitch('v', -1);
|
||||
app.commandLine.appendSwitch('vmodule', 'console=0');
|
||||
```
|
||||
This switch only works when `--enable-logging` is also passed.
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# MenuItem
|
||||
|
||||
The `menu-item` module allows you to add items to an application or content
|
||||
The `menu-item` module allows you to add items to an application or context
|
||||
[`menu`](menu.md).
|
||||
|
||||
See [`menu`](menu.md) for examples.
|
||||
|
|
|
@ -237,9 +237,9 @@ Generally, the `template` is just an array of `options` for constructing a
|
|||
You can also attach other fields to the element of the `template` and they
|
||||
will become properties of the constructed menu items.
|
||||
|
||||
### `Menu.popup(browserWindow[, x, y])`
|
||||
### `Menu.popup([browserWindow, x, y])`
|
||||
|
||||
* `browserWindow` BrowserWindow
|
||||
* `browserWindow` BrowserWindow (optional)
|
||||
* `x` Number (optional)
|
||||
* `y` Number (**required** if `x` is used)
|
||||
|
||||
|
|
|
@ -9,7 +9,25 @@ upstream node:
|
|||
* `process.versions['chrome']` String - Version of Chromium.
|
||||
* `process.resourcesPath` String - Path to JavaScript source code.
|
||||
|
||||
# Methods
|
||||
## Events
|
||||
|
||||
### Event: 'loaded'
|
||||
|
||||
Emitted when Electron has loaded its internal initialization script and is
|
||||
beginning to load the web page or the main script.
|
||||
|
||||
It can be used by the preload script to add removed Node global symbols back to
|
||||
the global scope when node integration is turned off:
|
||||
|
||||
```js
|
||||
// preload.js
|
||||
process.once('loaded', function() {
|
||||
global.setImmediate = setImmediate;
|
||||
global.clearImmediate = clearImmediate;
|
||||
});
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
The `process` object has the following method:
|
||||
|
||||
|
@ -17,7 +35,7 @@ The `process` object has the following method:
|
|||
|
||||
Causes the main thread of the current process hang.
|
||||
|
||||
## process.setFdLimit(maxDescriptors) _OS X_ _Linux_
|
||||
### process.setFdLimit(maxDescriptors) _OS X_ _Linux_
|
||||
|
||||
* `maxDescriptors` Integer
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ position, etc. You should not use this module until the `ready` event of the
|
|||
|
||||
**Note:** In the renderer / DevTools, `window.screen` is a reserved
|
||||
DOM property, so writing `var screen = require('screen')` will not work. In our
|
||||
examples below, we use `atomScreen` as the variable name instead.
|
||||
examples below, we use `electronScreen` as the variable name instead.
|
||||
|
||||
An example of creating a window that fills the whole screen:
|
||||
|
||||
|
@ -19,8 +19,8 @@ var BrowserWindow = require('browser-window');
|
|||
var mainWindow;
|
||||
|
||||
app.on('ready', function() {
|
||||
var atomScreen = require('screen');
|
||||
var size = atomScreen.getPrimaryDisplay().workAreaSize;
|
||||
var electronScreen = require('screen');
|
||||
var size = electronScreen.getPrimaryDisplay().workAreaSize;
|
||||
mainWindow = new BrowserWindow({ width: size.width, height: size.height });
|
||||
});
|
||||
```
|
||||
|
@ -34,11 +34,11 @@ var BrowserWindow = require('browser-window');
|
|||
var mainWindow;
|
||||
|
||||
app.on('ready', function() {
|
||||
var atomScreen = require('screen');
|
||||
var displays = atomScreen.getAllDisplays();
|
||||
var electronScreen = require('screen');
|
||||
var displays = electronScreen.getAllDisplays();
|
||||
var externalDisplay = null;
|
||||
for (var i in displays) {
|
||||
if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) {
|
||||
if (displays[i].bounds.x != 0 || displays[i].bounds.y != 0) {
|
||||
externalDisplay = displays[i];
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -191,3 +191,30 @@ proxy-uri = [<proxy-scheme>"://"]<proxy-host>[":"<proxy-port>]
|
|||
|
||||
Sets download saving directory. By default, the download directory will be the
|
||||
`Downloads` under the respective app folder.
|
||||
|
||||
### `session.enableNetworkEmulation(options)`
|
||||
|
||||
* `options` Object
|
||||
* `offline` Boolean - Whether to emulate network outage.
|
||||
* `latency` Double - RTT in ms
|
||||
* `downloadThroughput` Double - Download rate in Bps
|
||||
* `uploadThroughput` Double - Upload rate in Bps
|
||||
|
||||
Emulates network with the given configuration for the `session`.
|
||||
|
||||
```javascript
|
||||
// To emulate a GPRS connection with 50kbps throughput and 500 ms latency.
|
||||
window.webContents.session.enableNetworkEmulation({
|
||||
latency: 500,
|
||||
downloadThroughput: 6400,
|
||||
uploadThroughput: 6400
|
||||
});
|
||||
|
||||
// To emulate a network outage.
|
||||
window.webContents.session.enableNetworkEmulation({offline: true});
|
||||
```
|
||||
|
||||
### `session.disableNetworkEmulation`
|
||||
|
||||
Disables any network emulation already active for the `session`. Resets to
|
||||
the original network configuration.
|
||||
|
|
|
@ -154,6 +154,18 @@ Emitted when a plugin process has crashed.
|
|||
|
||||
Emitted when `webContents` is destroyed.
|
||||
|
||||
### Event: 'devtools-opened'
|
||||
|
||||
Emitted when DevTools is opened.
|
||||
|
||||
### Event: 'devtools-closed'
|
||||
|
||||
Emitted when DevTools is closed.
|
||||
|
||||
### Event: 'devtools-focused'
|
||||
|
||||
Emitted when DevTools is focused / opened.
|
||||
|
||||
## Instance Methods
|
||||
|
||||
The `webContents` object has the following instance methods:
|
||||
|
@ -441,6 +453,40 @@ Adds the specified path to DevTools workspace.
|
|||
|
||||
Removes the specified path from DevTools workspace.
|
||||
|
||||
### `webContents.openDevTools([options])`
|
||||
|
||||
* `options` Object (optional). Properties:
|
||||
* `detach` Boolean - opens DevTools in a new window
|
||||
|
||||
Opens the developer tools.
|
||||
|
||||
### `webContents.closeDevTools()`
|
||||
|
||||
Closes the developer tools.
|
||||
|
||||
### `webContents.isDevToolsOpened()`
|
||||
|
||||
Returns whether the developer tools are opened.
|
||||
|
||||
### `webContents.toggleDevTools()`
|
||||
|
||||
Toggles the developer tools.
|
||||
|
||||
### `webContents.isDevToolsFocused()`
|
||||
|
||||
Returns whether the developer tools is focused.
|
||||
|
||||
### `webContents.inspectElement(x, y)`
|
||||
|
||||
* `x` Integer
|
||||
* `y` Integer
|
||||
|
||||
Starts inspecting element at position (`x`, `y`).
|
||||
|
||||
### `webContents.inspectServiceWorker()`
|
||||
|
||||
Opens the developer tools for the service worker context.
|
||||
|
||||
### `webContents.send(channel[, args...])`
|
||||
|
||||
* `channel` String
|
||||
|
@ -574,3 +620,14 @@ is in 32bit ARGB format).
|
|||
### `webContents.endFrameSubscription()`
|
||||
|
||||
End subscribing for frame presentation events.
|
||||
|
||||
## Instance Properties
|
||||
|
||||
`WebContents` objects also have the following properties:
|
||||
|
||||
### `webContents.devToolsWebContents`
|
||||
|
||||
Get the `WebContents` of DevTools for this `WebContents`.
|
||||
|
||||
**Note:** Users should never store this object because it may become `null`
|
||||
when the DevTools has been closed.
|
||||
|
|
|
@ -143,8 +143,8 @@ working as expected.
|
|||
|
||||
### electron-prebuilt
|
||||
|
||||
If you've installed `electron-prebuilt` globally with `npm`, then you need only
|
||||
run the following in your app's source directory:
|
||||
If you've installed `electron-prebuilt` globally with `npm`, then you will only need
|
||||
to run the following in your app's source directory:
|
||||
|
||||
```bash
|
||||
electron .
|
||||
|
@ -158,7 +158,7 @@ If you've installed it locally, then run:
|
|||
|
||||
### Manually Downloaded Electron Binary
|
||||
|
||||
If you downloaded Electron manually, you can also just use the included
|
||||
If you downloaded Electron manually, you can also use the included
|
||||
binary to execute your app directly.
|
||||
|
||||
#### Windows
|
||||
|
|
23
docs/tutorial/supported-platforms.md
Normal file
23
docs/tutorial/supported-platforms.md
Normal file
|
@ -0,0 +1,23 @@
|
|||
# Supported Platforms
|
||||
|
||||
Following platforms are supported by Electron:
|
||||
|
||||
### OS X
|
||||
|
||||
Only 64bit binaries are provided for OS X, and the minimum OS X version supported is OS X 10.8.
|
||||
|
||||
### Windows
|
||||
|
||||
Windows 7 and later are supported, Electron should be able to run on Windows Vista, but there is no testing done on it.
|
||||
|
||||
Both `x86` and `x64` binaries are provided for Windows. Please note, the `ARM` version of Windows is not supported for now.
|
||||
|
||||
### Linux
|
||||
|
||||
The prebuilt `ia32`(`i686`) and `x64`(`amd64`) binaries of Electron are built on Ubuntu 12.04, the `arm` binary is built against ARM v7 with hard-float ABI and NEON for Debian Wheezy.
|
||||
|
||||
Whether the prebuilt binary can run on a distribution depends on whether the distribution includes the libraries that Electron is linked to on the building platform, so only Ubuntu 12.04 is guaranteed to work, but following platforms are also verified to be able to run the prebuilt binaries of Electron:
|
||||
|
||||
* Ubuntu 12.04 and later
|
||||
* Fedora 21
|
||||
* Debian 8
|
|
@ -74,7 +74,7 @@ driver.
|
|||
First you need to download the `chromedriver` binary, and run it:
|
||||
|
||||
```bash
|
||||
$ chromedriver --url-base=/wd/hub --port=9515
|
||||
$ chromedriver --url-base=wd/hub --port=9515
|
||||
Starting ChromeDriver (v2.10.291558) on port 9515
|
||||
Only local connections are allowed.
|
||||
```
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
'atom/common/api/lib/native-image.coffee',
|
||||
'atom/common/api/lib/shell.coffee',
|
||||
'atom/common/lib/init.coffee',
|
||||
'atom/common/lib/reset-search-paths.coffee',
|
||||
'atom/renderer/lib/chrome-api.coffee',
|
||||
'atom/renderer/lib/init.coffee',
|
||||
'atom/renderer/lib/inspector.coffee',
|
||||
|
@ -123,12 +124,14 @@
|
|||
'atom/browser/atom_download_manager_delegate.h',
|
||||
'atom/browser/atom_browser_main_parts.cc',
|
||||
'atom/browser/atom_browser_main_parts.h',
|
||||
'atom/browser/atom_browser_main_parts_linux.cc',
|
||||
'atom/browser/atom_browser_main_parts_mac.mm',
|
||||
'atom/browser/atom_browser_main_parts_posix.cc',
|
||||
'atom/browser/atom_javascript_dialog_manager.cc',
|
||||
'atom/browser/atom_javascript_dialog_manager.h',
|
||||
'atom/browser/atom_quota_permission_context.cc',
|
||||
'atom/browser/atom_quota_permission_context.h',
|
||||
'atom/browser/atom_resource_dispatcher_host_delegate.cc',
|
||||
'atom/browser/atom_resource_dispatcher_host_delegate.h',
|
||||
'atom/browser/atom_speech_recognition_manager_delegate.cc',
|
||||
'atom/browser/atom_speech_recognition_manager_delegate.h',
|
||||
'atom/browser/atom_ssl_config_service.cc',
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
{
|
||||
"name": "electron",
|
||||
"devDependencies": {
|
||||
"asar": "0.8.x",
|
||||
"asar": "^0.8.0",
|
||||
"coffee-script": "^1.9.2",
|
||||
"coffeelint": "^1.9.4",
|
||||
"request": "*",
|
||||
"runas": "3.x"
|
||||
"runas": "^3.0.0"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
|
|
@ -8,7 +8,7 @@ from lib.config import get_target_arch
|
|||
from lib.util import safe_mkdir, rm_rf, extract_zip, tempdir, download
|
||||
|
||||
|
||||
VERSION = 'v0.7.0'
|
||||
VERSION = 'v0.8.0'
|
||||
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||
FRAMEWORKS_URL = 'http://github.com/atom/atom-shell-frameworks/releases' \
|
||||
'/download/' + VERSION
|
||||
|
|
2
vendor/brightray
vendored
2
vendor/brightray
vendored
|
@ -1 +1 @@
|
|||
Subproject commit 8e443520e695674fd26585cfa24a0ec0b6140c27
|
||||
Subproject commit c44f99278bc4f6823f81b6f3a8d75881d697fd01
|
2
vendor/node
vendored
2
vendor/node
vendored
|
@ -1 +1 @@
|
|||
Subproject commit ac25693ad1d4c248e69a89147fd3995c3bf6c946
|
||||
Subproject commit f4243f5c84a371632d8d72a1a2210a0e994afdcc
|
Loading…
Reference in a new issue