Merge pull request #4325 from atom/download-item-cleanup

Cleanup DownloadItem related code
This commit is contained in:
Cheng Zhao 2016-02-02 20:36:54 +08:00
commit 808b02edda
5 changed files with 109 additions and 108 deletions

View file

@ -48,89 +48,49 @@ namespace atom {
namespace api { namespace api {
namespace { namespace {
// The wrapDownloadItem funtion which is implemented in JavaScript // The wrapDownloadItem funtion which is implemented in JavaScript
using WrapDownloadItemCallback = base::Callback<void(v8::Local<v8::Value>)>; using WrapDownloadItemCallback = base::Callback<void(v8::Local<v8::Value>)>;
WrapDownloadItemCallback g_wrap_download_item; WrapDownloadItemCallback g_wrap_download_item;
char kDownloadItemSavePathKey[] = "DownloadItemSavePathKey";
std::map<uint32, linked_ptr<v8::Global<v8::Value>>> g_download_item_objects; std::map<uint32, linked_ptr<v8::Global<v8::Value>>> g_download_item_objects;
} // namespace } // namespace
DownloadItem::SavePathData::SavePathData(const base::FilePath& path) : DownloadItem::DownloadItem(content::DownloadItem* download_item)
path_(path) { : download_item_(download_item) {
}
const base::FilePath& DownloadItem::SavePathData::path() {
return path_;
}
DownloadItem::DownloadItem(content::DownloadItem* download_item) :
download_item_(download_item) {
download_item_->AddObserver(this); download_item_->AddObserver(this);
AttachAsUserData(download_item);
} }
DownloadItem::~DownloadItem() { DownloadItem::~DownloadItem() {
Destroy(download_item_); if (download_item_) {
} // Destroyed by either garbage collection or destroy().
download_item_->RemoveObserver(this);
void DownloadItem::Destroy(content::DownloadItem* item) { download_item_->Remove();
if (item) {
OnDownloadDestroyed(item);
MarkDestroyed();
// Destroy the native class in next tick.
base::MessageLoop::current()->PostTask(FROM_HERE, GetDestroyClosure());
} }
// Remove from the global map.
auto iter = g_download_item_objects.find(weak_map_id());
if (iter != g_download_item_objects.end())
g_download_item_objects.erase(iter);
} }
void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) { void DownloadItem::OnDownloadUpdated(content::DownloadItem* item) {
download_item_->IsDone() ? Emit("done", item->GetState()) : Emit("updated"); if (download_item_->IsDone()) {
Emit("done", item->GetState());
// Destroy the item once item is downloaded.
base::MessageLoop::current()->PostTask(FROM_HERE, GetDestroyClosure());
} else {
Emit("updated");
}
} }
void DownloadItem::OnDownloadDestroyed(content::DownloadItem* download_item) { void DownloadItem::OnDownloadDestroyed(content::DownloadItem* 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; download_item_ = nullptr;
} // Destroy the native class immediately when downloadItem is destroyed.
delete this;
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::GetFilename() {
return base::UTF16ToUTF8(net::GenerateFileName(GetURL(),
GetContentDisposition(),
std::string(),
download_item_->GetSuggestedFilename(),
GetMimeType(),
std::string()).LossyDisplayName());
}
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() { void DownloadItem::Pause() {
@ -143,6 +103,48 @@ void DownloadItem::Resume() {
void DownloadItem::Cancel() { void DownloadItem::Cancel() {
download_item_->Cancel(true); download_item_->Cancel(true);
download_item_->Remove();
}
int64 DownloadItem::GetReceivedBytes() const {
return download_item_->GetReceivedBytes();
}
int64 DownloadItem::GetTotalBytes() const {
return download_item_->GetTotalBytes();
}
std::string DownloadItem::GetMimeType() const {
return download_item_->GetMimeType();
}
bool DownloadItem::HasUserGesture() const {
return download_item_->HasUserGesture();
}
std::string DownloadItem::GetFilename() const {
return base::UTF16ToUTF8(net::GenerateFileName(GetURL(),
GetContentDisposition(),
std::string(),
download_item_->GetSuggestedFilename(),
GetMimeType(),
std::string()).LossyDisplayName());
}
std::string DownloadItem::GetContentDisposition() const {
return download_item_->GetContentDisposition();
}
const GURL& DownloadItem::GetURL() const {
return download_item_->GetURL();
}
void DownloadItem::SetSavePath(const base::FilePath& path) {
save_path_ = path;
}
base::FilePath DownloadItem::GetSavePath() const {
return save_path_;
} }
// static // static
@ -155,29 +157,31 @@ void DownloadItem::BuildPrototype(v8::Isolate* isolate,
.SetMethod("cancel", &DownloadItem::Cancel) .SetMethod("cancel", &DownloadItem::Cancel)
.SetMethod("getReceivedBytes", &DownloadItem::GetReceivedBytes) .SetMethod("getReceivedBytes", &DownloadItem::GetReceivedBytes)
.SetMethod("getTotalBytes", &DownloadItem::GetTotalBytes) .SetMethod("getTotalBytes", &DownloadItem::GetTotalBytes)
.SetMethod("getURL", &DownloadItem::GetURL)
.SetMethod("getMimeType", &DownloadItem::GetMimeType) .SetMethod("getMimeType", &DownloadItem::GetMimeType)
.SetMethod("hasUserGesture", &DownloadItem::HasUserGesture) .SetMethod("hasUserGesture", &DownloadItem::HasUserGesture)
.SetMethod("getFilename", &DownloadItem::GetFilename) .SetMethod("getFilename", &DownloadItem::GetFilename)
.SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition) .SetMethod("getContentDisposition", &DownloadItem::GetContentDisposition)
.SetMethod("setSavePath", &DownloadItem::SetSavePath); .SetMethod("getURL", &DownloadItem::GetURL)
.SetMethod("setSavePath", &DownloadItem::SetSavePath)
.SetMethod("getSavePath", &DownloadItem::GetSavePath);
} }
// static // static
mate::Handle<DownloadItem> DownloadItem::Create( mate::Handle<DownloadItem> DownloadItem::Create(
v8::Isolate* isolate, content::DownloadItem* item) { v8::Isolate* isolate, content::DownloadItem* item) {
auto existing = TrackableObject::FromWrappedClass(isolate, item);
if (existing)
return mate::CreateHandle(isolate, static_cast<DownloadItem*>(existing));
auto handle = mate::CreateHandle(isolate, new DownloadItem(item)); auto handle = mate::CreateHandle(isolate, new DownloadItem(item));
g_wrap_download_item.Run(handle.ToV8()); g_wrap_download_item.Run(handle.ToV8());
g_download_item_objects[item->GetId()] = make_linked_ptr(
// Reference this object in case it got garbage collected.
g_download_item_objects[handle->weak_map_id()] = make_linked_ptr(
new v8::Global<v8::Value>(isolate, handle.ToV8())); new v8::Global<v8::Value>(isolate, handle.ToV8()));
return handle; return handle;
} }
// static
void* DownloadItem::UserDataKey() {
return &kDownloadItemSavePathKey;
}
void ClearWrapDownloadItem() { void ClearWrapDownloadItem() {
g_wrap_download_item.Reset(); g_wrap_download_item.Reset();
} }

View file

@ -20,23 +20,25 @@ namespace api {
class DownloadItem : public mate::TrackableObject<DownloadItem>, class DownloadItem : public mate::TrackableObject<DownloadItem>,
public content::DownloadItem::Observer { public content::DownloadItem::Observer {
public: public:
class SavePathData : public base::SupportsUserData::Data {
public:
explicit SavePathData(const base::FilePath& path);
const base::FilePath& path();
private:
base::FilePath path_;
};
static mate::Handle<DownloadItem> Create(v8::Isolate* isolate, static mate::Handle<DownloadItem> Create(v8::Isolate* isolate,
content::DownloadItem* item); content::DownloadItem* item);
static void* UserDataKey();
// mate::TrackableObject: // mate::TrackableObject:
static void BuildPrototype(v8::Isolate* isolate, static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::ObjectTemplate> prototype);
void Destroy(content::DownloadItem* download_item); void Pause();
void Resume();
void Cancel();
int64 GetReceivedBytes() const;
int64 GetTotalBytes() const;
std::string GetMimeType() const;
bool HasUserGesture() const;
std::string GetFilename() const;
std::string GetContentDisposition() const;
const GURL& GetURL() const;
void SetSavePath(const base::FilePath& path);
base::FilePath GetSavePath() const;
protected: protected:
explicit DownloadItem(content::DownloadItem* download_item); explicit DownloadItem(content::DownloadItem* download_item);
@ -46,19 +48,8 @@ class DownloadItem : public mate::TrackableObject<DownloadItem>,
void OnDownloadUpdated(content::DownloadItem* download) override; void OnDownloadUpdated(content::DownloadItem* download) override;
void OnDownloadDestroyed(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 GetFilename();
std::string GetContentDisposition();
const GURL& GetURL();
void SetSavePath(const base::FilePath& path);
private: private:
base::FilePath save_path_;
content::DownloadItem* download_item_; content::DownloadItem* download_item_;
DISALLOW_COPY_AND_ASSIGN(DownloadItem); DISALLOW_COPY_AND_ASSIGN(DownloadItem);

View file

@ -306,14 +306,12 @@ void Session::OnDownloadCreated(content::DownloadManager* manager,
auto web_contents = item->GetWebContents(); auto web_contents = item->GetWebContents();
if (SavePageHandler::IsSavePageTypes(item->GetMimeType())) if (SavePageHandler::IsSavePageTypes(item->GetMimeType()))
return; return;
auto download_item_handle = DownloadItem::Create(isolate(), item);
bool prevent_default = Emit( bool prevent_default = Emit(
"will-download", "will-download",
download_item_handle, DownloadItem::Create(isolate(), item),
api::WebContents::CreateFrom(isolate(), web_contents)); api::WebContents::CreateFrom(isolate(), web_contents));
if (prevent_default) { if (prevent_default) {
item->Cancel(true); item->Cancel(true);
download_item_handle->Destroy(item);
item->Remove(); item->Remove();
} }
} }

View file

@ -109,16 +109,24 @@ bool AtomDownloadManagerDelegate::DetermineDownloadTarget(
download->GetForcedFilePath()); download->GetForcedFilePath());
return true; return true;
} }
base::SupportsUserData::Data* save_path = download->GetUserData(
atom::api::DownloadItem::UserDataKey()); // Try to get the save path from JS wrapper.
if (save_path) { {
const base::FilePath& default_download_path = v8::Isolate* isolate = v8::Isolate::GetCurrent();
static_cast<api::DownloadItem::SavePathData*>(save_path)->path(); v8::Locker locker(isolate);
callback.Run(default_download_path, v8::HandleScope handle_scope(isolate);
content::DownloadItem::TARGET_DISPOSITION_OVERWRITE, api::DownloadItem* download_item = api::DownloadItem::FromWrappedClass(
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, isolate, download);
default_download_path); if (download_item) {
return true; base::FilePath save_path = download_item->GetSavePath();
if (!save_path.empty()) {
callback.Run(save_path,
content::DownloadItem::TARGET_DISPOSITION_OVERWRITE,
content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
save_path);
return true;
}
}
} }
AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>( AtomBrowserContext* browser_context = static_cast<AtomBrowserContext*>(

2
vendor/native_mate vendored

@ -1 +1 @@
Subproject commit 26520c5cf4b6a60da2c5cba971393f94b82f5939 Subproject commit e719eab878c264bb03188d0cd6eb9ad6882bc13a