| Index: chrome/browser/extensions/extension_downloads.cc
|
| diff --git a/chrome/browser/extensions/extension_downloads.cc b/chrome/browser/extensions/extension_downloads.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..17730a737b67a42ee8060c6a7b27b00b750229f6
|
| --- /dev/null
|
| +++ b/chrome/browser/extensions/extension_downloads.cc
|
| @@ -0,0 +1,415 @@
|
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "chrome/browser/extensions/extension_downloads.h"
|
| +
|
| +#include <algorithm>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/logging.h"
|
| +#include "base/stl_util-inl.h"
|
| +#include "base/values.h"
|
| +#include "chrome/browser/browser_process.h"
|
| +#include "chrome/browser/download/download_create_info.h"
|
| +#include "chrome/browser/extensions/extension_event_router.h"
|
| +#include "chrome/browser/download/download_file_manager.h"
|
| +#include "chrome/browser/download/download_item.h"
|
| +#include "chrome/browser/download/download_manager.h"
|
| +#include "chrome/browser/download/download_query.h"
|
| +#include "chrome/browser/download/download_util.h"
|
| +#include "chrome/browser/icon_loader.h"
|
| +#include "chrome/browser/icon_manager.h"
|
| +#include "chrome/browser/renderer_host/chrome_render_message_filter.h"
|
| +#include "chrome/browser/ui/browser_list.h"
|
| +#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
|
| +#include "content/browser/renderer_host/render_view_host.h"
|
| +#include "content/browser/renderer_host/resource_dispatcher_host.h"
|
| +
|
| +bool DownloadsDownloadFunction::RunImpl() {
|
| + EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options_));
|
| + EXTENSION_FUNCTION_VALIDATE(options_->GetString("url", &url_));
|
| + if (url_.empty()) {
|
| + error_ = "'url' cannot be empty.";
|
| + return false;
|
| + }
|
| + rdh_ = g_browser_process->resource_dispatcher_host();
|
| + if (rdh_ == NULL) {
|
| + error_ = "I'm afraid I can't do that.";
|
| + return false;
|
| + }
|
| + VLOG(1) << __FUNCTION__ << " " << url_;
|
| + products_ = new DictionaryValue();
|
| + result_.reset(products_);
|
| + options_->GetString("filename", &filename_);
|
| + options_->GetBoolean("save_as", &save_as_);
|
| + options_->GetString("method", &method_);
|
| + options_->GetDictionary("headers", &extra_headers_);
|
| + options_->GetString("body", &post_body_);
|
| + // TODO sanity check method_, extra_headers_, filename_
|
| + dl_man_ = profile()->GetDownloadManager();
|
| + tab_contents_ = BrowserList::GetLastActive()->GetSelectedTabContentsWrapper()
|
| + ->tab_contents();
|
| + resource_context_ = &profile()->GetResourceContext();
|
| + render_process_host_id_ = tab_contents_->GetRenderProcessHost()->id();
|
| + render_view_host_routing_id_ = tab_contents_->render_view_host()
|
| + ->routing_id();
|
| + VLOG(1) << __FUNCTION__ << " " << url_;
|
| + if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, NewRunnableMethod(
|
| + this, &DownloadsDownloadFunction::BeginDownloadOnIOThread))) {
|
| + error_ = "I'm afraid I can't do that.";
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +void DownloadsDownloadFunction::BeginDownloadOnIOThread() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + DVLOG(1) << __FUNCTION__ << " " << url_;
|
| + DownloadSaveInfo save_info;
|
| + save_info.file_path = FilePath(filename_);
|
| + net::URLRequest* request = new net::URLRequest(GURL(url_), rdh_);
|
| + if (method_.empty()) {
|
| + method_ = "GET";
|
| + }
|
| + request->set_method(method_);
|
| + if (extra_headers_ != NULL) {
|
| + DictionaryValue::key_iterator headers_end = extra_headers_->end_keys();
|
| + for (DictionaryValue::key_iterator headers_iter =
|
| + extra_headers_->begin_keys();
|
| + headers_iter != headers_end; ++headers_iter) {
|
| + std::string value;
|
| + if (extra_headers_->GetStringWithoutPathExpansion(
|
| + *headers_iter, &value)) {
|
| + request->SetExtraRequestHeaderByName(
|
| + *headers_iter, value, false/*overwrite*/);
|
| + }
|
| + }
|
| + }
|
| + if (!post_body_.empty()) {
|
| + request->AppendBytesToUpload(post_body_.data(), post_body_.size());
|
| + }
|
| + rdh_->BeginDownload(
|
| + request,
|
| + save_info,
|
| + save_as_,
|
| + base::Bind(&DownloadsDownloadFunction::OnStarted, this),
|
| + render_process_host_id_,
|
| + render_view_host_routing_id_,
|
| + *resource_context_);
|
| +}
|
| +
|
| +void DownloadsDownloadFunction::OnStarted(int dl_id, int error) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| + VLOG(1) << __FUNCTION__ << " " << url_ << " " << dl_id << " " << error;
|
| + dl_id_ = dl_id;
|
| + dl_error_ = error;
|
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(
|
| + this, &DownloadsDownloadFunction::RespondOnUIThread));
|
| +}
|
| +
|
| +void DownloadsDownloadFunction::RespondOnUIThread() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + VLOG(1) << __FUNCTION__ << " " << url_ << " " << dl_man_ << " " << filename_
|
| + << " " << dl_id_ << " " << dl_error_ << " " << method_;
|
| + if (dl_id_ >= 0) {
|
| + products_->Set("id", Value::CreateIntegerValue(dl_id_));
|
| + } else {
|
| + products_->Set("error", Value::CreateIntegerValue(dl_error_));
|
| + }
|
| + SendResponse(true);
|
| +}
|
| +
|
| +bool DownloadsSearchFunction::RunImpl() {
|
| + DictionaryValue* query_json = NULL;
|
| + EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &query_json));
|
| + CHECK(query_json);
|
| + download_util::DownloadQuery query(*query_json);
|
| + DownloadManager* dlman = profile()->GetDownloadManager();
|
| + if (dlman == NULL) {
|
| + error_ = "I'm afraid I can't do that.";
|
| + return false;
|
| + }
|
| + ListValue* results = new ListValue();
|
| + if (!dlman->Search(
|
| + download_util::DownloadQuery(*query_json),
|
| + NULL/*DownloadItem results*/,
|
| + true/*merge_parent_manager*/,
|
| + &error_,
|
| + results)) {
|
| + VLOG(1) << __PRETTY_FUNCTION__ << " " << error_;
|
| + return false;
|
| + }
|
| + result_.reset(results);
|
| + return true;
|
| +}
|
| +
|
| +bool DownloadsPauseFunction::RunImpl() {
|
| + int dl_id = 0;
|
| + EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
|
| + DownloadManager* dlman = profile()->GetDownloadManager();
|
| + if (dlman == NULL) {
|
| + error_ = "I'm afraid I can't do that.";
|
| + return false;
|
| + }
|
| + DownloadItem* item = dlman->GetDownloadItem(dl_id);
|
| + if (item == NULL) {
|
| + error_ = "Non-existent download";
|
| + return false;
|
| + }
|
| + VLOG(1) << __FUNCTION__ << " " << item;
|
| + if (!item->is_paused()) {
|
| + item->TogglePause();
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool DownloadsResumeFunction::RunImpl() {
|
| + int dl_id = 0;
|
| + EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
|
| + DownloadManager* dlman = profile()->GetDownloadManager();
|
| + if (dlman == NULL) {
|
| + error_ = "I'm afraid I can't do that.";
|
| + return false;
|
| + }
|
| + DownloadItem* item = dlman->GetDownloadItem(dl_id);
|
| + if (item == NULL) {
|
| + error_ = "Non-existent download";
|
| + return false;
|
| + }
|
| + VLOG(1) << __FUNCTION__ << " " << item;
|
| + if (item->is_paused()) {
|
| + item->TogglePause();
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool DownloadsCancelFunction::RunImpl() {
|
| + int dl_id = 0;
|
| + EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
|
| + DownloadManager* dlman = profile()->GetDownloadManager();
|
| + if (dlman == NULL) {
|
| + error_ = "I'm afraid I can't do that.";
|
| + return false;
|
| + }
|
| + DownloadItem* item = dlman->GetDownloadItem(dl_id);
|
| + if (item == NULL) {
|
| + error_ = "Non-existent download";
|
| + return false;
|
| + }
|
| + VLOG(1) << __FUNCTION__ << " " << item;
|
| + item->Cancel(true);
|
| + return true;
|
| +}
|
| +
|
| +bool DownloadsEraseFunction::RunImpl() {
|
| + return true;
|
| +}
|
| +
|
| +bool DownloadsSetDestinationFunction::RunImpl() {
|
| + int dl_id = 0;
|
| + std::string rel_dest_path;
|
| + if ((args_.get() == NULL) ||
|
| + (args_->GetSize() < 2) ||
|
| + !args_->GetInteger(0, &dl_id) ||
|
| + (dl_id == 0) ||
|
| + !args_->GetString(1, &rel_dest_path) ||
|
| + rel_dest_path.empty()) return false;
|
| + DownloadManager* dlman = profile()->GetDownloadManager();
|
| + DownloadItem* item = dlman->GetDownloadItem(dl_id);
|
| + if (item == NULL) return false;
|
| + VLOG(1) << __FUNCTION__ << " " << dl_id << " " << item << " "
|
| + << rel_dest_path;
|
| + return true;
|
| +}
|
| +
|
| +bool DownloadsAcceptDangerFunction::RunImpl() {
|
| + int dl_id = 0;
|
| + EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
|
| + DownloadManager* dlman = profile()->GetDownloadManager();
|
| + if (dlman == NULL) {
|
| + error_ = "I'm afraid I can't do that.";
|
| + return false;
|
| + }
|
| + DownloadItem* item = dlman->GetDownloadItem(dl_id);
|
| + if (item == NULL) {
|
| + error_ = "Non-existent download";
|
| + return false;
|
| + }
|
| + VLOG(1) << __FUNCTION__ << " " << item;
|
| + item->Cancel(true);
|
| + return true;
|
| +}
|
| +
|
| +bool DownloadsShowFunction::RunImpl() {
|
| + int dl_id = 0;
|
| + if ((args_.get() == NULL) ||
|
| + (args_->GetSize() < 1) ||
|
| + !args_->GetInteger(0, &dl_id) ||
|
| + (dl_id == 0)) return false;
|
| + DownloadManager* dlman = profile()->GetDownloadManager();
|
| + DownloadItem* item = dlman->GetDownloadItem(dl_id);
|
| + if (item == NULL) return false;
|
| + VLOG(1) << __FUNCTION__ << " " << item;
|
| + return true;
|
| +}
|
| +
|
| +bool DownloadsDragFunction::RunImpl() {
|
| + int dl_id = 0;
|
| + if ((args_.get() == NULL) ||
|
| + (args_->GetSize() < 1) ||
|
| + !args_->GetInteger(0, &dl_id) ||
|
| + (dl_id == 0)) return false;
|
| + DownloadManager* dlman = profile()->GetDownloadManager();
|
| + DownloadItem* item = dlman->GetDownloadItem(dl_id);
|
| + if (item == NULL) return false;
|
| + IconManager* im = g_browser_process->icon_manager();
|
| + gfx::Image* icon = im->LookupIcon(item->GetUserVerifiedFilePath(),
|
| + IconLoader::NORMAL);
|
| + gfx::NativeView view = BrowserList::GetLastActive()
|
| + ->GetSelectedTabContentsWrapper()->tab_contents()->GetNativeView();
|
| + download_util::DragDownload(item, icon, view);
|
| + VLOG(1) << __FUNCTION__ << " " << dl_id;
|
| + return true;
|
| +}
|
| +
|
| +struct DownloadsEventRouter::EventListener {
|
| + std::string ext_id;
|
| + base::WeakPtr<IPC::Message::Sender> ipc_sender;
|
| +
|
| + EventListener(std::string eid, base::WeakPtr<IPC::Message::Sender> ipcs)
|
| + : ext_id(eid),
|
| + ipc_sender(ipcs) {
|
| + }
|
| + ~EventListener() {}
|
| +
|
| + void SendEvent() {
|
| + }
|
| +
|
| + // Comparator to work with std::set.
|
| + bool operator<(const EventListener& that) const {
|
| + return ext_id < that.ext_id;
|
| + }
|
| +
|
| + // Allow copy and assign.
|
| +};
|
| +
|
| +class DownloadsEventRouter::ManagerObserver
|
| + : public DownloadManager::Observer {
|
| + public:
|
| + ManagerObserver(DownloadsEventRouter* router,
|
| + ProfileId profile_id,
|
| + DownloadManager* manager)
|
| + : router_(router),
|
| + profile_id_(profile_id),
|
| + manager_(manager) {
|
| + DCHECK(router);
|
| + DCHECK(manager_);
|
| + manager_->AddObserver(this);
|
| + }
|
| + ~ManagerObserver() {
|
| + if (manager_) manager_->RemoveObserver(this);
|
| + }
|
| +
|
| + virtual void ModelChanged() {
|
| + DCHECK(manager_);
|
| + DVLOG(1) << __FUNCTION__ << " " << manager_ << " " << profile_id_ << " " << router_;
|
| + router_->DispatchEvent(DownloadsEventRouter::CHANGED, profile_id_, 0);
|
| + }
|
| +
|
| + virtual void ManagerGoingDown() {
|
| + manager_ = NULL;
|
| + }
|
| +
|
| + private:
|
| + DownloadsEventRouter* router_;
|
| + ProfileId profile_id_;
|
| + DownloadManager* manager_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ManagerObserver);
|
| +};
|
| +
|
| +class DownloadsEventRouter::ItemObserver : public DownloadItem::Observer {
|
| + public:
|
| + ItemObserver() {}
|
| + ~ItemObserver() {}
|
| +
|
| + virtual void OnDownloadUpdated(DownloadItem* download) {
|
| + DVLOG(1) << __FUNCTION__ << " " << download->id();
|
| + }
|
| +
|
| + virtual void OnDownloadOpened(DownloadItem* download) {
|
| + DVLOG(1) << __FUNCTION__ << " " << download->id();
|
| + }
|
| +
|
| + private:
|
| + DISALLOW_COPY_AND_ASSIGN(ItemObserver);
|
| +};
|
| +
|
| +DownloadsEventRouter::DownloadsEventRouter() {
|
| +}
|
| +
|
| +DownloadsEventRouter::~DownloadsEventRouter() {
|
| +}
|
| +
|
| +DownloadsEventRouter* DownloadsEventRouter::GetInstance() {
|
| + return Singleton<DownloadsEventRouter>::get();
|
| +}
|
| +
|
| +void DownloadsEventRouter::AddEventListener(
|
| + EventType event_type,
|
| + ProfileId profile_id,
|
| + const std::string& extension_id,
|
| + base::WeakPtr<IPC::Message::Sender> ipc_sender) {
|
| + DVLOG(1) << __FUNCTION__
|
| + << " " << event_type
|
| + << " " << profile_id
|
| + << " " << extension_id
|
| + << " " << BrowserThread::CurrentlyOn(BrowserThread::UI);
|
| + if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
|
| + DCHECK(BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
|
| + NewRunnableMethod(this, &DownloadsEventRouter::AddEventListener,
|
| + event_type, profile_id, extension_id, ipc_sender)));
|
| + return;
|
| + }
|
| + Profile* profile = reinterpret_cast<Profile*>(profile_id); // XXX
|
| + DownloadManager* dlman = profile->GetDownloadManager();
|
| + DCHECK(dlman);
|
| + listeners_[profile_id][event_type].insert(EventListener(
|
| + extension_id, ipc_sender));
|
| + if (manager_observers_.find(profile_id) == manager_observers_.end()) {
|
| + manager_observers_[profile_id] = new ManagerObserver(this, profile_id, dlman);
|
| + }
|
| +}
|
| +
|
| +void DownloadsEventRouter::DispatchEvent(
|
| + EventType event_type,
|
| + ProfileId profile_id,
|
| + int download_id) {
|
| + DVLOG(1) << __FUNCTION__
|
| + << " " << event_type
|
| + << " " << profile_id
|
| + << " " << download_id
|
| + << " " << BrowserThread::CurrentlyOn(BrowserThread::IO);
|
| + if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
|
| + DCHECK(BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
|
| + NewRunnableMethod(this, &DownloadsEventRouter::DispatchEvent,
|
| + event_type, profile_id, download_id)));
|
| + return;
|
| + }
|
| + LOG(ERROR) << __FUNCTION__ << " " << event_type << " " << profile_id << " " << download_id;
|
| + if (event_type == CREATED) {
|
| + //item_observers_[profile_id].insert(ItemObserver(this, profile_id));
|
| + } else if (event_type == ERASED) {
|
| + //item_observers_[profile_id];
|
| + }
|
| + const ListenerSet& listeners = listeners_[profile_id][event_type];
|
| + for (ListenerSet::iterator listener = listeners.begin();
|
| + listener != listeners.end(); ++listener) {
|
| + //(*listener)->ipc_sender->Send(new ExtensionMsg_MessageInvoke(
|
| + //MSG_ROUTING_CONTROL, (*listener)->ext_id, kDispatchEvent, args, event_url));
|
| + //ExtensionEventRouter::DispatchEvent(
|
| + // (*listener)->ipc_sender.get(), (*listener)->ext_id, (*it)->sub_event_name,
|
| + // json_args, GURL());
|
| + }
|
| +}
|
|
|