From 87b9b0bc31a8b7aa1b69cfbb185188a78c8b67f9 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Sun, 20 Sep 2015 18:45:34 +0800 Subject: [PATCH 01/47] Implement session.setOpenDownloadDialog() API. --- atom/browser/api/atom_api_session.cc | 11 +++++++- atom/browser/api/atom_api_session.h | 2 ++ .../browser/atom_download_manager_delegate.cc | 25 +++++++++++++------ atom/browser/atom_download_manager_delegate.h | 2 ++ 4 files changed, 31 insertions(+), 9 deletions(-) diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index f07ab8b7804..062c7500ef0 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -9,6 +9,7 @@ #include "atom/browser/api/atom_api_cookies.h" #include "atom/browser/atom_browser_context.h" +#include "atom/browser/atom_download_manager_delegate.h" #include "atom/browser/api/atom_api_web_contents.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/gurl_converter.h" @@ -245,7 +246,7 @@ Session::~Session() { } void Session::OnDownloadCreated(content::DownloadManager* manager, - content::DownloadItem* item) { + content::DownloadItem* item) { auto web_contents = item->GetWebContents(); bool prevent_default = Emit("will-download", item, api::WebContents::CreateFrom(isolate(), @@ -305,6 +306,13 @@ void Session::SetDownloadPath(const base::FilePath& path) { prefs::kDownloadDefaultDirectory, path); } +void Session::SetOpenDownloadDialog(bool open_download_dialog) { + AtomDownloadManagerDelegate* delegate = + static_cast( + browser_context()->GetDownloadManagerDelegate()); + delegate->SetOpenDownloadDialog(open_download_dialog); +} + v8::Local Session::Cookies(v8::Isolate* isolate) { if (cookies_.IsEmpty()) { auto handle = atom::api::Cookies::Create(isolate, browser_context()); @@ -321,6 +329,7 @@ mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( .SetMethod("clearStorageData", &Session::ClearStorageData) .SetMethod("setProxy", &Session::SetProxy) .SetMethod("setDownloadPath", &Session::SetDownloadPath) + .SetMethod("setOpenDownloadDialog", &Session::SetOpenDownloadDialog) .SetProperty("cookies", &Session::Cookies); } diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 14406e57af5..2c53cfdac5a 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -43,6 +43,8 @@ class Session: public mate::TrackableObject, AtomBrowserContext* browser_context() const { return browser_context_.get(); } + void SetOpenDownloadDialog(bool open_download_dialog); + protected: explicit Session(AtomBrowserContext* browser_context); ~Session(); diff --git a/atom/browser/atom_download_manager_delegate.cc b/atom/browser/atom_download_manager_delegate.cc index b573a396332..7cc2c171459 100644 --- a/atom/browser/atom_download_manager_delegate.cc +++ b/atom/browser/atom_download_manager_delegate.cc @@ -23,7 +23,8 @@ namespace atom { AtomDownloadManagerDelegate::AtomDownloadManagerDelegate( content::DownloadManager* manager) : download_manager_(manager), - weak_ptr_factory_(this) {} + weak_ptr_factory_(this), + open_download_dialog_(true) {} AtomDownloadManagerDelegate::~AtomDownloadManagerDelegate() { if (download_manager_) { @@ -74,22 +75,30 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated( window = relay->window.get(); file_dialog::Filters filters; - base::FilePath path; - if (!file_dialog::ShowSaveDialog(window, item->GetURL().spec(), default_path, + base::FilePath path = default_path; + if (open_download_dialog_ && + !file_dialog::ShowSaveDialog(window, item->GetURL().spec(), default_path, filters, &path)) { return; } - // Remeber the last selected download directory. - AtomBrowserContext* browser_context = static_cast( - download_manager_->GetBrowserContext()); - browser_context->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory, - path.DirName()); + if (open_download_dialog_) { + // Remeber the last selected download directory. + AtomBrowserContext* browser_context = static_cast( + download_manager_->GetBrowserContext()); + browser_context->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory, + path.DirName()); + } callback.Run(path, content::DownloadItem::TARGET_DISPOSITION_PROMPT, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path); } +void AtomDownloadManagerDelegate::SetOpenDownloadDialog( + bool open_download_dialog) { + open_download_dialog_ = open_download_dialog; +} + void AtomDownloadManagerDelegate::Shutdown() { weak_ptr_factory_.InvalidateWeakPtrs(); download_manager_ = nullptr; diff --git a/atom/browser/atom_download_manager_delegate.h b/atom/browser/atom_download_manager_delegate.h index 2df3a7d45a6..d518e16bcbd 100644 --- a/atom/browser/atom_download_manager_delegate.h +++ b/atom/browser/atom_download_manager_delegate.h @@ -34,6 +34,7 @@ class AtomDownloadManagerDelegate : public content::DownloadManagerDelegate { void OnDownloadPathGenerated(uint32 download_id, const content::DownloadTargetCallback& callback, const base::FilePath& default_path); + void SetOpenDownloadDialog(bool open_download_dialog); // content::DownloadManagerDelegate: void Shutdown() override; @@ -48,6 +49,7 @@ class AtomDownloadManagerDelegate : public content::DownloadManagerDelegate { private: content::DownloadManager* download_manager_; base::WeakPtrFactory weak_ptr_factory_; + bool open_download_dialog_; DISALLOW_COPY_AND_ASSIGN(AtomDownloadManagerDelegate); }; From 5ec74451ef32e91bcb9fabd6df4b35faa8581091 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Sun, 20 Sep 2015 18:56:10 +0800 Subject: [PATCH 02/47] Introduce DownloadItem for supporting more downloading features. --- atom/browser/api/atom_api_download_item.cc | 131 +++++++++++++++++++++ atom/browser/api/atom_api_download_item.h | 59 ++++++++++ atom/browser/api/atom_api_session.cc | 21 +--- atom/browser/api/lib/app.coffee | 8 ++ atom/common/node_bindings.cc | 1 + filenames.gypi | 2 + 6 files changed, 206 insertions(+), 16 deletions(-) create mode 100644 atom/browser/api/atom_api_download_item.cc create mode 100644 atom/browser/api/atom_api_download_item.h diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc new file mode 100644 index 00000000000..aa1e719f485 --- /dev/null +++ b/atom/browser/api/atom_api_download_item.cc @@ -0,0 +1,131 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/api/atom_api_download_item.h" + +#include "atom/common/native_mate_converters/callback.h" +#include "atom/common/native_mate_converters/gurl_converter.h" +#include "atom/common/node_includes.h" +#include "native_mate/dictionary.h" + +namespace atom { + +namespace api { + +namespace { +// The wrapDownloadItem funtion which is implemented in JavaScript +using WrapDownloadItemCallback = base::Callback)>; +WrapDownloadItemCallback g_wrap_download_item; +} // namespace + +DownloadItem::DownloadItem(content::DownloadItem* download_item) : + download_item_(download_item) { + download_item_->AddObserver(this); +} + +DownloadItem::~DownloadItem() { + download_item_->RemoveObserver(this); +} + +void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) { + if (download_item_ == item) + download_item_->IsDone() ? Emit("completed") : Emit("updated"); +} + +void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download) { + if (download_item_ == download) { + download_item_->RemoveObserver(this); + } +} + +bool DownloadItem::IsDestroyed() const { + return download_item_ == nullptr; +}; + +void DownloadItem::Destroy() { + download_item_ = nullptr; +}; + +int64 DownloadItem::GetReceivedBytes() { + return download_item_->GetReceivedBytes(); +} + +int64 DownloadItem::GetTotalBytes() { + return download_item_->GetTotalBytes(); +} + +const GURL& DownloadItem::GetURL() { + return download_item_->GetURL(); +} + +std::string DownloadItem::GetMimeType() { + return download_item_->GetMimeType(); +} + +bool DownloadItem::HasUserGesture() { + return download_item_->HasUserGesture(); +} + +std::string DownloadItem::GetSuggestedFilename() { + return download_item_->GetSuggestedFilename(); +} + +void DownloadItem::Pause() { + download_item_->Pause(); +} + +void DownloadItem::Resume() { + download_item_->Resume(); +} + +void DownloadItem::Cancel() { + download_item_->Cancel(true); +} + +mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder( + v8::Isolate* isolate) { + return mate::ObjectTemplateBuilder(isolate) + .SetMethod("pause", &DownloadItem::Pause) + .SetMethod("resume", &DownloadItem::Resume) + .SetMethod("cancel", &DownloadItem::Cancel) + .SetMethod("getReceiveBytes", &DownloadItem::GetReceivedBytes) + .SetMethod("getTotalBytes", &DownloadItem::GetTotalBytes) + .SetMethod("getURL", &DownloadItem::GetURL) + .SetMethod("getMimeType", &DownloadItem::GetMimeType) + .SetMethod("hasUserGesture", &DownloadItem::HasUserGesture) + .SetMethod("getSuggestedFilename", &DownloadItem::GetSuggestedFilename); +} + +void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) { + g_wrap_download_item = callback; +} + +void ClearWrapDownloadItem() { + g_wrap_download_item.Reset(); +} + +mate::Handle DownloadItem::Create( + v8::Isolate* isolate, content::DownloadItem* item) { + auto handle = mate::CreateHandle(isolate, new DownloadItem(item)); + g_wrap_download_item.Run(handle.ToV8()); + return handle; +} + +} // namespace api + +} // namespace atom + +namespace { + +void Initialize(v8::Local exports, v8::Local unused, + v8::Local context, void* priv) { + v8::Isolate* isolate = context->GetIsolate(); + mate::Dictionary dict(isolate, exports); + dict.SetMethod("_setWrapDownloadItem", &atom::api::SetWrapDownloadItem); + dict.SetMethod("_clearWrapDownloadItem", &atom::api::ClearWrapDownloadItem); +} + +} // namespace + +NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_browser_download_item, Initialize); diff --git a/atom/browser/api/atom_api_download_item.h b/atom/browser/api/atom_api_download_item.h new file mode 100644 index 00000000000..31546c1c62f --- /dev/null +++ b/atom/browser/api/atom_api_download_item.h @@ -0,0 +1,59 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_ +#define ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_ + +#include + +#include "atom/browser/api/trackable_object.h" +#include "content/public/browser/download_item.h" +#include "native_mate/handle.h" +#include "url/gurl.h" + +namespace atom { + +namespace api { + +class DownloadItem : public mate::TrackableObject, + public content::DownloadItem::Observer { + public: + DownloadItem(content::DownloadItem* download_item); + ~DownloadItem(); + static mate::Handle Create(v8::Isolate* isolate, + content::DownloadItem* item); + + // Override content::DownloadItem::Observer methods + void OnDownloadUpdated(content::DownloadItem* download) override; + void OnDownloadDestroyed(content::DownloadItem* download) override; + + void Pause(); + void Resume(); + void Cancel(); + int64 GetReceivedBytes(); + int64 GetTotalBytes(); + std::string GetMimeType(); + bool HasUserGesture(); + std::string GetSuggestedFilename(); + const GURL& GetURL(); + + private: + // mate::Wrappable: + mate::ObjectTemplateBuilder GetObjectTemplateBuilder( + v8::Isolate* isolate) override; + bool IsDestroyed() const override; + + // mate::TrackableObject: + void Destroy() override; + + content::DownloadItem* download_item_; + + DISALLOW_COPY_AND_ASSIGN(DownloadItem); +}; + +} // namespace api + +} // namespace atom + +#endif // ATOM_BROWSER_API_ATOM_API_DOWNLOAD_ITEM_H_ diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 062c7500ef0..27e52e112ed 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -8,6 +8,7 @@ #include #include "atom/browser/api/atom_api_cookies.h" +#include "atom/browser/api/atom_api_download_item.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/atom_download_manager_delegate.h" #include "atom/browser/api/atom_api_web_contents.h" @@ -102,19 +103,6 @@ struct Converter { } }; -template<> -struct Converter { - static v8::Local ToV8(v8::Isolate* isolate, - content::DownloadItem* val) { - mate::Dictionary dict(isolate, v8::Object::New(isolate)); - dict.Set("url", val->GetURL()); - dict.Set("filename", val->GetSuggestedFilename()); - dict.Set("mimeType", val->GetMimeType()); - dict.Set("hasUserGesture", val->HasUserGesture()); - return dict.GetHandle(); - } -}; - } // namespace mate namespace atom { @@ -248,9 +236,10 @@ Session::~Session() { void Session::OnDownloadCreated(content::DownloadManager* manager, content::DownloadItem* item) { auto web_contents = item->GetWebContents(); - bool prevent_default = Emit("will-download", item, - api::WebContents::CreateFrom(isolate(), - web_contents)); + bool prevent_default = Emit( + "will-download", + DownloadItem::Create(isolate(), item), + api::WebContents::CreateFrom(isolate(), web_contents)); if (prevent_default) { item->Cancel(true); item->Remove(); diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index f5b137eb0bb..39f6395560a 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -2,6 +2,7 @@ EventEmitter = require('events').EventEmitter bindings = process.atomBinding 'app' sessionBindings = process.atomBinding 'session' +downloadItemBindings = process.atomBinding 'download_item' app = bindings.app app.__proto__ = EventEmitter.prototype @@ -10,6 +11,10 @@ wrapSession = (session) -> # session is an Event Emitter. session.__proto__ = EventEmitter.prototype +wrapDownloadItem = (download_item) -> + # download_item is an Event Emitter. + download_item.__proto__ = EventEmitter.prototype + app.setApplicationMenu = (menu) -> require('menu').setApplicationMenu menu @@ -51,5 +56,8 @@ app.on 'activate', (event, hasVisibleWindows) -> @emit 'activate-with-no-open-wi sessionBindings._setWrapSession wrapSession process.once 'exit', sessionBindings._clearWrapSession +downloadItemBindings._setWrapDownloadItem wrapDownloadItem +process.once 'exit', downloadItemBindings._clearWrapDownloadItem + # Only one App object pemitted. module.exports = app diff --git a/atom/common/node_bindings.cc b/atom/common/node_bindings.cc index 5aec200550a..2da68854ad1 100644 --- a/atom/common/node_bindings.cc +++ b/atom/common/node_bindings.cc @@ -34,6 +34,7 @@ REFERENCE_MODULE(atom_browser_app); REFERENCE_MODULE(atom_browser_auto_updater); REFERENCE_MODULE(atom_browser_content_tracing); REFERENCE_MODULE(atom_browser_dialog); +REFERENCE_MODULE(atom_browser_download_item); REFERENCE_MODULE(atom_browser_menu); REFERENCE_MODULE(atom_browser_power_monitor); REFERENCE_MODULE(atom_browser_power_save_blocker); diff --git a/filenames.gypi b/filenames.gypi index 461c812753c..3f40436380c 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -71,6 +71,8 @@ 'atom/browser/api/atom_api_content_tracing.cc', 'atom/browser/api/atom_api_cookies.cc', 'atom/browser/api/atom_api_cookies.h', + 'atom/browser/api/atom_api_download_item.cc', + 'atom/browser/api/atom_api_download_item.h', 'atom/browser/api/atom_api_dialog.cc', 'atom/browser/api/atom_api_global_shortcut.cc', 'atom/browser/api/atom_api_global_shortcut.h', From dd3813170466b77a5168ba82b804eeaf6db60c1a Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Sun, 20 Sep 2015 19:08:31 +0800 Subject: [PATCH 03/47] :memo: Add DownloadItem doc. --- docs/api/download-item.md | 83 +++++++++++++++++++++++++++++++++++++++ docs/api/session.md | 15 ++++--- 2 files changed, 92 insertions(+), 6 deletions(-) create mode 100644 docs/api/download-item.md diff --git a/docs/api/download-item.md b/docs/api/download-item.md new file mode 100644 index 00000000000..eacff629467 --- /dev/null +++ b/docs/api/download-item.md @@ -0,0 +1,83 @@ +# DownloadItem + +`DownloadItem` is an EventEmitter represents a download item in Electron. It +is used in `will-download` event of `Session` module, and allows users to +control the download item. + +```javascript +// Disable showing the download saving dialog. +win.webContents.session.setOpenDownloadDialog(false); + +win.webContents.session.on('will-download', function(event, item, webContents) { + console.log("Download from " + item.getURL()); + console.log(item.getMimeType()); + console.log(item.getSuggestedFilename()); + console.log(item.getTotalBytes()); + item.on('updated', function() { + console.log('Recived bytes: ' + item.getReceiveBytes()); + }); + item.on('completed', function() { + if (item.getReceiveBytes() >= item.getTotalBytes()) { + console.log("Download successfully"); + } else { + console.log("Download is cancelled or interrupted that can't be resumed"); + } + }); +``` + + +## Events + +### Event: 'updated' + +Emits when the `downloadItem` gets updated. + +### Event: 'completed' + +Emits when the download is in a terminal state. This includes a completed +download, a cancelled download(via `downloadItem.cancel()`), and interrputed +download that can't be resumed. + +## Methods + +The `downloadItem` object has the following methods: + +### `downloadItem.pause()` + +Pauses the download. + +### `downloadItem.resume()` + +Resumes the download that has been paused. + +### `downloadItem.cancel()` + +Cancels the download operation. + +### `downloadItem.getURL()` + +Returns a `String` represents the origin url where the item is downloaded from. + +### `downloadItem.getMimeType()` + +Returns a `String` represents the mime type. + +### `downloadItem.hasUserGesture()` + +Returns a `Boolean` indicates whether the download has user gesture. + +### `downloadItem.getSuggestedFilename()` + +Returns a `String` represents the suggested file name of the download file. + +**Note:** The suggested file name is not always the same as the actual one saved +in local disk. If user changes the file name in a prompted download saving +dialog, the actual name of saved file will be different with the suggested one. + +### `downloadItem.getTotalBytes()` + +Returns a `Integer` represents the total size in bytes of the download item. + +### `downloadItem.getReceivedBytes()` + +Returns a `Integer` represents the received bytes of the download item. diff --git a/docs/api/session.md b/docs/api/session.md index 439cf8514e9..2219cf3bebb 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -18,11 +18,7 @@ var session = win.webContents.session ### Event: 'will-download' * `event` Event -* `item` Object - * `url` String - * `filename` String - * `mimeType` String - * `hasUserGesture` Boolean +* `item` [DownloadItem](download-item.md) * `webContents` [WebContents](web-contents.md) Fired when Electron is about to download `item` in `webContents`. @@ -32,7 +28,7 @@ Calling `event.preventDefault()` will cancel the download. ```javascript session.on('will-download', function(event, item, webContents) { event.preventDefault(); - require('request')(item.url, function(data) { + require('request')(item.getURL(), function(data) { require('fs').writeFileSync('/somewhere', data); }); }); @@ -195,3 +191,10 @@ proxy-uri = ["://"][":"] Sets download saving directory. By default, the download directory will be the `Downloads` under the respective app folder. + +### `session.setOpenDownloadDialog(openDownloadDialog)` + +* `openDownloadDialog` Boolean - Whether a download saving dialog will be + prompted when the download starts. + +By default, the download saving dialog is enable in Electron. From d0ee30101dbbf6f192966ce163e9fc2c05385e62 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Sun, 20 Sep 2015 19:28:33 +0800 Subject: [PATCH 04/47] Fix cpplint warnings. --- atom/browser/api/atom_api_download_item.cc | 4 ++-- atom/browser/api/atom_api_download_item.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc index aa1e719f485..2e3068a5d3c 100644 --- a/atom/browser/api/atom_api_download_item.cc +++ b/atom/browser/api/atom_api_download_item.cc @@ -41,11 +41,11 @@ void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download) { bool DownloadItem::IsDestroyed() const { return download_item_ == nullptr; -}; +} void DownloadItem::Destroy() { download_item_ = nullptr; -}; +} int64 DownloadItem::GetReceivedBytes() { return download_item_->GetReceivedBytes(); diff --git a/atom/browser/api/atom_api_download_item.h b/atom/browser/api/atom_api_download_item.h index 31546c1c62f..ca87a14ae80 100644 --- a/atom/browser/api/atom_api_download_item.h +++ b/atom/browser/api/atom_api_download_item.h @@ -19,7 +19,7 @@ namespace api { class DownloadItem : public mate::TrackableObject, public content::DownloadItem::Observer { public: - DownloadItem(content::DownloadItem* download_item); + explicit DownloadItem(content::DownloadItem* download_item); ~DownloadItem(); static mate::Handle Create(v8::Isolate* isolate, content::DownloadItem* item); From 4391e81dfeae7a5aa9cc45cb53174fe0f8626c3d Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 21 Sep 2015 09:38:06 +0800 Subject: [PATCH 05/47] Keep compatibility with old APIs. --- atom/browser/api/lib/app.coffee | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index 39f6395560a..3bf85c59051 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -14,6 +14,11 @@ wrapSession = (session) -> wrapDownloadItem = (download_item) -> # download_item is an Event Emitter. download_item.__proto__ = EventEmitter.prototype + # Be compatible with old APIs. + download_item.url = download_item.getURL() + download_item.filename = download_item.getSuggestedFilename() + download_item.mimeType = download_item.getMimeType() + download_item.hasUserGesture = download_item.hasUserGesture() app.setApplicationMenu = (menu) -> require('menu').setApplicationMenu menu From 997ac91fe03b3ed2a3bd133bb27e6ce8151b4498 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 21 Sep 2015 09:38:38 +0800 Subject: [PATCH 06/47] Add `donwloadItem.getContentDisposition()` API. --- atom/browser/api/atom_api_download_item.cc | 7 ++++++- atom/browser/api/atom_api_download_item.h | 1 + docs/api/download-item.md | 5 +++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc index 2e3068a5d3c..b056695a20b 100644 --- a/atom/browser/api/atom_api_download_item.cc +++ b/atom/browser/api/atom_api_download_item.cc @@ -71,6 +71,10 @@ std::string DownloadItem::GetSuggestedFilename() { return download_item_->GetSuggestedFilename(); } +std::string DownloadItem::GetContentDisposition() { + return download_item_->GetContentDisposition(); +} + void DownloadItem::Pause() { download_item_->Pause(); } @@ -94,7 +98,8 @@ mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder( .SetMethod("getURL", &DownloadItem::GetURL) .SetMethod("getMimeType", &DownloadItem::GetMimeType) .SetMethod("hasUserGesture", &DownloadItem::HasUserGesture) - .SetMethod("getSuggestedFilename", &DownloadItem::GetSuggestedFilename); + .SetMethod("getSuggestedFilename", &DownloadItem::GetSuggestedFilename) + .SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition); } void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) { diff --git a/atom/browser/api/atom_api_download_item.h b/atom/browser/api/atom_api_download_item.h index ca87a14ae80..e12064c825e 100644 --- a/atom/browser/api/atom_api_download_item.h +++ b/atom/browser/api/atom_api_download_item.h @@ -36,6 +36,7 @@ class DownloadItem : public mate::TrackableObject, std::string GetMimeType(); bool HasUserGesture(); std::string GetSuggestedFilename(); + std::string GetContentDisposition(); const GURL& GetURL(); private: diff --git a/docs/api/download-item.md b/docs/api/download-item.md index eacff629467..afbc4aea364 100644 --- a/docs/api/download-item.md +++ b/docs/api/download-item.md @@ -81,3 +81,8 @@ Returns a `Integer` represents the total size in bytes of the download item. ### `downloadItem.getReceivedBytes()` Returns a `Integer` represents the received bytes of the download item. + +### `downloadItem.getContentDisposition()` + +Returns a `String` represents the Content-Disposition field from the response +header. From 57bf0cb615ec27482154e9742cf6284d27c9262a Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 21 Sep 2015 13:45:42 +0800 Subject: [PATCH 07/47] Refractor in `completed` event in DownloadItem. * Rename `completed` to `done`, making it align with Chromium's style. * Add 'state' in `done` event's result. It can check the download item final status: cancelled, completed, interrupted. --- atom/browser/api/atom_api_download_item.cc | 32 ++++++++++++++++++++-- docs/api/download-item.md | 13 +++++++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc index b056695a20b..6c6bb4dae9d 100644 --- a/atom/browser/api/atom_api_download_item.cc +++ b/atom/browser/api/atom_api_download_item.cc @@ -9,6 +9,32 @@ #include "atom/common/node_includes.h" #include "native_mate/dictionary.h" +namespace mate { + +template<> +struct Converter { + static v8::Local ToV8(v8::Isolate* isolate, + content::DownloadItem::DownloadState state) { + std::string download_state; + switch (state) { + case content::DownloadItem::COMPLETE: + download_state = "completed"; + break; + case content::DownloadItem::CANCELLED: + download_state = "cancelled"; + break; + case content::DownloadItem::INTERRUPTED: + download_state = "interrputed"; + break; + default: + break; + } + return ConvertToV8(isolate, download_state); + } +}; + +} // namespace mate + namespace atom { namespace api { @@ -29,8 +55,10 @@ DownloadItem::~DownloadItem() { } void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) { - if (download_item_ == item) - download_item_->IsDone() ? Emit("completed") : Emit("updated"); + if (download_item_ == item) { + download_item_->IsDone() ? + Emit("done", item->GetState()) : Emit("updated"); + } } void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download) { diff --git a/docs/api/download-item.md b/docs/api/download-item.md index afbc4aea364..7b496dbc2b1 100644 --- a/docs/api/download-item.md +++ b/docs/api/download-item.md @@ -16,8 +16,8 @@ win.webContents.session.on('will-download', function(event, item, webContents) { item.on('updated', function() { console.log('Recived bytes: ' + item.getReceiveBytes()); }); - item.on('completed', function() { - if (item.getReceiveBytes() >= item.getTotalBytes()) { + item.on('done', function(e, state) { + if (state == "completed") { console.log("Download successfully"); } else { console.log("Download is cancelled or interrupted that can't be resumed"); @@ -32,7 +32,13 @@ win.webContents.session.on('will-download', function(event, item, webContents) { Emits when the `downloadItem` gets updated. -### Event: 'completed' +### Event: 'done' + +* `event` Event +* `state` String + * `completed` - The download completed successfully. + * `cancelled` - The download has been cancelled. + * `interrupted` - An error broke the connection with the file server. Emits when the download is in a terminal state. This includes a completed download, a cancelled download(via `downloadItem.cancel()`), and interrputed @@ -77,6 +83,7 @@ dialog, the actual name of saved file will be different with the suggested one. ### `downloadItem.getTotalBytes()` Returns a `Integer` represents the total size in bytes of the download item. +If the size is unknown, it returns 0. ### `downloadItem.getReceivedBytes()` From 22168bc6d841ff4bfec73718ce058fdf09ef3289 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 21 Sep 2015 14:03:36 +0800 Subject: [PATCH 08/47] Allow emitting 'done' event when user cancel the download saving dialog. --- .../browser/atom_download_manager_delegate.cc | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/atom/browser/atom_download_manager_delegate.cc b/atom/browser/atom_download_manager_delegate.cc index 7cc2c171459..88daec2f462 100644 --- a/atom/browser/atom_download_manager_delegate.cc +++ b/atom/browser/atom_download_manager_delegate.cc @@ -75,20 +75,24 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated( window = relay->window.get(); file_dialog::Filters filters; - base::FilePath path = default_path; - if (open_download_dialog_ && - !file_dialog::ShowSaveDialog(window, item->GetURL().spec(), default_path, - filters, &path)) { - return; + base::FilePath path; + if (!open_download_dialog_) { + // Use default_path if download dialog is disabled. + path = default_path; + } else { + if (file_dialog::ShowSaveDialog(window, item->GetURL().spec(), default_path, + filters, &path)) { + // Remember the last selected download directory. + AtomBrowserContext* browser_context = static_cast( + download_manager_->GetBrowserContext()); + browser_context->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory, + path.DirName()); + } } - if (open_download_dialog_) { - // Remeber the last selected download directory. - AtomBrowserContext* browser_context = static_cast( - download_manager_->GetBrowserContext()); - browser_context->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory, - path.DirName()); - } + // Running the DownloadTargetCallback with an empty FilePath signals that the + // download should be cancelled. + // If user cancels the file save dialog, run the callback with empty FilePath. callback.Run(path, content::DownloadItem::TARGET_DISPOSITION_PROMPT, content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path); From 5ef9c7e1a19fca478185538838c19663ad2cf8c0 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Mon, 21 Sep 2015 21:44:51 +0800 Subject: [PATCH 09/47] Add spec for download item. --- spec/api-session-spec.coffee | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/spec/api-session-spec.coffee b/spec/api-session-spec.coffee index 34a08ee50f0..fe5765b45fd 100644 --- a/spec/api-session-spec.coffee +++ b/spec/api-session-spec.coffee @@ -2,6 +2,7 @@ assert = require 'assert' remote = require 'remote' http = require 'http' path = require 'path' +fs = require 'fs' app = remote.require 'app' BrowserWindow = remote.require 'browser-window' @@ -72,3 +73,52 @@ describe 'session module', -> quotas: ['persistent'], w.webContents.session.clearStorageData options, -> w.webContents.send 'getcount' + + describe 'DownloadItem', -> + # A 5MB mock pdf. + mockPDF = new Buffer(1024*1024*5) + contentDisposition = 'inline; filename="mock.pdf"' + # TODO(hokein): Change the download directory to spec/fixtures directory. + # We have to use the # default download directory due to the broken + # session.setDownloadPath API is broken. Once the API is fixed, we can make + # this change. + defaultDownloadDir = path.join app.getPath('userData'), 'Downloads' + downloadFilePath = path.join defaultDownloadDir, "mock.pdf" + downloadServer = http.createServer (req, res) -> + res.writeHead 200, { + 'Content-Length': mockPDF.length, + 'Content-Type': 'application/pdf', + 'Content-Disposition': contentDisposition + } + res.end mockPDF + downloadServer.close() + + it 'can download successfully', (done) -> + downloadServer.listen 0, '127.0.0.1', -> + {port} = downloadServer.address() + w.loadUrl "#{url}:#{port}" + w.webContents.session.setOpenDownloadDialog false + + w.webContents.session.once 'will-download', (e, item, webContents) -> + item.on 'done', (e, state) -> + assert.equal state, "completed" + assert.equal item.getContentDisposition(), contentDisposition + assert.equal item.getReceiveBytes(), mockPDF.length + assert.equal item.getTotalBytes(), mockPDF.length + assert fs.existsSync downloadFilePath + fs.unlinkSync downloadFilePath + done() + assert.equal item.getURL(), "#{url}:#{port}/" + assert.equal item.getMimeType(), "application/pdf" + + it 'can cancel download', (done) -> + downloadServer.listen 0, '127.0.0.1', -> + {port} = downloadServer.address() + w.loadUrl "#{url}:#{port}/" + w.webContents.session.setOpenDownloadDialog false + w.webContents.session.once 'will-download', (e, item, webContents) -> + item.pause() + item.on 'done', (e, state) -> + assert.equal state, "cancelled" + done() + item.cancel() From 748b1387d2d8e4de788b7368d8ddb19dd97fd740 Mon Sep 17 00:00:00 2001 From: Robo Date: Mon, 21 Sep 2015 22:13:32 +0530 Subject: [PATCH 10/47] browser: switch to set minimum version for TLS fallback --- atom/browser/atom_browser_context.cc | 5 +++ atom/browser/atom_browser_context.h | 1 + atom/browser/atom_ssl_config_service.cc | 47 ++++++++++++++++++++++++ atom/browser/atom_ssl_config_service.h | 28 ++++++++++++++ atom/common/options_switches.cc | 4 ++ atom/common/options_switches.h | 1 + docs/api/chrome-command-line-switches.md | 5 +++ filenames.gypi | 2 + 8 files changed, 93 insertions(+) create mode 100644 atom/browser/atom_ssl_config_service.cc create mode 100644 atom/browser/atom_ssl_config_service.h diff --git a/atom/browser/atom_browser_context.cc b/atom/browser/atom_browser_context.cc index d1ef09e70ff..6823fbaee90 100644 --- a/atom/browser/atom_browser_context.cc +++ b/atom/browser/atom_browser_context.cc @@ -6,6 +6,7 @@ #include "atom/browser/atom_browser_main_parts.h" #include "atom/browser/atom_download_manager_delegate.h" +#include "atom/browser/atom_ssl_config_service.h" #include "atom/browser/browser.h" #include "atom/browser/net/atom_url_request_job_factory.h" #include "atom/browser/net/asar/asar_protocol_handler.h" @@ -156,6 +157,10 @@ content::BrowserPluginGuestManager* AtomBrowserContext::GetGuestManager() { return guest_manager_.get(); } +net::SSLConfigService* AtomBrowserContext::CreateSSLConfigService() { + return new AtomSSLConfigService; +} + void AtomBrowserContext::RegisterPrefs(PrefRegistrySimple* pref_registry) { pref_registry->RegisterFilePathPref(prefs::kSelectFileLastDirectory, base::FilePath()); diff --git a/atom/browser/atom_browser_context.h b/atom/browser/atom_browser_context.h index c99461ad9a8..839359c1ef5 100644 --- a/atom/browser/atom_browser_context.h +++ b/atom/browser/atom_browser_context.h @@ -27,6 +27,7 @@ class AtomBrowserContext : public brightray::BrowserContext { content::URLRequestInterceptorScopedVector* interceptors) override; net::HttpCache::BackendFactory* CreateHttpCacheBackendFactory( const base::FilePath& base_path) override; + net::SSLConfigService* CreateSSLConfigService() override; // content::BrowserContext: content::DownloadManagerDelegate* GetDownloadManagerDelegate() override; diff --git a/atom/browser/atom_ssl_config_service.cc b/atom/browser/atom_ssl_config_service.cc new file mode 100644 index 00000000000..f19dbacf7dd --- /dev/null +++ b/atom/browser/atom_ssl_config_service.cc @@ -0,0 +1,47 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#include "atom/browser/atom_ssl_config_service.h" + +#include + +#include "base/command_line.h" +#include "atom/common/options_switches.h" +#include "content/public/browser/browser_thread.h" +#include "net/socket/ssl_client_socket.h" + +namespace atom { + +namespace { + +uint16 GetSSLProtocolVersion(const std::string& version_string) { + uint16 version = 0; // Invalid + if (version_string == "tls1") + version = net::SSL_PROTOCOL_VERSION_TLS1; + else if (version_string == "tls1.1") + version = net::SSL_PROTOCOL_VERSION_TLS1_1; + else if (version_string == "tls1.2") + version = net::SSL_PROTOCOL_VERSION_TLS1_2; + return version; +} + +} // namespace + +AtomSSLConfigService::AtomSSLConfigService() { + auto cmd_line = base::CommandLine::ForCurrentProcess(); + if (cmd_line->HasSwitch(switches::kSSLVersionFallbackMin)) { + auto version_string = + cmd_line->GetSwitchValueASCII(switches::kSSLVersionFallbackMin); + config_.version_fallback_min = GetSSLProtocolVersion(version_string); + } +} + +AtomSSLConfigService::~AtomSSLConfigService() { +} + +void AtomSSLConfigService::GetSSLConfig(net::SSLConfig* config) { + *config = config_; +} + +} // namespace atom diff --git a/atom/browser/atom_ssl_config_service.h b/atom/browser/atom_ssl_config_service.h new file mode 100644 index 00000000000..3fa91c62c43 --- /dev/null +++ b/atom/browser/atom_ssl_config_service.h @@ -0,0 +1,28 @@ +// Copyright (c) 2015 GitHub, Inc. +// Use of this source code is governed by the MIT license that can be +// found in the LICENSE file. + +#ifndef ATOM_BROWSER_ATOM_SSL_CONFIG_SERVICE_H_ +#define ATOM_BROWSER_ATOM_SSL_CONFIG_SERVICE_H_ + +#include "net/ssl/ssl_config_service.h" + +namespace atom { + +class AtomSSLConfigService : public net::SSLConfigService { + public: + AtomSSLConfigService(); + ~AtomSSLConfigService() override; + + // net::SSLConfigService: + void GetSSLConfig(net::SSLConfig* config) override; + + private: + net::SSLConfig config_; + + DISALLOW_COPY_AND_ASSIGN(AtomSSLConfigService); +}; + +} // namespace atom + +#endif // ATOM_BROWSER_ATOM_SSL_CONFIG_SERVICE_H_ diff --git a/atom/common/options_switches.cc b/atom/common/options_switches.cc index c70e1ba4afa..46687becf84 100644 --- a/atom/common/options_switches.cc +++ b/atom/common/options_switches.cc @@ -113,6 +113,10 @@ const char kDisableHttpCache[] = "disable-http-cache"; // Register schemes to standard. const char kRegisterStandardSchemes[] = "register-standard-schemes"; +// The minimum SSL/TLS version ("tls1", "tls1.1", or "tls1.2") that +// TLS fallback will accept. +const char kSSLVersionFallbackMin[] = "ssl-version-fallback-min"; + // The browser process app model ID const char kAppUserModelId[] = "app-user-model-id"; diff --git a/atom/common/options_switches.h b/atom/common/options_switches.h index e62f3116661..16046d19c82 100644 --- a/atom/common/options_switches.h +++ b/atom/common/options_switches.h @@ -59,6 +59,7 @@ extern const char kPageVisibility[]; extern const char kDisableHttpCache[]; extern const char kRegisterStandardSchemes[]; +extern const char kSSLVersionFallbackMin[]; extern const char kAppUserModelId[]; diff --git a/docs/api/chrome-command-line-switches.md b/docs/api/chrome-command-line-switches.md index 2f995c99b21..cd633fc0460 100644 --- a/docs/api/chrome-command-line-switches.md +++ b/docs/api/chrome-command-line-switches.md @@ -87,6 +87,11 @@ Sets the `version` of the pepper flash plugin. Enables net log events to be saved and writes them to `path`. +## --ssl-version-fallback-min=`version` + +Set the minimum SSL/TLS version ("tls1", "tls1.1" or "tls1.2") that TLS +fallback will accept. + ## --v=`log_level` Gives the default maximal active V-logging level; 0 is the default. Normally diff --git a/filenames.gypi b/filenames.gypi index 99d6bc6d50d..3258a032de8 100644 --- a/filenames.gypi +++ b/filenames.gypi @@ -129,6 +129,8 @@ 'atom/browser/atom_quota_permission_context.h', 'atom/browser/atom_speech_recognition_manager_delegate.cc', 'atom/browser/atom_speech_recognition_manager_delegate.h', + 'atom/browser/atom_ssl_config_service.cc', + 'atom/browser/atom_ssl_config_service.h', 'atom/browser/bridge_task_runner.cc', 'atom/browser/bridge_task_runner.h', 'atom/browser/browser.cc', From d8062ab9e102707f5fc6e1c5374b4130aa34298d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 23 Sep 2015 11:45:51 +0800 Subject: [PATCH 11/47] docs: win.setMenu is not available on OS X --- docs/api/browser-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index f1705c29175..a1870bc66af 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -665,7 +665,7 @@ Same as `webContents.loadUrl(url[, options])`. Same as `webContents.reload`. -### `win.setMenu(menu)` _OS X_ +### `win.setMenu(menu)` _Linux_ _Windows_ * `menu` Menu From 6c01cec8d289087741b4e7cee98a290f2f278a2c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 23 Sep 2015 13:49:43 +0800 Subject: [PATCH 12/47] Update node to not rely on GC to free memory --- vendor/node | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/node b/vendor/node index fa54694af43..d64246490d6 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit fa54694af4350bf1720ff47e97a07c7c09325ee2 +Subproject commit d64246490d697f387b888391b1aba65032703a0f From f8f8db7e88f44293fcccca5810d84405ec3443af Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 23 Sep 2015 13:55:14 +0800 Subject: [PATCH 13/47] spec: Test whether ffi works --- spec/modules-spec.coffee | 4 ++++ spec/package.json | 1 + 2 files changed, 5 insertions(+) diff --git a/spec/modules-spec.coffee b/spec/modules-spec.coffee index e7bdac36b3e..ed2d9fecb43 100644 --- a/spec/modules-spec.coffee +++ b/spec/modules-spec.coffee @@ -22,6 +22,10 @@ describe 'third-party module', -> assert.equal msg, 'ok' done() + describe 'ffi', -> + it 'does not crash', -> + require 'ffi' + describe 'q', -> Q = require 'q' diff --git a/spec/package.json b/spec/package.json index a3b0d590eff..8f43b711f19 100644 --- a/spec/package.json +++ b/spec/package.json @@ -5,6 +5,7 @@ "version": "0.1.0", "devDependencies": { "basic-auth": "^1.0.0", + "ffi": "2.0.0", "formidable": "1.0.16", "graceful-fs": "3.0.5", "mocha": "2.1.0", From 706deae1b0dc924fc8cb11f992f36c7cf56530ab Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 23 Sep 2015 15:44:50 +0800 Subject: [PATCH 14/47] spec: ffi is crashing on OS X --- spec/modules-spec.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/modules-spec.coffee b/spec/modules-spec.coffee index ed2d9fecb43..1406e0637ec 100644 --- a/spec/modules-spec.coffee +++ b/spec/modules-spec.coffee @@ -23,6 +23,7 @@ describe 'third-party module', -> done() describe 'ffi', -> + return if process.platform is 'darwin' it 'does not crash', -> require 'ffi' From 334c28d128e6e04eccfef0d023d739004a3cd89f Mon Sep 17 00:00:00 2001 From: Kostiantyn Kahanskyi Date: Wed, 23 Sep 2015 10:21:03 +0200 Subject: [PATCH 15/47] :memo: Include UTF-8 charset in quick start example Partially fixes #678 --- docs/tutorial/quick-start.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/tutorial/quick-start.md b/docs/tutorial/quick-start.md index 93cd0ebc5bd..4ce65a1dc1a 100644 --- a/docs/tutorial/quick-start.md +++ b/docs/tutorial/quick-start.md @@ -124,6 +124,7 @@ Finally the `index.html` is the web page you want to show: + Hello World! From 1520ebfe1fe53a10610ef1f242d366812cfa7dd1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Wed, 23 Sep 2015 17:31:26 +0800 Subject: [PATCH 16/47] Update brightray for #2861 --- vendor/brightray | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/brightray b/vendor/brightray index 25f3a9d0a5b..8e443520e69 160000 --- a/vendor/brightray +++ b/vendor/brightray @@ -1 +1 @@ -Subproject commit 25f3a9d0a5b73ec170a65f4e2e4c9ad91e23fc8c +Subproject commit 8e443520e695674fd26585cfa24a0ec0b6140c27 From 22e6f15795dc457c48d5e7c751191ebc219eed49 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Wed, 23 Sep 2015 11:20:26 -0700 Subject: [PATCH 17/47] Remove GUID from Shell_NotifyIcon calls https://github.com/atom/electron/issues/2468#issuecomment-142684129 has the details --- atom/browser/ui/win/notify_icon.cc | 30 ------------------------------ atom/browser/ui/win/notify_icon.h | 4 ---- 2 files changed, 34 deletions(-) diff --git a/atom/browser/ui/win/notify_icon.cc b/atom/browser/ui/win/notify_icon.cc index 4026d9ec4a6..84c2c0252be 100644 --- a/atom/browser/ui/win/notify_icon.cc +++ b/atom/browser/ui/win/notify_icon.cc @@ -30,29 +30,6 @@ NotifyIcon::NotifyIcon(NotifyIconHost* host, message_id_(message), menu_model_(NULL), has_tray_app_id_hash_(false) { - // NB: If we have an App Model ID, we should propagate that to the tray. - // Doing this prevents duplicate items from showing up in the notification - // preferences (i.e. "Always Show / Show notifications only / etc") - PWSTR explicit_app_id; - if (SUCCEEDED(GetCurrentProcessExplicitAppUserModelID(&explicit_app_id))) { - // GUIDs and MD5 hashes are the same length. So convenient! - base::MD5Sum(explicit_app_id, - sizeof(wchar_t) * wcslen(explicit_app_id), - reinterpret_cast(&tray_app_id_hash_)); - - // Set the GUID to version 4 as described in RFC 4122, section 4.4. - // The format of GUID version 4 must be like - // xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, where y is one of [8, 9, A, B]. - tray_app_id_hash_.Data3 &= 0x0fff; - tray_app_id_hash_.Data3 |= 0x4000; - - // Set y to one of [8, 9, A, B]. - tray_app_id_hash_.Data4[0] = 1; - - has_tray_app_id_hash_ = true; - CoTaskMemFree(explicit_app_id); - } - NOTIFYICONDATA icon_data; InitIconData(&icon_data); icon_data.uFlags |= NIF_MESSAGE; @@ -202,13 +179,6 @@ void NotifyIcon::InitIconData(NOTIFYICONDATA* icon_data) { icon_data->cbSize = sizeof(NOTIFYICONDATA); icon_data->hWnd = window_; icon_data->uID = icon_id_; - - if (has_tray_app_id_hash_) { - icon_data->uFlags |= NIF_GUID; - memcpy(reinterpret_cast(&icon_data->guidItem), - &tray_app_id_hash_, - sizeof(GUID)); - } } } // namespace atom diff --git a/atom/browser/ui/win/notify_icon.h b/atom/browser/ui/win/notify_icon.h index 136186b689b..d368dec7132 100644 --- a/atom/browser/ui/win/notify_icon.h +++ b/atom/browser/ui/win/notify_icon.h @@ -79,10 +79,6 @@ class NotifyIcon : public TrayIcon { // The context menu. ui::SimpleMenuModel* menu_model_; - // A hash of the app model ID - GUID tray_app_id_hash_; - bool has_tray_app_id_hash_; - DISALLOW_COPY_AND_ASSIGN(NotifyIcon); }; From b0e5039951b8f17f15b0978e873dd4010530ad39 Mon Sep 17 00:00:00 2001 From: Paul Betts Date: Wed, 23 Sep 2015 11:26:57 -0700 Subject: [PATCH 18/47] Fix initializer --- atom/browser/ui/win/notify_icon.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/atom/browser/ui/win/notify_icon.cc b/atom/browser/ui/win/notify_icon.cc index 84c2c0252be..03274abe987 100644 --- a/atom/browser/ui/win/notify_icon.cc +++ b/atom/browser/ui/win/notify_icon.cc @@ -28,8 +28,7 @@ NotifyIcon::NotifyIcon(NotifyIconHost* host, icon_id_(id), window_(window), message_id_(message), - menu_model_(NULL), - has_tray_app_id_hash_(false) { + menu_model_(NULL) { NOTIFYICONDATA icon_data; InitIconData(&icon_data); icon_data.uFlags |= NIF_MESSAGE; From d621755f1386777d12525069a5742f1848327807 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Thu, 24 Sep 2015 12:47:30 +0900 Subject: [PATCH 19/47] Update as upstream, improve grammar --- docs-translations/ko-KR/README.md | 6 +++--- .../ko-KR/api/chrome-command-line-switches.md | 10 +++++++--- docs-translations/ko-KR/api/web-view-tag.md | 12 ++++++++++-- docs-translations/ko-KR/api/window-open.md | 4 ++++ 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/docs-translations/ko-KR/README.md b/docs-translations/ko-KR/README.md index 2fb242fae90..1e0ba63e7b6 100644 --- a/docs-translations/ko-KR/README.md +++ b/docs-translations/ko-KR/README.md @@ -26,7 +26,7 @@ * [`` 태그](api/web-view-tag.md) * [`window.open` 함수](api/window-open.md) -### 메인 프로세스를 위한 모듈들: +### 메인 프로세스에서 사용할 수 있는 모듈: * [app (0% 번역됨)](api/app.md) * [auto-updater](api/auto-updater.md) @@ -44,13 +44,13 @@ * [web-contents (0% 번역됨)](api/web-contents.md) * [tray](api/tray.md) -### 랜더러 프로세스를 위한 모듈들 (웹 페이지): +### 랜더러 프로세스에서 사용할 수 있는 모듈 (웹 페이지): * [ipc (renderer)](api/ipc-renderer.md) * [remote](api/remote.md) * [web-frame](api/web-frame.md) -### 두 프로세스에서 모두 사용 가능한 모듈들: +### 두 프로세스 모두 사용할 수 있는 모듈: * [clipboard](api/clipboard.md) * [crash-reporter](api/crash-reporter.md) diff --git a/docs-translations/ko-KR/api/chrome-command-line-switches.md b/docs-translations/ko-KR/api/chrome-command-line-switches.md index 5b9bf472204..2d9158fcc2f 100644 --- a/docs-translations/ko-KR/api/chrome-command-line-switches.md +++ b/docs-translations/ko-KR/api/chrome-command-line-switches.md @@ -1,6 +1,6 @@ # 크롬 Command-Line 스위치 지원 -다음 Command-Line 스위치들은 크롬 브라우저에서 제공되는 추가 옵션이며 Electron에서도 지원합니다. +크롬 Command-Line 스위치는 크롬 브라우저에서 제공되는 추가 옵션이며 Electron에서도 지원합니다. [app][app]의 [ready][ready]이벤트가 작동하기 전에 [app.commandLine.appendSwitch][append-switch] API를 사용하면 어플리케이션 내부에서 스위치들을 추가할 수 있습니다: @@ -80,7 +80,11 @@ Pepper 플래시 플러그인의 버전을 설정합니다. ## --log-net-log=`path` -Net log 이벤트를 지정한 `path`에 로그로 기록합니다. +Net log 이벤트를 활성화하고 `path`에 로그를 기록합니다. + +## --ssl-version-fallback-min=`version` + +Fallback SSL/TLS 최소 버전을 지정합니다. ("tls1", "tls1.1", "tls1.2") ## --v=`log_level` @@ -93,7 +97,7 @@ Net log 이벤트를 지정한 `path`에 로그로 기록합니다. `--v` 옵션에 전달된 값을 덮어쓰고 모듈당 최대 V-logging 레벨을 지정합니다. 예를 들어 `my_module=2,foo*=3`는 `my_module.*`, `foo*.*`와 같은 파일 이름 패턴을 가진 모든 소스 코드들의 로깅 레벨을 각각 2와 3으로 설정합니다. -슬래시(`/`), 백슬래시(`\`)를 포함하는 모든 패턴은 모듈뿐만 아니라 모든 경로명에 대해서도 테스트 됩니다. +또한 슬래시(`/`) 또는 백슬래시(`\`)를 포함하는 패턴은 지정한 경로에 대해 패턴을 테스트 합니다. 예를 들어 `*/foo/bar/*=2` 표현식은 `foo/bar` 디렉터리 안의 모든 소스 코드의 로깅 레벨을 2로 지정합니다. 모든 크로미움과 관련된 로그를 비활성화하고 어플리케이션의 로그만 활성화 하려면 다음과 같이 코드를 작성하면 됩니다: diff --git a/docs-translations/ko-KR/api/web-view-tag.md b/docs-translations/ko-KR/api/web-view-tag.md index b3f05de7f33..69b94465aed 100644 --- a/docs-translations/ko-KR/api/web-view-tag.md +++ b/docs-translations/ko-KR/api/web-view-tag.md @@ -135,6 +135,14 @@ 즉. 작동중인 랜더러 프로세스의 세션은 변경할 수 없습니다. 이후 이 값을 바꾸려고 시도하면 DOM 예외를 발생시킵니다. +### `allowpopups` + +```html + +``` + +"on"으로 지정하면 페이지에서 새로운 창을 열 수 있도록 허용합니다. + ## Methods `webview` 태그는 다음과 같은 메서드를 가지고 있습니다: @@ -467,8 +475,8 @@ Returns: * `url` String * `frameName` String -* `disposition` String - Can be `default`, `foreground-tab`, `background-tab`, - `new-window` and `other` +* `disposition` String - `default`, `foreground-tab`, `background-tab`, `new-window`, `other`를 사용할 수 있습니다. +* `options` Object - 새로운 `BrowserWindow`를 만들 때 사용되어야 하는 옵션. 페이지가 새로운 브라우저 창을 생성할 때 발생하는 이벤트입니다. diff --git a/docs-translations/ko-KR/api/window-open.md b/docs-translations/ko-KR/api/window-open.md index a4cf3bce5c9..828c46e679e 100644 --- a/docs-translations/ko-KR/api/window-open.md +++ b/docs-translations/ko-KR/api/window-open.md @@ -6,6 +6,8 @@ 프록시 객체는 브라우저의 웹 페이지 창과 호환될 수 있도록 일부 제한된 표준 기능만 가지고 있습니다. 창의 모든 컨트롤 권한을 가지려면 `BrowserWindow`를 직접 생성해서 사용해야 합니다. +새롭게 생성된 `BrowserWindow`는 기본적으로 부모 창의 옵션을 상속합니다. 이 옵션을 변경하려면 새 창을 열 때 `features` 인자를 지정해야 합니다. + ### `window.open(url[, frameName][, features])` * `url` String @@ -14,6 +16,8 @@ `BrowserWindowProxy` 클래스의 객체를 반환하는 새로운 윈도우를 생성합니다. +`features` 문자열은 표준 브라우저의 포맷을 따르고 있지만, 각 기능은 `BrowserWindow`의 옵션이어야 합니다. + ### `window.opener.postMessage(message, targetOrigin)` * `message` String From 9b1fa04988c2db6653a8537fb7fd645f2c76f24b Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Sep 2015 12:01:57 +0800 Subject: [PATCH 20/47] win: Fix building --- atom/browser/ui/win/notify_icon.cc | 7 ------- 1 file changed, 7 deletions(-) diff --git a/atom/browser/ui/win/notify_icon.cc b/atom/browser/ui/win/notify_icon.cc index 03274abe987..c88d4c810ef 100644 --- a/atom/browser/ui/win/notify_icon.cc +++ b/atom/browser/ui/win/notify_icon.cc @@ -4,10 +4,7 @@ #include "atom/browser/ui/win/notify_icon.h" -#include - #include "atom/browser/ui/win/notify_icon_host.h" -#include "base/md5.h" #include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" #include "base/win/windows_version.h" @@ -57,10 +54,6 @@ void NotifyIcon::HandleClickEvent(const gfx::Point& cursor_pos, icon_id.uID = icon_id_; icon_id.hWnd = window_; icon_id.cbSize = sizeof(NOTIFYICONIDENTIFIER); - if (has_tray_app_id_hash_) - memcpy(reinterpret_cast(&icon_id.guidItem), - &tray_app_id_hash_, - sizeof(GUID)); RECT rect = { 0 }; Shell_NotifyIconGetRect(&icon_id, &rect); From 9e90ea8734521f249d555256849b83710bb0dc1f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Sep 2015 12:11:07 +0800 Subject: [PATCH 21/47] win: Fix leaking of fd when reading file in asar --- atom/common/asar/archive.cc | 20 +++++++++----------- atom/common/asar/archive.h | 1 + 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/atom/common/asar/archive.cc b/atom/common/asar/archive.cc index 0b2f59ae0f1..969f958956c 100644 --- a/atom/common/asar/archive.cc +++ b/atom/common/asar/archive.cc @@ -115,6 +115,14 @@ bool FillFileInfoWithNode(Archive::FileInfo* info, Archive::Archive(const base::FilePath& path) : path_(path), file_(path_, base::File::FLAG_OPEN | base::File::FLAG_READ), +#if defined(OS_WIN) + fd_(_open_osfhandle( + reinterpret_cast(file_.GetPlatformFile()), 0)), +#elif defined(OS_POSIX) + fd_(file_.GetPlatformFile()), +#else + fd_(-1), +#endif header_size_(0) { } @@ -271,17 +279,7 @@ bool Archive::CopyFileOut(const base::FilePath& path, base::FilePath* out) { } int Archive::GetFD() const { - if (!file_.IsValid()) - return -1; - -#if defined(OS_WIN) - return - _open_osfhandle(reinterpret_cast(file_.GetPlatformFile()), 0); -#elif defined(OS_POSIX) - return file_.GetPlatformFile(); -#else - return -1; -#endif + return fd_; } } // namespace asar diff --git a/atom/common/asar/archive.h b/atom/common/asar/archive.h index dda7aa78e0c..f2ff2f76d67 100644 --- a/atom/common/asar/archive.h +++ b/atom/common/asar/archive.h @@ -69,6 +69,7 @@ class Archive { private: base::FilePath path_; base::File file_; + int fd_; uint32 header_size_; scoped_ptr header_; From 269f70c12ab8eaeff2da8e0f32ebcfffcb794d8f Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Sep 2015 12:15:18 +0800 Subject: [PATCH 22/47] spec: Reading asar file should not leak fd --- spec/asar-spec.coffee | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/spec/asar-spec.coffee b/spec/asar-spec.coffee index 4ef9337f3ab..1e6ee691036 100644 --- a/spec/asar-spec.coffee +++ b/spec/asar-spec.coffee @@ -8,6 +8,10 @@ describe 'asar package', -> describe 'node api', -> describe 'fs.readFileSync', -> + it 'does not leak fd', -> + for i in [1..10000] + fs.readFileSync(path.join(process.resourcesPath, 'atom.asar', 'renderer', 'api', 'lib', 'ipc.js')) + it 'reads a normal file', -> file1 = path.join fixtures, 'asar', 'a.asar', 'file1' assert.equal fs.readFileSync(file1).toString().trim(), 'file1' From 576257470bf1fe4ab7b68887a0526144f3b2f260 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Sep 2015 12:20:29 +0800 Subject: [PATCH 23/47] spec: Remove the will-navigate test It is unreliable to test in renderer process, remove it for now. --- spec/api-browser-window-spec.coffee | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/spec/api-browser-window-spec.coffee b/spec/api-browser-window-spec.coffee index de713a6545c..2e4a66b92b9 100644 --- a/spec/api-browser-window-spec.coffee +++ b/spec/api-browser-window-spec.coffee @@ -294,16 +294,6 @@ describe 'browser-window module', -> w.show() w.minimize() - describe 'will-navigate event', -> - @timeout 10000 - it 'emits when user starts a navigation', (done) -> - url = "file://#{fixtures}/pages/will-navigate.html" - w.webContents.on 'will-navigate', (event, u) -> - event.preventDefault() - assert.equal u, url - done() - w.loadUrl url - xdescribe 'beginFrameSubscription method', -> it 'subscribes frame updates', (done) -> w.loadUrl "file://#{fixtures}/api/blank.html" From 5ca5c4fb92ab2ba75308d91796e0113869148d8a Mon Sep 17 00:00:00 2001 From: Robo Date: Tue, 22 Sep 2015 22:21:49 +0530 Subject: [PATCH 24/47] browser: hide webcontents when window not shown --- atom/browser/native_window.cc | 7 ++++++- spec/chromium-spec.coffee | 17 +++++++++++++++++ spec/fixtures/pages/document-hidden.html | 7 +++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 spec/fixtures/pages/document-hidden.html diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index 4d5f273340a..e06633d7b7c 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -159,8 +159,13 @@ void NativeWindow::InitFromOptions(const mate::Dictionary& options) { // Then show it. bool show = true; options.Get(switches::kShow, &show); - if (show) + if (show) { Show(); + } else { + // When RenderView is created it sets to visible, this is to prevent + // breaking the visibility API. + web_contents()->WasHidden(); + } } void NativeWindow::SetSize(const gfx::Size& size) { diff --git a/spec/chromium-spec.coffee b/spec/chromium-spec.coffee index 4dd39aff5fd..a782079026a 100644 --- a/spec/chromium-spec.coffee +++ b/spec/chromium-spec.coffee @@ -23,6 +23,23 @@ describe 'chromium feature', -> {port} = server.address() $.get "http://127.0.0.1:#{port}" + describe 'document.hidden', -> + BrowserWindow = remote.require 'browser-window' + ipc = remote.require 'ipc' + url = "file://#{fixtures}/pages/document-hidden.html" + w = null + + afterEach -> + w?.destroy() + ipc.removeAllListeners 'hidden' + + it 'is set correctly when window is not shown', (done) -> + ipc.once 'hidden', (event, hidden) -> + assert hidden + done() + w = new BrowserWindow(show:false) + w.loadUrl url + describe 'navigator.webkitGetUserMedia', -> it 'calls its callbacks', (done) -> @timeout 5000 diff --git a/spec/fixtures/pages/document-hidden.html b/spec/fixtures/pages/document-hidden.html new file mode 100644 index 00000000000..17920bff079 --- /dev/null +++ b/spec/fixtures/pages/document-hidden.html @@ -0,0 +1,7 @@ + + + + + From fe2d9ee0f69a96b78edf595e626138f416e26030 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Sep 2015 14:16:45 +0800 Subject: [PATCH 25/47] Update libchromium to have the V8 patch --- script/lib/config.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/lib/config.py b/script/lib/config.py index 0df68bd773b..68f216785d6 100644 --- a/script/lib/config.py +++ b/script/lib/config.py @@ -8,7 +8,7 @@ import sys BASE_URL = os.getenv('LIBCHROMIUMCONTENT_MIRROR') or \ 'http://github-janky-artifacts.s3.amazonaws.com/libchromiumcontent' -LIBCHROMIUMCONTENT_COMMIT = '8482fe555913dea3bde8a74f754524e2cfb02bc5' +LIBCHROMIUMCONTENT_COMMIT = '04523758cda2a96d2454f9056fb1fb9a1c1f95f1' PLATFORM = { 'cygwin': 'win32', From 497732fb6f191fab881330b6b5617f3c19754da7 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Sep 2015 15:06:06 +0800 Subject: [PATCH 26/47] Revert "spec: ffi is crashing on OS X" This reverts commit 706deae1b0dc924fc8cb11f992f36c7cf56530ab. --- spec/modules-spec.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/spec/modules-spec.coffee b/spec/modules-spec.coffee index 1406e0637ec..ed2d9fecb43 100644 --- a/spec/modules-spec.coffee +++ b/spec/modules-spec.coffee @@ -23,7 +23,6 @@ describe 'third-party module', -> done() describe 'ffi', -> - return if process.platform is 'darwin' it 'does not crash', -> require 'ffi' From e3fab8b5b3ed7ab772e4187992b2d39410c5e711 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Sep 2015 15:08:38 +0800 Subject: [PATCH 27/47] spec: Run an example of ffi --- spec/modules-spec.coffee | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/spec/modules-spec.coffee b/spec/modules-spec.coffee index ed2d9fecb43..1cdc6cf0ea5 100644 --- a/spec/modules-spec.coffee +++ b/spec/modules-spec.coffee @@ -24,7 +24,9 @@ describe 'third-party module', -> describe 'ffi', -> it 'does not crash', -> - require 'ffi' + ffi = require 'ffi' + libm = ffi.Library('libm', ceil: [ 'double', [ 'double' ] ]) + assert.equal libm.ceil(1.5), 2 describe 'q', -> Q = require 'q' From 0861d5d44bb0e2692535aa63cb46eed303524ac4 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 24 Sep 2015 15:55:45 +0800 Subject: [PATCH 28/47] Redefine 'will-download' design. --- atom/browser/api/atom_api_download_item.cc | 62 ++++++++++++++----- atom/browser/api/atom_api_download_item.h | 18 ++++-- atom/browser/api/atom_api_session.cc | 9 --- atom/browser/api/atom_api_session.h | 2 - atom/browser/api/lib/app.coffee | 2 +- .../browser/atom_download_manager_delegate.cc | 56 ++++++++--------- atom/browser/atom_download_manager_delegate.h | 1 - docs/api/download-item.md | 17 +++-- docs/api/session.md | 7 --- spec/api-session-spec.coffee | 53 ++++++++-------- spec/static/main.js | 23 +++++++ 11 files changed, 149 insertions(+), 101 deletions(-) diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc index 6c6bb4dae9d..3d150462bde 100644 --- a/atom/browser/api/atom_api_download_item.cc +++ b/atom/browser/api/atom_api_download_item.cc @@ -4,9 +4,13 @@ #include "atom/browser/api/atom_api_download_item.h" +#include + #include "atom/common/native_mate_converters/callback.h" +#include "atom/common/native_mate_converters/file_path_converter.h" #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/node_includes.h" +#include "base/memory/linked_ptr.h" #include "native_mate/dictionary.h" namespace mate { @@ -43,27 +47,36 @@ namespace { // The wrapDownloadItem funtion which is implemented in JavaScript using WrapDownloadItemCallback = base::Callback)>; WrapDownloadItemCallback g_wrap_download_item; + +char kDownloadItemSavePathKey[] = "DownloadItemSavePathKey"; + +std::map>> g_download_item_objects; } // namespace +DownloadItem::SavePathData::SavePathData(const base::FilePath& path) : + path_(path) { +} + +const base::FilePath& DownloadItem::SavePathData::path() { + return path_; +} + DownloadItem::DownloadItem(content::DownloadItem* download_item) : download_item_(download_item) { download_item_->AddObserver(this); } DownloadItem::~DownloadItem() { - download_item_->RemoveObserver(this); + Destroy(); } -void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) { - if (download_item_ == item) { - download_item_->IsDone() ? - Emit("done", item->GetState()) : Emit("updated"); - } -} - -void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download) { - if (download_item_ == download) { +void DownloadItem::Destroy() { + if (download_item_) { download_item_->RemoveObserver(this); + auto iter = g_download_item_objects.find(download_item_->GetId()); + if (iter != g_download_item_objects.end()) + g_download_item_objects.erase(iter); + download_item_ = nullptr; } } @@ -71,8 +84,12 @@ bool DownloadItem::IsDestroyed() const { return download_item_ == nullptr; } -void DownloadItem::Destroy() { - download_item_ = nullptr; +void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) { + download_item_->IsDone() ? Emit("done", item->GetState()) : Emit("updated"); +} + +void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download) { + Destroy(); } int64 DownloadItem::GetReceivedBytes() { @@ -83,7 +100,7 @@ int64 DownloadItem::GetTotalBytes() { return download_item_->GetTotalBytes(); } -const GURL& DownloadItem::GetURL() { +const GURL& DownloadItem::GetUrl() { return download_item_->GetURL(); } @@ -103,6 +120,10 @@ std::string DownloadItem::GetContentDisposition() { return download_item_->GetContentDisposition(); } +void DownloadItem::SetSavePath(const base::FilePath& path) { + download_item_->SetUserData(UserDataKey(), new SavePathData(path)); +} + void DownloadItem::Pause() { download_item_->Pause(); } @@ -121,13 +142,14 @@ mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder( .SetMethod("pause", &DownloadItem::Pause) .SetMethod("resume", &DownloadItem::Resume) .SetMethod("cancel", &DownloadItem::Cancel) - .SetMethod("getReceiveBytes", &DownloadItem::GetReceivedBytes) + .SetMethod("getReceivedBytes", &DownloadItem::GetReceivedBytes) .SetMethod("getTotalBytes", &DownloadItem::GetTotalBytes) - .SetMethod("getURL", &DownloadItem::GetURL) + .SetMethod("getUrl", &DownloadItem::GetUrl) .SetMethod("getMimeType", &DownloadItem::GetMimeType) .SetMethod("hasUserGesture", &DownloadItem::HasUserGesture) .SetMethod("getSuggestedFilename", &DownloadItem::GetSuggestedFilename) - .SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition); + .SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition) + .SetMethod("setSavePath", &DownloadItem::SetSavePath); } void SetWrapDownloadItem(const WrapDownloadItemCallback& callback) { @@ -138,13 +160,21 @@ void ClearWrapDownloadItem() { g_wrap_download_item.Reset(); } +// static mate::Handle DownloadItem::Create( v8::Isolate* isolate, content::DownloadItem* item) { auto handle = mate::CreateHandle(isolate, new DownloadItem(item)); g_wrap_download_item.Run(handle.ToV8()); + g_download_item_objects[item->GetId()] = make_linked_ptr( + new v8::Global(isolate, handle.ToV8())); return handle; } +// static +void* DownloadItem::UserDataKey() { + return &kDownloadItemSavePathKey; +} + } // namespace api } // namespace atom diff --git a/atom/browser/api/atom_api_download_item.h b/atom/browser/api/atom_api_download_item.h index e12064c825e..3e90ced8a81 100644 --- a/atom/browser/api/atom_api_download_item.h +++ b/atom/browser/api/atom_api_download_item.h @@ -8,6 +8,7 @@ #include #include "atom/browser/api/trackable_object.h" +#include "base/files/file_path.h" #include "content/public/browser/download_item.h" #include "native_mate/handle.h" #include "url/gurl.h" @@ -16,9 +17,17 @@ namespace atom { namespace api { -class DownloadItem : public mate::TrackableObject, +class DownloadItem : public mate::EventEmitter, public content::DownloadItem::Observer { public: + class SavePathData : public base::SupportsUserData::Data { + public: + explicit SavePathData(const base::FilePath& path); + const base::FilePath& path(); + private: + base::FilePath path_; + }; + explicit DownloadItem(content::DownloadItem* download_item); ~DownloadItem(); static mate::Handle Create(v8::Isolate* isolate, @@ -37,16 +46,17 @@ class DownloadItem : public mate::TrackableObject, bool HasUserGesture(); std::string GetSuggestedFilename(); std::string GetContentDisposition(); - const GURL& GetURL(); + const GURL& GetUrl(); + void SetSavePath(const base::FilePath& path); + static void* UserDataKey(); private: // mate::Wrappable: mate::ObjectTemplateBuilder GetObjectTemplateBuilder( v8::Isolate* isolate) override; bool IsDestroyed() const override; - // mate::TrackableObject: - void Destroy() override; + void Destroy(); content::DownloadItem* download_item_; diff --git a/atom/browser/api/atom_api_session.cc b/atom/browser/api/atom_api_session.cc index 27e52e112ed..7d5f75cac09 100644 --- a/atom/browser/api/atom_api_session.cc +++ b/atom/browser/api/atom_api_session.cc @@ -10,7 +10,6 @@ #include "atom/browser/api/atom_api_cookies.h" #include "atom/browser/api/atom_api_download_item.h" #include "atom/browser/atom_browser_context.h" -#include "atom/browser/atom_download_manager_delegate.h" #include "atom/browser/api/atom_api_web_contents.h" #include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/gurl_converter.h" @@ -295,13 +294,6 @@ void Session::SetDownloadPath(const base::FilePath& path) { prefs::kDownloadDefaultDirectory, path); } -void Session::SetOpenDownloadDialog(bool open_download_dialog) { - AtomDownloadManagerDelegate* delegate = - static_cast( - browser_context()->GetDownloadManagerDelegate()); - delegate->SetOpenDownloadDialog(open_download_dialog); -} - v8::Local Session::Cookies(v8::Isolate* isolate) { if (cookies_.IsEmpty()) { auto handle = atom::api::Cookies::Create(isolate, browser_context()); @@ -318,7 +310,6 @@ mate::ObjectTemplateBuilder Session::GetObjectTemplateBuilder( .SetMethod("clearStorageData", &Session::ClearStorageData) .SetMethod("setProxy", &Session::SetProxy) .SetMethod("setDownloadPath", &Session::SetDownloadPath) - .SetMethod("setOpenDownloadDialog", &Session::SetOpenDownloadDialog) .SetProperty("cookies", &Session::Cookies); } diff --git a/atom/browser/api/atom_api_session.h b/atom/browser/api/atom_api_session.h index 2c53cfdac5a..14406e57af5 100644 --- a/atom/browser/api/atom_api_session.h +++ b/atom/browser/api/atom_api_session.h @@ -43,8 +43,6 @@ class Session: public mate::TrackableObject, AtomBrowserContext* browser_context() const { return browser_context_.get(); } - void SetOpenDownloadDialog(bool open_download_dialog); - protected: explicit Session(AtomBrowserContext* browser_context); ~Session(); diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index 3bf85c59051..48ddd1768e8 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -15,7 +15,7 @@ wrapDownloadItem = (download_item) -> # download_item is an Event Emitter. download_item.__proto__ = EventEmitter.prototype # Be compatible with old APIs. - download_item.url = download_item.getURL() + download_item.url = download_item.getUrl() download_item.filename = download_item.getSuggestedFilename() download_item.mimeType = download_item.getMimeType() download_item.hasUserGesture = download_item.hasUserGesture() diff --git a/atom/browser/atom_download_manager_delegate.cc b/atom/browser/atom_download_manager_delegate.cc index 88daec2f462..b6b65668255 100644 --- a/atom/browser/atom_download_manager_delegate.cc +++ b/atom/browser/atom_download_manager_delegate.cc @@ -6,6 +6,7 @@ #include +#include "atom/browser/api/atom_api_download_item.h" #include "atom/browser/atom_browser_context.h" #include "atom/browser/native_window.h" #include "atom/browser/ui/file_dialog.h" @@ -23,8 +24,7 @@ namespace atom { AtomDownloadManagerDelegate::AtomDownloadManagerDelegate( content::DownloadManager* manager) : download_manager_(manager), - weak_ptr_factory_(this), - open_download_dialog_(true) {} + weak_ptr_factory_(this) {} AtomDownloadManagerDelegate::~AtomDownloadManagerDelegate() { if (download_manager_) { @@ -74,20 +74,14 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated( if (relay) window = relay->window.get(); - file_dialog::Filters filters; base::FilePath path; - if (!open_download_dialog_) { - // Use default_path if download dialog is disabled. - path = default_path; - } else { - if (file_dialog::ShowSaveDialog(window, item->GetURL().spec(), default_path, - filters, &path)) { - // Remember the last selected download directory. - AtomBrowserContext* browser_context = static_cast( - download_manager_->GetBrowserContext()); - browser_context->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory, - path.DirName()); - } + if (file_dialog::ShowSaveDialog(window, item->GetURL().spec(), default_path, + file_dialog::Filters(), &path)) { + // Remember the last selected download directory. + AtomBrowserContext* browser_context = static_cast( + download_manager_->GetBrowserContext()); + browser_context->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory, + path.DirName()); } // Running the DownloadTargetCallback with an empty FilePath signals that the @@ -98,11 +92,6 @@ void AtomDownloadManagerDelegate::OnDownloadPathGenerated( content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, path); } -void AtomDownloadManagerDelegate::SetOpenDownloadDialog( - bool open_download_dialog) { - open_download_dialog_ = open_download_dialog; -} - void AtomDownloadManagerDelegate::Shutdown() { weak_ptr_factory_.InvalidateWeakPtrs(); download_manager_ = nullptr; @@ -113,6 +102,25 @@ bool AtomDownloadManagerDelegate::DetermineDownloadTarget( const content::DownloadTargetCallback& callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + if (!download->GetForcedFilePath().empty()) { + callback.Run(download->GetForcedFilePath(), + content::DownloadItem::TARGET_DISPOSITION_OVERWRITE, + content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + download->GetForcedFilePath()); + return true; + } + base::SupportsUserData::Data* save_path = download->GetUserData( + atom::api::DownloadItem::UserDataKey()); + if (save_path) { + const base::FilePath& default_download_path = + static_cast(save_path)->path(); + callback.Run(default_download_path, + content::DownloadItem::TARGET_DISPOSITION_OVERWRITE, + content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, + default_download_path); + return true; + } + AtomBrowserContext* browser_context = static_cast( download_manager_->GetBrowserContext()); base::FilePath default_download_path = browser_context->prefs()->GetFilePath( @@ -123,14 +131,6 @@ bool AtomDownloadManagerDelegate::DetermineDownloadTarget( default_download_path = path.Append(FILE_PATH_LITERAL("Downloads")); } - if (!download->GetForcedFilePath().empty()) { - callback.Run(download->GetForcedFilePath(), - content::DownloadItem::TARGET_DISPOSITION_OVERWRITE, - content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, - download->GetForcedFilePath()); - return true; - } - CreateDownloadPathCallback download_path_callback = base::Bind(&AtomDownloadManagerDelegate::OnDownloadPathGenerated, weak_ptr_factory_.GetWeakPtr(), diff --git a/atom/browser/atom_download_manager_delegate.h b/atom/browser/atom_download_manager_delegate.h index d518e16bcbd..d602cb9aca8 100644 --- a/atom/browser/atom_download_manager_delegate.h +++ b/atom/browser/atom_download_manager_delegate.h @@ -49,7 +49,6 @@ class AtomDownloadManagerDelegate : public content::DownloadManagerDelegate { private: content::DownloadManager* download_manager_; base::WeakPtrFactory weak_ptr_factory_; - bool open_download_dialog_; DISALLOW_COPY_AND_ASSIGN(AtomDownloadManagerDelegate); }; diff --git a/docs/api/download-item.md b/docs/api/download-item.md index 7b496dbc2b1..d18433c3fe2 100644 --- a/docs/api/download-item.md +++ b/docs/api/download-item.md @@ -5,16 +5,15 @@ is used in `will-download` event of `Session` module, and allows users to control the download item. ```javascript -// Disable showing the download saving dialog. -win.webContents.session.setOpenDownloadDialog(false); - +// In the main process. win.webContents.session.on('will-download', function(event, item, webContents) { - console.log("Download from " + item.getURL()); + // Set the save path, making Electron not to prompt a save dialog. + item.setSavePath('/tmp/save.pdf'); console.log(item.getMimeType()); console.log(item.getSuggestedFilename()); console.log(item.getTotalBytes()); item.on('updated', function() { - console.log('Recived bytes: ' + item.getReceiveBytes()); + console.log('Recived bytes: ' + item.getReceivedBytes()); }); item.on('done', function(e, state) { if (state == "completed") { @@ -48,6 +47,14 @@ download that can't be resumed. The `downloadItem` object has the following methods: +### `downloadItem.setSavePath(path)` + +* `path` String - Set the save file path of the download item. + +The API is only available in session's `will-download` callback function. +If user doesn't set the save path via the API, Electron will use the original +routine to determine the save path(Usually prompts a save dialog). + ### `downloadItem.pause()` Pauses the download. diff --git a/docs/api/session.md b/docs/api/session.md index 2219cf3bebb..ae0aacf4657 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -191,10 +191,3 @@ proxy-uri = ["://"][":"] Sets download saving directory. By default, the download directory will be the `Downloads` under the respective app folder. - -### `session.setOpenDownloadDialog(openDownloadDialog)` - -* `openDownloadDialog` Boolean - Whether a download saving dialog will be - prompted when the download starts. - -By default, the download saving dialog is enable in Electron. diff --git a/spec/api-session-spec.coffee b/spec/api-session-spec.coffee index fe5765b45fd..fb036bc412b 100644 --- a/spec/api-session-spec.coffee +++ b/spec/api-session-spec.coffee @@ -75,15 +75,11 @@ describe 'session module', -> w.webContents.send 'getcount' describe 'DownloadItem', -> - # A 5MB mock pdf. - mockPDF = new Buffer(1024*1024*5) + # A 5 MB mock pdf. + mockPDF = new Buffer 1024 * 1024 * 5 contentDisposition = 'inline; filename="mock.pdf"' - # TODO(hokein): Change the download directory to spec/fixtures directory. - # We have to use the # default download directory due to the broken - # session.setDownloadPath API is broken. Once the API is fixed, we can make - # this change. - defaultDownloadDir = path.join app.getPath('userData'), 'Downloads' - downloadFilePath = path.join defaultDownloadDir, "mock.pdf" + ipc = require 'ipc' + downloadFilePath = path.join fixtures, 'mock.pdf' downloadServer = http.createServer (req, res) -> res.writeHead 200, { 'Content-Length': mockPDF.length, @@ -96,29 +92,30 @@ describe 'session module', -> it 'can download successfully', (done) -> downloadServer.listen 0, '127.0.0.1', -> {port} = downloadServer.address() + ipc.sendSync 'set-download-option', false w.loadUrl "#{url}:#{port}" - w.webContents.session.setOpenDownloadDialog false - - w.webContents.session.once 'will-download', (e, item, webContents) -> - item.on 'done', (e, state) -> - assert.equal state, "completed" - assert.equal item.getContentDisposition(), contentDisposition - assert.equal item.getReceiveBytes(), mockPDF.length - assert.equal item.getTotalBytes(), mockPDF.length - assert fs.existsSync downloadFilePath - fs.unlinkSync downloadFilePath - done() - assert.equal item.getURL(), "#{url}:#{port}/" - assert.equal item.getMimeType(), "application/pdf" + ipc.once 'download-done', (state, url, mimeType, receivedBytes, + totalBytes, disposition) -> + assert.equal state, 'completed' + assert.equal url, "http://127.0.0.1:#{port}/" + assert.equal mimeType, 'application/pdf' + assert.equal receivedBytes, mockPDF.length + assert.equal totalBytes, mockPDF.length + assert.equal disposition, contentDisposition + assert fs.existsSync downloadFilePath + fs.unlinkSync downloadFilePath + done() it 'can cancel download', (done) -> downloadServer.listen 0, '127.0.0.1', -> {port} = downloadServer.address() + ipc.sendSync 'set-download-option', true w.loadUrl "#{url}:#{port}/" - w.webContents.session.setOpenDownloadDialog false - w.webContents.session.once 'will-download', (e, item, webContents) -> - item.pause() - item.on 'done', (e, state) -> - assert.equal state, "cancelled" - done() - item.cancel() + ipc.once 'download-done', (state, url, mimeType, receivedBytes, + totalBytes, disposition) -> + assert.equal state, 'cancelled' + assert.equal mimeType, 'application/pdf' + assert.equal receivedBytes, 0 + assert.equal totalBytes, mockPDF.length + assert.equal disposition, contentDisposition + done() diff --git a/spec/static/main.js b/spec/static/main.js index 38ba7cc089d..6f84c3f1c7c 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -1,6 +1,7 @@ var app = require('app'); var ipc = require('ipc'); var dialog = require('dialog'); +var path = require('path'); var BrowserWindow = require('browser-window'); var window = null; @@ -73,4 +74,26 @@ app.on('ready', function() { }); if (chosen == 0) window.destroy(); }); + + // For session's download test, listen 'will-download' event in browser, and + // reply the result to renderer for verifying + var downloadFilePath = path.join(__dirname, '..', 'fixtures', 'mock.pdf'); + require('ipc').on('set-download-option', function(event, need_cancel) { + window.webContents.session.once('will-download', + function(e, item, webContents) { + item.setSavePath(downloadFilePath); + item.on('done', function(e, state) { + window.webContents.send('download-done', + state, + item.getUrl(), + item.getMimeType(), + item.getReceivedBytes(), + item.getTotalBytes(), + item.getContentDisposition()); + }); + if (need_cancel) + item.cancel(); + }); + event.returnValue = "done"; + }); }); From 39695cdb85151a41f861d222fb3191ad3507a6aa Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Sep 2015 16:17:42 +0800 Subject: [PATCH 29/47] docs: Set npm_config_runtime when using npm Refs https://github.com/mapbox/node-pre-gyp/pull/175. --- docs/tutorial/using-native-node-modules.md | 25 +++++++++++----------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/tutorial/using-native-node-modules.md b/docs/tutorial/using-native-node-modules.md index c338494cde2..0e6477fc4c0 100644 --- a/docs/tutorial/using-native-node-modules.md +++ b/docs/tutorial/using-native-node-modules.md @@ -34,6 +34,19 @@ npm install --save-dev electron-rebuild node ./node_modules/.bin/electron-rebuild ``` +### The npm Way + +You can also use `npm` to install modules. The steps are exactly the same with +Node modules, except that you need to setup some environment variables: + +```bash +export npm_config_disturl=https://atom.io/download/atom-shell +export npm_config_target=0.33.1 +export npm_config_arch=x64 +export npm_config_runtime=electron +HOME=~/.electron-gyp npm install module-name +``` + ### The node-gyp Way To build Node modules with headers of Electron, you need to tell `node-gyp` @@ -48,15 +61,3 @@ The `HOME=~/.electron-gyp` changes where to find development headers. The `--target=0.29.1` is version of Electron. The `--dist-url=...` specifies where to download the headers. The `--arch=x64` says the module is built for 64bit system. - -### The npm Way - -You can also use `npm` to install modules. The steps are exactly the same with -Node modules, except that you need to setup some environment variables: - -```bash -export npm_config_disturl=https://atom.io/download/atom-shell -export npm_config_target=0.29.1 -export npm_config_arch=x64 -HOME=~/.electron-gyp npm install module-name -``` From 1879392c7baaef8c51e2e90b6cce125b94ade572 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 24 Sep 2015 16:31:41 +0800 Subject: [PATCH 30/47] Reimplement downloadItem.getFilename API. Previously, the suggested file name(Always 'empty') returned by 'download_item->GetSuggestedFilename' is not the same with the default one saved in local disk. The patch reimplement this API allowing it to return the default file name, which is more expected from user. --- atom/browser/api/atom_api_download_item.cc | 13 ++++++++++--- atom/browser/api/atom_api_download_item.h | 2 +- atom/browser/api/lib/app.coffee | 2 +- docs/api/download-item.md | 15 +++++++-------- spec/api-session-spec.coffee | 6 ++++-- spec/static/main.js | 3 ++- 6 files changed, 25 insertions(+), 16 deletions(-) diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc index 3d150462bde..6b3dfbf3f7d 100644 --- a/atom/browser/api/atom_api_download_item.cc +++ b/atom/browser/api/atom_api_download_item.cc @@ -11,7 +11,9 @@ #include "atom/common/native_mate_converters/gurl_converter.h" #include "atom/common/node_includes.h" #include "base/memory/linked_ptr.h" +#include "base/strings/utf_string_conversions.h" #include "native_mate/dictionary.h" +#include "net/base/filename_util.h" namespace mate { @@ -112,8 +114,13 @@ bool DownloadItem::HasUserGesture() { return download_item_->HasUserGesture(); } -std::string DownloadItem::GetSuggestedFilename() { - return download_item_->GetSuggestedFilename(); +std::string DownloadItem::GetFilename() { + return base::UTF16ToUTF8(net::GenerateFileName(GetUrl(), + GetContentDisposition(), + std::string(), + download_item_->GetSuggestedFilename(), + GetMimeType(), + std::string()).LossyDisplayName()); } std::string DownloadItem::GetContentDisposition() { @@ -147,7 +154,7 @@ mate::ObjectTemplateBuilder DownloadItem::GetObjectTemplateBuilder( .SetMethod("getUrl", &DownloadItem::GetUrl) .SetMethod("getMimeType", &DownloadItem::GetMimeType) .SetMethod("hasUserGesture", &DownloadItem::HasUserGesture) - .SetMethod("getSuggestedFilename", &DownloadItem::GetSuggestedFilename) + .SetMethod("getFilename", &DownloadItem::GetFilename) .SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition) .SetMethod("setSavePath", &DownloadItem::SetSavePath); } diff --git a/atom/browser/api/atom_api_download_item.h b/atom/browser/api/atom_api_download_item.h index 3e90ced8a81..e7b30dd13aa 100644 --- a/atom/browser/api/atom_api_download_item.h +++ b/atom/browser/api/atom_api_download_item.h @@ -44,7 +44,7 @@ class DownloadItem : public mate::EventEmitter, int64 GetTotalBytes(); std::string GetMimeType(); bool HasUserGesture(); - std::string GetSuggestedFilename(); + std::string GetFilename(); std::string GetContentDisposition(); const GURL& GetUrl(); void SetSavePath(const base::FilePath& path); diff --git a/atom/browser/api/lib/app.coffee b/atom/browser/api/lib/app.coffee index 48ddd1768e8..18c80dc2b1f 100644 --- a/atom/browser/api/lib/app.coffee +++ b/atom/browser/api/lib/app.coffee @@ -16,7 +16,7 @@ wrapDownloadItem = (download_item) -> download_item.__proto__ = EventEmitter.prototype # Be compatible with old APIs. download_item.url = download_item.getUrl() - download_item.filename = download_item.getSuggestedFilename() + download_item.filename = download_item.getFilename() download_item.mimeType = download_item.getMimeType() download_item.hasUserGesture = download_item.hasUserGesture() diff --git a/docs/api/download-item.md b/docs/api/download-item.md index d18433c3fe2..722dc5d8cf7 100644 --- a/docs/api/download-item.md +++ b/docs/api/download-item.md @@ -10,10 +10,10 @@ win.webContents.session.on('will-download', function(event, item, webContents) { // Set the save path, making Electron not to prompt a save dialog. item.setSavePath('/tmp/save.pdf'); console.log(item.getMimeType()); - console.log(item.getSuggestedFilename()); + console.log(item.getFilename()); console.log(item.getTotalBytes()); item.on('updated', function() { - console.log('Recived bytes: ' + item.getReceivedBytes()); + console.log('Received bytes: ' + item.getReceivedBytes()); }); item.on('done', function(e, state) { if (state == "completed") { @@ -24,7 +24,6 @@ win.webContents.session.on('will-download', function(event, item, webContents) { }); ``` - ## Events ### Event: 'updated' @@ -79,13 +78,13 @@ Returns a `String` represents the mime type. Returns a `Boolean` indicates whether the download has user gesture. -### `downloadItem.getSuggestedFilename()` +### `downloadItem.getFilename()` -Returns a `String` represents the suggested file name of the download file. +Returns a `String` represents the file name of the download item. -**Note:** The suggested file name is not always the same as the actual one saved -in local disk. If user changes the file name in a prompted download saving -dialog, the actual name of saved file will be different with the suggested one. +**Note:** The file name is not always the same as the actual one saved in local +disk. If user changes the file name in a prompted download saving dialog, the +actual name of saved file will be different. ### `downloadItem.getTotalBytes()` diff --git a/spec/api-session-spec.coffee b/spec/api-session-spec.coffee index fb036bc412b..9e083d27c0f 100644 --- a/spec/api-session-spec.coffee +++ b/spec/api-session-spec.coffee @@ -95,8 +95,9 @@ describe 'session module', -> ipc.sendSync 'set-download-option', false w.loadUrl "#{url}:#{port}" ipc.once 'download-done', (state, url, mimeType, receivedBytes, - totalBytes, disposition) -> + totalBytes, disposition, filename) -> assert.equal state, 'completed' + assert.equal filename, 'mock.pdf' assert.equal url, "http://127.0.0.1:#{port}/" assert.equal mimeType, 'application/pdf' assert.equal receivedBytes, mockPDF.length @@ -112,8 +113,9 @@ describe 'session module', -> ipc.sendSync 'set-download-option', true w.loadUrl "#{url}:#{port}/" ipc.once 'download-done', (state, url, mimeType, receivedBytes, - totalBytes, disposition) -> + totalBytes, disposition, filename) -> assert.equal state, 'cancelled' + assert.equal filename, 'mock.pdf' assert.equal mimeType, 'application/pdf' assert.equal receivedBytes, 0 assert.equal totalBytes, mockPDF.length diff --git a/spec/static/main.js b/spec/static/main.js index 6f84c3f1c7c..5b10bb6d43d 100644 --- a/spec/static/main.js +++ b/spec/static/main.js @@ -89,7 +89,8 @@ app.on('ready', function() { item.getMimeType(), item.getReceivedBytes(), item.getTotalBytes(), - item.getContentDisposition()); + item.getContentDisposition(), + item.getFilename()); }); if (need_cancel) item.cancel(); From fc422e5d552e2c3f30e0d7bc2864de596880b6e1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Sep 2015 18:08:56 +0800 Subject: [PATCH 31/47] spec: Increase timeout for setTimeout test --- spec/node-spec.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/node-spec.coffee b/spec/node-spec.coffee index c8d569e01ad..fc3fcc57f8d 100644 --- a/spec/node-spec.coffee +++ b/spec/node-spec.coffee @@ -66,6 +66,7 @@ describe 'node feature', -> describe 'contexts', -> describe 'setTimeout in fs callback', -> it 'does not crash', (done) -> + @timeout 10000 fs.readFile __filename, -> setTimeout done, 0 From da57a3101fc1539fdeeaae9ff628f29ada29f60a Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Sep 2015 18:15:57 +0800 Subject: [PATCH 32/47] Call WasShown when showing window Otherwise WebContents would be invisible when window is hidden at first and then show later. Refs #2879. --- atom/browser/native_window_mac.mm | 4 ++++ atom/browser/native_window_views.cc | 3 +++ 2 files changed, 7 insertions(+) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 9555914c899..6a99f1cf422 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -467,6 +467,8 @@ bool NativeWindowMac::IsFocused() { } void NativeWindowMac::Show() { + web_contents()->WasShown(); + // This method is supposed to put focus on window, however if the app does not // have focus then "makeKeyAndOrderFront" will only show the window. [NSApp activateIgnoringOtherApps:YES]; @@ -475,11 +477,13 @@ void NativeWindowMac::Show() { } void NativeWindowMac::ShowInactive() { + web_contents()->WasShown(); [window_ orderFrontRegardless]; } void NativeWindowMac::Hide() { [window_ orderOut:nil]; + web_contents()->WasHidden(); } bool NativeWindowMac::IsVisible() { diff --git a/atom/browser/native_window_views.cc b/atom/browser/native_window_views.cc index 45697c96683..70707219f3f 100644 --- a/atom/browser/native_window_views.cc +++ b/atom/browser/native_window_views.cc @@ -338,15 +338,18 @@ bool NativeWindowViews::IsFocused() { } void NativeWindowViews::Show() { + web_contents()->WasShown(); window_->native_widget_private()->ShowWithWindowState(GetRestoredState()); } void NativeWindowViews::ShowInactive() { + web_contents()->WasShown(); window_->ShowInactive(); } void NativeWindowViews::Hide() { window_->Hide(); + web_contents()->WasHidden(); } bool NativeWindowViews::IsVisible() { From 06cc1339597fa5b75f14a7695f6517100f23fcc6 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Thu, 24 Sep 2015 19:31:09 +0800 Subject: [PATCH 33/47] Some cleanup. --- atom/browser/api/atom_api_download_item.h | 8 +++++--- atom/browser/atom_download_manager_delegate.h | 1 - 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/atom/browser/api/atom_api_download_item.h b/atom/browser/api/atom_api_download_item.h index e7b30dd13aa..14074a4bed0 100644 --- a/atom/browser/api/atom_api_download_item.h +++ b/atom/browser/api/atom_api_download_item.h @@ -28,10 +28,13 @@ class DownloadItem : public mate::EventEmitter, base::FilePath path_; }; - explicit DownloadItem(content::DownloadItem* download_item); - ~DownloadItem(); static mate::Handle Create(v8::Isolate* isolate, content::DownloadItem* item); + static void* UserDataKey(); + + protected: + explicit DownloadItem(content::DownloadItem* download_item); + ~DownloadItem(); // Override content::DownloadItem::Observer methods void OnDownloadUpdated(content::DownloadItem* download) override; @@ -49,7 +52,6 @@ class DownloadItem : public mate::EventEmitter, const GURL& GetUrl(); void SetSavePath(const base::FilePath& path); - static void* UserDataKey(); private: // mate::Wrappable: mate::ObjectTemplateBuilder GetObjectTemplateBuilder( diff --git a/atom/browser/atom_download_manager_delegate.h b/atom/browser/atom_download_manager_delegate.h index d602cb9aca8..2df3a7d45a6 100644 --- a/atom/browser/atom_download_manager_delegate.h +++ b/atom/browser/atom_download_manager_delegate.h @@ -34,7 +34,6 @@ class AtomDownloadManagerDelegate : public content::DownloadManagerDelegate { void OnDownloadPathGenerated(uint32 download_id, const content::DownloadTargetCallback& callback, const base::FilePath& default_path); - void SetOpenDownloadDialog(bool open_download_dialog); // content::DownloadManagerDelegate: void Shutdown() override; From a0638fe801fc0c502f2bd6c42923e098c02b5ee1 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Thu, 24 Sep 2015 21:06:24 +0800 Subject: [PATCH 34/47] spec: Suppress the setTimeout test on Travis CI Not sure why it failed there. --- spec/node-spec.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/node-spec.coffee b/spec/node-spec.coffee index fc3fcc57f8d..969fc76f41f 100644 --- a/spec/node-spec.coffee +++ b/spec/node-spec.coffee @@ -65,8 +65,8 @@ describe 'node feature', -> describe 'contexts', -> describe 'setTimeout in fs callback', -> + return if process.env.TRAVIS is 'true' it 'does not crash', (done) -> - @timeout 10000 fs.readFile __filename, -> setTimeout done, 0 From 01f06431423195891f6f6f63f3135d83ec8eca20 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 25 Sep 2015 09:34:04 +0800 Subject: [PATCH 35/47] Fix inconsistent docs: downloadItem.getURL() => downloadItem.getUrl() --- docs/api/download-item.md | 2 +- docs/api/session.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/api/download-item.md b/docs/api/download-item.md index 722dc5d8cf7..5097fde83f5 100644 --- a/docs/api/download-item.md +++ b/docs/api/download-item.md @@ -66,7 +66,7 @@ Resumes the download that has been paused. Cancels the download operation. -### `downloadItem.getURL()` +### `downloadItem.getUrl()` Returns a `String` represents the origin url where the item is downloaded from. diff --git a/docs/api/session.md b/docs/api/session.md index ae0aacf4657..64991ab7530 100644 --- a/docs/api/session.md +++ b/docs/api/session.md @@ -28,7 +28,7 @@ Calling `event.preventDefault()` will cancel the download. ```javascript session.on('will-download', function(event, item, webContents) { event.preventDefault(); - require('request')(item.getURL(), function(data) { + require('request')(item.getUrl(), function(data) { require('fs').writeFileSync('/somewhere', data); }); }); From 109d8352e1f0970c3382a89ff72289065a04af49 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Sep 2015 12:52:16 +0800 Subject: [PATCH 36/47] Update node, fixes #2894 --- vendor/node | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/node b/vendor/node index d64246490d6..558bfc04829 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit d64246490d697f387b888391b1aba65032703a0f +Subproject commit 558bfc048294acb57f702f1a802eddd01ebf2794 From 004d3ced5323f55fb094c400365d21edcf4e109c Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Sep 2015 13:04:54 +0800 Subject: [PATCH 37/47] Update node to fix building on Windows --- vendor/node | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/node b/vendor/node index 558bfc04829..ac25693ad1d 160000 --- a/vendor/node +++ b/vendor/node @@ -1 +1 @@ -Subproject commit 558bfc048294acb57f702f1a802eddd01ebf2794 +Subproject commit ac25693ad1d4c248e69a89147fd3995c3bf6c946 From 4a64d1d9467e00748f4e157af664a51aed564e38 Mon Sep 17 00:00:00 2001 From: Haojian Wu Date: Fri, 25 Sep 2015 13:13:11 +0800 Subject: [PATCH 38/47] :memo: fix a typo interrputed => interrupted --- atom/browser/api/atom_api_download_item.cc | 2 +- docs/api/download-item.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/atom/browser/api/atom_api_download_item.cc b/atom/browser/api/atom_api_download_item.cc index 6b3dfbf3f7d..ec4dcd84b28 100644 --- a/atom/browser/api/atom_api_download_item.cc +++ b/atom/browser/api/atom_api_download_item.cc @@ -30,7 +30,7 @@ struct Converter { download_state = "cancelled"; break; case content::DownloadItem::INTERRUPTED: - download_state = "interrputed"; + download_state = "interrupted"; break; default: break; diff --git a/docs/api/download-item.md b/docs/api/download-item.md index 5097fde83f5..53cd56cca9e 100644 --- a/docs/api/download-item.md +++ b/docs/api/download-item.md @@ -39,7 +39,7 @@ Emits when the `downloadItem` gets updated. * `interrupted` - An error broke the connection with the file server. Emits when the download is in a terminal state. This includes a completed -download, a cancelled download(via `downloadItem.cancel()`), and interrputed +download, a cancelled download(via `downloadItem.cancel()`), and interrupted download that can't be resumed. ## Methods From 6f944ad49b85b772166fb14951c9a4c8ce4b963d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Sep 2015 16:21:08 +0800 Subject: [PATCH 39/47] Clean up code --- atom/browser/native_window_mac.mm | 36 ++++++++++++++----------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index 6a99f1cf422..c87e4b2dca1 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -351,21 +351,19 @@ NativeWindowMac::NativeWindowMac( bool useStandardWindow = true; options.Get(switches::kStandardWindow, &useStandardWindow); + // New title bar styles are available in Yosemite or newer + std::string titleBarStyle; + if (base::mac::IsOSYosemiteOrLater()) + options.Get(switches::kTitleBarStyle, &titleBarStyle); + NSUInteger styleMask = NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask; if (!useStandardWindow || transparent() || !has_frame()) { styleMask |= NSTexturedBackgroundWindowMask; } - - std::string titleBarStyle = "default"; - options.Get(switches::kTitleBarStyle, &titleBarStyle); - - if (base::mac::IsOSYosemiteOrLater()) { - // New title bar styles are available in Yosemite or newer - if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) { - styleMask |= NSFullSizeContentViewWindowMask; - styleMask |= NSUnifiedTitleAndToolbarWindowMask; - } + if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) { + styleMask |= NSFullSizeContentViewWindowMask; + styleMask |= NSUnifiedTitleAndToolbarWindowMask; } window_.reset([[AtomNSWindow alloc] @@ -394,16 +392,14 @@ NativeWindowMac::NativeWindowMac( [window_ setReleasedWhenClosed:NO]; // Configure title bar look on Yosemite or newer - if (base::mac::IsOSYosemiteOrLater()) { - if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) { - [window_ setTitlebarAppearsTransparent:YES]; - [window_ setTitleVisibility:NSWindowTitleHidden]; - if (titleBarStyle == "hidden-inset") { - NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]; - toolbar.showsBaselineSeparator = NO; - [window_ setToolbar:toolbar]; - [toolbar release]; - } + if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) { + [window_ setTitlebarAppearsTransparent:YES]; + [window_ setTitleVisibility:NSWindowTitleHidden]; + if (titleBarStyle == "hidden-inset") { + base::scoped_nsobject toolbar( + [[NSToolbar alloc] initWithIdentifier:@"titlebarStylingToolbar"]); + [toolbar setShowsBaselineSeparator:NO]; + [window_ setToolbar:toolbar]; } } From 7884a2319c5fb65c262435efc274c0f362c4f87e Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Sep 2015 16:38:36 +0800 Subject: [PATCH 40/47] osx: Make draggable region work for window with hidden titlebar --- atom/browser/native_window.cc | 3 ++- atom/browser/native_window.h | 10 ++++++++++ atom/browser/native_window_mac.mm | 9 ++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/atom/browser/native_window.cc b/atom/browser/native_window.cc index e06633d7b7c..c3620bba705 100644 --- a/atom/browser/native_window.cc +++ b/atom/browser/native_window.cc @@ -68,6 +68,7 @@ NativeWindow::NativeWindow( const mate::Dictionary& options) : content::WebContentsObserver(inspectable_web_contents->GetWebContents()), has_frame_(true), + force_using_draggable_region_(false), transparent_(false), enable_larger_than_screen_(false), is_closed_(false), @@ -473,7 +474,7 @@ bool NativeWindow::OnMessageReceived(const IPC::Message& message) { void NativeWindow::UpdateDraggableRegions( const std::vector& regions) { // Draggable region is not supported for non-frameless window. - if (has_frame_) + if (has_frame_ && !force_using_draggable_region_) return; draggable_region_ = DraggableRegionsToSkRegion(regions); } diff --git a/atom/browser/native_window.h b/atom/browser/native_window.h index e9a2b9433d1..5c8d8c73b0f 100644 --- a/atom/browser/native_window.h +++ b/atom/browser/native_window.h @@ -219,6 +219,13 @@ class NativeWindow : public content::WebContentsObserver, bool enable_larger_than_screen() const { return enable_larger_than_screen_; } gfx::ImageSkia icon() const { return icon_; } + bool force_using_draggable_region() const { + return force_using_draggable_region_; + } + void set_force_using_draggable_region(bool force) { + force_using_draggable_region_ = true; + } + void set_has_dialog_attached(bool has_dialog_attached) { has_dialog_attached_ = has_dialog_attached; } @@ -257,6 +264,9 @@ class NativeWindow : public content::WebContentsObserver, // Whether window has standard frame. bool has_frame_; + // Force the window to be aware of draggable regions. + bool force_using_draggable_region_; + // Whether window is transparent. bool transparent_; diff --git a/atom/browser/native_window_mac.mm b/atom/browser/native_window_mac.mm index c87e4b2dca1..f0a685e4d95 100644 --- a/atom/browser/native_window_mac.mm +++ b/atom/browser/native_window_mac.mm @@ -391,7 +391,7 @@ NativeWindowMac::NativeWindowMac( // We will manage window's lifetime ourselves. [window_ setReleasedWhenClosed:NO]; - // Configure title bar look on Yosemite or newer + // Hide the title bar. if ((titleBarStyle == "hidden") || (titleBarStyle == "hidden-inset")) { [window_ setTitlebarAppearsTransparent:YES]; [window_ setTitleVisibility:NSWindowTitleHidden]; @@ -401,6 +401,8 @@ NativeWindowMac::NativeWindowMac( [toolbar setShowsBaselineSeparator:NO]; [window_ setToolbar:toolbar]; } + // We should be aware of draggable regions when using hidden titlebar. + set_force_using_draggable_region(true); } // On OS X the initial window size doesn't include window frame. @@ -432,6 +434,11 @@ NativeWindowMac::NativeWindowMac( [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; InstallView(); + + // Install the DraggableRegionView if it is forced to use draggable regions + // for normal window. + if (has_frame() && force_using_draggable_region()) + InstallDraggableRegionView(); } NativeWindowMac::~NativeWindowMac() { From c0528c5049dc42ab191367b0a463274f72f46818 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 25 Sep 2015 17:50:53 +0800 Subject: [PATCH 41/47] Bump v0.33.2 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 2 +- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/atom.gyp b/atom.gyp index 3a46f242a23..41d671d7a29 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.33.1', + 'version%': '0.33.2', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 6260173b825..745b12520c2 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,7 +17,7 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.33.1 + 0.33.2 LSMinimumSystemVersion 10.8.0 NSMainNibFile diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index 0583c2df3be..e0b9fa5cfe8 100644 --- a/atom/browser/resources/win/atom.rc +++ b/atom/browser/resources/win/atom.rc @@ -56,8 +56,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,33,1,0 - PRODUCTVERSION 0,33,1,0 + FILEVERSION 0,33,2,0 + PRODUCTVERSION 0,33,2,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.33.1" + VALUE "FileVersion", "0.33.2" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.33.1" + VALUE "ProductVersion", "0.33.2" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 5f9d0f3ca0b..56dcd67fb0f 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -7,7 +7,7 @@ #define ATOM_MAJOR_VERSION 0 #define ATOM_MINOR_VERSION 33 -#define ATOM_PATCH_VERSION 1 +#define ATOM_PATCH_VERSION 2 #define ATOM_VERSION_IS_RELEASE 1 From 775c90b7337bcb74a3d5d21f803f4a7034c6ff24 Mon Sep 17 00:00:00 2001 From: Josh Abernathy Date: Fri, 25 Sep 2015 11:37:30 -0400 Subject: [PATCH 42/47] Use 0.8.0. This picks up the fix for https://github.com/atom/atom/issues/7061. --- script/update-external-binaries.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/update-external-binaries.py b/script/update-external-binaries.py index 49e73435ab5..fae268ea8cb 100755 --- a/script/update-external-binaries.py +++ b/script/update-external-binaries.py @@ -8,7 +8,7 @@ from lib.config import get_target_arch from lib.util import safe_mkdir, rm_rf, extract_zip, tempdir, download -VERSION = 'v0.7.0' +VERSION = 'v0.8.0' SOURCE_ROOT = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) FRAMEWORKS_URL = 'http://github.com/atom/atom-shell-frameworks/releases' \ '/download/' + VERSION From 56520159f73ba6fbc3faa41a6c0977e923c4e088 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Sat, 26 Sep 2015 10:36:26 +0900 Subject: [PATCH 43/47] Update as upstream, fix small typo --- docs-translations/ko-KR/api/session.md | 8 ++---- .../ko-KR/tutorial/quick-start.md | 1 + .../tutorial/using-native-node-modules.md | 27 ++++++++++--------- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/docs-translations/ko-KR/api/session.md b/docs-translations/ko-KR/api/session.md index cb912aabb10..4c6ead1647f 100644 --- a/docs-translations/ko-KR/api/session.md +++ b/docs-translations/ko-KR/api/session.md @@ -17,11 +17,7 @@ var session = win.webContents.session ### Event: 'will-download' * `event` Event -* `item` Object - * `url` String - * `filename` String - * `mimeType` String - * `hasUserGesture` Boolean +* `item` [DownloadItem](download-item.md) * `webContents` [WebContents](web-contents.md) Electron의 `webContents`에서 `item`을 다운로드할 때 발생하는 이벤트입니다. @@ -31,7 +27,7 @@ Electron의 `webContents`에서 `item`을 다운로드할 때 발생하는 이 ```javascript session.on('will-download', function(event, item, webContents) { event.preventDefault(); - require('request')(item.url, function(data) { + require('request')(item.getUrl(), function(data) { require('fs').writeFileSync('/somewhere', data); }); }); diff --git a/docs-translations/ko-KR/tutorial/quick-start.md b/docs-translations/ko-KR/tutorial/quick-start.md index 8c2e043061e..4a6ce6d2252 100644 --- a/docs-translations/ko-KR/tutorial/quick-start.md +++ b/docs-translations/ko-KR/tutorial/quick-start.md @@ -111,6 +111,7 @@ app.on('ready', function() { + 헬로 월드! diff --git a/docs-translations/ko-KR/tutorial/using-native-node-modules.md b/docs-translations/ko-KR/tutorial/using-native-node-modules.md index 913c300be88..ed64abb492f 100644 --- a/docs-translations/ko-KR/tutorial/using-native-node-modules.md +++ b/docs-translations/ko-KR/tutorial/using-native-node-modules.md @@ -29,7 +29,20 @@ npm install --save-dev electron-rebuild node ./node_modules/.bin/electron-rebuild ``` -### node-gyp을 이용한 방법 +### `npm`을 이용한 방법 + +또한 `npm`을 통해 설치할 수도 있습니다. +환경변수가 필요한 것을 제외하고 일반 Node 모듈을 설치하는 방법과 완전히 똑같습니다: + +```bash +export npm_config_disturl=https://atom.io/download/atom-shell +export npm_config_target=0.33.1 +export npm_config_arch=x64 +export npm_config_runtime=electron +HOME=~/.electron-gyp npm install module-name +``` + +### `node-gyp`를 이용한 방법 Node 모듈을 `node-gyp`를 사용하여 Electron을 타겟으로 빌드할 때는 `node-gyp`에 헤더 다운로드 주소와 버전을 알려주어야 합니다: @@ -40,15 +53,3 @@ $ HOME=~/.electron-gyp node-gyp rebuild --target=0.29.1 --arch=x64 --dist-url=ht `HOME=~/.electron-gyp`은 변경할 헤더의 위치를 찾습니다. `--target=0.29.1`은 Electron의 버전입니다. `--dist-url=...`은 헤더를 다운로드 하는 주소입니다. `--arch=x64`는 64비트 시스템을 타겟으로 빌드 한다는 것을 `node-gyp`에게 알려줍니다. - -### npm을 이용한 방법 - -또한 `npm`을 통해 설치할 수도 있습니다. -환경변수가 필요한 것을 제외하고 일반 Node 모듈을 설치하는 방법과 완전히 똑같습니다: - -```bash -export npm_config_disturl=https://atom.io/download/atom-shell -export npm_config_target=0.29.1 -export npm_config_arch=x64 -HOME=~/.electron-gyp npm install module-name -``` From 690f859a78cb1928b299fc126b8f8720044cdc33 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Sat, 26 Sep 2015 22:06:01 +0800 Subject: [PATCH 44/47] Bump v0.33.3 --- atom.gyp | 2 +- atom/browser/resources/mac/Info.plist | 2 +- atom/browser/resources/win/atom.rc | 8 ++++---- atom/common/atom_version.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/atom.gyp b/atom.gyp index 41d671d7a29..42069ea8462 100644 --- a/atom.gyp +++ b/atom.gyp @@ -4,7 +4,7 @@ 'product_name%': 'Electron', 'company_name%': 'GitHub, Inc', 'company_abbr%': 'github', - 'version%': '0.33.2', + 'version%': '0.33.3', }, 'includes': [ 'filenames.gypi', diff --git a/atom/browser/resources/mac/Info.plist b/atom/browser/resources/mac/Info.plist index 745b12520c2..eb39cb35f94 100644 --- a/atom/browser/resources/mac/Info.plist +++ b/atom/browser/resources/mac/Info.plist @@ -17,7 +17,7 @@ CFBundleIconFile atom.icns CFBundleVersion - 0.33.2 + 0.33.3 LSMinimumSystemVersion 10.8.0 NSMainNibFile diff --git a/atom/browser/resources/win/atom.rc b/atom/browser/resources/win/atom.rc index e0b9fa5cfe8..6fba6cf8067 100644 --- a/atom/browser/resources/win/atom.rc +++ b/atom/browser/resources/win/atom.rc @@ -56,8 +56,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,33,2,0 - PRODUCTVERSION 0,33,2,0 + FILEVERSION 0,33,3,0 + PRODUCTVERSION 0,33,3,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -74,12 +74,12 @@ BEGIN BEGIN VALUE "CompanyName", "GitHub, Inc." VALUE "FileDescription", "Electron" - VALUE "FileVersion", "0.33.2" + VALUE "FileVersion", "0.33.3" VALUE "InternalName", "electron.exe" VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved." VALUE "OriginalFilename", "electron.exe" VALUE "ProductName", "Electron" - VALUE "ProductVersion", "0.33.2" + VALUE "ProductVersion", "0.33.3" VALUE "SquirrelAwareVersion", "1" END END diff --git a/atom/common/atom_version.h b/atom/common/atom_version.h index 56dcd67fb0f..4f240347540 100644 --- a/atom/common/atom_version.h +++ b/atom/common/atom_version.h @@ -7,7 +7,7 @@ #define ATOM_MAJOR_VERSION 0 #define ATOM_MINOR_VERSION 33 -#define ATOM_PATCH_VERSION 2 +#define ATOM_PATCH_VERSION 3 #define ATOM_VERSION_IS_RELEASE 1 From 9f30e5f52635c797f633fbbc1c4417f1fad5664b Mon Sep 17 00:00:00 2001 From: Gohy Leandre Date: Sat, 26 Sep 2015 17:23:34 +0200 Subject: [PATCH 45/47] Add ability to preload modules (--require, -r) --- atom/browser/default_app/main.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/atom/browser/default_app/main.js b/atom/browser/default_app/main.js index 4d854dc35cb..1b92685d13a 100644 --- a/atom/browser/default_app/main.js +++ b/atom/browser/default_app/main.js @@ -13,8 +13,8 @@ app.on('window-all-closed', function() { // Parse command line options. var argv = process.argv.slice(1); -var option = { file: null, help: null, version: null, webdriver: null }; -for (var i in argv) { +var option = { file: null, help: null, version: null, webdriver: null, modules: [] }; +for (var i = 0; i < argv.length; i++) { if (argv[i] == '--version' || argv[i] == '-v') { option.version = true; break; @@ -23,6 +23,9 @@ for (var i in argv) { break; } else if (argv[i] == '--test-type=webdriver') { option.webdriver = true; + } else if (argv[i] == '--require' || argv[i] == '-r') { + option.modules.push(argv[++i]); + continue; } else if (argv[i][0] == '-') { continue; } else { @@ -212,6 +215,10 @@ app.once('ready', function() { Menu.setApplicationMenu(menu); }); +if (option.modules.length > 0) { + require('module')._preloadModules(option.modules); +} + // Start the specified app if there is one specified in command line, otherwise // start the default app. if (option.file && !option.webdriver) { @@ -253,6 +260,7 @@ if (option.file && !option.webdriver) { helpMessage += "A path to an Electron application may be specified. The path must be to \n"; helpMessage += "an index.js file or to a folder containing a package.json or index.js file.\n\n"; helpMessage += "Options:\n"; + helpMessage += " -r, --require Module to preload (option can be repeated)"; helpMessage += " -h, --help Print this usage message.\n"; helpMessage += " -v, --version Print the version."; console.log(helpMessage); From 457147365af2bbd3b69a0bf35cac8ce78110b76c Mon Sep 17 00:00:00 2001 From: fscherwi Date: Sun, 27 Sep 2015 14:44:28 +0200 Subject: [PATCH 46/47] standardize package.json --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 101fdeee257..a125d13b68e 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "electron", "devDependencies": { - "asar": "0.8.x", + "asar": "^0.8.0", "coffee-script": "^1.9.2", "coffeelint": "^1.9.4", "request": "*", - "runas": "3.x" + "runas": "^3.0.0" }, "private": true, "scripts": { From 397fbeae28db234b042baf144aa61f952e43d3b5 Mon Sep 17 00:00:00 2001 From: Plusb Preco Date: Sun, 27 Sep 2015 22:20:35 +0900 Subject: [PATCH 47/47] Update example variable name prefix (atom to electron) * Update variable name prefix as `atom` to `electron` --- docs-translations/ko-KR/api/screen.md | 10 +++++----- docs/api/screen.md | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs-translations/ko-KR/api/screen.md b/docs-translations/ko-KR/api/screen.md index 26975cbb1e2..5e0805749f3 100644 --- a/docs-translations/ko-KR/api/screen.md +++ b/docs-translations/ko-KR/api/screen.md @@ -6,7 +6,7 @@ `screen`은 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter)를 상속 받았습니다. **참고:** 랜더러 / DevTools에선 이미 DOM 속성이 `window.screen`을 가지고 있으므로 `screen = require('screen')` 형식으로 모듈을 사용할 수 없습니다. -밑의 예제와 같이 `atomScreen` 같은 이름으로 모듈 이름을 대체하여 사용해야 합니다. +밑의 예제와 같이 `electronScreen` 같은 이름으로 모듈 이름을 대체하여 사용해야 합니다. 다음 예제는 화면 전체를 채우는 윈도우 창을 생성합니다: @@ -17,8 +17,8 @@ var BrowserWindow = require('browser-window'); var mainWindow; app.on('ready', function() { - var atomScreen = require('screen'); - var size = atomScreen.getPrimaryDisplay().workAreaSize; + var electronScreen = require('screen'); + var size = electronScreen.getPrimaryDisplay().workAreaSize; mainWindow = new BrowserWindow({ width: size.width, height: size.height }); }); ``` @@ -32,8 +32,8 @@ var BrowserWindow = require('browser-window'); var mainWindow; app.on('ready', function() { - var atomScreen = require('screen'); - var displays = atomScreen.getAllDisplays(); + var electronScreen = require('screen'); + var displays = electronScreen.getAllDisplays(); var externalDisplay = null; for (var i in displays) { if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) { diff --git a/docs/api/screen.md b/docs/api/screen.md index 934e3eaf5a7..da15c7326f1 100644 --- a/docs/api/screen.md +++ b/docs/api/screen.md @@ -8,7 +8,7 @@ position, etc. You should not use this module until the `ready` event of the **Note:** In the renderer / DevTools, `window.screen` is a reserved DOM property, so writing `var screen = require('screen')` will not work. In our -examples below, we use `atomScreen` as the variable name instead. +examples below, we use `electronScreen` as the variable name instead. An example of creating a window that fills the whole screen: @@ -19,8 +19,8 @@ var BrowserWindow = require('browser-window'); var mainWindow; app.on('ready', function() { - var atomScreen = require('screen'); - var size = atomScreen.getPrimaryDisplay().workAreaSize; + var electronScreen = require('screen'); + var size = electronScreen.getPrimaryDisplay().workAreaSize; mainWindow = new BrowserWindow({ width: size.width, height: size.height }); }); ``` @@ -34,8 +34,8 @@ var BrowserWindow = require('browser-window'); var mainWindow; app.on('ready', function() { - var atomScreen = require('screen'); - var displays = atomScreen.getAllDisplays(); + var electronScreen = require('screen'); + var displays = electronScreen.getAllDisplays(); var externalDisplay = null; for (var i in displays) { if (displays[i].bounds.x > 0 || displays[i].bounds.y > 0) {