Home | History | Annotate | Download | only in download
      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 // Objects that handle file operations for saving files, on the file thread.
      6 //
      7 // The SaveFileManager owns a set of SaveFile objects, each of which connects
      8 // with a SaveItem object which belongs to one SavePackage and runs on the file
      9 // thread for saving data in order to avoid disk activity on either network IO
     10 // thread or the UI thread. It coordinates the notifications from the network
     11 // and UI.
     12 //
     13 // The SaveFileManager itself is a singleton object owned by the
     14 // ResourceDispatcherHost.
     15 //
     16 // The data sent to SaveFileManager have 2 sources, one is from
     17 // ResourceDispatcherHost, run in network IO thread, the all sub-resources
     18 // and save-only-HTML pages will be got from network IO. The second is from
     19 // render process, those html pages which are serialized from DOM will be
     20 // composed in render process and encoded to its original encoding, then sent
     21 // to UI loop in browser process, then UI loop will dispatch the data to
     22 // SaveFileManager on the file thread. SaveFileManager will directly
     23 // call SaveFile's method to persist data.
     24 //
     25 // A typical saving job operation involves multiple threads:
     26 //
     27 // Updating an in progress save file
     28 // io_thread
     29 //      |----> data from net   ---->|
     30 //                                  |
     31 //                                  |
     32 //      |----> data from    ---->|  |
     33 //      |      render process    |  |
     34 // ui_thread                     |  |
     35 //                      file_thread (writes to disk)
     36 //                              |----> stats ---->|
     37 //                                              ui_thread (feedback for user)
     38 //
     39 //
     40 // Cancel operations perform the inverse order when triggered by a user action:
     41 // ui_thread (user click)
     42 //    |----> cancel command ---->|
     43 //    |           |      file_thread (close file)
     44 //    |           |---------------------> cancel command ---->|
     45 //    |                                               io_thread (stops net IO
     46 // ui_thread (user close tab)                                    for saving)
     47 //    |----> cancel command ---->|
     48 //                            Render process(stop serializing DOM and sending
     49 //                                           data)
     50 //
     51 //
     52 // The SaveFileManager tracks saving requests, mapping from a save ID
     53 // (unique integer created in the IO thread) to the SavePackage for the
     54 // tab where the saving job was initiated. In the event of a tab closure
     55 // during saving, the SavePackage will notice the SaveFileManage to
     56 // cancel all SaveFile job.
     57 
     58 #ifndef CHROME_BROWSER_DOWNLOAD_SAVE_FILE_MANAGER_H__
     59 #define CHROME_BROWSER_DOWNLOAD_SAVE_FILE_MANAGER_H__
     60 #pragma once
     61 
     62 #include <string>
     63 
     64 #include "base/basictypes.h"
     65 #include "base/hash_tables.h"
     66 #include "base/memory/ref_counted.h"
     67 #include "chrome/browser/download/save_types.h"
     68 
     69 namespace net {
     70 class IOBuffer;
     71 }
     72 class FilePath;
     73 class GURL;
     74 class SaveFile;
     75 class SavePackage;
     76 class ResourceDispatcherHost;
     77 class Task;
     78 
     79 namespace net {
     80 class URLRequestContextGetter;
     81 }
     82 
     83 class SaveFileManager
     84     : public base::RefCountedThreadSafe<SaveFileManager> {
     85  public:
     86   explicit SaveFileManager(ResourceDispatcherHost* rdh);
     87 
     88   // Lifetime management.
     89   void Shutdown();
     90 
     91   // Called on the IO thread
     92   int GetNextId();
     93 
     94   // Save the specified URL. Called on the UI thread and forwarded to the
     95   // ResourceDispatcherHost on the IO thread.
     96   void SaveURL(const GURL& url,
     97                const GURL& referrer,
     98                int render_process_host_id,
     99                int render_view_id,
    100                SaveFileCreateInfo::SaveFileSource save_source,
    101                const FilePath& file_full_path,
    102                net::URLRequestContextGetter* request_context_getter,
    103                SavePackage* save_package);
    104 
    105   // Notifications sent from the IO thread and run on the file thread:
    106   void StartSave(SaveFileCreateInfo* info);
    107   void UpdateSaveProgress(int save_id, net::IOBuffer* data, int size);
    108   void SaveFinished(int save_id,
    109                     const GURL& save_url,
    110                     int render_process_id,
    111                     bool is_success);
    112 
    113   // Notifications sent from the UI thread and run on the file thread.
    114   // Cancel a SaveFile instance which has specified save id.
    115   void CancelSave(int save_id);
    116 
    117   // Called on the UI thread to remove a save package from SaveFileManager's
    118   // tracking map.
    119   void RemoveSaveFile(int save_id, const GURL& save_url,
    120                       SavePackage* package);
    121 
    122 #if !defined(OS_MACOSX)
    123   // Handler for shell operations sent from the UI to the file thread. Mac OS X
    124   // requires opening downloads on the UI thread, so it does not use this
    125   // method.
    126   void OnShowSavedFileInShell(const FilePath full_path);
    127 #endif
    128 
    129   // Helper function for deleting specified file.
    130   void DeleteDirectoryOrFile(const FilePath& full_path, bool is_dir);
    131 
    132   // Runs on file thread to save a file by copying from file system when
    133   // original url is using file scheme.
    134   void SaveLocalFile(const GURL& original_file_url,
    135                      int save_id,
    136                      int render_process_id);
    137 
    138   // Renames all the successfully saved files.
    139   // |final_names| points to a vector which contains pairs of save ids and
    140   // final names of successfully saved files.
    141   void RenameAllFiles(
    142       const FinalNameList& final_names,
    143       const FilePath& resource_dir,
    144       int render_process_id,
    145       int render_view_id,
    146       int save_package_id);
    147 
    148   // When the user cancels the saving, we need to remove all remaining saved
    149   // files of this page saving job from save_file_map_.
    150   void RemoveSavedFileFromFileMap(const SaveIDList & save_ids);
    151 
    152  private:
    153   friend class base::RefCountedThreadSafe<SaveFileManager>;
    154 
    155   ~SaveFileManager();
    156 
    157   // A cleanup helper that runs on the file thread.
    158   void OnShutdown();
    159 
    160   // Called only on UI thread to get the SavePackage for a tab's profile.
    161   static SavePackage* GetSavePackageFromRenderIds(int render_process_id,
    162                                                   int review_view_id);
    163 
    164   // Register a starting request. Associate the save URL with a
    165   // SavePackage for further matching.
    166   void RegisterStartingRequest(const GURL& save_url,
    167                                SavePackage* save_package);
    168   // Unregister a start request according save URL, disassociate
    169   // the save URL and SavePackage.
    170   SavePackage* UnregisterStartingRequest(const GURL& save_url,
    171                                          int tab_id);
    172 
    173   // Look up the SavePackage according to save id.
    174   SavePackage* LookupPackage(int save_id);
    175 
    176   // Called only on the file thread.
    177   // Look up one in-progress saving item according to save id.
    178   SaveFile* LookupSaveFile(int save_id);
    179 
    180   // Help function for sending notification of canceling specific request.
    181   void SendCancelRequest(int save_id);
    182 
    183   // Notifications sent from the file thread and run on the UI thread.
    184 
    185   // Lookup the SaveManager for this TabContents' saving profile and inform it
    186   // the saving job has been started.
    187   void OnStartSave(const SaveFileCreateInfo* info);
    188   // Update the SavePackage with the current state of a started saving job.
    189   // If the SavePackage for this saving job is gone, cancel the request.
    190   void OnUpdateSaveProgress(int save_id,
    191                             int64 bytes_so_far,
    192                             bool write_success);
    193   // Update the SavePackage with the finish state, and remove the request
    194   // tracking entries.
    195   void OnSaveFinished(int save_id, int64 bytes_so_far, bool is_success);
    196   // For those requests that do not have valid save id, use
    197   // map:(url, SavePackage) to find the request and remove it.
    198   void OnErrorFinished(const GURL& save_url, int tab_id);
    199   // Notifies SavePackage that the whole page saving job is finished.
    200   void OnFinishSavePageJob(int render_process_id,
    201                            int render_view_id,
    202                            int save_package_id);
    203 
    204   // Notifications sent from the UI thread and run on the file thread.
    205 
    206   // Deletes a specified file on the file thread.
    207   void OnDeleteDirectoryOrFile(const FilePath& full_path, bool is_dir);
    208 
    209   // Notifications sent from the UI thread and run on the IO thread
    210 
    211   // Initiates a request for URL to be saved.
    212   void OnSaveURL(const GURL& url,
    213                  const GURL& referrer,
    214                  int render_process_host_id,
    215                  int render_view_id,
    216                  net::URLRequestContextGetter* request_context_getter);
    217   // Handler for a notification sent to the IO thread for generating save id.
    218   void OnRequireSaveJobFromOtherSource(SaveFileCreateInfo* info);
    219   // Call ResourceDispatcherHost's CancelRequest method to execute cancel
    220   // action in the IO thread.
    221   void ExecuteCancelSaveRequest(int render_process_id, int request_id);
    222 
    223   // Unique ID for the next SaveFile object.
    224   int next_id_;
    225 
    226   // A map of all saving jobs by using save id.
    227   typedef base::hash_map<int, SaveFile*> SaveFileMap;
    228   SaveFileMap save_file_map_;
    229 
    230   ResourceDispatcherHost* resource_dispatcher_host_;
    231 
    232   // Tracks which SavePackage to send data to, called only on UI thread.
    233   // SavePackageMap maps save IDs to their SavePackage.
    234   typedef base::hash_map<int, SavePackage*> SavePackageMap;
    235   SavePackageMap packages_;
    236 
    237   // There is a gap between after calling SaveURL() and before calling
    238   // StartSave(). In this gap, each request does not have save id for tracking.
    239   // But sometimes users might want to stop saving job or ResourceDispatcherHost
    240   // calls SaveFinished with save id -1 for network error. We name the requests
    241   // as starting requests. For tracking those starting requests, we need to
    242   // have some data structure.
    243   // First we use a hashmap to map the request URL to SavePackage, then we
    244   // use a hashmap to map the tab id (we actually use render_process_id) to the
    245   // hashmap since it is possible to save same URL in different tab at
    246   // same time.
    247   typedef base::hash_map<std::string, SavePackage*> StartingRequestsMap;
    248   typedef base::hash_map<int, StartingRequestsMap> TabToStartingRequestsMap;
    249   TabToStartingRequestsMap tab_starting_requests_;
    250 
    251   DISALLOW_COPY_AND_ASSIGN(SaveFileManager);
    252 };
    253 
    254 #endif  // CHROME_BROWSER_DOWNLOAD_SAVE_FILE_MANAGER_H__
    255