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 000000000000..aa1e719f4857 --- /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 000000000000..31546c1c62fc --- /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 062c7500ef04..27e52e112ed0 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 f5b137eb0bb2..39f6395560a6 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 5aec200550ad..2da68854ad14 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 461c812753c9..3f40436380c1 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',