mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
128 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8a73d91ea1 | ||
|
|
879de42372 | ||
|
|
32b8366d30 | ||
|
|
95662d4233 | ||
|
|
2f36216cb0 | ||
|
|
2513358eb5 | ||
|
|
21fa395b61 | ||
|
|
afde383e28 | ||
|
|
ee9964c141 | ||
|
|
bf66aeb8ee | ||
|
|
f706bb45cb | ||
|
|
0b1b0940d2 | ||
|
|
0db2769781 | ||
|
|
47c18fef7f | ||
|
|
48412769df | ||
|
|
528f7bd45f | ||
|
|
78322b5231 | ||
|
|
c23ba7b504 | ||
|
|
6aa69a06c8 | ||
|
|
0e94977d42 | ||
|
|
ba4f502b1e | ||
|
|
651dabf47e | ||
|
|
af72842728 | ||
|
|
49ac363eef | ||
|
|
66bbf00b7a | ||
|
|
0398316192 | ||
|
|
b428b2eb99 | ||
|
|
ab6cb042f6 | ||
|
|
9c8b3e3c2e | ||
|
|
b27abd2011 | ||
|
|
bf1a4e12f1 | ||
|
|
20acead8be | ||
|
|
d07482c5f6 | ||
|
|
26ac34d0e0 | ||
|
|
b7816d85a1 | ||
|
|
c99b20206c | ||
|
|
d97155d7b0 | ||
|
|
10af87008d | ||
|
|
ed633b3250 | ||
|
|
e0fddcb7ce | ||
|
|
aa55e397d4 | ||
|
|
7943f7f7eb | ||
|
|
869e086a41 | ||
|
|
a96618e5cd | ||
|
|
02b2459db6 | ||
|
|
bef6909218 | ||
|
|
1ade8dcee7 | ||
|
|
e1e1c173fe | ||
|
|
5ee805e451 | ||
|
|
f2b91d5e1d | ||
|
|
1cd3918494 | ||
|
|
cb8f975528 | ||
|
|
42afc071eb | ||
|
|
79d4724a15 | ||
|
|
e699cac92c | ||
|
|
a3d2a490da | ||
|
|
58795eaa7e | ||
|
|
9f29f66768 | ||
|
|
14d01544d4 | ||
|
|
cf7cf098d8 | ||
|
|
e9636bb87b | ||
|
|
c82f5c8da8 | ||
|
|
246a145930 | ||
|
|
c9371bceec | ||
|
|
bd1f0e78a8 | ||
|
|
90c24de0f0 | ||
|
|
5cb97545fd | ||
|
|
db8361a0a9 | ||
|
|
57bfc63d23 | ||
|
|
fbd74c0e2d | ||
|
|
993c52dcd5 | ||
|
|
f5a8ec0cd3 | ||
|
|
747698fe9b | ||
|
|
e0dae4054a | ||
|
|
070d26e68e | ||
|
|
e6830e9ac8 | ||
|
|
aba3b721c5 | ||
|
|
62fd76f7e4 | ||
|
|
66e96f69fc | ||
|
|
9a825c5cbd | ||
|
|
02bcdc1c19 | ||
|
|
f13d8407ee | ||
|
|
739c432c98 | ||
|
|
94084639f2 | ||
|
|
e6f748d77f | ||
|
|
212cd67f08 | ||
|
|
90480fff4e | ||
|
|
4a1b6d76b2 | ||
|
|
6d663d1d01 | ||
|
|
e5e94ed437 | ||
|
|
621867e518 | ||
|
|
716037544a | ||
|
|
b92d5071fa | ||
|
|
ef255db069 | ||
|
|
24f8c51959 | ||
|
|
4b20ac3dc6 | ||
|
|
34521e5880 | ||
|
|
45fb3ec41d | ||
|
|
caa0634df8 | ||
|
|
15a05b3639 | ||
|
|
edcae49e52 | ||
|
|
81283db2da | ||
|
|
f56d1ea7b4 | ||
|
|
fea5559fbc | ||
|
|
b360122b35 | ||
|
|
185d3a7c02 | ||
|
|
f90fb8cc72 | ||
|
|
111dcbac25 | ||
|
|
e28bdcdd46 | ||
|
|
395b0c4224 | ||
|
|
217b1afe87 | ||
|
|
8d8bfcd120 | ||
|
|
2637cafda5 | ||
|
|
c764b7b023 | ||
|
|
522ae765ea | ||
|
|
9cf3811a56 | ||
|
|
6d2cc8aedf | ||
|
|
058046304d | ||
|
|
7ff0e0214e | ||
|
|
2be5393768 | ||
|
|
b54caccb22 | ||
|
|
c499dfbb22 | ||
|
|
f6ba308ff8 | ||
|
|
10e195a444 | ||
|
|
490a12d38a | ||
|
|
e004d53d2a | ||
|
|
4788323582 | ||
|
|
80d574482e |
5
atom.gyp
5
atom.gyp
@@ -38,6 +38,7 @@
|
||||
'atom/common/api/lib/clipboard.coffee',
|
||||
'atom/common/api/lib/crash-reporter.coffee',
|
||||
'atom/common/api/lib/id-weak-map.coffee',
|
||||
'atom/common/api/lib/original-fs.coffee',
|
||||
'atom/common/api/lib/screen.coffee',
|
||||
'atom/common/api/lib/shell.coffee',
|
||||
'atom/common/lib/init.coffee',
|
||||
@@ -586,10 +587,10 @@
|
||||
'-rpath \$$ORIGIN',
|
||||
# Make native module dynamic loading work.
|
||||
'-rdynamic',
|
||||
'<!@(pkg-config --libs-only-L --libs-only-other dbus-1)',
|
||||
'<!@(pkg-config --libs-only-L --libs-only-other dbus-1 x11 xrandr xext gconf-2.0)',
|
||||
],
|
||||
'libraries': [
|
||||
'<!@(pkg-config --libs-only-l dbus-1)',
|
||||
'<!@(pkg-config --libs-only-l dbus-1 x11 xrandr xext gconf-2.0)',
|
||||
],
|
||||
},
|
||||
# Required settings of using breakpad.
|
||||
|
||||
@@ -89,6 +89,10 @@ void AtomMainDelegate::PreSandboxStartup() {
|
||||
command_line->AppendSwitch("atom-shell-switches-end");
|
||||
}
|
||||
|
||||
void AtomMainDelegate::ProcessExiting(const std::string& process_type) {
|
||||
LOG(ERROR) << "ProcessExiting: " << process_type;
|
||||
}
|
||||
|
||||
content::ContentBrowserClient* AtomMainDelegate::CreateContentBrowserClient() {
|
||||
browser_client_.reset(new AtomBrowserClient);
|
||||
return browser_client_.get();
|
||||
|
||||
@@ -19,6 +19,7 @@ class AtomMainDelegate : public brightray::MainDelegate {
|
||||
// content::ContentMainDelegate:
|
||||
virtual bool BasicStartupComplete(int* exit_code) OVERRIDE;
|
||||
virtual void PreSandboxStartup() OVERRIDE;
|
||||
virtual void ProcessExiting(const std::string& process_type) OVERRIDE;
|
||||
virtual content::ContentBrowserClient* CreateContentBrowserClient() OVERRIDE;
|
||||
virtual content::ContentRendererClient*
|
||||
CreateContentRendererClient() OVERRIDE;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "atom/browser/api/atom_api_menu.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/browser.h"
|
||||
#include "atom/common/native_mate_converters/file_path_converter.h"
|
||||
@@ -32,6 +33,32 @@
|
||||
|
||||
using atom::Browser;
|
||||
|
||||
namespace mate {
|
||||
|
||||
#if defined(OS_WIN)
|
||||
template<>
|
||||
struct Converter<Browser::UserTask> {
|
||||
static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
|
||||
Browser::UserTask* out) {
|
||||
mate::Dictionary dict;
|
||||
if (!ConvertFromV8(isolate, val, &dict))
|
||||
return false;
|
||||
if (!dict.Get("program", &(out->program)) ||
|
||||
!dict.Get("title", &(out->title)))
|
||||
return false;
|
||||
if (dict.Get("iconPath", &(out->icon_path)) &&
|
||||
!dict.Get("iconIndex", &(out->icon_index)))
|
||||
return false;
|
||||
dict.Get("arguments", &(out->arguments));
|
||||
dict.Get("description", &(out->description));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace mate
|
||||
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace api {
|
||||
@@ -157,6 +184,14 @@ mate::ObjectTemplateBuilder App::GetObjectTemplateBuilder(
|
||||
.SetMethod("getName", base::Bind(&Browser::GetName, browser))
|
||||
.SetMethod("setName", base::Bind(&Browser::SetName, browser))
|
||||
.SetMethod("isReady", base::Bind(&Browser::is_ready, browser))
|
||||
.SetMethod("addRecentDocument",
|
||||
base::Bind(&Browser::AddRecentDocument, browser))
|
||||
.SetMethod("clearRecentDocuments",
|
||||
base::Bind(&Browser::ClearRecentDocuments, browser))
|
||||
#if defined(OS_WIN)
|
||||
.SetMethod("setUserTasks",
|
||||
base::Bind(&Browser::SetUserTasks, browser))
|
||||
#endif
|
||||
.SetMethod("getDataPath", &App::GetDataPath)
|
||||
.SetMethod("resolveProxy", &App::ResolveProxy)
|
||||
.SetMethod("setDesktopName", &App::SetDesktopName);
|
||||
@@ -191,12 +226,15 @@ int DockBounce(const std::string& type) {
|
||||
request_id = Browser::Get()->DockBounce(Browser::BOUNCE_INFORMATIONAL);
|
||||
return request_id;
|
||||
}
|
||||
|
||||
void DockSetMenu(atom::api::Menu* menu) {
|
||||
Browser::Get()->DockSetMenu(menu->model());
|
||||
}
|
||||
#endif
|
||||
|
||||
void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
|
||||
v8::Handle<v8::Context> context, void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
Browser* browser = Browser::Get();
|
||||
CommandLine* command_line = CommandLine::ForCurrentProcess();
|
||||
|
||||
mate::Dictionary dict(isolate, exports);
|
||||
@@ -206,20 +244,17 @@ void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
|
||||
base::Bind(&CommandLine::AppendArg,
|
||||
base::Unretained(command_line)));
|
||||
#if defined(OS_MACOSX)
|
||||
auto browser = base::Unretained(Browser::Get());
|
||||
dict.SetMethod("dockBounce", &DockBounce);
|
||||
dict.SetMethod("dockCancelBounce",
|
||||
base::Bind(&Browser::DockCancelBounce,
|
||||
base::Unretained(browser)));
|
||||
base::Bind(&Browser::DockCancelBounce, browser));
|
||||
dict.SetMethod("dockSetBadgeText",
|
||||
base::Bind(&Browser::DockSetBadgeText,
|
||||
base::Unretained(browser)));
|
||||
base::Bind(&Browser::DockSetBadgeText, browser));
|
||||
dict.SetMethod("dockGetBadgeText",
|
||||
base::Bind(&Browser::DockGetBadgeText,
|
||||
base::Unretained(browser)));
|
||||
dict.SetMethod("dockHide",
|
||||
base::Bind(&Browser::DockHide, base::Unretained(browser)));
|
||||
dict.SetMethod("dockShow",
|
||||
base::Bind(&Browser::DockShow, base::Unretained(browser)));
|
||||
base::Bind(&Browser::DockGetBadgeText, browser));
|
||||
dict.SetMethod("dockHide", base::Bind(&Browser::DockHide, browser));
|
||||
dict.SetMethod("dockShow", base::Bind(&Browser::DockShow, browser));
|
||||
dict.SetMethod("dockSetMenu", &DockSetMenu);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -33,20 +33,19 @@ class App : public mate::EventEmitter,
|
||||
App();
|
||||
virtual ~App();
|
||||
|
||||
// BrowserObserver implementations:
|
||||
virtual void OnWillQuit(bool* prevent_default) OVERRIDE;
|
||||
virtual void OnWindowAllClosed() OVERRIDE;
|
||||
virtual void OnQuit() OVERRIDE;
|
||||
virtual void OnOpenFile(bool* prevent_default,
|
||||
const std::string& file_path) OVERRIDE;
|
||||
virtual void OnOpenURL(const std::string& url) OVERRIDE;
|
||||
virtual void OnActivateWithNoOpenWindows() OVERRIDE;
|
||||
virtual void OnWillFinishLaunching() OVERRIDE;
|
||||
virtual void OnFinishLaunching() OVERRIDE;
|
||||
// BrowserObserver:
|
||||
void OnWillQuit(bool* prevent_default) override;
|
||||
void OnWindowAllClosed() override;
|
||||
void OnQuit() override;
|
||||
void OnOpenFile(bool* prevent_default, const std::string& file_path) override;
|
||||
void OnOpenURL(const std::string& url) override;
|
||||
void OnActivateWithNoOpenWindows() override;
|
||||
void OnWillFinishLaunching() override;
|
||||
void OnFinishLaunching() override;
|
||||
|
||||
// mate::Wrappable implementations:
|
||||
virtual mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate);
|
||||
// mate::Wrappable:
|
||||
mate::ObjectTemplateBuilder GetObjectTemplateBuilder(
|
||||
v8::Isolate* isolate) override;
|
||||
|
||||
private:
|
||||
base::FilePath GetDataPath();
|
||||
|
||||
@@ -103,6 +103,7 @@ void Initialize(v8::Handle<v8::Object> exports, v8::Handle<v8::Value> unused,
|
||||
v8::Handle<v8::Context> context, void* priv) {
|
||||
mate::Dictionary dict(context->GetIsolate(), exports);
|
||||
dict.SetMethod("showMessageBox", &ShowMessageBox);
|
||||
dict.SetMethod("showErrorBox", &atom::ShowErrorBox);
|
||||
dict.SetMethod("showOpenDialog", &ShowOpenDialog);
|
||||
dict.SetMethod("showSaveDialog", &ShowSaveDialog);
|
||||
}
|
||||
|
||||
@@ -41,17 +41,17 @@ class Menu : public mate::Wrappable,
|
||||
virtual ~Menu();
|
||||
|
||||
// ui::SimpleMenuModel::Delegate implementations:
|
||||
virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
|
||||
virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
|
||||
virtual bool IsCommandIdVisible(int command_id) const OVERRIDE;
|
||||
virtual bool GetAcceleratorForCommandId(
|
||||
bool IsCommandIdChecked(int command_id) const override;
|
||||
bool IsCommandIdEnabled(int command_id) const override;
|
||||
bool IsCommandIdVisible(int command_id) const override;
|
||||
bool GetAcceleratorForCommandId(
|
||||
int command_id,
|
||||
ui::Accelerator* accelerator) OVERRIDE;
|
||||
virtual bool IsItemForCommandIdDynamic(int command_id) const OVERRIDE;
|
||||
virtual base::string16 GetLabelForCommandId(int command_id) const OVERRIDE;
|
||||
virtual base::string16 GetSublabelForCommandId(int command_id) const OVERRIDE;
|
||||
virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
|
||||
virtual void MenuWillShow(ui::SimpleMenuModel* source) OVERRIDE;
|
||||
ui::Accelerator* accelerator) override;
|
||||
bool IsItemForCommandIdDynamic(int command_id) const override;
|
||||
base::string16 GetLabelForCommandId(int command_id) const override;
|
||||
base::string16 GetSublabelForCommandId(int command_id) const override;
|
||||
void ExecuteCommand(int command_id, int event_flags) override;
|
||||
void MenuWillShow(ui::SimpleMenuModel* source) override;
|
||||
|
||||
virtual void AttachToWindow(Window* window);
|
||||
virtual void Popup(Window* window) = 0;
|
||||
|
||||
@@ -286,8 +286,14 @@ bool WebContents::IsAlive() const {
|
||||
return web_contents() != NULL;
|
||||
}
|
||||
|
||||
void WebContents::LoadURL(const GURL& url) {
|
||||
void WebContents::LoadURL(const GURL& url, const mate::Dictionary& options) {
|
||||
content::NavigationController::LoadURLParams params(url);
|
||||
|
||||
GURL http_referrer;
|
||||
if (options.Get("httpreferrer", &http_referrer))
|
||||
params.referrer = content::Referrer(http_referrer.GetAsReferrer(),
|
||||
blink::WebReferrerPolicyDefault);
|
||||
|
||||
params.transition_type = content::PAGE_TRANSITION_TYPED;
|
||||
params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
|
||||
web_contents()->GetController().LoadURLWithParams(params);
|
||||
@@ -313,15 +319,15 @@ void WebContents::Stop() {
|
||||
web_contents()->Stop();
|
||||
}
|
||||
|
||||
void WebContents::Reload() {
|
||||
void WebContents::Reload(const mate::Dictionary& options) {
|
||||
// Navigating to a URL would always restart the renderer process, we want this
|
||||
// because normal reloading will break our node integration.
|
||||
// This is done by AtomBrowserClient::ShouldSwapProcessesForNavigation.
|
||||
LoadURL(GetURL());
|
||||
LoadURL(GetURL(), options);
|
||||
}
|
||||
|
||||
void WebContents::ReloadIgnoringCache() {
|
||||
Reload();
|
||||
void WebContents::ReloadIgnoringCache(const mate::Dictionary& options) {
|
||||
Reload(options);
|
||||
}
|
||||
|
||||
bool WebContents::CanGoBack() const {
|
||||
@@ -438,14 +444,14 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder(
|
||||
template_.Reset(isolate, mate::ObjectTemplateBuilder(isolate)
|
||||
.SetMethod("destroy", &WebContents::Destroy)
|
||||
.SetMethod("isAlive", &WebContents::IsAlive)
|
||||
.SetMethod("loadUrl", &WebContents::LoadURL)
|
||||
.SetMethod("_loadUrl", &WebContents::LoadURL)
|
||||
.SetMethod("getUrl", &WebContents::GetURL)
|
||||
.SetMethod("getTitle", &WebContents::GetTitle)
|
||||
.SetMethod("isLoading", &WebContents::IsLoading)
|
||||
.SetMethod("isWaitingForResponse", &WebContents::IsWaitingForResponse)
|
||||
.SetMethod("stop", &WebContents::Stop)
|
||||
.SetMethod("reload", &WebContents::Reload)
|
||||
.SetMethod("reloadIgnoringCache", &WebContents::ReloadIgnoringCache)
|
||||
.SetMethod("_reload", &WebContents::Reload)
|
||||
.SetMethod("_reloadIgnoringCache", &WebContents::ReloadIgnoringCache)
|
||||
.SetMethod("canGoBack", &WebContents::CanGoBack)
|
||||
.SetMethod("canGoForward", &WebContents::CanGoForward)
|
||||
.SetMethod("canGoToOffset", &WebContents::CanGoToOffset)
|
||||
|
||||
@@ -41,14 +41,14 @@ class WebContents : public mate::EventEmitter,
|
||||
|
||||
void Destroy();
|
||||
bool IsAlive() const;
|
||||
void LoadURL(const GURL& url);
|
||||
void LoadURL(const GURL& url, const mate::Dictionary& options);
|
||||
GURL GetURL() const;
|
||||
base::string16 GetTitle() const;
|
||||
bool IsLoading() const;
|
||||
bool IsWaitingForResponse() const;
|
||||
void Stop();
|
||||
void Reload();
|
||||
void ReloadIgnoringCache();
|
||||
void Reload(const mate::Dictionary& options);
|
||||
void ReloadIgnoringCache(const mate::Dictionary& options);
|
||||
bool CanGoBack() const;
|
||||
bool CanGoForward() const;
|
||||
bool CanGoToOffset(int offset) const;
|
||||
|
||||
@@ -378,6 +378,22 @@ void Window::SetProgressBar(double progress) {
|
||||
window_->SetProgressBar(progress);
|
||||
}
|
||||
|
||||
void Window::SetAutoHideMenuBar(bool auto_hide) {
|
||||
window_->SetAutoHideMenuBar(auto_hide);
|
||||
}
|
||||
|
||||
bool Window::IsMenuBarAutoHide() {
|
||||
return window_->IsMenuBarAutoHide();
|
||||
}
|
||||
|
||||
void Window::SetMenuBarVisibility(bool visible) {
|
||||
window_->SetMenuBarVisibility(visible);
|
||||
}
|
||||
|
||||
bool Window::IsMenuBarVisible() {
|
||||
return window_->IsMenuBarVisible();
|
||||
}
|
||||
|
||||
mate::Handle<WebContents> Window::GetWebContents(v8::Isolate* isolate) const {
|
||||
return WebContents::CreateFrom(isolate, window_->GetWebContents());
|
||||
}
|
||||
@@ -443,6 +459,10 @@ void Window::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("capturePage", &Window::CapturePage)
|
||||
.SetMethod("print", &Window::Print)
|
||||
.SetMethod("setProgressBar", &Window::SetProgressBar)
|
||||
.SetMethod("setAutoHideMenuBar", &Window::SetAutoHideMenuBar)
|
||||
.SetMethod("isMenuBarAutoHide", &Window::IsMenuBarAutoHide)
|
||||
.SetMethod("setMenuBarVisibility", &Window::SetMenuBarVisibility)
|
||||
.SetMethod("isMenuBarVisible", &Window::IsMenuBarVisible)
|
||||
.SetMethod("_getWebContents", &Window::GetWebContents)
|
||||
.SetMethod("_getDevToolsWebContents", &Window::GetDevToolsWebContents);
|
||||
}
|
||||
|
||||
@@ -111,6 +111,10 @@ class Window : public mate::EventEmitter,
|
||||
void CapturePage(mate::Arguments* args);
|
||||
void Print(mate::Arguments* args);
|
||||
void SetProgressBar(double progress);
|
||||
void SetAutoHideMenuBar(bool auto_hide);
|
||||
bool IsMenuBarAutoHide();
|
||||
void SetMenuBarVisibility(bool visible);
|
||||
bool IsMenuBarVisible();
|
||||
|
||||
// APIs for WebContents.
|
||||
mate::Handle<WebContents> GetWebContents(v8::Isolate* isolate) const;
|
||||
|
||||
@@ -26,6 +26,7 @@ if process.platform is 'darwin'
|
||||
getBadge: bindings.dockGetBadgeText
|
||||
hide: bindings.dockHide
|
||||
show: bindings.dockShow
|
||||
setMenu: bindings.dockSetMenu
|
||||
|
||||
# Be compatible with old API.
|
||||
app.once 'ready', -> app.emit 'finish-launching'
|
||||
|
||||
@@ -90,8 +90,8 @@ BrowserWindow::send = -> @webContents.send.apply @webContents, arguments
|
||||
# Be compatible with old API.
|
||||
BrowserWindow::restart = -> @webContents.reload()
|
||||
BrowserWindow::getUrl = -> @webContents.getUrl()
|
||||
BrowserWindow::reload = -> @webContents.reload()
|
||||
BrowserWindow::reloadIgnoringCache = -> @webContents.reloadIgnoringCache()
|
||||
BrowserWindow::reload = -> @webContents.reload.apply @webContents, arguments
|
||||
BrowserWindow::reloadIgnoringCache = -> @webContents.reloadIgnoringCache.apply @webContents, arguments
|
||||
BrowserWindow::getPageTitle = -> @webContents.getTitle()
|
||||
BrowserWindow::isLoading = -> @webContents.isLoading()
|
||||
BrowserWindow::isWaitingForResponse = -> @webContents.isWaitingForResponse()
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
binding = process.atomBinding 'dialog'
|
||||
v8Util = process.atomBinding 'v8_util'
|
||||
app = require 'app'
|
||||
BrowserWindow = require 'browser-window'
|
||||
|
||||
fileDialogProperties =
|
||||
@@ -22,8 +23,12 @@ parseArgs = (window, options, callback) ->
|
||||
options = null
|
||||
[window, options, callback]
|
||||
|
||||
checkAppInitialized = ->
|
||||
throw new Error('dialog module can only be used after app is ready') unless app.isReady()
|
||||
|
||||
module.exports =
|
||||
showOpenDialog: (args...) ->
|
||||
checkAppInitialized()
|
||||
[window, options, callback] = parseArgs args...
|
||||
|
||||
options ?= title: 'Open', properties: ['openFile']
|
||||
@@ -52,6 +57,7 @@ module.exports =
|
||||
wrappedCallback
|
||||
|
||||
showSaveDialog: (args...) ->
|
||||
checkAppInitialized()
|
||||
[window, options, callback] = parseArgs args...
|
||||
|
||||
options ?= title: 'Save'
|
||||
@@ -72,6 +78,7 @@ module.exports =
|
||||
wrappedCallback
|
||||
|
||||
showMessageBox: (args...) ->
|
||||
checkAppInitialized()
|
||||
[window, options, callback] = parseArgs args...
|
||||
|
||||
options ?= type: 'none'
|
||||
@@ -93,5 +100,8 @@ module.exports =
|
||||
window,
|
||||
callback
|
||||
|
||||
showErrorBox: (args...) ->
|
||||
binding.showErrorBox args...
|
||||
|
||||
# Mark standard asynchronous functions.
|
||||
v8Util.setHiddenValue f, 'asynchronous', true for k, f of module.exports
|
||||
|
||||
@@ -26,6 +26,11 @@ module.exports.wrap = (webContents) ->
|
||||
webContents.getId = -> "#{@getProcessId()}-#{@getRoutingId()}"
|
||||
webContents.equal = (other) -> @getId() is other.getId()
|
||||
|
||||
# Provide a default parameter for |urlOptions|.
|
||||
webContents.loadUrl = (url, urlOptions={}) -> @_loadUrl url, urlOptions
|
||||
webContents.reload = (urlOptions={}) -> @_reload urlOptions
|
||||
webContents.reloadIgnoringCache = (urlOptions={}) -> @_reloadIgnoringCache urlOptions
|
||||
|
||||
# Translate |disposition| to string for 'new-window' event.
|
||||
webContents.on '-new-window', (args..., disposition) ->
|
||||
disposition =
|
||||
|
||||
@@ -154,6 +154,12 @@ void AtomBrowserClient::AppendExtraCommandLineSwitches(
|
||||
command_line->AppendSwitchASCII(
|
||||
switches::kNodeIntegration,
|
||||
info.node_integration ? "true" : "false");
|
||||
if (info.plugins)
|
||||
command_line->AppendSwitch(switches::kEnablePlugins);
|
||||
if (!info.preload_script.empty())
|
||||
command_line->AppendSwitchPath(
|
||||
switches::kPreloadScript,
|
||||
info.preload_script);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ void AtomBrowserMainParts::PreMainMessageLoopStart() {
|
||||
// Force the NSApplication subclass to be used.
|
||||
NSApplication* application = [AtomApplication sharedApplication];
|
||||
|
||||
AtomApplicationDelegate* delegate = [AtomApplicationDelegate alloc];
|
||||
AtomApplicationDelegate* delegate = [[AtomApplicationDelegate alloc] init];
|
||||
[NSApp setDelegate:(id<NSFileManagerDelegate>)delegate];
|
||||
|
||||
base::FilePath frameworkPath = brightray::MainApplicationBundlePath()
|
||||
@@ -41,7 +41,8 @@ void AtomBrowserMainParts::PreMainMessageLoopStart() {
|
||||
}
|
||||
|
||||
void AtomBrowserMainParts::PostDestroyThreads() {
|
||||
[[AtomApplication sharedApplication] setDelegate:nil];
|
||||
[[NSApp delegate] release];
|
||||
[NSApp setDelegate:nil];
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -70,6 +70,10 @@ std::string Browser::GetName() const {
|
||||
|
||||
void Browser::SetName(const std::string& name) {
|
||||
name_override_ = name;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
SetAppUserModelID(name);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Browser::OpenFile(const std::string& file_path) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#define ATOM_BROWSER_BROWSER_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/compiler_specific.h"
|
||||
@@ -13,6 +14,19 @@
|
||||
#include "atom/browser/browser_observer.h"
|
||||
#include "atom/browser/window_list_observer.h"
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/strings/string16.h"
|
||||
#endif
|
||||
|
||||
namespace base {
|
||||
class FilePath;
|
||||
}
|
||||
|
||||
namespace ui {
|
||||
class MenuModel;
|
||||
}
|
||||
|
||||
namespace atom {
|
||||
|
||||
// This class is used for control application-wide operations.
|
||||
@@ -44,6 +58,12 @@ class Browser : public WindowListObserver {
|
||||
// Overrides the application name.
|
||||
void SetName(const std::string& name);
|
||||
|
||||
// Add the |path| to recent documents list.
|
||||
void AddRecentDocument(const base::FilePath& path);
|
||||
|
||||
// Clear the recent documents list.
|
||||
void ClearRecentDocuments();
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// Bounce the dock icon.
|
||||
enum BounceType {
|
||||
@@ -60,8 +80,28 @@ class Browser : public WindowListObserver {
|
||||
// Hide/Show dock.
|
||||
void DockHide();
|
||||
void DockShow();
|
||||
|
||||
// Set docks' menu.
|
||||
void DockSetMenu(ui::MenuModel* model);
|
||||
#endif // defined(OS_MACOSX)
|
||||
|
||||
#if defined(OS_WIN)
|
||||
struct UserTask {
|
||||
base::FilePath program;
|
||||
base::string16 arguments;
|
||||
base::string16 title;
|
||||
base::string16 description;
|
||||
base::FilePath icon_path;
|
||||
int icon_index;
|
||||
};
|
||||
|
||||
// Add a custom task to jump list.
|
||||
void SetUserTasks(const std::vector<UserTask>& tasks);
|
||||
|
||||
// Set the application user model ID, called when "SetName" is called.
|
||||
void SetAppUserModelID(const std::string& name);
|
||||
#endif
|
||||
|
||||
// Tell the application to open a file.
|
||||
bool OpenFile(const std::string& file_path);
|
||||
|
||||
@@ -100,8 +140,8 @@ class Browser : public WindowListObserver {
|
||||
|
||||
private:
|
||||
// WindowListObserver implementations:
|
||||
virtual void OnWindowCloseCancelled(NativeWindow* window) OVERRIDE;
|
||||
virtual void OnWindowAllClosed() OVERRIDE;
|
||||
void OnWindowCloseCancelled(NativeWindow* window) override;
|
||||
void OnWindowAllClosed() override;
|
||||
|
||||
// Observers of the browser.
|
||||
ObserverList<BrowserObserver> observers_;
|
||||
@@ -112,6 +152,10 @@ class Browser : public WindowListObserver {
|
||||
std::string version_override_;
|
||||
std::string name_override_;
|
||||
|
||||
#if defined(OS_WIN)
|
||||
base::string16 app_user_model_id_;
|
||||
#endif
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(Browser);
|
||||
};
|
||||
|
||||
|
||||
@@ -24,6 +24,12 @@ void Browser::Focus() {
|
||||
}
|
||||
}
|
||||
|
||||
void Browser::AddRecentDocument(const base::FilePath& path) {
|
||||
}
|
||||
|
||||
void Browser::ClearRecentDocuments() {
|
||||
}
|
||||
|
||||
std::string Browser::GetExecutableFileVersion() const {
|
||||
return ATOM_VERSION_STRING;
|
||||
}
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
#include "atom/browser/browser.h"
|
||||
|
||||
#import "atom/browser/mac/atom_application.h"
|
||||
#import "atom/browser/mac/atom_application_delegate.h"
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "atom/browser/window_list.h"
|
||||
#import "base/mac/bundle_locations.h"
|
||||
#import "base/mac/foundation_util.h"
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
|
||||
namespace atom {
|
||||
@@ -16,6 +18,14 @@ void Browser::Focus() {
|
||||
[[AtomApplication sharedApplication] activateIgnoringOtherApps:YES];
|
||||
}
|
||||
|
||||
void Browser::AddRecentDocument(const base::FilePath& path) {
|
||||
NSURL* u = [NSURL fileURLWithPath:base::mac::FilePathToNSString(path)];
|
||||
[[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL:u];
|
||||
}
|
||||
|
||||
void Browser::ClearRecentDocuments() {
|
||||
}
|
||||
|
||||
std::string Browser::GetExecutableFileVersion() const {
|
||||
NSDictionary* infoDictionary = base::mac::OuterBundle().infoDictionary;
|
||||
NSString *version = [infoDictionary objectForKey:@"CFBundleVersion"];
|
||||
@@ -60,4 +70,9 @@ void Browser::DockShow() {
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
}
|
||||
|
||||
void Browser::DockSetMenu(ui::MenuModel* model) {
|
||||
AtomApplicationDelegate* delegate = [NSApp delegate];
|
||||
[delegate setApplicationDockMenu:model];
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -4,14 +4,21 @@
|
||||
|
||||
#include "atom/browser/browser.h"
|
||||
|
||||
#include <atlbase.h>
|
||||
#include <propkey.h>
|
||||
#include <windows.h>
|
||||
#include <shlobj.h>
|
||||
#include <shobjidl.h>
|
||||
|
||||
#include "base/base_paths.h"
|
||||
#include "base/file_version_info.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/win/win_util.h"
|
||||
#include "base/win/windows_version.h"
|
||||
#include "atom/common/atom_version.h"
|
||||
|
||||
namespace atom {
|
||||
@@ -39,6 +46,83 @@ void Browser::Focus() {
|
||||
EnumWindows(&WindowsEnumerationHandler, reinterpret_cast<LPARAM>(&pid));
|
||||
}
|
||||
|
||||
void Browser::AddRecentDocument(const base::FilePath& path) {
|
||||
if (base::win::GetVersion() < base::win::VERSION_WIN7)
|
||||
return;
|
||||
|
||||
CComPtr<IShellItem> item;
|
||||
HRESULT hr = SHCreateItemFromParsingName(
|
||||
path.value().c_str(), NULL, IID_PPV_ARGS(&item));
|
||||
if (SUCCEEDED(hr)) {
|
||||
SHARDAPPIDINFO info;
|
||||
info.psi = item;
|
||||
info.pszAppID = app_user_model_id_.c_str();
|
||||
SHAddToRecentDocs(SHARD_APPIDINFO, &info);
|
||||
}
|
||||
}
|
||||
|
||||
void Browser::ClearRecentDocuments() {
|
||||
CComPtr<IApplicationDestinations> destinations;
|
||||
if (FAILED(destinations.CoCreateInstance(CLSID_ApplicationDestinations,
|
||||
NULL, CLSCTX_INPROC_SERVER)))
|
||||
return;
|
||||
if (FAILED(destinations->SetAppID(app_user_model_id_.c_str())))
|
||||
return;
|
||||
destinations->RemoveAllDestinations();
|
||||
}
|
||||
|
||||
void Browser::SetUserTasks(const std::vector<UserTask>& tasks) {
|
||||
CComPtr<ICustomDestinationList> destinations;
|
||||
if (FAILED(destinations.CoCreateInstance(CLSID_DestinationList)))
|
||||
return;
|
||||
if (FAILED(destinations->SetAppID(app_user_model_id_.c_str())))
|
||||
return;
|
||||
|
||||
// Start a transaction that updates the JumpList of this application.
|
||||
UINT max_slots;
|
||||
CComPtr<IObjectArray> removed;
|
||||
if (FAILED(destinations->BeginList(&max_slots, IID_PPV_ARGS(&removed))))
|
||||
return;
|
||||
|
||||
CComPtr<IObjectCollection> collection;
|
||||
if (FAILED(collection.CoCreateInstance(CLSID_EnumerableObjectCollection)))
|
||||
return;
|
||||
|
||||
for (auto& task : tasks) {
|
||||
CComPtr<IShellLink> link;
|
||||
if (FAILED(link.CoCreateInstance(CLSID_ShellLink)) ||
|
||||
FAILED(link->SetPath(task.program.value().c_str())) ||
|
||||
FAILED(link->SetArguments(task.arguments.c_str())) ||
|
||||
FAILED(link->SetDescription(task.description.c_str())))
|
||||
return;
|
||||
|
||||
if (!task.icon_path.empty() &&
|
||||
FAILED(link->SetIconLocation(task.icon_path.value().c_str(),
|
||||
task.icon_index)))
|
||||
return;
|
||||
|
||||
CComQIPtr<IPropertyStore> property_store = link;
|
||||
if (!base::win::SetStringValueForPropertyStore(property_store, PKEY_Title,
|
||||
task.title.c_str()))
|
||||
return;
|
||||
|
||||
if (FAILED(collection->AddObject(link)))
|
||||
return;
|
||||
}
|
||||
|
||||
// When the list is empty "AddUserTasks" could fail, so we don't check return
|
||||
// value for it.
|
||||
CComQIPtr<IObjectArray> task_array = collection;
|
||||
destinations->AddUserTasks(task_array);
|
||||
destinations->CommitList();
|
||||
}
|
||||
|
||||
void Browser::SetAppUserModelID(const std::string& name) {
|
||||
app_user_model_id_ = base::UTF8ToUTF16(
|
||||
base::StringPrintf("atom-shell.app.%s", name));
|
||||
SetCurrentProcessExplicitAppUserModelID(app_user_model_id_.c_str());
|
||||
}
|
||||
|
||||
std::string Browser::GetExecutableFileVersion() const {
|
||||
base::FilePath path;
|
||||
if (PathService::Get(base::FILE_EXE, &path)) {
|
||||
|
||||
@@ -48,14 +48,7 @@ if (option.file && !option.webdriver) {
|
||||
} catch(e) {
|
||||
if (e.code == 'MODULE_NOT_FOUND') {
|
||||
app.focus();
|
||||
console.error(e.stack);
|
||||
dialog.showMessageBox({
|
||||
type: 'warning',
|
||||
buttons: ['OK'],
|
||||
title: 'Error opening app',
|
||||
message: 'The app provided is not a valid atom-shell app, please read the docs on how to write one:',
|
||||
detail: 'https://github.com/atom/atom-shell/tree/master/docs'
|
||||
});
|
||||
dialog.showErrorBox('Error opening app', 'The app provided is not a valid atom-shell app, please read the docs on how to write one:\nhttps://github.com/atom/atom-shell/tree/master/docs');
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.error('App throwed an error when running', e);
|
||||
|
||||
@@ -33,7 +33,8 @@ createGuest = (embedder, params) ->
|
||||
guestInstanceId: id
|
||||
storagePartitionId: params.storagePartitionId
|
||||
guestInstances[id] = {guest, embedder}
|
||||
webViewManager.addGuest id, embedder, guest, params.nodeIntegration
|
||||
preload = params.preload ? ''
|
||||
webViewManager.addGuest id, embedder, guest, params.nodeIntegration, params.plugins, preload
|
||||
|
||||
# Destroy guest when the embedder is gone.
|
||||
embedder.once 'render-view-deleted', ->
|
||||
@@ -46,7 +47,10 @@ createGuest = (embedder, params) ->
|
||||
max = width: params.maxwidth, height: params.maxheight
|
||||
@setAutoSize params.autosize, min, max
|
||||
if params.src
|
||||
@loadUrl params.src
|
||||
if params.httpreferrer
|
||||
@loadUrl params.src, {httpreferrer: params.httpreferrer}
|
||||
else
|
||||
@loadUrl params.src
|
||||
if params.allowtransparency?
|
||||
@setAllowTransparency params.allowtransparency
|
||||
|
||||
|
||||
@@ -45,13 +45,9 @@ process.once 'BIND_DONE', ->
|
||||
# Don't quit on fatal error.
|
||||
process.on 'uncaughtException', (error) ->
|
||||
# Show error in GUI.
|
||||
message = error.stack ? "#{error.name}: #{error.message}"
|
||||
require('dialog').showMessageBox
|
||||
type: 'warning'
|
||||
title: 'A javascript error occured in the browser'
|
||||
message: 'uncaughtException'
|
||||
detail: message
|
||||
buttons: ['OK']
|
||||
stack = error.stack ? "#{error.name}: #{error.message}"
|
||||
message = "Uncaught Exception:\n#{stack}"
|
||||
require('dialog').showErrorBox 'A JavaScript error occured in the browser process', message
|
||||
|
||||
# Emit 'exit' event on quit.
|
||||
require('app').on 'quit', ->
|
||||
|
||||
@@ -4,7 +4,16 @@
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
#import "atom/browser/ui/cocoa/atom_menu_controller.h"
|
||||
|
||||
@interface AtomApplicationDelegate : NSObject<NSApplicationDelegate> {
|
||||
@private
|
||||
base::scoped_nsobject<AtomMenuController> menu_controller_;
|
||||
}
|
||||
|
||||
- (id)init;
|
||||
|
||||
// Sets the menu that will be returned in "applicationDockMenu:".
|
||||
- (void)setApplicationDockMenu:(ui::MenuModel*)model;
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,6 +10,16 @@
|
||||
|
||||
@implementation AtomApplicationDelegate
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
menu_controller_.reset([[AtomMenuController alloc] init]);
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setApplicationDockMenu:(ui::MenuModel*)model {
|
||||
[menu_controller_ populateWithModel:model];
|
||||
}
|
||||
|
||||
- (void)applicationWillFinishLaunching:(NSNotification*)notify {
|
||||
atom::Browser::Get()->WillFinishLaunching();
|
||||
}
|
||||
@@ -18,6 +28,10 @@
|
||||
atom::Browser::Get()->DidFinishLaunching();
|
||||
}
|
||||
|
||||
- (NSMenu*)applicationDockMenu:(NSApplication*)sender {
|
||||
return [menu_controller_ menu];
|
||||
}
|
||||
|
||||
- (BOOL)application:(NSApplication*)sender
|
||||
openFile:(NSString*)filename {
|
||||
std::string filename_str(base::SysNSStringToUTF8(filename));
|
||||
|
||||
@@ -101,6 +101,13 @@ NativeWindow::NativeWindow(content::WebContents* web_contents,
|
||||
// Read icon before window is created.
|
||||
options.Get(switches::kIcon, &icon_);
|
||||
|
||||
// The "preload" option must be absolute path.
|
||||
if (options.Get(switches::kPreloadScript, &preload_script_) &&
|
||||
!preload_script_.IsAbsolute()) {
|
||||
LOG(ERROR) << "Path of \"preload\" script must be absolute.";
|
||||
preload_script_.clear();
|
||||
}
|
||||
|
||||
// Be compatible with old API of "node-integration" option.
|
||||
std::string old_string_token;
|
||||
if (options.Get(switches::kNodeIntegration, &old_string_token) &&
|
||||
@@ -236,6 +243,20 @@ void NativeWindow::Print(bool silent, bool print_background) {
|
||||
PrintNow(silent, print_background);
|
||||
}
|
||||
|
||||
void NativeWindow::SetAutoHideMenuBar(bool auto_hide) {
|
||||
}
|
||||
|
||||
bool NativeWindow::IsMenuBarAutoHide() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void NativeWindow::SetMenuBarVisibility(bool visible) {
|
||||
}
|
||||
|
||||
bool NativeWindow::IsMenuBarVisible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NativeWindow::HasModalDialog() {
|
||||
return has_dialog_attached_;
|
||||
}
|
||||
@@ -349,6 +370,10 @@ void NativeWindow::AppendExtraCommandLineSwitches(
|
||||
command_line->AppendSwitchASCII(switches::kNodeIntegration,
|
||||
node_integration_ ? "true" : "false");
|
||||
|
||||
// Append --preload.
|
||||
if (!preload_script_.empty())
|
||||
command_line->AppendSwitchPath(switches::kPreloadScript, preload_script_);
|
||||
|
||||
// Append --zoom-factor.
|
||||
if (zoom_factor_ != 1.0)
|
||||
command_line->AppendSwitchASCII(switches::kZoomFactor,
|
||||
|
||||
@@ -161,6 +161,12 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
// Print current page.
|
||||
virtual void Print(bool silent, bool print_background);
|
||||
|
||||
// Toggle the menu bar.
|
||||
virtual void SetAutoHideMenuBar(bool auto_hide);
|
||||
virtual bool IsMenuBarAutoHide();
|
||||
virtual void SetMenuBarVisibility(bool visible);
|
||||
virtual bool IsMenuBarVisible();
|
||||
|
||||
// The same with closing a tab in a real browser.
|
||||
//
|
||||
// Should be called by platform code when user want to close the window.
|
||||
@@ -318,6 +324,9 @@ class NativeWindow : public brightray::DefaultWebContentsDelegate,
|
||||
// Web preferences.
|
||||
mate::PersistentDictionary web_preferences_;
|
||||
|
||||
// The script to load before page's JavaScript starts to run.
|
||||
base::FilePath preload_script_;
|
||||
|
||||
// Page's default zoom factor.
|
||||
double zoom_factor_;
|
||||
|
||||
|
||||
@@ -113,9 +113,12 @@ bool IsAltKey(const content::NativeWebKeyboardEvent& event) {
|
||||
|
||||
bool IsAltModifier(const content::NativeWebKeyboardEvent& event) {
|
||||
typedef content::NativeWebKeyboardEvent::Modifiers Modifiers;
|
||||
return (event.modifiers == Modifiers::AltKey) ||
|
||||
(event.modifiers == (Modifiers::AltKey | Modifiers::IsLeft)) ||
|
||||
(event.modifiers == (Modifiers::AltKey | Modifiers::IsRight));
|
||||
int modifiers = event.modifiers;
|
||||
modifiers &= ~Modifiers::NumLockOn;
|
||||
modifiers &= ~Modifiers::CapsLockOn;
|
||||
return (modifiers == Modifiers::AltKey) ||
|
||||
(modifiers == (Modifiers::AltKey | Modifiers::IsLeft)) ||
|
||||
(modifiers == (Modifiers::AltKey | Modifiers::IsRight));
|
||||
}
|
||||
|
||||
class NativeWindowClientView : public views::ClientView {
|
||||
@@ -224,6 +227,23 @@ NativeWindowViews::NativeWindowViews(content::WebContents* web_contents,
|
||||
use_content_size_)
|
||||
bounds = ContentBoundsToWindowBounds(bounds);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
if (!has_frame_) {
|
||||
// Set Window style so that we get a minimize and maximize animation when
|
||||
// frameless.
|
||||
DWORD frame_style = WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX |
|
||||
WS_CAPTION;
|
||||
::SetWindowLong(GetAcceleratedWidget(), GWL_STYLE, frame_style);
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO(zcbenz): This was used to force using native frame on Windows 2003, we
|
||||
// should check whether setting it in InitParams can work.
|
||||
if (has_frame_) {
|
||||
window_->set_frame_type(views::Widget::FrameType::FRAME_TYPE_FORCE_NATIVE);
|
||||
window_->FrameTypeChanged();
|
||||
}
|
||||
|
||||
window_->UpdateWindowIcon();
|
||||
window_->CenterWindow(bounds.size());
|
||||
Layout();
|
||||
@@ -541,6 +561,38 @@ void NativeWindowViews::SetProgressBar(double progress) {
|
||||
#endif
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetAutoHideMenuBar(bool auto_hide) {
|
||||
menu_bar_autohide_ = auto_hide;
|
||||
}
|
||||
|
||||
bool NativeWindowViews::IsMenuBarAutoHide() {
|
||||
return menu_bar_autohide_;
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetMenuBarVisibility(bool visible) {
|
||||
if (!menu_bar_ || menu_bar_visible_ == visible)
|
||||
return;
|
||||
|
||||
// Always show the accelerator when the auto-hide menu bar shows.
|
||||
if (menu_bar_autohide_)
|
||||
menu_bar_->SetAcceleratorVisibility(visible);
|
||||
|
||||
menu_bar_visible_ = visible;
|
||||
if (visible) {
|
||||
DCHECK_EQ(child_count(), 1);
|
||||
AddChildView(menu_bar_.get());
|
||||
} else {
|
||||
DCHECK_EQ(child_count(), 2);
|
||||
RemoveChildView(menu_bar_.get());
|
||||
}
|
||||
|
||||
Layout();
|
||||
}
|
||||
|
||||
bool NativeWindowViews::IsMenuBarVisible() {
|
||||
return menu_bar_visible_;
|
||||
}
|
||||
|
||||
gfx::AcceleratedWidget NativeWindowViews::GetAcceleratedWidget() {
|
||||
return GetNativeWindow()->GetHost()->GetAcceleratedWidget();
|
||||
}
|
||||
@@ -582,10 +634,8 @@ void NativeWindowViews::OnWidgetActivationChanged(
|
||||
GetWebContents()->Focus();
|
||||
|
||||
// Hide menu bar when window is blured.
|
||||
if (!active && menu_bar_autohide_ && menu_bar_visible_) {
|
||||
if (!active && menu_bar_autohide_ && menu_bar_visible_)
|
||||
SetMenuBarVisibility(false);
|
||||
Layout();
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowViews::DeleteDelegate() {
|
||||
@@ -657,22 +707,18 @@ views::ClientView* NativeWindowViews::CreateClientView(views::Widget* widget) {
|
||||
views::NonClientFrameView* NativeWindowViews::CreateNonClientFrameView(
|
||||
views::Widget* widget) {
|
||||
#if defined(OS_WIN)
|
||||
if (ui::win::IsAeroGlassEnabled()) {
|
||||
WinFrameView* frame_view = new WinFrameView;
|
||||
frame_view->Init(this, widget);
|
||||
return frame_view;
|
||||
}
|
||||
#elif defined(OS_LINUX)
|
||||
WinFrameView* frame_view = new WinFrameView;
|
||||
frame_view->Init(this, widget);
|
||||
return frame_view;
|
||||
#else
|
||||
if (has_frame_) {
|
||||
return new views::NativeFrameView(widget);
|
||||
} else {
|
||||
FramelessView* frame_view = new FramelessView;
|
||||
FramelessView* frame_view = new FramelessView;
|
||||
frame_view->Init(this, widget);
|
||||
return frame_view;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gfx::ImageSkia NativeWindowViews::GetDevToolsWindowIcon() {
|
||||
@@ -681,10 +727,8 @@ gfx::ImageSkia NativeWindowViews::GetDevToolsWindowIcon() {
|
||||
|
||||
void NativeWindowViews::HandleMouseDown() {
|
||||
// Hide menu bar when web view is clicked.
|
||||
if (menu_bar_autohide_ && menu_bar_visible_) {
|
||||
if (menu_bar_autohide_ && menu_bar_visible_)
|
||||
SetMenuBarVisibility(false);
|
||||
Layout();
|
||||
}
|
||||
}
|
||||
|
||||
void NativeWindowViews::HandleKeyboardEvent(
|
||||
@@ -704,10 +748,8 @@ void NativeWindowViews::HandleKeyboardEvent(
|
||||
if (event.type == blink::WebInputEvent::RawKeyDown && !IsAltKey(event) &&
|
||||
IsAltModifier(event)) {
|
||||
if (!menu_bar_visible_ &&
|
||||
(menu_bar_->GetAcceleratorIndex(event.windowsKeyCode) != -1)) {
|
||||
(menu_bar_->GetAcceleratorIndex(event.windowsKeyCode) != -1))
|
||||
SetMenuBarVisibility(true);
|
||||
Layout();
|
||||
}
|
||||
menu_bar_->ActivateAccelerator(event.windowsKeyCode);
|
||||
return;
|
||||
}
|
||||
@@ -716,8 +758,7 @@ void NativeWindowViews::HandleKeyboardEvent(
|
||||
return;
|
||||
|
||||
// Toggle the menu bar only when a single Alt is released.
|
||||
if (event.type == blink::WebInputEvent::RawKeyDown && IsAltKey(event) &&
|
||||
IsAltModifier(event)) {
|
||||
if (event.type == blink::WebInputEvent::RawKeyDown && IsAltKey(event)) {
|
||||
// When a single Alt is pressed:
|
||||
menu_bar_alt_pressed_ = true;
|
||||
} else if (event.type == blink::WebInputEvent::KeyUp && IsAltKey(event) &&
|
||||
@@ -728,7 +769,6 @@ void NativeWindowViews::HandleKeyboardEvent(
|
||||
// When a single Alt is released right after a Alt is pressed:
|
||||
menu_bar_alt_pressed_ = false;
|
||||
SetMenuBarVisibility(!menu_bar_visible_);
|
||||
Layout();
|
||||
} else {
|
||||
// When any other keys except single Alt have been pressed/released:
|
||||
menu_bar_alt_pressed_ = false;
|
||||
@@ -766,24 +806,6 @@ gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
|
||||
return window_bounds;
|
||||
}
|
||||
|
||||
void NativeWindowViews::SetMenuBarVisibility(bool visible) {
|
||||
if (!menu_bar_)
|
||||
return;
|
||||
|
||||
// Always show the accelerator when the auto-hide menu bar shows.
|
||||
if (menu_bar_autohide_)
|
||||
menu_bar_->SetAcceleratorVisibility(visible);
|
||||
|
||||
menu_bar_visible_ = visible;
|
||||
if (visible) {
|
||||
DCHECK_EQ(child_count(), 1);
|
||||
AddChildView(menu_bar_.get());
|
||||
} else {
|
||||
DCHECK_EQ(child_count(), 2);
|
||||
RemoveChildView(menu_bar_.get());
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
NativeWindow* NativeWindow::Create(content::WebContents* web_contents,
|
||||
const mate::Dictionary& options) {
|
||||
|
||||
@@ -32,47 +32,51 @@ class NativeWindowViews : public NativeWindow,
|
||||
virtual ~NativeWindowViews();
|
||||
|
||||
// NativeWindow:
|
||||
virtual void Close() OVERRIDE;
|
||||
virtual void CloseImmediately() OVERRIDE;
|
||||
virtual void Move(const gfx::Rect& pos) OVERRIDE;
|
||||
virtual void Focus(bool focus) OVERRIDE;
|
||||
virtual bool IsFocused() OVERRIDE;
|
||||
virtual void Show() OVERRIDE;
|
||||
virtual void ShowInactive() OVERRIDE;
|
||||
virtual void Hide() OVERRIDE;
|
||||
virtual bool IsVisible() OVERRIDE;
|
||||
virtual void Maximize() OVERRIDE;
|
||||
virtual void Unmaximize() OVERRIDE;
|
||||
virtual bool IsMaximized() OVERRIDE;
|
||||
virtual void Minimize() OVERRIDE;
|
||||
virtual void Restore() OVERRIDE;
|
||||
virtual bool IsMinimized() OVERRIDE;
|
||||
virtual void SetFullscreen(bool fullscreen) OVERRIDE;
|
||||
virtual bool IsFullscreen() OVERRIDE;
|
||||
virtual void SetSize(const gfx::Size& size) OVERRIDE;
|
||||
virtual gfx::Size GetSize() OVERRIDE;
|
||||
virtual void SetContentSize(const gfx::Size& size) OVERRIDE;
|
||||
virtual gfx::Size GetContentSize() OVERRIDE;
|
||||
virtual void SetMinimumSize(const gfx::Size& size) OVERRIDE;
|
||||
virtual gfx::Size GetMinimumSize() OVERRIDE;
|
||||
virtual void SetMaximumSize(const gfx::Size& size) OVERRIDE;
|
||||
virtual gfx::Size GetMaximumSize() OVERRIDE;
|
||||
virtual void SetResizable(bool resizable) OVERRIDE;
|
||||
virtual bool IsResizable() OVERRIDE;
|
||||
virtual void SetAlwaysOnTop(bool top) OVERRIDE;
|
||||
virtual bool IsAlwaysOnTop() OVERRIDE;
|
||||
virtual void Center() OVERRIDE;
|
||||
virtual void SetPosition(const gfx::Point& position) OVERRIDE;
|
||||
virtual gfx::Point GetPosition() OVERRIDE;
|
||||
virtual void SetTitle(const std::string& title) OVERRIDE;
|
||||
virtual std::string GetTitle() OVERRIDE;
|
||||
virtual void FlashFrame(bool flash) OVERRIDE;
|
||||
virtual void SetSkipTaskbar(bool skip) OVERRIDE;
|
||||
virtual void SetKiosk(bool kiosk) OVERRIDE;
|
||||
virtual bool IsKiosk() OVERRIDE;
|
||||
virtual void SetMenu(ui::MenuModel* menu_model) OVERRIDE;
|
||||
virtual gfx::NativeWindow GetNativeWindow() OVERRIDE;
|
||||
virtual void SetProgressBar(double value) OVERRIDE;
|
||||
void Close() override;
|
||||
void CloseImmediately() override;
|
||||
void Move(const gfx::Rect& pos) override;
|
||||
void Focus(bool focus) override;
|
||||
bool IsFocused() override;
|
||||
void Show() override;
|
||||
void ShowInactive() override;
|
||||
void Hide() override;
|
||||
bool IsVisible() override;
|
||||
void Maximize() override;
|
||||
void Unmaximize() override;
|
||||
bool IsMaximized() override;
|
||||
void Minimize() override;
|
||||
void Restore() override;
|
||||
bool IsMinimized() override;
|
||||
void SetFullscreen(bool fullscreen) override;
|
||||
bool IsFullscreen() override;
|
||||
void SetSize(const gfx::Size& size) override;
|
||||
gfx::Size GetSize() override;
|
||||
void SetContentSize(const gfx::Size& size) override;
|
||||
gfx::Size GetContentSize() override;
|
||||
void SetMinimumSize(const gfx::Size& size) override;
|
||||
gfx::Size GetMinimumSize() override;
|
||||
void SetMaximumSize(const gfx::Size& size) override;
|
||||
gfx::Size GetMaximumSize() override;
|
||||
void SetResizable(bool resizable) override;
|
||||
bool IsResizable() override;
|
||||
void SetAlwaysOnTop(bool top) override;
|
||||
bool IsAlwaysOnTop() override;
|
||||
void Center() override;
|
||||
void SetPosition(const gfx::Point& position) override;
|
||||
gfx::Point GetPosition() override;
|
||||
void SetTitle(const std::string& title) override;
|
||||
std::string GetTitle() override;
|
||||
void FlashFrame(bool flash) override;
|
||||
void SetSkipTaskbar(bool skip) override;
|
||||
void SetKiosk(bool kiosk) override;
|
||||
bool IsKiosk() override;
|
||||
void SetMenu(ui::MenuModel* menu_model) override;
|
||||
gfx::NativeWindow GetNativeWindow() override;
|
||||
void SetProgressBar(double value) override;
|
||||
void SetAutoHideMenuBar(bool auto_hide) override;
|
||||
bool IsMenuBarAutoHide() override;
|
||||
void SetMenuBarVisibility(bool visible) override;
|
||||
bool IsMenuBarVisible() override;
|
||||
|
||||
gfx::AcceleratedWidget GetAcceleratedWidget();
|
||||
|
||||
@@ -81,43 +85,43 @@ class NativeWindowViews : public NativeWindow,
|
||||
|
||||
private:
|
||||
// NativeWindow:
|
||||
virtual void UpdateDraggableRegions(
|
||||
const std::vector<DraggableRegion>& regions) OVERRIDE;
|
||||
void UpdateDraggableRegions(
|
||||
const std::vector<DraggableRegion>& regions) override;
|
||||
|
||||
// views::WidgetObserver:
|
||||
virtual void OnWidgetActivationChanged(
|
||||
views::Widget* widget, bool active) OVERRIDE;
|
||||
void OnWidgetActivationChanged(
|
||||
views::Widget* widget, bool active) override;
|
||||
|
||||
// views::WidgetDelegate:
|
||||
virtual void DeleteDelegate() OVERRIDE;
|
||||
virtual views::View* GetInitiallyFocusedView() OVERRIDE;
|
||||
virtual bool CanResize() const OVERRIDE;
|
||||
virtual bool CanMaximize() const OVERRIDE;
|
||||
virtual base::string16 GetWindowTitle() const OVERRIDE;
|
||||
virtual bool ShouldHandleSystemCommands() const OVERRIDE;
|
||||
virtual gfx::ImageSkia GetWindowAppIcon() OVERRIDE;
|
||||
virtual gfx::ImageSkia GetWindowIcon() OVERRIDE;
|
||||
virtual views::Widget* GetWidget() OVERRIDE;
|
||||
virtual const views::Widget* GetWidget() const OVERRIDE;
|
||||
virtual views::View* GetContentsView() OVERRIDE;
|
||||
virtual bool ShouldDescendIntoChildForEventHandling(
|
||||
void DeleteDelegate() override;
|
||||
views::View* GetInitiallyFocusedView() override;
|
||||
bool CanResize() const override;
|
||||
bool CanMaximize() const override;
|
||||
base::string16 GetWindowTitle() const override;
|
||||
bool ShouldHandleSystemCommands() const override;
|
||||
gfx::ImageSkia GetWindowAppIcon() override;
|
||||
gfx::ImageSkia GetWindowIcon() override;
|
||||
views::Widget* GetWidget() override;
|
||||
const views::Widget* GetWidget() const override;
|
||||
views::View* GetContentsView() override;
|
||||
bool ShouldDescendIntoChildForEventHandling(
|
||||
gfx::NativeView child,
|
||||
const gfx::Point& location) OVERRIDE;
|
||||
virtual views::ClientView* CreateClientView(views::Widget* widget) OVERRIDE;
|
||||
virtual views::NonClientFrameView* CreateNonClientFrameView(
|
||||
views::Widget* widget) OVERRIDE;
|
||||
const gfx::Point& location) override;
|
||||
views::ClientView* CreateClientView(views::Widget* widget) override;
|
||||
views::NonClientFrameView* CreateNonClientFrameView(
|
||||
views::Widget* widget) override;
|
||||
|
||||
// brightray::InspectableWebContentsDelegate:
|
||||
virtual gfx::ImageSkia GetDevToolsWindowIcon() OVERRIDE;
|
||||
gfx::ImageSkia GetDevToolsWindowIcon() override;
|
||||
|
||||
// content::WebContentsDelegate:
|
||||
virtual void HandleMouseDown() OVERRIDE;
|
||||
virtual void HandleKeyboardEvent(
|
||||
void HandleMouseDown() override;
|
||||
void HandleKeyboardEvent(
|
||||
content::WebContents*,
|
||||
const content::NativeWebKeyboardEvent& event) OVERRIDE;
|
||||
const content::NativeWebKeyboardEvent& event) override;
|
||||
|
||||
// views::View:
|
||||
virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
|
||||
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
|
||||
|
||||
// Register accelerators supported by the menu model.
|
||||
void RegisterAccelerators(ui::MenuModel* menu_model);
|
||||
@@ -126,9 +130,6 @@ class NativeWindowViews : public NativeWindow,
|
||||
// in client area we need to substract/add menu bar's height in convertions.
|
||||
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& content_bounds);
|
||||
|
||||
// Show/Hide the menu bar.
|
||||
void SetMenuBarVisibility(bool visible);
|
||||
|
||||
scoped_ptr<views::Widget> window_;
|
||||
views::View* web_view_; // Managed by inspectable_web_contents_.
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>atom.icns</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>0.19.1</string>
|
||||
<string>0.19.3</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.8.0</string>
|
||||
<key>NSMainNibFile</key>
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 0,19,1,0
|
||||
PRODUCTVERSION 0,19,1,0
|
||||
FILEVERSION 0,19,3,0
|
||||
PRODUCTVERSION 0,19,3,0
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -68,12 +68,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Atom-Shell"
|
||||
VALUE "FileVersion", "0.19.1"
|
||||
VALUE "FileVersion", "0.19.3"
|
||||
VALUE "InternalName", "atom.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2013 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "atom.exe"
|
||||
VALUE "ProductName", "Atom-Shell"
|
||||
VALUE "ProductVersion", "0.19.1"
|
||||
VALUE "ProductVersion", "0.19.3"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
|
||||
@@ -39,6 +39,9 @@ class MenuModel;
|
||||
// to the contents of the model after calling this will not be noticed.
|
||||
- (id)initWithModel:(ui::MenuModel*)model;
|
||||
|
||||
// Populate current NSMenu with |model|.
|
||||
- (void)populateWithModel:(ui::MenuModel*)model;
|
||||
|
||||
// Programmatically close the constructed menu.
|
||||
- (void)cancel;
|
||||
|
||||
|
||||
@@ -70,7 +70,8 @@ int EventFlagsFromNSEvent(NSEvent* event) {
|
||||
@synthesize model = model_;
|
||||
|
||||
- (id)init {
|
||||
self = [super init];
|
||||
if ((self = [super init]))
|
||||
[self menu];
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -93,6 +94,22 @@ int EventFlagsFromNSEvent(NSEvent* event) {
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (void)populateWithModel:(ui::MenuModel*)model {
|
||||
if (!menu_)
|
||||
return;
|
||||
|
||||
model_ = model;
|
||||
[menu_ removeAllItems];
|
||||
|
||||
const int count = model->GetItemCount();
|
||||
for (int index = 0; index < count; index++) {
|
||||
if (model->GetTypeAt(index) == ui::MenuModel::TYPE_SEPARATOR)
|
||||
[self addSeparatorToMenu:menu_ atIndex:index];
|
||||
else
|
||||
[self addItemToMenu:menu_ atIndex:index fromModel:model];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cancel {
|
||||
if (isMenuOpen_) {
|
||||
[menu_ cancelTracking];
|
||||
@@ -235,10 +252,13 @@ int EventFlagsFromNSEvent(NSEvent* event) {
|
||||
}
|
||||
|
||||
- (NSMenu*)menu {
|
||||
if (!menu_ && model_) {
|
||||
menu_.reset([[self menuFromModel:model_] retain]);
|
||||
[menu_ setDelegate:self];
|
||||
}
|
||||
if (menu_)
|
||||
return menu_.get();
|
||||
|
||||
menu_.reset([[NSMenu alloc] initWithTitle:@""]);
|
||||
[menu_ setDelegate:self];
|
||||
if (model_)
|
||||
[self populateWithModel:model_];
|
||||
return menu_.get();
|
||||
}
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ class FileDialog {
|
||||
NULL,
|
||||
IID_PPV_ARGS(&folder_item));
|
||||
if (SUCCEEDED(hr))
|
||||
GetPtr()->SetDefaultFolder(folder_item);
|
||||
GetPtr()->SetFolder(folder_item);
|
||||
}
|
||||
|
||||
scoped_ptr<T> dialog_;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "base/callback_forward.h"
|
||||
#include "base/strings/string16.h"
|
||||
|
||||
namespace atom {
|
||||
|
||||
@@ -37,6 +38,10 @@ void ShowMessageBox(NativeWindow* parent_window,
|
||||
const std::string& detail,
|
||||
const MessageBoxCallback& callback);
|
||||
|
||||
// Like ShowMessageBox with simplest settings, but safe to call at very early
|
||||
// stage of application.
|
||||
void ShowErrorBox(const base::string16& title, const base::string16& content);
|
||||
|
||||
} // namespace atom
|
||||
|
||||
#endif // ATOM_BROWSER_UI_MESSAGE_BOX_H_
|
||||
|
||||
@@ -141,4 +141,13 @@ void ShowMessageBox(NativeWindow* parent_window,
|
||||
contextInfo:nil];
|
||||
}
|
||||
|
||||
void ShowErrorBox(const base::string16& title, const base::string16& content) {
|
||||
NSAlert* alert = [[NSAlert alloc] init];
|
||||
[alert setMessageText:base::SysUTF16ToNSString(title)];
|
||||
[alert setInformativeText:base::SysUTF16ToNSString(content)];
|
||||
[alert setAlertStyle:NSWarningAlertStyle];
|
||||
[alert runModal];
|
||||
[alert release];
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
|
||||
#include "atom/browser/ui/message_box.h"
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include <gtk/gtk.h>
|
||||
#endif
|
||||
|
||||
#include "atom/browser/native_window.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
@@ -23,9 +27,20 @@
|
||||
#include "ui/wm/core/shadow_types.h"
|
||||
|
||||
#if defined(USE_X11)
|
||||
#include "atom/browser/browser.h"
|
||||
#include "ui/views/window/native_frame_view.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
#include "ui/base/win/message_box_win.h"
|
||||
#endif
|
||||
|
||||
#define ANSI_FOREGROUND_RED "\x1b[31m"
|
||||
#define ANSI_FOREGROUND_BLACK "\x1b[30m"
|
||||
#define ANSI_TEXT_BOLD "\x1b[1m"
|
||||
#define ANSI_BACKGROUND_GRAY "\x1b[47m"
|
||||
#define ANSI_RESET "\x1b[0m"
|
||||
|
||||
namespace atom {
|
||||
|
||||
namespace {
|
||||
@@ -350,4 +365,29 @@ void ShowMessageBox(NativeWindow* parent_window,
|
||||
dialog->Show();
|
||||
}
|
||||
|
||||
void ShowErrorBox(const base::string16& title, const base::string16& content) {
|
||||
#if defined(OS_WIN)
|
||||
ui::MessageBox(NULL, content, title, MB_OK | MB_ICONERROR | MB_TASKMODAL);
|
||||
#elif defined(USE_X11)
|
||||
if (Browser::Get()->is_ready()) {
|
||||
GtkWidget* dialog = gtk_message_dialog_new(
|
||||
NULL, GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
|
||||
"%s", base::UTF16ToUTF8(title).c_str());
|
||||
gtk_message_dialog_format_secondary_text(
|
||||
GTK_MESSAGE_DIALOG(dialog),
|
||||
"%s", base::UTF16ToUTF8(content).c_str());
|
||||
gtk_dialog_run(GTK_DIALOG(dialog));
|
||||
gtk_widget_destroy(dialog);
|
||||
} else {
|
||||
fprintf(stderr,
|
||||
ANSI_TEXT_BOLD ANSI_BACKGROUND_GRAY
|
||||
ANSI_FOREGROUND_RED "%s\n"
|
||||
ANSI_FOREGROUND_BLACK "%s"
|
||||
ANSI_RESET "\n",
|
||||
base::UTF16ToUTF8(title).c_str(),
|
||||
base::UTF16ToUTF8(content).c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace atom
|
||||
|
||||
@@ -27,21 +27,21 @@ class FramelessView : public views::NonClientFrameView {
|
||||
|
||||
protected:
|
||||
// views::NonClientFrameView:
|
||||
virtual gfx::Rect GetBoundsForClientView() const OVERRIDE;
|
||||
virtual gfx::Rect GetWindowBoundsForClientBounds(
|
||||
const gfx::Rect& client_bounds) const OVERRIDE;
|
||||
virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE;
|
||||
virtual void GetWindowMask(const gfx::Size& size,
|
||||
gfx::Path* window_mask) OVERRIDE;
|
||||
virtual void ResetWindowControls() OVERRIDE;
|
||||
virtual void UpdateWindowIcon() OVERRIDE;
|
||||
virtual void UpdateWindowTitle() OVERRIDE;
|
||||
gfx::Rect GetBoundsForClientView() const override;
|
||||
gfx::Rect GetWindowBoundsForClientBounds(
|
||||
const gfx::Rect& client_bounds) const override;
|
||||
int NonClientHitTest(const gfx::Point& point) override;
|
||||
void GetWindowMask(const gfx::Size& size,
|
||||
gfx::Path* window_mask) override;
|
||||
void ResetWindowControls() override;
|
||||
void UpdateWindowIcon() override;
|
||||
void UpdateWindowTitle() override;
|
||||
|
||||
// Overridden from View:
|
||||
virtual gfx::Size GetPreferredSize() const OVERRIDE;
|
||||
virtual gfx::Size GetMinimumSize() const OVERRIDE;
|
||||
virtual gfx::Size GetMaximumSize() const OVERRIDE;
|
||||
virtual const char* GetClassName() const OVERRIDE;
|
||||
gfx::Size GetPreferredSize() const override;
|
||||
gfx::Size GetMinimumSize() const override;
|
||||
gfx::Size GetMaximumSize() const override;
|
||||
const char* GetClassName() const override;
|
||||
|
||||
// Not owned.
|
||||
NativeWindowViews* window_;
|
||||
|
||||
@@ -51,15 +51,14 @@ class MenuBar : public views::View,
|
||||
|
||||
protected:
|
||||
// views::View:
|
||||
virtual const char* GetClassName() const OVERRIDE;
|
||||
const char* GetClassName() const override;
|
||||
|
||||
// views::ButtonListener:
|
||||
virtual void ButtonPressed(views::Button* sender,
|
||||
const ui::Event& event) OVERRIDE;
|
||||
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
|
||||
|
||||
// views::MenuButtonListener:
|
||||
virtual void OnMenuButtonClicked(views::View* source,
|
||||
const gfx::Point& point) OVERRIDE;
|
||||
void OnMenuButtonClicked(views::View* source,
|
||||
const gfx::Point& point) override;
|
||||
|
||||
private:
|
||||
SkColor background_color_;
|
||||
|
||||
@@ -90,6 +90,10 @@ bool MenuDelegate::IsCommandEnabled(int id) const {
|
||||
return delegate()->IsCommandEnabled(id);
|
||||
}
|
||||
|
||||
bool MenuDelegate::IsCommandVisible(int id) const {
|
||||
return delegate()->IsCommandVisible(id);
|
||||
}
|
||||
|
||||
bool MenuDelegate::IsItemChecked(int id) const {
|
||||
return delegate()->IsItemChecked(id);
|
||||
}
|
||||
|
||||
@@ -30,25 +30,25 @@ class MenuDelegate : public views::MenuDelegate {
|
||||
|
||||
protected:
|
||||
// views::MenuDelegate:
|
||||
virtual void ExecuteCommand(int id) OVERRIDE;
|
||||
virtual void ExecuteCommand(int id, int mouse_event_flags) OVERRIDE;
|
||||
virtual bool IsTriggerableEvent(views::MenuItemView* source,
|
||||
const ui::Event& e) OVERRIDE;
|
||||
virtual bool GetAccelerator(int id,
|
||||
ui::Accelerator* accelerator) const OVERRIDE;
|
||||
virtual base::string16 GetLabel(int id) const OVERRIDE;
|
||||
virtual const gfx::FontList* GetLabelFontList(int id) const OVERRIDE;
|
||||
virtual bool IsCommandEnabled(int id) const OVERRIDE;
|
||||
virtual bool IsItemChecked(int id) const OVERRIDE;
|
||||
virtual void SelectionChanged(views::MenuItemView* menu) OVERRIDE;
|
||||
virtual void WillShowMenu(views::MenuItemView* menu) OVERRIDE;
|
||||
virtual void WillHideMenu(views::MenuItemView* menu) OVERRIDE;
|
||||
virtual views::MenuItemView* GetSiblingMenu(
|
||||
void ExecuteCommand(int id) override;
|
||||
void ExecuteCommand(int id, int mouse_event_flags) override;
|
||||
bool IsTriggerableEvent(views::MenuItemView* source,
|
||||
const ui::Event& e) override;
|
||||
bool GetAccelerator(int id, ui::Accelerator* accelerator) const override;
|
||||
base::string16 GetLabel(int id) const override;
|
||||
const gfx::FontList* GetLabelFontList(int id) const override;
|
||||
bool IsCommandEnabled(int id) const override;
|
||||
bool IsCommandVisible(int id) const override;
|
||||
bool IsItemChecked(int id) const override;
|
||||
void SelectionChanged(views::MenuItemView* menu) override;
|
||||
void WillShowMenu(views::MenuItemView* menu) override;
|
||||
void WillHideMenu(views::MenuItemView* menu) override;
|
||||
views::MenuItemView* GetSiblingMenu(
|
||||
views::MenuItemView* menu,
|
||||
const gfx::Point& screen_point,
|
||||
views::MenuAnchorPosition* anchor,
|
||||
bool* has_mnemonics,
|
||||
views::MenuButton** button);
|
||||
views::MenuButton** button) override;
|
||||
|
||||
private:
|
||||
// Gets the cached menu item view from the model.
|
||||
|
||||
@@ -15,10 +15,10 @@ class MenuLayout : public views::FillLayout {
|
||||
virtual ~MenuLayout();
|
||||
|
||||
// views::LayoutManager:
|
||||
virtual void Layout(views::View* host) OVERRIDE;
|
||||
virtual gfx::Size GetPreferredSize(const views::View* host) const OVERRIDE;
|
||||
virtual int GetPreferredHeightForWidth(
|
||||
const views::View* host, int width) const OVERRIDE;
|
||||
void Layout(views::View* host) override;
|
||||
gfx::Size GetPreferredSize(const views::View* host) const override;
|
||||
int GetPreferredHeightForWidth(
|
||||
const views::View* host, int width) const override;
|
||||
|
||||
private:
|
||||
bool HasMenu(const views::View* host) const;
|
||||
|
||||
@@ -26,7 +26,7 @@ class SubmenuButton : public views::MenuButton {
|
||||
base::char16 accelerator() const { return accelerator_; }
|
||||
|
||||
// views::MenuButton:
|
||||
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;
|
||||
void OnPaint(gfx::Canvas* canvas) override;
|
||||
|
||||
private:
|
||||
bool GetUnderlinePosition(const base::string16& text,
|
||||
|
||||
@@ -15,14 +15,14 @@ class WinFrameView : public FramelessView {
|
||||
virtual ~WinFrameView();
|
||||
|
||||
// views::NonClientFrameView:
|
||||
virtual gfx::Rect GetWindowBoundsForClientBounds(
|
||||
const gfx::Rect& client_bounds) const OVERRIDE;
|
||||
virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE;
|
||||
gfx::Rect GetWindowBoundsForClientBounds(
|
||||
const gfx::Rect& client_bounds) const override;
|
||||
int NonClientHitTest(const gfx::Point& point) override;
|
||||
|
||||
// views::View:
|
||||
virtual gfx::Size GetMinimumSize() const OVERRIDE;
|
||||
virtual gfx::Size GetMaximumSize() const OVERRIDE;
|
||||
virtual const char* GetClassName() const OVERRIDE;
|
||||
gfx::Size GetMinimumSize() const override;
|
||||
gfx::Size GetMaximumSize() const override;
|
||||
const char* GetClassName() const override;
|
||||
|
||||
private:
|
||||
void ClientAreaSizeToWindowSize(gfx::Size* size) const;
|
||||
|
||||
@@ -7,12 +7,14 @@
|
||||
#include "atom/browser/api/atom_api_web_contents.h"
|
||||
#include "atom/browser/atom_browser_context.h"
|
||||
#include "atom/browser/web_view/web_view_renderer_state.h"
|
||||
#include "atom/common/native_mate_converters/gurl_converter.h"
|
||||
#include "base/bind.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
#include "net/base/filename_util.h"
|
||||
|
||||
#include "atom/common/node_includes.h"
|
||||
|
||||
@@ -43,12 +45,15 @@ WebViewManager::~WebViewManager() {
|
||||
void WebViewManager::AddGuest(int guest_instance_id,
|
||||
content::WebContents* embedder,
|
||||
content::WebContents* web_contents,
|
||||
bool node_integration) {
|
||||
bool node_integration,
|
||||
bool plugins,
|
||||
const GURL& preload_url) {
|
||||
web_contents_map_[guest_instance_id] = { web_contents, embedder };
|
||||
|
||||
WebViewRendererState::WebViewInfo web_view_info = {
|
||||
guest_instance_id, node_integration
|
||||
guest_instance_id, node_integration, plugins
|
||||
};
|
||||
net::FileURLToFilePath(preload_url, &web_view_info.preload_script);
|
||||
content::BrowserThread::PostTask(
|
||||
content::BrowserThread::IO,
|
||||
FROM_HERE,
|
||||
|
||||
@@ -23,7 +23,9 @@ class WebViewManager : public content::BrowserPluginGuestManager {
|
||||
void AddGuest(int guest_instance_id,
|
||||
content::WebContents* embedder,
|
||||
content::WebContents* web_contents,
|
||||
bool node_integration);
|
||||
bool node_integration,
|
||||
bool plugins,
|
||||
const GURL& preload_url);
|
||||
void RemoveGuest(int guest_instance_id);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/memory/singleton.h"
|
||||
|
||||
namespace atom {
|
||||
@@ -22,6 +23,8 @@ class WebViewRendererState {
|
||||
struct WebViewInfo {
|
||||
int guest_instance_id;
|
||||
bool node_integration;
|
||||
bool plugins;
|
||||
base::FilePath preload_script;
|
||||
};
|
||||
|
||||
static WebViewRendererState* GetInstance();
|
||||
|
||||
@@ -1,18 +1,21 @@
|
||||
{spawn} = require 'child_process'
|
||||
binding = process.atomBinding 'crash_reporter'
|
||||
fs = require 'fs'
|
||||
os = require 'os'
|
||||
path = require 'path'
|
||||
{spawn} = require 'child_process'
|
||||
|
||||
class CrashReporter
|
||||
start: (options={}) ->
|
||||
{productName, companyName, submitUrl, autoSubmit, ignoreSystemCrashHandler, extra} = options
|
||||
{@productName, companyName, submitUrl, autoSubmit, ignoreSystemCrashHandler, extra} = options
|
||||
|
||||
productName ?= 'Atom-Shell'
|
||||
@productName ?= 'Atom-Shell'
|
||||
companyName ?= 'GitHub, Inc'
|
||||
submitUrl ?= 'http://54.249.141.255:1127/post'
|
||||
autoSubmit ?= true
|
||||
ignoreSystemCrashHandler ?= false
|
||||
extra ?= {}
|
||||
|
||||
extra._productName ?= productName
|
||||
extra._productName ?= @productName
|
||||
extra._companyName ?= companyName
|
||||
extra._version ?=
|
||||
if process.type is 'browser'
|
||||
@@ -20,12 +23,12 @@ class CrashReporter
|
||||
else
|
||||
require('remote').require('app').getVersion()
|
||||
|
||||
start = -> binding.start productName, companyName, submitUrl, autoSubmit, ignoreSystemCrashHandler, extra
|
||||
start = => binding.start @productName, companyName, submitUrl, autoSubmit, ignoreSystemCrashHandler, extra
|
||||
|
||||
if process.platform is 'win32'
|
||||
args = [
|
||||
"--reporter-url=#{submitUrl}"
|
||||
"--application-name=#{productName}"
|
||||
"--application-name=#{@productName}"
|
||||
"--v=1"
|
||||
]
|
||||
env = ATOM_SHELL_INTERNAL_CRASH_SERVICE: 1
|
||||
@@ -35,4 +38,20 @@ class CrashReporter
|
||||
else
|
||||
start()
|
||||
|
||||
module.exports = new CrashReporter
|
||||
getLastCrashReport: ->
|
||||
tmpdir =
|
||||
if process.platform is 'win32'
|
||||
os.tmpdir()
|
||||
else
|
||||
'/tmp'
|
||||
log = path.join tmpdir, "#{@productName} Crashes", 'uploads.log'
|
||||
try
|
||||
reports = String(fs.readFileSync(log)).split('\n')
|
||||
return null unless reports.length > 1
|
||||
[time, id] = reports[reports.length - 2].split ','
|
||||
return {date: new Date(parseInt(time) * 1000), id}
|
||||
catch e
|
||||
return null
|
||||
|
||||
crashRepoter = new CrashReporter
|
||||
module.exports = crashRepoter
|
||||
|
||||
6
atom/common/api/lib/original-fs.coffee
Normal file
6
atom/common/api/lib/original-fs.coffee
Normal file
@@ -0,0 +1,6 @@
|
||||
fs = require 'fs'
|
||||
|
||||
copied = {}
|
||||
copied[k] = v for k, v of fs
|
||||
|
||||
module.exports = copied
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#define ATOM_MAJOR_VERSION 0
|
||||
#define ATOM_MINOR_VERSION 19
|
||||
#define ATOM_PATCH_VERSION 1
|
||||
#define ATOM_PATCH_VERSION 3
|
||||
|
||||
#define ATOM_VERSION_IS_RELEASE 1
|
||||
|
||||
|
||||
@@ -12,11 +12,12 @@
|
||||
|
||||
#include "base/debug/crash_logging.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/files/file_util.h"
|
||||
#include "base/linux_util.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/process/memory.h"
|
||||
#include "base/memory/singleton.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "vendor/breakpad/src/client/linux/handler/exception_handler.h"
|
||||
#include "vendor/breakpad/src/common/linux/linux_libc_support.h"
|
||||
|
||||
@@ -61,7 +62,7 @@ void CrashReporterLinux::InitBreakpad(const std::string& product_name,
|
||||
const std::string& submit_url,
|
||||
bool auto_submit,
|
||||
bool skip_system_crash_handler) {
|
||||
EnableCrashDumping();
|
||||
EnableCrashDumping(product_name);
|
||||
|
||||
crash_keys_.SetKeyValue("prod", "Atom-Shell");
|
||||
crash_keys_.SetKeyValue("ver", version.c_str());
|
||||
@@ -76,11 +77,15 @@ void CrashReporterLinux::SetUploadParameters() {
|
||||
upload_parameters_["platform"] = "linux";
|
||||
}
|
||||
|
||||
void CrashReporterLinux::EnableCrashDumping() {
|
||||
base::FilePath tmp_path("/tmp");
|
||||
PathService::Get(base::DIR_TEMP, &tmp_path);
|
||||
void CrashReporterLinux::EnableCrashDumping(const std::string& product_name) {
|
||||
std::string dump_dir = "/tmp/" + product_name + " Crashes";
|
||||
base::FilePath dumps_path(dump_dir);
|
||||
base::CreateDirectory(dumps_path);
|
||||
|
||||
std::string log_file = base::StringPrintf(
|
||||
"%s/%s", dump_dir.c_str(), "uploads.log");
|
||||
strncpy(g_crash_log_path, log_file.c_str(), sizeof(g_crash_log_path));
|
||||
|
||||
base::FilePath dumps_path(tmp_path);
|
||||
MinidumpDescriptor minidump_descriptor(dumps_path.value());
|
||||
minidump_descriptor.set_size_limit(kMaxMinidumpFileSize);
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ class CrashReporterLinux : public CrashReporter {
|
||||
CrashReporterLinux();
|
||||
virtual ~CrashReporterLinux();
|
||||
|
||||
void EnableCrashDumping();
|
||||
void EnableCrashDumping(const std::string& product_name);
|
||||
|
||||
static bool CrashDone(const google_breakpad::MinidumpDescriptor& minidump,
|
||||
void* context,
|
||||
|
||||
@@ -75,6 +75,10 @@ uint64_t kernel_timeval_to_ms(struct kernel_timeval *tv) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool my_isxdigit(char c) {
|
||||
return (c >= '0' && c <= '9') || ((c | 0x20) >= 'a' && (c | 0x20) <= 'f');
|
||||
}
|
||||
|
||||
size_t LengthWithoutTrailingSpaces(const char* str, size_t len) {
|
||||
while (len > 0 && str[len - 1] == ' ') {
|
||||
len--;
|
||||
@@ -345,13 +349,12 @@ void ExecUploadProcessOrTerminate(const BreakpadInfo& info,
|
||||
kWgetBinary,
|
||||
header,
|
||||
post_file,
|
||||
// TODO(zcbenz): Enabling custom upload url.
|
||||
info.upload_url,
|
||||
"--timeout=60", // Set a timeout so we don't hang forever.
|
||||
"--tries=1", // Don't retry if the upload fails.
|
||||
"--quiet", // Be silent.
|
||||
"-O", // output reply to /dev/null.
|
||||
"/dev/null",
|
||||
"/dev/fd/3",
|
||||
NULL,
|
||||
};
|
||||
static const char msg[] = "Cannot upload crash dump: cannot exec "
|
||||
@@ -361,8 +364,98 @@ void ExecUploadProcessOrTerminate(const BreakpadInfo& info,
|
||||
sys__exit(1);
|
||||
}
|
||||
|
||||
// Runs in the helper process to wait for the upload process running
|
||||
// ExecUploadProcessOrTerminate() to finish. Returns the number of bytes written
|
||||
// to |fd| and save the written contents to |buf|.
|
||||
// |buf| needs to be big enough to hold |bytes_to_read| + 1 characters.
|
||||
size_t WaitForCrashReportUploadProcess(int fd, size_t bytes_to_read,
|
||||
char* buf) {
|
||||
size_t bytes_read = 0;
|
||||
|
||||
// Upload should finish in about 10 seconds. Add a few more 500 ms
|
||||
// internals to account for process startup time.
|
||||
for (size_t wait_count = 0; wait_count < 24; ++wait_count) {
|
||||
struct kernel_pollfd poll_fd;
|
||||
poll_fd.fd = fd;
|
||||
poll_fd.events = POLLIN | POLLPRI | POLLERR;
|
||||
int ret = sys_poll(&poll_fd, 1, 500);
|
||||
if (ret < 0) {
|
||||
// Error
|
||||
break;
|
||||
} else if (ret > 0) {
|
||||
// There is data to read.
|
||||
ssize_t len = HANDLE_EINTR(
|
||||
sys_read(fd, buf + bytes_read, bytes_to_read - bytes_read));
|
||||
if (len < 0)
|
||||
break;
|
||||
bytes_read += len;
|
||||
if (bytes_read == bytes_to_read)
|
||||
break;
|
||||
}
|
||||
// |ret| == 0 -> timed out, continue waiting.
|
||||
// or |bytes_read| < |bytes_to_read| still, keep reading.
|
||||
}
|
||||
buf[bytes_to_read] = 0; // Always NUL terminate the buffer.
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
// |buf| should be |expected_len| + 1 characters in size and NULL terminated.
|
||||
bool IsValidCrashReportId(const char* buf, size_t bytes_read,
|
||||
size_t expected_len) {
|
||||
if (bytes_read != expected_len)
|
||||
return false;
|
||||
for (size_t i = 0; i < bytes_read; ++i) {
|
||||
if (!my_isxdigit(buf[i]) && buf[i] != '-')
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// |buf| should be |expected_len| + 1 characters in size and NULL terminated.
|
||||
void HandleCrashReportId(const char* buf, size_t bytes_read,
|
||||
size_t expected_len) {
|
||||
if (!IsValidCrashReportId(buf, bytes_read, expected_len)) {
|
||||
static const char msg[] = "Failed to get crash dump id.";
|
||||
WriteLog(msg, sizeof(msg) - 1);
|
||||
WriteNewline();
|
||||
|
||||
static const char id_msg[] = "Report Id: ";
|
||||
WriteLog(id_msg, sizeof(id_msg) - 1);
|
||||
WriteLog(buf, bytes_read);
|
||||
WriteNewline();
|
||||
return;
|
||||
}
|
||||
|
||||
// Write crash dump id to stderr.
|
||||
static const char msg[] = "Crash dump id: ";
|
||||
WriteLog(msg, sizeof(msg) - 1);
|
||||
WriteLog(buf, my_strlen(buf));
|
||||
WriteNewline();
|
||||
|
||||
// Write crash dump id to crash log as: seconds_since_epoch,crash_id
|
||||
struct kernel_timeval tv;
|
||||
if (!sys_gettimeofday(&tv, NULL)) {
|
||||
uint64_t time = kernel_timeval_to_ms(&tv) / 1000;
|
||||
char time_str[kUint64StringSize];
|
||||
const unsigned time_len = my_uint64_len(time);
|
||||
my_uint64tos(time_str, time, time_len);
|
||||
|
||||
const int kLogOpenFlags = O_CREAT | O_WRONLY | O_APPEND | O_CLOEXEC;
|
||||
int log_fd = sys_open(g_crash_log_path, kLogOpenFlags, 0600);
|
||||
if (log_fd > 0) {
|
||||
sys_write(log_fd, time_str, time_len);
|
||||
sys_write(log_fd, ",", 1);
|
||||
sys_write(log_fd, buf, my_strlen(buf));
|
||||
sys_write(log_fd, "\n", 1);
|
||||
IGNORE_RET(sys_close(log_fd));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
char g_crash_log_path[256];
|
||||
|
||||
void HandleCrashDump(const BreakpadInfo& info) {
|
||||
int dumpfd;
|
||||
bool keep_fd = false;
|
||||
@@ -616,33 +709,13 @@ void HandleCrashDump(const BreakpadInfo& info) {
|
||||
// Helper process.
|
||||
if (upload_child > 0) {
|
||||
IGNORE_RET(sys_close(fds[1]));
|
||||
char id_buf[17]; // Crash report IDs are expected to be 16 chars.
|
||||
ssize_t len = -1;
|
||||
// Upload should finish in about 10 seconds. Add a few more 500 ms
|
||||
// internals to account for process startup time.
|
||||
for (size_t wait_count = 0; wait_count < 24; ++wait_count) {
|
||||
struct kernel_pollfd poll_fd;
|
||||
poll_fd.fd = fds[0];
|
||||
poll_fd.events = POLLIN | POLLPRI | POLLERR;
|
||||
int ret = sys_poll(&poll_fd, 1, 500);
|
||||
if (ret < 0) {
|
||||
// Error
|
||||
break;
|
||||
} else if (ret > 0) {
|
||||
// There is data to read.
|
||||
len = HANDLE_EINTR(sys_read(fds[0], id_buf, sizeof(id_buf) - 1));
|
||||
break;
|
||||
}
|
||||
// ret == 0 -> timed out, continue waiting.
|
||||
}
|
||||
if (len > 0) {
|
||||
// Write crash dump id to stderr.
|
||||
id_buf[len] = 0;
|
||||
static const char msg[] = "\nCrash dump id: ";
|
||||
WriteLog(msg, sizeof(msg) - 1);
|
||||
WriteLog(id_buf, my_strlen(id_buf));
|
||||
WriteLog("\n", 1);
|
||||
}
|
||||
|
||||
const size_t kCrashIdLength = 36;
|
||||
char id_buf[kCrashIdLength + 1];
|
||||
size_t bytes_read =
|
||||
WaitForCrashReportUploadProcess(fds[0], kCrashIdLength, id_buf);
|
||||
HandleCrashReportId(id_buf, bytes_read, kCrashIdLength);
|
||||
|
||||
if (sys_waitpid(upload_child, NULL, WNOHANG) == 0) {
|
||||
// Upload process is still around, kill it.
|
||||
sys_kill(upload_child, SIGKILL);
|
||||
@@ -666,4 +739,8 @@ size_t WriteLog(const char* buf, size_t nbytes) {
|
||||
return sys_write(2, buf, nbytes);
|
||||
}
|
||||
|
||||
size_t WriteNewline() {
|
||||
return WriteLog("\n", 1);
|
||||
}
|
||||
|
||||
} // namespace crash_reporter
|
||||
|
||||
@@ -32,6 +32,10 @@ struct BreakpadInfo {
|
||||
void HandleCrashDump(const BreakpadInfo& info);
|
||||
|
||||
size_t WriteLog(const char* buf, size_t nbytes);
|
||||
size_t WriteNewline();
|
||||
|
||||
// Global variable storing the path of upload log.
|
||||
extern char g_crash_log_path[256];
|
||||
|
||||
} // namespace crash_reporter
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "base/command_line.h"
|
||||
#include "base/file_util.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/time/time.h"
|
||||
#include "base/win/windows_version.h"
|
||||
#include "vendor/breakpad/src/client/windows/crash_generation/client_info.h"
|
||||
#include "vendor/breakpad/src/client/windows/crash_generation/crash_generation_server.h"
|
||||
@@ -66,6 +68,30 @@ bool WriteCustomInfoToFile(const std::wstring& dump_path, const CrashMap& map) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WriteReportIDToFile(const std::wstring& dump_path,
|
||||
const std::wstring& report_id) {
|
||||
std::wstring file_path(dump_path);
|
||||
size_t last_slash = file_path.rfind(L'\\');
|
||||
if (last_slash == std::wstring::npos)
|
||||
return false;
|
||||
file_path.resize(last_slash);
|
||||
file_path += L"\\uploads.log";
|
||||
|
||||
std::wofstream file(file_path.c_str(),
|
||||
std::ios_base::out | std::ios_base::app | std::ios::binary);
|
||||
if (!file.is_open())
|
||||
return false;
|
||||
|
||||
int64 seconds_since_epoch =
|
||||
(base::Time::Now() - base::Time::UnixEpoch()).InSeconds();
|
||||
std::wstring line = base::Int64ToString16(seconds_since_epoch);
|
||||
line += L',';
|
||||
line += report_id;
|
||||
line += L'\n';
|
||||
file.write(line.c_str(), static_cast<std::streamsize>(line.length()));
|
||||
return true;
|
||||
}
|
||||
|
||||
// The window procedure task is to handle when a) the user logs off.
|
||||
// b) the system shuts down or c) when the user closes the window.
|
||||
LRESULT __stdcall CrashSvcWndProc(HWND hwnd, UINT message,
|
||||
@@ -422,6 +448,7 @@ DWORD CrashService::AsyncSendDump(void* context) {
|
||||
++info->self->requests_sent_;
|
||||
++info->self->requests_handled_;
|
||||
retry_round = 0;
|
||||
WriteReportIDToFile(info->dump_path, report_id);
|
||||
break;
|
||||
case google_breakpad::RESULT_THROTTLED:
|
||||
report_id = L"<throttled>";
|
||||
|
||||
@@ -35,5 +35,8 @@ if process.type is 'browser'
|
||||
global.setTimeout = wrapWithActivateUvLoop timers.setTimeout
|
||||
global.setInterval = wrapWithActivateUvLoop timers.setInterval
|
||||
|
||||
# Initialize the "original-fs" module before asar support is loaded.
|
||||
require 'original-fs'
|
||||
|
||||
# Add support for asar packages.
|
||||
require './asar'
|
||||
|
||||
@@ -66,6 +66,9 @@ const char kEnablePlugins[] = "enable-plugins";
|
||||
// Instancd ID of guest WebContents.
|
||||
const char kGuestInstanceID[] = "guest-instance-id";
|
||||
|
||||
// Script that will be loaded by guest WebContents before other scripts.
|
||||
const char kPreloadScript[] = "preload";
|
||||
|
||||
// Web runtime features.
|
||||
const char kExperimentalFeatures[] = "experimental-features";
|
||||
const char kExperimentalCanvasFeatures[] = "experimental-canvas-features";
|
||||
|
||||
@@ -38,6 +38,7 @@ extern const char kDarkTheme[];
|
||||
extern const char kDirectWrite[];
|
||||
extern const char kEnablePlugins[];
|
||||
extern const char kGuestInstanceID[];
|
||||
extern const char kPreloadScript[];
|
||||
|
||||
extern const char kExperimentalFeatures[];
|
||||
extern const char kExperimentalCanvasFeatures[];
|
||||
|
||||
@@ -31,13 +31,17 @@ for arg in process.argv
|
||||
require('web-frame').setName 'ATOM_SHELL_GUEST_WEB_VIEW'
|
||||
else if arg.indexOf('--node-integration=') == 0
|
||||
nodeIntegration = arg.substr arg.indexOf('=') + 1
|
||||
else if arg.indexOf('--preload=') == 0
|
||||
preloadScript = arg.substr arg.indexOf('=') + 1
|
||||
|
||||
if location.protocol is 'chrome-devtools:'
|
||||
# Override some inspector APIs.
|
||||
require path.join(__dirname, 'inspector')
|
||||
nodeIntegration = 'true'
|
||||
else if location.protocol is 'chrome-extension:'
|
||||
# Add implementations of chrome API.
|
||||
require path.join(__dirname, 'chrome-api')
|
||||
nodeIntegration = 'true'
|
||||
else
|
||||
# Override default web functions.
|
||||
require path.join(__dirname, 'override')
|
||||
@@ -86,3 +90,11 @@ else
|
||||
delete global.process
|
||||
delete global.setImmediate
|
||||
delete global.clearImmediate
|
||||
|
||||
# Load the script specfied by the "preload" attribute.
|
||||
if preloadScript
|
||||
try
|
||||
require preloadScript
|
||||
catch error
|
||||
throw error unless error.code is 'MODULE_NOT_FOUND'
|
||||
console.error "Unable to load preload script #{preloadScript}"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
window.onload = ->
|
||||
# Use menu API to show context menu.
|
||||
InspectorFrontendHost.showContextMenu = (event, items) ->
|
||||
createMenu items, event
|
||||
InspectorFrontendHost.showContextMenuAtPoint = (x, y, items, document) ->
|
||||
createMenu items
|
||||
|
||||
# Use dialog API to override file chooser dialog.
|
||||
WebInspector.createFileSelectorElement = (callback) ->
|
||||
@@ -32,17 +32,19 @@ convertToMenuTemplate = (items) ->
|
||||
label: item.label
|
||||
enabled: item.enabled
|
||||
if item.id?
|
||||
transformed.click = -> WebInspector.contextMenuItemSelected item.id
|
||||
transformed.click = -> InspectorFrontendAPI.contextMenuItemSelected item.id
|
||||
template.push transformed
|
||||
template
|
||||
|
||||
createMenu = (items, event) ->
|
||||
createMenu = (items) ->
|
||||
remote = require 'remote'
|
||||
Menu = remote.require 'menu'
|
||||
|
||||
menu = Menu.buildFromTemplate convertToMenuTemplate(items)
|
||||
menu.popup remote.getCurrentWindow()
|
||||
event.consume true
|
||||
# The menu is expected to show asynchronously.
|
||||
setImmediate ->
|
||||
menu.popup remote.getCurrentWindow()
|
||||
InspectorFrontendAPI.contextMenuCleared()
|
||||
|
||||
showFileChooserDialog = (callback) ->
|
||||
remote = require 'remote'
|
||||
|
||||
@@ -20,6 +20,8 @@ WEB_VIEW_ATTRIBUTE_MINHEIGHT = 'minheight'
|
||||
WEB_VIEW_ATTRIBUTE_MINWIDTH = 'minwidth'
|
||||
WEB_VIEW_ATTRIBUTE_PARTITION = 'partition'
|
||||
WEB_VIEW_ATTRIBUTE_NODEINTEGRATION = 'nodeintegration'
|
||||
WEB_VIEW_ATTRIBUTE_PLUGINS = 'plugins'
|
||||
WEB_VIEW_ATTRIBUTE_PRELOAD = 'preload'
|
||||
AUTO_SIZE_ATTRIBUTES = [
|
||||
WEB_VIEW_ATTRIBUTE_AUTOSIZE,
|
||||
WEB_VIEW_ATTRIBUTE_MAXHEIGHT,
|
||||
@@ -37,6 +39,8 @@ ERROR_MSG_CONTENTWINDOW_NOT_AVAILABLE = '<webview>: ' +
|
||||
'contentWindow is not available at this time. It will become available ' +
|
||||
'when the page has finished loading.'
|
||||
ERROR_MSG_INVALID_PARTITION_ATTRIBUTE = 'Invalid partition attribute.'
|
||||
ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE =
|
||||
'Only "file:" or "asar:" protocol is supported in "preload" attribute.'
|
||||
|
||||
# Represents the state of the storage partition.
|
||||
class Partition
|
||||
@@ -193,6 +197,12 @@ class WebView
|
||||
# No setter.
|
||||
enumerable: true
|
||||
|
||||
@httpreferrer = @webviewNode.getAttribute 'httpreferrer'
|
||||
Object.defineProperty @webviewNode, 'httpreferrer',
|
||||
get: => @httpreferrer
|
||||
set: (value) => @webviewNode.setAttribute 'httpreferrer', value
|
||||
enumerable: true
|
||||
|
||||
# The purpose of this mutation observer is to catch assignment to the src
|
||||
# attribute without any changes to its value. This is useful in the case
|
||||
# where the webview guest has crashed and navigating to the same address
|
||||
@@ -207,7 +217,7 @@ class WebView
|
||||
params =
|
||||
attributes: true,
|
||||
attributeOldValue: true,
|
||||
attributeFilter: ['src', 'partition']
|
||||
attributeFilter: ['src', 'partition', 'httpreferrer']
|
||||
@srcAndPartitionObserver.observe @webviewNode, params
|
||||
|
||||
# This observer monitors mutations to attributes of the <webview> and
|
||||
@@ -241,6 +251,21 @@ class WebView
|
||||
return unless @guestInstanceId
|
||||
|
||||
guestViewInternal.setAllowTransparency @guestInstanceId, @allowtransparency
|
||||
else if name is 'httpreferrer'
|
||||
oldValue ?= ''
|
||||
newValue ?= ''
|
||||
|
||||
if newValue == '' and oldValue != ''
|
||||
@webviewNode.setAttribute 'httpreferrer', oldValue
|
||||
|
||||
@httpreferrer = newValue
|
||||
|
||||
result = {}
|
||||
# If the httpreferrer changes treat it as though the src changes and reload
|
||||
# the page with the new httpreferrer.
|
||||
@parseSrcAttribute result
|
||||
|
||||
throw result.error if result.error?
|
||||
else if name is 'src'
|
||||
# We treat null attribute (attribute removed) and the empty string as
|
||||
# one case.
|
||||
@@ -360,7 +385,8 @@ class WebView
|
||||
return
|
||||
|
||||
# Navigate to |this.src|.
|
||||
remote.getGuestWebContents(@guestInstanceId).loadUrl @src
|
||||
urlOptions = if @httpreferrer then {@httpreferrer} else {}
|
||||
remote.getGuestWebContents(@guestInstanceId).loadUrl @src, urlOptions
|
||||
|
||||
parseAttributes: ->
|
||||
return unless @elementAttached
|
||||
@@ -377,6 +403,18 @@ class WebView
|
||||
params =
|
||||
storagePartitionId: storagePartitionId
|
||||
nodeIntegration: @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_NODEINTEGRATION
|
||||
plugins: @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_PLUGINS
|
||||
if @webviewNode.hasAttribute WEB_VIEW_ATTRIBUTE_PRELOAD
|
||||
preload = @webviewNode.getAttribute WEB_VIEW_ATTRIBUTE_PRELOAD
|
||||
# Get the full path.
|
||||
a = document.createElement 'a'
|
||||
a.href = preload
|
||||
params.preload = a.href
|
||||
# Only support file: or asar: protocol.
|
||||
protocol = params.preload.substr 0, 5
|
||||
unless protocol in ['file:', 'asar:']
|
||||
delete params.preload
|
||||
console.error ERROR_MSG_INVALID_PRELOAD_ATTRIBUTE
|
||||
guestViewInternal.createGuest 'webview', params, (guestInstanceId) =>
|
||||
@pendingGuestCreation = false
|
||||
unless @elementAttached
|
||||
@@ -431,6 +469,7 @@ class WebView
|
||||
# set via this.onAttach().
|
||||
storagePartitionId: @partition.toAttribute()
|
||||
userAgentOverride: @userAgentOverride
|
||||
httpreferrer: @httpreferrer
|
||||
|
||||
attachWindow: (guestInstanceId, isNewWindow) ->
|
||||
@guestInstanceId = guestInstanceId
|
||||
@@ -517,11 +556,12 @@ registerWebViewElement = ->
|
||||
"isCrashed"
|
||||
"setUserAgent"
|
||||
"executeJavaScript"
|
||||
"insertCSS",
|
||||
"openDevTools",
|
||||
"closeDevTools",
|
||||
"isDevToolsOpened",
|
||||
"insertCSS"
|
||||
"openDevTools"
|
||||
"closeDevTools"
|
||||
"isDevToolsOpened"
|
||||
"send"
|
||||
"getId"
|
||||
]
|
||||
|
||||
# Forward proto.foo* method calls to WebView.foo*.
|
||||
|
||||
@@ -4,9 +4,11 @@
|
||||
* [Application distribution](tutorial/application-distribution.md)
|
||||
* [Application packaging](tutorial/application-packaging.md)
|
||||
* [Using native node modules](tutorial/using-native-node-modules.md)
|
||||
* [Desktop environment integration](tutorial/desktop-environment-integration.md)
|
||||
* [Debugging browser process](tutorial/debugging-browser-process.md)
|
||||
* [Using Selenium and WebDriver](tutorial/using-selenium-and-webdriver.md)
|
||||
* [DevTools extension](tutorial/devtools-extension.md)
|
||||
* [Online/offline event detection](tutorial/online-offline-events.md)
|
||||
|
||||
## API references
|
||||
|
||||
@@ -55,3 +57,4 @@ Modules for both sides:
|
||||
* [Build instructions (Mac)](development/build-instructions-mac.md)
|
||||
* [Build instructions (Windows)](development/build-instructions-windows.md)
|
||||
* [Build instructions (Linux)](development/build-instructions-linux.md)
|
||||
* [Setting up symbol server in debugger](development/setting-up-symbol-server.md)
|
||||
|
||||
@@ -123,6 +123,43 @@ preferred over `name` by atom-shell.
|
||||
Resolves the proxy information for `url`, the `callback` would be called with
|
||||
`callback(proxy)` when the request is done.
|
||||
|
||||
## app.addRecentDocument(path)
|
||||
|
||||
* `path` String
|
||||
|
||||
Adds `path` to recent documents list.
|
||||
|
||||
This list is managed by the system, on Windows you can visit the list from task
|
||||
bar, and on Mac you can visit it from dock menu.
|
||||
|
||||
## app.clearRecentDocuments()
|
||||
|
||||
Clears the recent documents list.
|
||||
|
||||
## app.setUserTasks(tasks)
|
||||
|
||||
* `tasks` Array - Array of `Task` objects
|
||||
|
||||
Adds `tasks` to the [Tasks][tasks] category of JumpList on Windows.
|
||||
|
||||
The `tasks` is an array of `Task` objects in following format:
|
||||
|
||||
* `Task` Object
|
||||
* `program` String - Path of the program to execute, usually you should
|
||||
specify `process.execPath` which opens current program
|
||||
* `arguments` String - The arguments of command line when `program` is
|
||||
executed
|
||||
* `title` String - The string to be displayed in a JumpList
|
||||
* `description` String - Description of this task
|
||||
* `iconPath` String - The absolute path to an icon to be displayed in a
|
||||
JumpList, it can be arbitrary resource file that contains an icon, usually
|
||||
you can specify `process.execPath` to show the icon of the program
|
||||
* `iconIndex` Integer - The icon index in the icon file. If an icon file
|
||||
consists of two or more icons, set this value to identify the icon. If an
|
||||
icon file consists of one icon, this value is 0
|
||||
|
||||
**Note:** This API is only available on Windows.
|
||||
|
||||
## app.commandLine.appendSwitch(switch, [value])
|
||||
|
||||
Append a switch [with optional value] to Chromium's command line.
|
||||
@@ -185,3 +222,14 @@ Hides the dock icon.
|
||||
Shows the dock icon.
|
||||
|
||||
**Note:** This API is only available on Mac.
|
||||
|
||||
## app.dock.setMenu(menu)
|
||||
|
||||
* `menu` Menu
|
||||
|
||||
Sets the application [dock menu][dock-menu].
|
||||
|
||||
**Note:** This API is only available on Mac.
|
||||
|
||||
[dock-menu]:https://developer.apple.com/library/mac/documentation/Carbon/Conceptual/customizing_docktile/concepts/dockconcepts.html#//apple_ref/doc/uid/TP30000986-CH2-TPXREF103
|
||||
[tasks]:http://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks
|
||||
|
||||
@@ -41,7 +41,8 @@ You can also create a window without chrome by using
|
||||
* `resizable` Boolean - Whether window is resizable
|
||||
* `always-on-top` Boolean - Whether the window should always stay on top of
|
||||
other windows
|
||||
* `fullscreen` Boolean - Whether the window should show in fullscreen
|
||||
* `fullscreen` Boolean - Whether the window should show in fullscreen, when
|
||||
set to `false` the fullscreen button would also be hidden on OS X
|
||||
* `skip-taskbar` Boolean - Do not show window in taskbar
|
||||
* `zoom-factor` Number - The default zoom factor of the page, zoom factor is
|
||||
zoom percent / 100, so `3.0` represents `300%`
|
||||
@@ -60,7 +61,11 @@ You can also create a window without chrome by using
|
||||
* `enable-larger-than-screen` Boolean - Enable the window to be resized larger
|
||||
than screen.
|
||||
* `dark-theme` Boolean - Forces using dark theme for the window, only works on
|
||||
some GTK+3 desktop environments.
|
||||
some GTK+3 desktop environments
|
||||
* `preload` String - Specifies a script that will be loaded before other
|
||||
scripts run in the window. This script will always have access to node APIs
|
||||
no matter whether node integration is turned on for the window, and the path
|
||||
of `preload` script has to be absolute path.
|
||||
* `web-preferences` Object - Settings of web page's features
|
||||
* `javascript` Boolean
|
||||
* `web-security` Boolean
|
||||
@@ -501,6 +506,31 @@ On Linux platform, only supports Unity desktop environment, you need to specify
|
||||
the `*.desktop` file name to `desktopName` field in `package.json`. By default,
|
||||
it will assume `app.getName().desktop`.
|
||||
|
||||
### BrowserWindow.setAutoHideMenuBar(hide)
|
||||
|
||||
* `hide` Boolean
|
||||
|
||||
Sets whether the window menu bar should hide itself automatically. Once set the
|
||||
menu bar will only show when users press the single `Alt` key.
|
||||
|
||||
If the menu bar is already visible, calling `setAutoHideMenuBar(true)` won't
|
||||
hide it immediately.
|
||||
|
||||
### BrowserWindow.isMenuBarAutoHide()
|
||||
|
||||
Returns whether menu bar automatically hides itself.
|
||||
|
||||
### BrowserWindow.setMenuBarVisibility(visible)
|
||||
|
||||
* `visible` Boolean
|
||||
|
||||
Sets whether the menu bar should be visible. If the menu bar is auto-hide, users
|
||||
can still bring up the menu bar by pressing the single `Alt` key.
|
||||
|
||||
### BrowserWindow.isMenuBarVisible()
|
||||
|
||||
Returns whether the menu bar is visible.
|
||||
|
||||
## Class: WebContents
|
||||
|
||||
A `WebContents` is responsible for rendering and controlling a web page.
|
||||
|
||||
@@ -7,7 +7,7 @@ module is emitted:
|
||||
|
||||
```javascript
|
||||
var app = require('app');
|
||||
app.commandLine.appendSwitch('remote-debugging-port', '88315');
|
||||
app.commandLine.appendSwitch('remote-debugging-port', '8315');
|
||||
app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1');
|
||||
|
||||
app.on('ready', function() {
|
||||
|
||||
@@ -27,6 +27,11 @@ crashReporter.start({
|
||||
* Only string properties are send correctly.
|
||||
* Nested objects are not supported.
|
||||
|
||||
## crashReporter.getLastCrashReport()
|
||||
|
||||
Returns the date and ID of last crash report, when there was no crash report
|
||||
sent or the crash reporter is not started, `null` will be returned.
|
||||
|
||||
# crash-reporter payload
|
||||
|
||||
The crash reporter will send the following data to the `submitUrl` as `POST`:
|
||||
|
||||
@@ -50,7 +50,7 @@ and displays a "loading..." message during the load time:
|
||||
### src
|
||||
|
||||
```html
|
||||
<webview src="http://www.google.com/"></webview>
|
||||
<webview src="https://www.github.com/"></webview>
|
||||
```
|
||||
|
||||
Returns the visible URL. Writing to this attribute initiates top-level
|
||||
@@ -64,7 +64,7 @@ The `src` attribute can also accept data URLs, such as
|
||||
### autosize
|
||||
|
||||
```html
|
||||
<webview src="http://www.google.com/" autosize="on" minwidth="576" minheight="432"></webview>
|
||||
<webview src="https://www.github.com/" autosize="on" minwidth="576" minheight="432"></webview>
|
||||
```
|
||||
|
||||
If "on", the `webview` will container will automatically resize within the
|
||||
@@ -82,6 +82,36 @@ than the minimum values or greater than the maximum.
|
||||
If "on", the guest page in `webview` will have node integration and can use node
|
||||
APIs like `require` and `process` to access low level system resources.
|
||||
|
||||
### plugins
|
||||
|
||||
```html
|
||||
<webview src="https://www.github.com/" plugins></webview>
|
||||
```
|
||||
|
||||
If "on", the guest page in `webview` will be able to use browser plugins.
|
||||
|
||||
### preload
|
||||
|
||||
```html
|
||||
<webview src="https://www.github.com/" preload="./test.js"></webview>
|
||||
```
|
||||
|
||||
Specifies a script that will be loaded before other scripts run in the guest
|
||||
page. The protocol of script's URL must be either `file:` or `asar:`, because it
|
||||
will be loaded by `require` in guest page under the hood.
|
||||
|
||||
When the guest page doesn't have node integration this script will still have
|
||||
access to all Node APIs, but global objects injected by Node will be deleted
|
||||
after this script has done execution.
|
||||
|
||||
### httpreferrer
|
||||
|
||||
```html
|
||||
<webview src="https://www.github.com/" httpreferrer="http://cheng.guru"></webview>
|
||||
```
|
||||
|
||||
Sets the referrer URL for the guest page.
|
||||
|
||||
## Methods
|
||||
|
||||
### `<webview>`.getUrl()
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
On Ubuntu you could install the libraries via:
|
||||
|
||||
```bash
|
||||
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk2.0-dev libnotify-dev gcc-multilib g++-multilib
|
||||
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk2.0-dev libnotify-dev libgnome-keyring-dev libgconf2-dev gcc-multilib g++-multilib
|
||||
```
|
||||
|
||||
Latest Node.js could be installed via ppa:
|
||||
|
||||
@@ -2,15 +2,16 @@
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* Windows 2008 at least
|
||||
* Visual Studio 2013
|
||||
* Windows 7 / Server 2008 R2 or higher
|
||||
* Visual Studio 2013 - [download VS 2013 Community Edition for
|
||||
free](http://www.visualstudio.com/products/visual-studio-community-vs)
|
||||
* [Python 2.7](http://www.python.org/download/releases/2.7/)
|
||||
* 32bit [node.js](http://nodejs.org/)
|
||||
* 32bit [node.js](http://nodejs.org/download/)
|
||||
* [git](http://git-scm.com)
|
||||
|
||||
The instructions below are executed under [cygwin](http://www.cygwin.com),
|
||||
but it's not a requirement, you can also build atom-shell under the Windows
|
||||
command prompt or other terminals.
|
||||
If you don't have a Windows installation at the moment,
|
||||
[modern.ie](https://www.modern.ie/en-us/virtualization-tools#downloads) has
|
||||
timebombed versions of Windows that you can use to build Atom Shell.
|
||||
|
||||
The building of atom-shell is done entirely with command-line scripts, so you
|
||||
can use any editor you like to develop atom-shell, but it also means you can
|
||||
@@ -22,8 +23,8 @@ Studio will come in the future.
|
||||
|
||||
## Getting the code
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/atom/atom-shell.git
|
||||
```powershell
|
||||
git clone https://github.com/atom/atom-shell.git
|
||||
```
|
||||
|
||||
## Bootstrapping
|
||||
@@ -32,23 +33,23 @@ The bootstrap script will download all necessary build dependencies and create
|
||||
build project files. Notice that we're using `ninja` to build atom-shell so
|
||||
there is no Visual Studio project generated.
|
||||
|
||||
```bash
|
||||
$ cd atom-shell
|
||||
$ python script/bootstrap.py
|
||||
```powershell
|
||||
cd atom-shell
|
||||
python script\bootstrap.py
|
||||
```
|
||||
|
||||
## Building
|
||||
|
||||
Build both Release and Debug targets:
|
||||
|
||||
```bash
|
||||
$ python script/build.py
|
||||
```powershell
|
||||
python script\build.py
|
||||
```
|
||||
|
||||
You can also only build the Debug target:
|
||||
|
||||
```bash
|
||||
$ python script/build.py -c Debug
|
||||
```powershell
|
||||
python script\build.py -c Debug
|
||||
```
|
||||
|
||||
After building is done, you can find `atom.exe` under `out\Debug`.
|
||||
@@ -60,8 +61,8 @@ Currently atom-shell can only be built for 32bit target on Windows, support for
|
||||
|
||||
## Tests
|
||||
|
||||
```bash
|
||||
$ python script/test.py
|
||||
```powershell
|
||||
python script\test.py
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
@@ -73,7 +74,7 @@ the `VS2012 Command Prompt` console to execute the build scripts.
|
||||
|
||||
### Assertion failed: ((handle))->activecnt >= 0
|
||||
|
||||
When building under cygwin, you could see `bootstrap.py` failed with following
|
||||
If building under Cygwin, you may see `bootstrap.py` failed with following
|
||||
error:
|
||||
|
||||
```
|
||||
@@ -91,8 +92,8 @@ Traceback (most recent call last):
|
||||
subprocess.CalledProcessError: Command '['npm.cmd', 'install']' returned non-zero exit status 3
|
||||
```
|
||||
|
||||
This is caused by a bug when using cygwin python and win32 node together. The
|
||||
solution is to use the win32 python to execute the bootstrap script (supposing
|
||||
This is caused by a bug when using Cygwin python and Win32 node together. The
|
||||
solution is to use the Win32 python to execute the bootstrap script (supposing
|
||||
you have installed python under `C:\Python27`):
|
||||
|
||||
```bash
|
||||
@@ -102,3 +103,11 @@ you have installed python under `C:\Python27`):
|
||||
### LNK1181: cannot open input file 'kernel32.lib'
|
||||
|
||||
Try reinstalling 32bit node.js.
|
||||
|
||||
### Error: ENOENT, stat 'C:\Users\USERNAME\AppData\Roaming\npm'
|
||||
|
||||
Simply making that directory [should fix the problem](http://stackoverflow.com/a/25095327/102704):
|
||||
|
||||
```powershell
|
||||
mkdir ~\AppData\Roaming\npm
|
||||
```
|
||||
|
||||
56
docs/development/setting-up-symbol-server.md
Normal file
56
docs/development/setting-up-symbol-server.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# Setting up symbol server in debugger
|
||||
|
||||
Debug symbols allow you to have better debugging sessions. They have information
|
||||
about the functions contained in executables and dynamic libraries and provide
|
||||
you with information to get clean call stacks. A Symbol Server allows the
|
||||
debugger to load the correct symbols, binaries and sources automatically without
|
||||
forcing users to download large debugging files. The server functions like
|
||||
[Microsoft's symbol server](http://support.microsoft.com/kb/311503) so the
|
||||
documentation there can be useful.
|
||||
|
||||
Note that because released atom-shell builds are heavily optimized, debugging is
|
||||
not always easy. The debugger will not be able to show you the content of all
|
||||
variables and the execution path can seem strange because of inlining, tail
|
||||
calls, and other compiler optimizations. The only workaround is to build an
|
||||
unoptimized local build.
|
||||
|
||||
The official symbol server URL for atom-shell is
|
||||
http://54.249.141.255:8086/atom-shell/symbols.
|
||||
You cannot visit this URL directly: you must add it to the symbol path of your
|
||||
debugging tool. In the examples below, a local cache directory is used to avoid
|
||||
repeatedly fetching the PDB from the server. Replace `c:\code\symbols` with an
|
||||
appropriate cache directory on your machine.
|
||||
|
||||
## Using the symbol server in Windbg
|
||||
|
||||
The Windbg symbol path is configured with a string value delimited with asterisk
|
||||
characters. To use only the atom-shell symbol server, add the following entry to
|
||||
your symbol path (__note:__ you can replace `c:\code\symbols` with any writable
|
||||
directory on your computer, if you'd prefer a different location for downloaded
|
||||
symbols):
|
||||
|
||||
```
|
||||
SRV*c:\code\symbols\*http://54.249.141.255:8086/atom-shell/symbols
|
||||
```
|
||||
|
||||
Set this string as `_NT_SYMBOL_PATH` in the environment, using the Windbg menus,
|
||||
or by typing the `.sympath` command. If you would like to get symbols from
|
||||
Microsoft's symbol server as well, you should list that first:
|
||||
|
||||
```
|
||||
SRV*c:\code\symbols\*http://msdl.microsoft.com/download/symbols;SRV*c:\code\symbols\*http://54.249.141.255:8086/atom-shell/symbols
|
||||
```
|
||||
|
||||
## Using the symbol server in Visual Studio
|
||||
|
||||
<img src='http://mdn.mozillademos.org/files/733/symbol-server-vc8express-menu.jpg'>
|
||||
<img src='http://mdn.mozillademos.org/files/2497/2005_options.gif'>
|
||||
|
||||
## Troubleshooting: Symbols will not load
|
||||
|
||||
Type the following commands in Windbg to print why symbols are not loading:
|
||||
|
||||
```
|
||||
> !sym noisy
|
||||
> .reload /f chromiumcontent.dll
|
||||
```
|
||||
@@ -95,6 +95,17 @@ var win = new BrowserWindow({width: 800, height: 600});
|
||||
win.loadUrl('asar:/path/to/example.asar/static/index.html');
|
||||
```
|
||||
|
||||
### Treating `asar` archive as normal file
|
||||
|
||||
For some cases like verifying the `asar` archive's checksum, we need to read the
|
||||
content of `asar` archive as file. For this purpose you can use the built-in
|
||||
`original-fs` module which provides original `fs` APIs without `asar` support:
|
||||
|
||||
```javascript
|
||||
var originalFs = require('original-fs');
|
||||
originalFs.readFileSync('/path/to/example.asar');
|
||||
```
|
||||
|
||||
## Limitations on Node API
|
||||
|
||||
Even though we tried hard to make `asar` archives in the Node API work like
|
||||
|
||||
201
docs/tutorial/desktop-environment-integration.md
Normal file
201
docs/tutorial/desktop-environment-integration.md
Normal file
@@ -0,0 +1,201 @@
|
||||
# Desktop environment integration
|
||||
|
||||
Different operating systems provide different features on integrating desktop
|
||||
applications into their desktop environments, for example, on Windows
|
||||
applications can put shortcuts in the JumpList of task bar, and on Mac
|
||||
applications can put a custom menu in the dock menu.
|
||||
|
||||
This guide introduces how to integrate your application into those desktop
|
||||
environments with atom-shell APIs.
|
||||
|
||||
## Recent documents (Windows & OS X)
|
||||
|
||||
Windows and OS X have provided easy access to recent documents opened by the
|
||||
application via JumpList and dock menu.
|
||||
|
||||
__JumpList:__
|
||||
|
||||

|
||||
|
||||
__Application dock menu:__
|
||||
|
||||
<img src="https://cloud.githubusercontent.com/assets/639601/5069610/2aa80758-6e97-11e4-8cfb-c1a414a10774.png" height="353" width="428" >
|
||||
|
||||
To add a file to recent documents, you can use
|
||||
[app.addRecentDocument][addrecentdocument] API:
|
||||
|
||||
```javascript
|
||||
var app = require('app');
|
||||
app.addRecentDocument('/Users/aryastark/github/atom-shell/README.md');
|
||||
```
|
||||
|
||||
And you can use [app.clearRecentDocuments](clearrecentdocuments) API to empty
|
||||
the recent documents list:
|
||||
|
||||
```javascript
|
||||
app.clearRecentDocuments();
|
||||
```
|
||||
|
||||
### Windows notes
|
||||
|
||||
In order to be able to use this feature on Windows, your application has to be
|
||||
registered as handler of the file type of the document, otherwise the file won't
|
||||
appear in JumpList even after you have added it. You can find everything on
|
||||
registering your application in [Application Registration][app-registration].
|
||||
|
||||
When a user clicks a file from JumpList, a new instance of your application will
|
||||
be started with the path of file appended in command line.
|
||||
|
||||
### OS X notes
|
||||
|
||||
When a file is requested from the recent documents menu, the `open-file` event
|
||||
of `app` module would be emitted for it.
|
||||
|
||||
## Custom dock menu (OS X)
|
||||
|
||||
OS X enables developers to specify a custom menu for dock, which usually
|
||||
contains some shortcuts for commonly used features of your application:
|
||||
|
||||
__Dock menu of Terminal.app:__
|
||||
|
||||
<img src="https://cloud.githubusercontent.com/assets/639601/5069962/6032658a-6e9c-11e4-9953-aa84006bdfff.png" height="354" width="341" >
|
||||
|
||||
To set your custom dock menu, you can use the `app.dock.setMenu` API, which is
|
||||
only available on OS X:
|
||||
|
||||
```javascript
|
||||
var app = require('app');
|
||||
var Menu = require('menu');
|
||||
var dockMenu = Menu.buildFromTemplate([
|
||||
{ label: 'New Window', click: function() { console.log('New Window'); } },
|
||||
{ label: 'New Window with Settings', submenu: [
|
||||
{ label: 'Basic' },
|
||||
{ label: 'Pro'},
|
||||
]},
|
||||
{ label: 'New Command...'},
|
||||
]);
|
||||
app.dock.setMenu(dockMenu);
|
||||
```
|
||||
|
||||
## User tasks (Windows)
|
||||
|
||||
On Windows you can specify custom actions in the `Tasks` category of JumpList,
|
||||
as quoted from MSDN:
|
||||
|
||||
> Applications define tasks based on both the program's features and the key
|
||||
> things a user is expected to do with them. Tasks should be context-free, in
|
||||
> that the application does not need to be running for them to work. They
|
||||
> should also be the statistically most common actions that a normal user would
|
||||
> perform in an application, such as compose an email message or open the
|
||||
> calendar in a mail program, create a new document in a word processor, launch
|
||||
> an application in a certain mode, or launch one of its subcommands. An
|
||||
> application should not clutter the menu with advanced features that standard
|
||||
> users won't need or one-time actions such as registration. Do not use tasks
|
||||
> for promotional items such as upgrades or special offers.
|
||||
>
|
||||
> It is strongly recommended that the task list be static. It should remain the
|
||||
> same regardless of the state or status of the application. While it is
|
||||
> possible to vary the list dynamically, you should consider that this could
|
||||
> confuse the user who does not expect that portion of the destination list to
|
||||
> change.
|
||||
|
||||
__Tasks of Internet Explorer:__
|
||||
|
||||

|
||||
|
||||
Unlike the dock menu in OS X which is a real menu, user tasks in Windows work
|
||||
like application shortcuts that when user clicks a task a program would be
|
||||
executed with specified arguments.
|
||||
|
||||
To set user tasks for your application, you can use
|
||||
[app.setUserTasks][setusertaskstasks] API:
|
||||
|
||||
```javascript
|
||||
var app = require('app');
|
||||
app.setUserTasks([
|
||||
{
|
||||
program: process.execPath,
|
||||
arguments: '--new-window',
|
||||
iconPath: process.execPath,
|
||||
iconIndex: 0,
|
||||
title: 'New Window'
|
||||
description: 'Create a new winodw',
|
||||
}
|
||||
]);
|
||||
```
|
||||
|
||||
To clean your tasks list, just call `app.setUserTasks` with empty array:
|
||||
|
||||
```javascript
|
||||
app.setUserTasks([]);
|
||||
```
|
||||
|
||||
The user tasks will still show even after your application closes, so the icon
|
||||
and program path specified for a task should exist until your application is
|
||||
uninstalled.
|
||||
|
||||
## Unity launcher shortcuts (Linux)
|
||||
|
||||
In Unity, you can add custom entries to its launcher via modifying `.desktop`
|
||||
file, see [Adding shortcuts to a launcher][unity-launcher].
|
||||
|
||||
__Launcher shortcuts of Audacious:__
|
||||
|
||||

|
||||
|
||||
## Progress bar in taskbar (Windows & Unity)
|
||||
|
||||
On Windows, a taskbar button can be used to display a progress bar. This enables
|
||||
a window to provide progress information to the user without that user having to
|
||||
switch to the window itself.
|
||||
|
||||
The Unity DE also has a simililar feature that allows you to specify progress
|
||||
bar in the lancher.
|
||||
|
||||
__Progress bar in taskbar button:__
|
||||
|
||||

|
||||
|
||||
__Progress bar in Unity launcher:__
|
||||
|
||||

|
||||
|
||||
To set the progress bar for a Window, you can use the
|
||||
[BrowserWindow.setProgressBar][setprogressbar] API:
|
||||
|
||||
```javascript
|
||||
var window = new BrowserWindow({...});
|
||||
window.setProgresssBar(0.5);
|
||||
```
|
||||
|
||||
## Represented file of window (OS X)
|
||||
|
||||
On OS X a window can set its represented file, so the file's icon can show in
|
||||
title bar, and when users Command-Click or Control-Click on the tile a path
|
||||
popup will show.
|
||||
|
||||
You can also set edited state of a window so the file icon can indicate whether
|
||||
the document in this window has been modified.
|
||||
|
||||
__Represented file popup menu:__
|
||||
|
||||
<img src="https://cloud.githubusercontent.com/assets/639601/5082061/670a949a-6f14-11e4-987a-9aaa04b23c1d.png" height="232" width="663" >
|
||||
|
||||
To set the represented file of window, you can use the
|
||||
[BrowserWindow.setRepresentedFilename][setrepresentedfilename] and
|
||||
[BrowserWindow.setDocumentEdited][setdocumentedited] APIs:
|
||||
|
||||
```javascript
|
||||
var window = new BrowserWindow({...});
|
||||
window.setRepresentedFilename('/etc/passwd');
|
||||
window.setDocumentEdited(true);
|
||||
```
|
||||
|
||||
[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath
|
||||
[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments
|
||||
[setusertaskstasks]: ../api/app.md#appsetusertaskstasks
|
||||
[setprogressbar]: ../api/browser-window.md#browserwindowsetprogressbarprogress
|
||||
[setrepresentedfilename]: ../api/browser-window.md#browserwindowsetrepresentedfilenamefilename
|
||||
[setdocumentedited]: ../api/browser-window.md#browserwindowsetdocumenteditededited
|
||||
[app-registration]: http://msdn.microsoft.com/en-us/library/windows/desktop/ee872121(v=vs.85).aspx
|
||||
[unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher
|
||||
80
docs/tutorial/online-offline-events.md
Normal file
80
docs/tutorial/online-offline-events.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Online/Offline Event Detection
|
||||
|
||||
Online and offline event detection can be implemented in the renderer process
|
||||
using standard HTML5 APIs, as shown in the following example.
|
||||
|
||||
_main.js_
|
||||
|
||||
```javascript
|
||||
var app = require('app');
|
||||
var BrowserWindow = require('browser-window');
|
||||
var onlineStatusWindow;
|
||||
|
||||
app.on('ready', function() {
|
||||
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false });
|
||||
onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html');
|
||||
});
|
||||
```
|
||||
|
||||
_online-status.html_
|
||||
|
||||
```html
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
var alertOnlineStatus = function() {
|
||||
window.alert(navigator.onLine ? 'online' : 'offline');
|
||||
};
|
||||
|
||||
window.addEventListener('online', alertOnlineStatus);
|
||||
window.addEventListener('offline', alertOnlineStatus);
|
||||
|
||||
alertOnlineStatus();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
There may be instances where one wants to respond to these events in the
|
||||
browser process as well. The browser process however does not have a
|
||||
`navigator` object and thus cannot detect these events directly. Using
|
||||
Atom-shell's inter-process communication utilities, the events can be forwarded
|
||||
to the browser process and handled as needed, as shown in the following example.
|
||||
|
||||
_main.js_
|
||||
|
||||
```javascript
|
||||
var app = require('app');
|
||||
var ipc = require('ipc');
|
||||
var BrowserWindow = require('browser-window');
|
||||
var onlineStatusWindow;
|
||||
|
||||
app.on('ready', function() {
|
||||
onlineStatusWindow = new BrowserWindow({ width: 0, height: 0, show: false });
|
||||
onlineStatusWindow.loadUrl('file://' + __dirname + '/online-status.html');
|
||||
});
|
||||
|
||||
ipc.on('online-status-changed', function(event, status) {
|
||||
console.log(status);
|
||||
});
|
||||
```
|
||||
|
||||
_online-status.html_
|
||||
|
||||
```html
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
var ipc = require('ipc');
|
||||
var updateOnlineStatus = function() {
|
||||
ipc.send('online-status-changed', navigator.onLine ? 'online' : 'offline');
|
||||
};
|
||||
|
||||
window.addEventListener('online', updateOnlineStatus);
|
||||
window.addEventListener('offline', updateOnlineStatus);
|
||||
|
||||
updateOnlineStatus();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "atom-shell",
|
||||
"version": "0.19.1",
|
||||
"version": "0.19.3",
|
||||
|
||||
"licenses": [
|
||||
{
|
||||
@@ -10,7 +10,7 @@
|
||||
],
|
||||
|
||||
"devDependencies": {
|
||||
"atom-package-manager": "0.102.0",
|
||||
"atom-package-manager": "0.111.0",
|
||||
"coffee-script": "~1.7.1",
|
||||
"coffeelint": "~1.3.0"
|
||||
},
|
||||
|
||||
@@ -114,7 +114,7 @@ def update_info_plist(version):
|
||||
|
||||
|
||||
def tag_version(version):
|
||||
execute(['git', 'commit', '-a', '-m', 'Bump v{0}.'.format(version)])
|
||||
execute(['git', 'commit', '-a', '-m', 'Bump v{0}'.format(version)])
|
||||
execute(['git', 'tag', 'v{0}'.format(version)])
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||
|
||||
LINUX_DEPS = [
|
||||
'libdbus-1-dev',
|
||||
'libgconf2-dev',
|
||||
'libgnome-keyring-dev',
|
||||
'libgtk2.0-dev',
|
||||
'libnotify-dev',
|
||||
|
||||
@@ -4,7 +4,7 @@ import platform
|
||||
import sys
|
||||
|
||||
BASE_URL = 'https://gh-contractor-zcbenz.s3.amazonaws.com/libchromiumcontent'
|
||||
LIBCHROMIUMCONTENT_COMMIT = '2dfdf169b582e3f051e1fec3dd7df2bc179e1aa6'
|
||||
LIBCHROMIUMCONTENT_COMMIT = 'bb95d5c7958c649bb346d59a13ee0d8f15464304'
|
||||
|
||||
ARCH = {
|
||||
'cygwin': '32bit',
|
||||
|
||||
@@ -183,6 +183,7 @@ def s3put(bucket, access_key, secret_key, prefix, key_prefix, files):
|
||||
'--secret_key', secret_key,
|
||||
'--prefix', prefix,
|
||||
'--key_prefix', key_prefix,
|
||||
'--no_overwrite',
|
||||
'--grant', 'public-read'
|
||||
] + files
|
||||
|
||||
|
||||
43
script/upload-windows-pdb.py
Executable file
43
script/upload-windows-pdb.py
Executable file
@@ -0,0 +1,43 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import glob
|
||||
|
||||
from lib.util import execute, rm_rf, safe_mkdir, s3put, s3_config
|
||||
|
||||
|
||||
SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__)))
|
||||
SYMBOLS_DIR = 'dist\\symbols'
|
||||
DOWNLOAD_DIR = 'vendor\\brightray\\vendor\\download\\libchromiumcontent'
|
||||
PDB_LIST = [
|
||||
'out\\Release\\atom.exe.pdb',
|
||||
DOWNLOAD_DIR + '\\Release\\chromiumcontent.dll.pdb',
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
os.chdir(SOURCE_ROOT)
|
||||
|
||||
rm_rf(SYMBOLS_DIR)
|
||||
safe_mkdir(SYMBOLS_DIR)
|
||||
for pdb in PDB_LIST:
|
||||
run_symstore(pdb, SYMBOLS_DIR, 'AtomShell')
|
||||
|
||||
bucket, access_key, secret_key = s3_config()
|
||||
files = glob.glob(SYMBOLS_DIR + '/*.pdb/*/*.pdb')
|
||||
files = [f.lower() for f in files]
|
||||
upload_symbols(bucket, access_key, secret_key, files)
|
||||
|
||||
|
||||
def run_symstore(pdb, dest, product):
|
||||
execute(['symstore', 'add', '/r', '/f', pdb, '/s', dest, '/t', product])
|
||||
|
||||
|
||||
def upload_symbols(bucket, access_key, secret_key, files):
|
||||
s3put(bucket, access_key, secret_key, SYMBOLS_DIR, 'atom-shell/symbols',
|
||||
files)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
sys.exit(main())
|
||||
@@ -59,19 +59,24 @@ def main():
|
||||
upload_atom_shell(github, release_id,
|
||||
os.path.join(DIST_DIR, CHROMEDRIVER_NAME))
|
||||
|
||||
# Upload node's headers to S3.
|
||||
bucket, access_key, secret_key = s3_config()
|
||||
upload_node(bucket, access_key, secret_key, ATOM_SHELL_VERSION)
|
||||
|
||||
if args.publish_release:
|
||||
# Press the publish button.
|
||||
publish_release(github, release_id)
|
||||
# Upload node's headers to S3.
|
||||
bucket, access_key, secret_key = s3_config()
|
||||
upload_node(bucket, access_key, secret_key, ATOM_SHELL_VERSION)
|
||||
|
||||
# Upload the SHASUMS.txt.
|
||||
execute([sys.executable,
|
||||
os.path.join(SOURCE_ROOT, 'script', 'upload-checksums.py'),
|
||||
'-v', ATOM_SHELL_VERSION])
|
||||
|
||||
# Upload PDBs to Windows symbol server.
|
||||
if TARGET_PLATFORM == 'win32':
|
||||
execute([sys.executable,
|
||||
os.path.join(SOURCE_ROOT, 'script', 'upload-windows-pdb.py')])
|
||||
|
||||
# Press the publish button.
|
||||
publish_release(github, release_id)
|
||||
|
||||
|
||||
def parse_args():
|
||||
parser = argparse.ArgumentParser(description='upload distribution file')
|
||||
|
||||
@@ -136,6 +136,16 @@ describe 'browser-window module', ->
|
||||
assert.equal after[0], size.width
|
||||
assert.equal after[1], size.height
|
||||
|
||||
describe '"preload" options', ->
|
||||
it 'loads the script before other scripts in window', (done) ->
|
||||
preload = path.join fixtures, 'module', 'set-global.js'
|
||||
remote.require('ipc').once 'preload', (event, test) ->
|
||||
assert.equal(test, 'preload')
|
||||
done()
|
||||
w.destroy()
|
||||
w = new BrowserWindow(show: false, width: 400, height: 400, preload: preload)
|
||||
w.loadUrl 'file://' + path.join(fixtures, 'api', 'preload.html')
|
||||
|
||||
describe 'beforeunload handler', ->
|
||||
it 'returning true would not prevent close', (done) ->
|
||||
w.on 'closed', ->
|
||||
|
||||
@@ -32,7 +32,7 @@ describe 'crash-reporter module', ->
|
||||
assert.equal fields['_version'], require('remote').require('app').getVersion()
|
||||
assert files['upload_file_minidump']['name']?
|
||||
|
||||
res.end()
|
||||
res.end('abc-123-def')
|
||||
server.close()
|
||||
done()
|
||||
server.listen 0, '127.0.0.1', ->
|
||||
|
||||
@@ -391,3 +391,17 @@ describe 'asar package', ->
|
||||
ipc.on 'dirname', (event, dirname) ->
|
||||
assert.equal dirname, path.dirname(p)
|
||||
done()
|
||||
|
||||
describe 'original-fs module', ->
|
||||
originalFs = require 'original-fs'
|
||||
|
||||
it 'uses the original fs api', ->
|
||||
changedApis = ['readFile', 'stat', 'lstat', 'realpath', 'exists']
|
||||
unchangedApis = ['read', 'write', 'writeFile', 'close']
|
||||
assert.notStrictEqual fs[api], originalFs[api] for api in changedApis
|
||||
assert.strictEqual fs[api], originalFs[api] for api in unchangedApis
|
||||
|
||||
it 'treats .asar as file', ->
|
||||
file = path.join fixtures, 'asar', 'a.asar'
|
||||
stats = originalFs.statSync file
|
||||
assert stats.isFile()
|
||||
|
||||
9
spec/fixtures/api/preload.html
vendored
Normal file
9
spec/fixtures/api/preload.html
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<body>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
if (!window.test)
|
||||
window.test = 'window'
|
||||
require('ipc').send('preload', window.test);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
1
spec/fixtures/module/preload.js
vendored
Normal file
1
spec/fixtures/module/preload.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
console.log([typeof require, typeof module, typeof process].join(' '));
|
||||
1
spec/fixtures/module/set-global.js
vendored
Normal file
1
spec/fixtures/module/set-global.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
window.test = 'preload';
|
||||
7
spec/fixtures/pages/e.html
vendored
Normal file
7
spec/fixtures/pages/e.html
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
console.log('Window script is loaded before preload script');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
7
spec/fixtures/pages/referrer.html
vendored
Normal file
7
spec/fixtures/pages/referrer.html
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
<script type="text/javascript" charset="utf-8">
|
||||
console.log(document.referrer);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -108,3 +108,11 @@ describe 'node feature', ->
|
||||
client.on 'error', (error) ->
|
||||
assert.equal error.code, 'ECONNREFUSED'
|
||||
done()
|
||||
|
||||
describe 'Buffer', ->
|
||||
it 'can be created from WebKit external string', ->
|
||||
p = document.createElement 'p'
|
||||
p.innerText = '闲云潭影日悠悠,物换星移几度秋'
|
||||
b = new Buffer(p.innerText)
|
||||
assert.equal b.toString(), '闲云潭影日悠悠,物换星移几度秋'
|
||||
assert.equal Buffer.byteLength(p.innerText), 45
|
||||
|
||||
@@ -47,6 +47,29 @@ describe '<webview> tag', ->
|
||||
webview.src = "file://#{fixtures}/pages/d.html"
|
||||
document.body.appendChild webview
|
||||
|
||||
describe 'preload attribute', ->
|
||||
it 'loads the script before other scripts in window', (done) ->
|
||||
listener = (e) ->
|
||||
assert.equal e.message, 'function object object'
|
||||
webview.removeEventListener 'console-message', listener
|
||||
done()
|
||||
webview.addEventListener 'console-message', listener
|
||||
webview.setAttribute 'preload', "#{fixtures}/module/preload.js"
|
||||
webview.src = "file://#{fixtures}/pages/e.html"
|
||||
document.body.appendChild webview
|
||||
|
||||
describe 'httpreferrer attribute', ->
|
||||
it 'sets the referrer url', (done) ->
|
||||
referrer = 'http://github.com/'
|
||||
listener = (e) ->
|
||||
assert.equal e.message, referrer
|
||||
webview.removeEventListener 'console-message', listener
|
||||
done()
|
||||
webview.addEventListener 'console-message', listener
|
||||
webview.setAttribute 'httpreferrer', referrer
|
||||
webview.src = "file://#{fixtures}/pages/referrer.html"
|
||||
document.body.appendChild webview
|
||||
|
||||
describe 'new-window event', ->
|
||||
it 'emits when window.open is called', (done) ->
|
||||
webview.addEventListener 'new-window', (e) ->
|
||||
|
||||
2
vendor/brightray
vendored
2
vendor/brightray
vendored
Submodule vendor/brightray updated: 57022bdad1...ddfebd0632
2
vendor/node
vendored
2
vendor/node
vendored
Submodule vendor/node updated: 94229c71b0...d26950326d
Reference in New Issue
Block a user