OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/extensions/extension_downloads.h" |
| 6 |
| 7 #include <algorithm> |
| 8 |
| 9 #include "base/bind.h" |
| 10 #include "base/logging.h" |
| 11 #include "base/stl_util-inl.h" |
| 12 #include "base/values.h" |
| 13 #include "chrome/browser/browser_process.h" |
| 14 #include "chrome/browser/download/download_create_info.h" |
| 15 #include "chrome/browser/extensions/extension_event_router.h" |
| 16 #include "chrome/browser/download/download_file_manager.h" |
| 17 #include "chrome/browser/download/download_item.h" |
| 18 #include "chrome/browser/download/download_manager.h" |
| 19 #include "chrome/browser/download/download_query.h" |
| 20 #include "chrome/browser/download/download_util.h" |
| 21 #include "chrome/browser/icon_loader.h" |
| 22 #include "chrome/browser/icon_manager.h" |
| 23 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" |
| 24 #include "chrome/browser/ui/browser_list.h" |
| 25 #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" |
| 26 #include "content/browser/renderer_host/render_view_host.h" |
| 27 #include "content/browser/renderer_host/resource_dispatcher_host.h" |
| 28 |
| 29 bool DownloadsDownloadFunction::RunImpl() { |
| 30 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options_)); |
| 31 EXTENSION_FUNCTION_VALIDATE(options_->GetString("url", &url_)); |
| 32 if (url_.empty()) { |
| 33 error_ = "'url' cannot be empty."; |
| 34 return false; |
| 35 } |
| 36 rdh_ = g_browser_process->resource_dispatcher_host(); |
| 37 if (rdh_ == NULL) { |
| 38 error_ = "I'm afraid I can't do that."; |
| 39 return false; |
| 40 } |
| 41 VLOG(1) << __FUNCTION__ << " " << url_; |
| 42 products_ = new DictionaryValue(); |
| 43 result_.reset(products_); |
| 44 options_->GetString("filename", &filename_); |
| 45 options_->GetBoolean("save_as", &save_as_); |
| 46 options_->GetString("method", &method_); |
| 47 options_->GetDictionary("headers", &extra_headers_); |
| 48 options_->GetString("body", &post_body_); |
| 49 // TODO sanity check method_, extra_headers_, filename_ |
| 50 dl_man_ = profile()->GetDownloadManager(); |
| 51 tab_contents_ = BrowserList::GetLastActive()->GetSelectedTabContentsWrapper() |
| 52 ->tab_contents(); |
| 53 resource_context_ = &profile()->GetResourceContext(); |
| 54 render_process_host_id_ = tab_contents_->GetRenderProcessHost()->id(); |
| 55 render_view_host_routing_id_ = tab_contents_->render_view_host() |
| 56 ->routing_id(); |
| 57 VLOG(1) << __FUNCTION__ << " " << url_; |
| 58 if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, NewRunnableMethod( |
| 59 this, &DownloadsDownloadFunction::BeginDownloadOnIOThread))) { |
| 60 error_ = "I'm afraid I can't do that."; |
| 61 return false; |
| 62 } |
| 63 return true; |
| 64 } |
| 65 |
| 66 void DownloadsDownloadFunction::BeginDownloadOnIOThread() { |
| 67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 68 DVLOG(1) << __FUNCTION__ << " " << url_; |
| 69 DownloadSaveInfo save_info; |
| 70 save_info.file_path = FilePath(filename_); |
| 71 net::URLRequest* request = new net::URLRequest(GURL(url_), rdh_); |
| 72 if (method_.empty()) { |
| 73 method_ = "GET"; |
| 74 } |
| 75 request->set_method(method_); |
| 76 if (extra_headers_ != NULL) { |
| 77 DictionaryValue::key_iterator headers_end = extra_headers_->end_keys(); |
| 78 for (DictionaryValue::key_iterator headers_iter = |
| 79 extra_headers_->begin_keys(); |
| 80 headers_iter != headers_end; ++headers_iter) { |
| 81 std::string value; |
| 82 if (extra_headers_->GetStringWithoutPathExpansion( |
| 83 *headers_iter, &value)) { |
| 84 request->SetExtraRequestHeaderByName( |
| 85 *headers_iter, value, false/*overwrite*/); |
| 86 } |
| 87 } |
| 88 } |
| 89 if (!post_body_.empty()) { |
| 90 request->AppendBytesToUpload(post_body_.data(), post_body_.size()); |
| 91 } |
| 92 rdh_->BeginDownload( |
| 93 request, |
| 94 save_info, |
| 95 save_as_, |
| 96 base::Bind(&DownloadsDownloadFunction::OnStarted, this), |
| 97 render_process_host_id_, |
| 98 render_view_host_routing_id_, |
| 99 *resource_context_); |
| 100 } |
| 101 |
| 102 void DownloadsDownloadFunction::OnStarted(int dl_id, int error) { |
| 103 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 104 VLOG(1) << __FUNCTION__ << " " << url_ << " " << dl_id << " " << error; |
| 105 dl_id_ = dl_id; |
| 106 dl_error_ = error; |
| 107 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod( |
| 108 this, &DownloadsDownloadFunction::RespondOnUIThread)); |
| 109 } |
| 110 |
| 111 void DownloadsDownloadFunction::RespondOnUIThread() { |
| 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 113 VLOG(1) << __FUNCTION__ << " " << url_ << " " << dl_man_ << " " << filename_ |
| 114 << " " << dl_id_ << " " << dl_error_ << " " << method_; |
| 115 if (dl_id_ >= 0) { |
| 116 products_->Set("id", Value::CreateIntegerValue(dl_id_)); |
| 117 } else { |
| 118 products_->Set("error", Value::CreateIntegerValue(dl_error_)); |
| 119 } |
| 120 SendResponse(true); |
| 121 } |
| 122 |
| 123 bool DownloadsSearchFunction::RunImpl() { |
| 124 DictionaryValue* query_json = NULL; |
| 125 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &query_json)); |
| 126 CHECK(query_json); |
| 127 download_util::DownloadQuery query(*query_json); |
| 128 DownloadManager* dlman = profile()->GetDownloadManager(); |
| 129 if (dlman == NULL) { |
| 130 error_ = "I'm afraid I can't do that."; |
| 131 return false; |
| 132 } |
| 133 ListValue* results = new ListValue(); |
| 134 if (!dlman->Search( |
| 135 download_util::DownloadQuery(*query_json), |
| 136 NULL/*DownloadItem results*/, |
| 137 true/*merge_parent_manager*/, |
| 138 &error_, |
| 139 results)) { |
| 140 VLOG(1) << __PRETTY_FUNCTION__ << " " << error_; |
| 141 return false; |
| 142 } |
| 143 result_.reset(results); |
| 144 return true; |
| 145 } |
| 146 |
| 147 bool DownloadsPauseFunction::RunImpl() { |
| 148 int dl_id = 0; |
| 149 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id)); |
| 150 DownloadManager* dlman = profile()->GetDownloadManager(); |
| 151 if (dlman == NULL) { |
| 152 error_ = "I'm afraid I can't do that."; |
| 153 return false; |
| 154 } |
| 155 DownloadItem* item = dlman->GetDownloadItem(dl_id); |
| 156 if (item == NULL) { |
| 157 error_ = "Non-existent download"; |
| 158 return false; |
| 159 } |
| 160 VLOG(1) << __FUNCTION__ << " " << item; |
| 161 if (!item->is_paused()) { |
| 162 item->TogglePause(); |
| 163 } |
| 164 return true; |
| 165 } |
| 166 |
| 167 bool DownloadsResumeFunction::RunImpl() { |
| 168 int dl_id = 0; |
| 169 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id)); |
| 170 DownloadManager* dlman = profile()->GetDownloadManager(); |
| 171 if (dlman == NULL) { |
| 172 error_ = "I'm afraid I can't do that."; |
| 173 return false; |
| 174 } |
| 175 DownloadItem* item = dlman->GetDownloadItem(dl_id); |
| 176 if (item == NULL) { |
| 177 error_ = "Non-existent download"; |
| 178 return false; |
| 179 } |
| 180 VLOG(1) << __FUNCTION__ << " " << item; |
| 181 if (item->is_paused()) { |
| 182 item->TogglePause(); |
| 183 } |
| 184 return true; |
| 185 } |
| 186 |
| 187 bool DownloadsCancelFunction::RunImpl() { |
| 188 int dl_id = 0; |
| 189 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id)); |
| 190 DownloadManager* dlman = profile()->GetDownloadManager(); |
| 191 if (dlman == NULL) { |
| 192 error_ = "I'm afraid I can't do that."; |
| 193 return false; |
| 194 } |
| 195 DownloadItem* item = dlman->GetDownloadItem(dl_id); |
| 196 if (item == NULL) { |
| 197 error_ = "Non-existent download"; |
| 198 return false; |
| 199 } |
| 200 VLOG(1) << __FUNCTION__ << " " << item; |
| 201 item->Cancel(true); |
| 202 return true; |
| 203 } |
| 204 |
| 205 bool DownloadsEraseFunction::RunImpl() { |
| 206 return true; |
| 207 } |
| 208 |
| 209 bool DownloadsSetDestinationFunction::RunImpl() { |
| 210 int dl_id = 0; |
| 211 std::string rel_dest_path; |
| 212 if ((args_.get() == NULL) || |
| 213 (args_->GetSize() < 2) || |
| 214 !args_->GetInteger(0, &dl_id) || |
| 215 (dl_id == 0) || |
| 216 !args_->GetString(1, &rel_dest_path) || |
| 217 rel_dest_path.empty()) return false; |
| 218 DownloadManager* dlman = profile()->GetDownloadManager(); |
| 219 DownloadItem* item = dlman->GetDownloadItem(dl_id); |
| 220 if (item == NULL) return false; |
| 221 VLOG(1) << __FUNCTION__ << " " << dl_id << " " << item << " " |
| 222 << rel_dest_path; |
| 223 return true; |
| 224 } |
| 225 |
| 226 bool DownloadsAcceptDangerFunction::RunImpl() { |
| 227 int dl_id = 0; |
| 228 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id)); |
| 229 DownloadManager* dlman = profile()->GetDownloadManager(); |
| 230 if (dlman == NULL) { |
| 231 error_ = "I'm afraid I can't do that."; |
| 232 return false; |
| 233 } |
| 234 DownloadItem* item = dlman->GetDownloadItem(dl_id); |
| 235 if (item == NULL) { |
| 236 error_ = "Non-existent download"; |
| 237 return false; |
| 238 } |
| 239 VLOG(1) << __FUNCTION__ << " " << item; |
| 240 item->Cancel(true); |
| 241 return true; |
| 242 } |
| 243 |
| 244 bool DownloadsShowFunction::RunImpl() { |
| 245 int dl_id = 0; |
| 246 if ((args_.get() == NULL) || |
| 247 (args_->GetSize() < 1) || |
| 248 !args_->GetInteger(0, &dl_id) || |
| 249 (dl_id == 0)) return false; |
| 250 DownloadManager* dlman = profile()->GetDownloadManager(); |
| 251 DownloadItem* item = dlman->GetDownloadItem(dl_id); |
| 252 if (item == NULL) return false; |
| 253 VLOG(1) << __FUNCTION__ << " " << item; |
| 254 return true; |
| 255 } |
| 256 |
| 257 bool DownloadsDragFunction::RunImpl() { |
| 258 int dl_id = 0; |
| 259 if ((args_.get() == NULL) || |
| 260 (args_->GetSize() < 1) || |
| 261 !args_->GetInteger(0, &dl_id) || |
| 262 (dl_id == 0)) return false; |
| 263 DownloadManager* dlman = profile()->GetDownloadManager(); |
| 264 DownloadItem* item = dlman->GetDownloadItem(dl_id); |
| 265 if (item == NULL) return false; |
| 266 IconManager* im = g_browser_process->icon_manager(); |
| 267 gfx::Image* icon = im->LookupIcon(item->GetUserVerifiedFilePath(), |
| 268 IconLoader::NORMAL); |
| 269 gfx::NativeView view = BrowserList::GetLastActive() |
| 270 ->GetSelectedTabContentsWrapper()->tab_contents()->GetNativeView(); |
| 271 download_util::DragDownload(item, icon, view); |
| 272 VLOG(1) << __FUNCTION__ << " " << dl_id; |
| 273 return true; |
| 274 } |
| 275 |
| 276 struct DownloadsEventRouter::EventListener { |
| 277 std::string ext_id; |
| 278 base::WeakPtr<IPC::Message::Sender> ipc_sender; |
| 279 |
| 280 EventListener(std::string eid, base::WeakPtr<IPC::Message::Sender> ipcs) |
| 281 : ext_id(eid), |
| 282 ipc_sender(ipcs) { |
| 283 } |
| 284 ~EventListener() {} |
| 285 |
| 286 void SendEvent() { |
| 287 } |
| 288 |
| 289 // Comparator to work with std::set. |
| 290 bool operator<(const EventListener& that) const { |
| 291 return ext_id < that.ext_id; |
| 292 } |
| 293 |
| 294 // Allow copy and assign. |
| 295 }; |
| 296 |
| 297 class DownloadsEventRouter::ManagerObserver |
| 298 : public DownloadManager::Observer { |
| 299 public: |
| 300 ManagerObserver(DownloadsEventRouter* router, |
| 301 ProfileId profile_id, |
| 302 DownloadManager* manager) |
| 303 : router_(router), |
| 304 profile_id_(profile_id), |
| 305 manager_(manager) { |
| 306 DCHECK(router); |
| 307 DCHECK(manager_); |
| 308 manager_->AddObserver(this); |
| 309 } |
| 310 ~ManagerObserver() { |
| 311 if (manager_) manager_->RemoveObserver(this); |
| 312 } |
| 313 |
| 314 virtual void ModelChanged() { |
| 315 DCHECK(manager_); |
| 316 DVLOG(1) << __FUNCTION__ << " " << manager_ << " " << profile_id_ << " " <<
router_; |
| 317 router_->DispatchEvent(DownloadsEventRouter::CHANGED, profile_id_, 0); |
| 318 } |
| 319 |
| 320 virtual void ManagerGoingDown() { |
| 321 manager_ = NULL; |
| 322 } |
| 323 |
| 324 private: |
| 325 DownloadsEventRouter* router_; |
| 326 ProfileId profile_id_; |
| 327 DownloadManager* manager_; |
| 328 |
| 329 DISALLOW_COPY_AND_ASSIGN(ManagerObserver); |
| 330 }; |
| 331 |
| 332 class DownloadsEventRouter::ItemObserver : public DownloadItem::Observer { |
| 333 public: |
| 334 ItemObserver() {} |
| 335 ~ItemObserver() {} |
| 336 |
| 337 virtual void OnDownloadUpdated(DownloadItem* download) { |
| 338 DVLOG(1) << __FUNCTION__ << " " << download->id(); |
| 339 } |
| 340 |
| 341 virtual void OnDownloadOpened(DownloadItem* download) { |
| 342 DVLOG(1) << __FUNCTION__ << " " << download->id(); |
| 343 } |
| 344 |
| 345 private: |
| 346 DISALLOW_COPY_AND_ASSIGN(ItemObserver); |
| 347 }; |
| 348 |
| 349 DownloadsEventRouter::DownloadsEventRouter() { |
| 350 } |
| 351 |
| 352 DownloadsEventRouter::~DownloadsEventRouter() { |
| 353 } |
| 354 |
| 355 DownloadsEventRouter* DownloadsEventRouter::GetInstance() { |
| 356 return Singleton<DownloadsEventRouter>::get(); |
| 357 } |
| 358 |
| 359 void DownloadsEventRouter::AddEventListener( |
| 360 EventType event_type, |
| 361 ProfileId profile_id, |
| 362 const std::string& extension_id, |
| 363 base::WeakPtr<IPC::Message::Sender> ipc_sender) { |
| 364 DVLOG(1) << __FUNCTION__ |
| 365 << " " << event_type |
| 366 << " " << profile_id |
| 367 << " " << extension_id |
| 368 << " " << BrowserThread::CurrentlyOn(BrowserThread::UI); |
| 369 if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) { |
| 370 DCHECK(BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 371 NewRunnableMethod(this, &DownloadsEventRouter::AddEventListener, |
| 372 event_type, profile_id, extension_id, ipc_sender))); |
| 373 return; |
| 374 } |
| 375 Profile* profile = reinterpret_cast<Profile*>(profile_id); // XXX |
| 376 DownloadManager* dlman = profile->GetDownloadManager(); |
| 377 DCHECK(dlman); |
| 378 listeners_[profile_id][event_type].insert(EventListener( |
| 379 extension_id, ipc_sender)); |
| 380 if (manager_observers_.find(profile_id) == manager_observers_.end()) { |
| 381 manager_observers_[profile_id] = new ManagerObserver(this, profile_id, dlman
); |
| 382 } |
| 383 } |
| 384 |
| 385 void DownloadsEventRouter::DispatchEvent( |
| 386 EventType event_type, |
| 387 ProfileId profile_id, |
| 388 int download_id) { |
| 389 DVLOG(1) << __FUNCTION__ |
| 390 << " " << event_type |
| 391 << " " << profile_id |
| 392 << " " << download_id |
| 393 << " " << BrowserThread::CurrentlyOn(BrowserThread::IO); |
| 394 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| 395 DCHECK(BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| 396 NewRunnableMethod(this, &DownloadsEventRouter::DispatchEvent, |
| 397 event_type, profile_id, download_id))); |
| 398 return; |
| 399 } |
| 400 LOG(ERROR) << __FUNCTION__ << " " << event_type << " " << profile_id << " " <<
download_id; |
| 401 if (event_type == CREATED) { |
| 402 //item_observers_[profile_id].insert(ItemObserver(this, profile_id)); |
| 403 } else if (event_type == ERASED) { |
| 404 //item_observers_[profile_id]; |
| 405 } |
| 406 const ListenerSet& listeners = listeners_[profile_id][event_type]; |
| 407 for (ListenerSet::iterator listener = listeners.begin(); |
| 408 listener != listeners.end(); ++listener) { |
| 409 //(*listener)->ipc_sender->Send(new ExtensionMsg_MessageInvoke( |
| 410 //MSG_ROUTING_CONTROL, (*listener)->ext_id, kDispatchEvent, args, event_
url)); |
| 411 //ExtensionEventRouter::DispatchEvent( |
| 412 // (*listener)->ipc_sender.get(), (*listener)->ext_id, (*it)->sub_event_n
ame, |
| 413 // json_args, GURL()); |
| 414 } |
| 415 } |
OLD | NEW |