15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/download/save_file_manager.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/download/save_file.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/download/save_package.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/resource_dispatcher_host_impl.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/render_view_host_impl.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/web_contents/web_contents_impl.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 21c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "net/base/filename_util.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h" 237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SaveFileManager::SaveFileManager() 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : next_id_(0) { 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SaveFileManager::~SaveFileManager() { 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for clean shutdown. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(save_file_map_.empty()); 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called during the browser shutdown process to clean up any state (open files, 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// timers) that live on the saving thread (file thread). 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::Shutdown() { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, FROM_HERE, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SaveFileManager::OnShutdown, this)); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stop file thread operations. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::OnShutdown() { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteValues(&save_file_map_); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SaveFile* SaveFileManager::LookupSaveFile(int save_id) { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFileMap::iterator it = save_file_map_.find(save_id); 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it == save_file_map_.end() ? NULL : it->second; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called on the IO thread when 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a) The ResourceDispatcherHostImpl has decided that a request is savable. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// b) The resource does not come from the network, but we still need a 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// save ID for for managing the status of the saving operation. So we 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// file a request from the file thread to the IO thread to generate a 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// unique save ID. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SaveFileManager::GetNextId() { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return next_id_++; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::RegisterStartingRequest(const GURL& save_url, 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackage* save_package) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure it runs in the UI thread. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int contents_id = save_package->contents_id(); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register this starting request. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartingRequestsMap& starting_requests = 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_starting_requests_[contents_id]; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool never_present = starting_requests.insert( 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartingRequestsMap::value_type(save_url.spec(), save_package)).second; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(never_present); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SavePackage* SaveFileManager::UnregisterStartingRequest( 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& save_url, int contents_id) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure it runs in UI thread. 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContentsToStartingRequestsMap::iterator it = 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_starting_requests_.find(contents_id); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != contents_starting_requests_.end()) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartingRequestsMap& requests = it->second; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartingRequestsMap::iterator sit = requests.find(save_url.spec()); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sit == requests.end()) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Found, erase it from starting list and return SavePackage. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackage* save_package = sit->second; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) requests.erase(sit); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is no element in requests, remove it 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (requests.empty()) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents_starting_requests_.erase(it); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return save_package; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Look up a SavePackage according to a save id. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SavePackage* SaveFileManager::LookupPackage(int save_id) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackageMap::iterator it = packages_.find(save_id); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != packages_.end()) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it->second; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Call from SavePackage for starting a saving job 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::SaveURL( 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Referrer& referrer, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int render_process_host_id, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int render_view_id, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFileCreateInfo::SaveFileSource save_source, 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& file_full_path, 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceContext* context, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackage* save_package) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register a saving job. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegisterStartingRequest(url, save_package); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (save_source == SaveFileCreateInfo::SAVE_FILE_FROM_NET) { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(url.is_valid()); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, FROM_HERE, 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SaveFileManager::OnSaveURL, this, url, referrer, 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_process_host_id, render_view_id, context)); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We manually start the save job. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFileCreateInfo* info = new SaveFileCreateInfo(file_full_path, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) url, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_source, 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) -1); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->render_process_id = render_process_host_id; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->render_view_id = render_view_id; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since the data will come from render process, so we need to start 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this kind of save job by ourself. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, FROM_HERE, 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SaveFileManager::OnRequireSaveJobFromOtherSource, 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, info)); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Utility function for look up table maintenance, called on the UI thread. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A manager may have multiple save page job (SavePackage) in progress, 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so we just look up the save id and remove it from the tracking table. 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the save id is -1, it means we just send a request to save, but the 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// saving action has still not happened, need to call UnregisterStartingRequest 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to remove it from the tracking map. 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::RemoveSaveFile(int save_id, const GURL& save_url, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackage* package) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(package); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A save page job (SavePackage) can only have one manager, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so remove it if it exists. 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (save_id == -1) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackage* old_package = 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnregisterStartingRequest(save_url, package->contents_id()); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(old_package, package); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackageMap::iterator it = packages_.find(save_id); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != packages_.end()) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) packages_.erase(it); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Static 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SavePackage* SaveFileManager::GetSavePackageFromRenderIds( 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int render_process_id, int render_view_id) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHostImpl* render_view_host = 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RenderViewHostImpl::FromID(render_process_id, render_view_id); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!render_view_host) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContentsImpl* contents = static_cast<WebContentsImpl*>( 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_host->GetDelegate()->GetAsWebContents()); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!contents) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return contents->save_package(); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SaveFileManager::DeleteDirectoryOrFile(const base::FilePath& full_path, 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_dir) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, FROM_HERE, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SaveFileManager::OnDeleteDirectoryOrFile, 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, full_path, is_dir)); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::SendCancelRequest(int save_id) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel the request which has specific save id. 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(save_id, -1); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, FROM_HERE, 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SaveFileManager::CancelSave, this, save_id)); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Notifications sent from the IO thread and run on the file thread: 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The IO thread created |info|, but the file thread (this method) uses it 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to create a SaveFile which will hold and finally destroy |info|. It will 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// then passes |info| to the UI thread for reporting saving status. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::StartSave(SaveFileCreateInfo* info) { 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(info); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No need to calculate hash. 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFile* save_file = new SaveFile(info, false); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(phajdan.jr): We should check the return value and handle errors here. 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file->Initialize(); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!LookupSaveFile(info->save_id)); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file_map_[info->save_id] = save_file; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->path = save_file->FullPath(); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, FROM_HERE, 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SaveFileManager::OnStartSave, this, info)); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We do forward an update to the UI thread here, since we do not use timer to 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// update the UI. If the user has canceled the saving action (in the UI 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thread). We may receive a few more updates before the IO thread gets the 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cancel message. We just delete the data since the SaveFile has been deleted. 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::UpdateSaveProgress(int save_id, 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::IOBuffer* data, 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int data_len) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFile* save_file = LookupSaveFile(save_id); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (save_file) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(save_file->InProgress()); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadInterruptReason reason = 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file->AppendDataToFile(data->data(), data_len); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, FROM_HERE, 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SaveFileManager::OnUpdateSaveProgress, 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file->save_id(), 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file->BytesSoFar(), 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reason == DOWNLOAD_INTERRUPT_REASON_NONE)); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The IO thread will call this when saving is completed or it got error when 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fetching data. In the former case, we forward the message to OnSaveFinished 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in UI thread. In the latter case, the save ID will be -1, which means the 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// saving action did not even start, so we need to call OnErrorFinished in UI 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// thread, which will use the save URL to find corresponding request record and 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// delete it. 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::SaveFinished(int save_id, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& save_url, 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int render_process_id, 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_success) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(20) << " " << __FUNCTION__ << "()" 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " save_id = " << save_id 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " save_url = \"" << save_url.spec() << "\"" 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " is_success = " << is_success; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFileMap::iterator it = save_file_map_.find(save_id); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != save_file_map_.end()) { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFile* save_file = it->second; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This routine may be called twice for the same from from 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SaveePackage::OnReceivedSerializedHtmlData, once for the file 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // itself, and once when all frames have been serialized. 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // So we can't assert that the file is InProgress() here. 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rdsmith): Fix this logic and put the DCHECK below back in. 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // DCHECK(save_file->InProgress()); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(20) << " " << __FUNCTION__ << "()" 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " save_file = " << save_file->DebugString(); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, FROM_HERE, 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SaveFileManager::OnSaveFinished, this, save_id, 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file->BytesSoFar(), is_success)); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file->Finish(); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file->Detach(); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (save_id == -1) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Before saving started, we got error. We still call finish process. 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!save_url.is_empty()); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, FROM_HERE, 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SaveFileManager::OnErrorFinished, this, save_url, 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_process_id)); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Notifications sent from the file thread and run on the UI thread. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::OnStartSave(const SaveFileCreateInfo* info) { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackage* save_package = 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSavePackageFromRenderIds(info->render_process_id, 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->render_view_id); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!save_package) { 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel this request. 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendCancelRequest(info->save_id); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Insert started saving job to tracking list. 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackageMap::iterator sit = packages_.find(info->save_id); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sit == packages_.end()) { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the registered request. If we can not find, it means we have 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // canceled the job before. 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackage* old_save_package = UnregisterStartingRequest(info->url, 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->render_process_id); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!old_save_package) { 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cancel this request. 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendCancelRequest(info->save_id); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(old_save_package, save_package); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) packages_[info->save_id] = save_package; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Forward this message to SavePackage. 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_package->StartSave(info); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::OnUpdateSaveProgress(int save_id, int64 bytes_so_far, 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool write_success) { 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackage* package = LookupPackage(save_id); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (package) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) package->UpdateSaveProgress(save_id, bytes_so_far, write_success); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SendCancelRequest(save_id); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::OnSaveFinished(int save_id, 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 bytes_so_far, 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_success) { 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackage* package = LookupPackage(save_id); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (package) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) package->SaveFinished(save_id, bytes_so_far, is_success); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::OnErrorFinished(const GURL& save_url, int contents_id) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackage* save_package = UnregisterStartingRequest(save_url, contents_id); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (save_package) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_package->SaveFailed(save_url); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Notifications sent from the UI thread and run on the IO thread. 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::OnSaveURL( 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const GURL& url, 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Referrer& referrer, 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int render_process_host_id, 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int render_view_id, 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceContext* context) { 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceDispatcherHostImpl::Get()->BeginSaveFile(url, 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) referrer, 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_process_host_id, 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_view_id, 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::OnRequireSaveJobFromOtherSource( 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFileCreateInfo* info) { 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(info->save_id, -1); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Generate a unique save id. 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->save_id = GetNextId(); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start real saving action. 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, FROM_HERE, 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SaveFileManager::StartSave, this, info)); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::ExecuteCancelSaveRequest(int render_process_id, 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int request_id) { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 3925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ResourceDispatcherHostImpl::Get()->CancelRequest( 3935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) render_process_id, request_id); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Notifications sent from the UI thread and run on the file thread. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method will be sent via a user action, or shutdown on the UI thread, 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and run on the file thread. We don't post a message back for cancels, 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but we do forward the cancel to the IO thread. Since this message has been 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sent from the UI thread, the saving job may have already completed and 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// won't exist in our map. 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::CancelSave(int save_id) { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFileMap::iterator it = save_file_map_.find(save_id); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != save_file_map_.end()) { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFile* save_file = it->second; 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!save_file->InProgress()) { 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We've won a race with the UI thread--we finished the file before 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the UI thread cancelled it on us. Unfortunately, in this situation 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the cancel wins, so we need to delete the now detached file. 4137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(save_file->FullPath(), false); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (save_file->save_source() == 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFileCreateInfo::SAVE_FILE_FROM_NET) { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the data comes from the net IO thread and hasn't completed 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // yet, then forward the cancel message to IO thread & cancel the 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // save locally. If the data doesn't come from the IO thread, 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we can ignore the message. 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::IO, FROM_HERE, 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SaveFileManager::ExecuteCancelSaveRequest, this, 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file->render_process_id(), save_file->request_id())); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Whatever the save file is complete or not, just delete it. This 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will delete the underlying file if InProgress() is true. 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file_map_.erase(it); 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete save_file; 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is possible that SaveItem which has specified save_id has been canceled 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before this function runs. So if we can not find corresponding SaveFile by 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// using specified save_id, just return. 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::SaveLocalFile(const GURL& original_file_url, 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int save_id, 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int render_process_id) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFile* save_file = LookupSaveFile(save_id); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!save_file) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If it has finished, just return. 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!save_file->InProgress()) 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Close the save file before the copy operation. 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file->Finish(); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file->Detach(); 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(original_file_url.SchemeIsFile()); 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath file_path; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net::FileURLToFilePath(original_file_url, &file_path); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we can not get valid file path from original URL, treat it as 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // disk error. 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (file_path.empty()) 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFinished(save_id, original_file_url, render_process_id, false); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Copy the local file to the temporary file. It will be renamed to its 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // final name later. 4617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch bool success = base::CopyFile(file_path, save_file->FullPath()); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!success) 4637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(save_file->FullPath(), false); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFinished(save_id, original_file_url, render_process_id, success); 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void SaveFileManager::OnDeleteDirectoryOrFile(const base::FilePath& full_path, 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_dir) { 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!full_path.empty()); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(full_path, is_dir); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::RenameAllFiles( 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FinalNameList& final_names, 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const base::FilePath& resource_dir, 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int render_process_id, 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int render_view_id, 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int save_package_id) { 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!resource_dir.empty() && !base::PathExists(resource_dir)) 484a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::CreateDirectory(resource_dir); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (FinalNameList::const_iterator i = final_names.begin(); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != final_names.end(); ++i) { 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFileMap::iterator it = save_file_map_.find(i->first); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != save_file_map_.end()) { 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFile* save_file = it->second; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!save_file->InProgress()); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file->Rename(i->second); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete save_file; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file_map_.erase(it); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::UI, FROM_HERE, 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SaveFileManager::OnFinishSavePageJob, this, 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) render_process_id, render_view_id, save_package_id)); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::OnFinishSavePageJob(int render_process_id, 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int render_view_id, 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int save_package_id) { 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SavePackage* save_package = 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetSavePackageFromRenderIds(render_process_id, render_view_id); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (save_package && save_package->id() == save_package_id) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_package->Finish(); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SaveFileManager::RemoveSavedFileFromFileMap( 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SaveIDList& save_ids) { 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (SaveIDList::const_iterator i = save_ids.begin(); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != save_ids.end(); ++i) { 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFileMap::iterator it = save_file_map_.find(*i); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != save_file_map_.end()) { 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SaveFile* save_file = it->second; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!save_file->InProgress()); 5267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch base::DeleteFile(save_file->FullPath(), false); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete save_file; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) save_file_map_.erase(it); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 534