Home | History | Annotate | Download | only in download
      1 // Copyright (c) 2012 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 // ResourceDispatcherHostImpl.
     15 //
     16 // The data sent to SaveFileManager have 2 sources, one is from
     17 // ResourceDispatcherHostImpl, 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 contents)                               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 (unique
     53 // integer created in the IO thread) to the SavePackage for the contents where
     54 // the saving job was initiated. In the event of a contents closure during
     55 // saving, the SavePackage will notify the SaveFileManage to cancel all SaveFile
     56 // jobs.
     57 
     58 #ifndef CONTENT_BROWSER_DOWNLOAD_SAVE_FILE_MANAGER_H_
     59 #define CONTENT_BROWSER_DOWNLOAD_SAVE_FILE_MANAGER_H_
     60 
     61 #include <string>
     62 
     63 #include "base/basictypes.h"
     64 #include "base/containers/hash_tables.h"
     65 #include "base/memory/ref_counted.h"
     66 #include "content/browser/download/save_types.h"
     67 #include "content/common/content_export.h"
     68 
     69 class GURL;
     70 
     71 namespace base {
     72 class FilePath;
     73 }
     74 
     75 namespace net {
     76 class IOBuffer;
     77 }
     78 
     79 namespace content {
     80 class ResourceContext;
     81 class SaveFile;
     82 class SavePackage;
     83 struct Referrer;
     84 
     85 class SaveFileManager : public base::RefCountedThreadSafe<SaveFileManager> {
     86  public:
     87   SaveFileManager();
     88 
     89   // Lifetime management.
     90   CONTENT_EXPORT void Shutdown();
     91 
     92   // Called on the IO thread. This generates unique IDs for
     93   // SaveFileResourceHandler objects (there's one per file in a SavePackage).
     94   // Note that this is different from the SavePackage's id.
     95   int GetNextId();
     96 
     97   // Save the specified URL. Called on the UI thread and forwarded to the
     98   // ResourceDispatcherHostImpl on the IO thread.
     99   void SaveURL(const GURL& url,
    100                const Referrer& referrer,
    101                int render_process_host_id,
    102                int render_view_id,
    103                SaveFileCreateInfo::SaveFileSource save_source,
    104                const base::FilePath& file_full_path,
    105                ResourceContext* context,
    106                SavePackage* save_package);
    107 
    108   // Notifications sent from the IO thread and run on the file thread:
    109   void StartSave(SaveFileCreateInfo* info);
    110   void UpdateSaveProgress(int save_id, net::IOBuffer* data, int size);
    111   void SaveFinished(int save_id,
    112                     const GURL& save_url,
    113                     int render_process_id,
    114                     bool is_success);
    115 
    116   // Notifications sent from the UI thread and run on the file thread.
    117   // Cancel a SaveFile instance which has specified save id.
    118   void CancelSave(int save_id);
    119 
    120   // Called on the UI thread to remove a save package from SaveFileManager's
    121   // tracking map.
    122   void RemoveSaveFile(int save_id, const GURL& save_url,
    123                       SavePackage* package);
    124 
    125   // Helper function for deleting specified file.
    126   void DeleteDirectoryOrFile(const base::FilePath& full_path, bool is_dir);
    127 
    128   // Runs on file thread to save a file by copying from file system when
    129   // original url is using file scheme.
    130   void SaveLocalFile(const GURL& original_file_url,
    131                      int save_id,
    132                      int render_process_id);
    133 
    134   // Renames all the successfully saved files.
    135   // |final_names| points to a vector which contains pairs of save ids and
    136   // final names of successfully saved files.
    137   void RenameAllFiles(
    138       const FinalNameList& final_names,
    139       const base::FilePath& resource_dir,
    140       int render_process_id,
    141       int render_view_id,
    142       int save_package_id);
    143 
    144   // When the user cancels the saving, we need to remove all remaining saved
    145   // files of this page saving job from save_file_map_.
    146   void RemoveSavedFileFromFileMap(const SaveIDList & save_ids);
    147 
    148  private:
    149   friend class base::RefCountedThreadSafe<SaveFileManager>;
    150 
    151   ~SaveFileManager();
    152 
    153   // A cleanup helper that runs on the file thread.
    154   void OnShutdown();
    155 
    156   // Called only on UI thread to get the SavePackage for a contents's browser
    157   // context.
    158   static SavePackage* GetSavePackageFromRenderIds(int render_process_id,
    159                                                   int review_view_id);
    160 
    161   // Register a starting request. Associate the save URL with a
    162   // SavePackage for further matching.
    163   void RegisterStartingRequest(const GURL& save_url,
    164                                SavePackage* save_package);
    165   // Unregister a start request according save URL, disassociate
    166   // the save URL and SavePackage.
    167   SavePackage* UnregisterStartingRequest(const GURL& save_url,
    168                                          int contents_id);
    169 
    170   // Look up the SavePackage according to save id.
    171   SavePackage* LookupPackage(int save_id);
    172 
    173   // Called only on the file thread.
    174   // Look up one in-progress saving item according to save id.
    175   SaveFile* LookupSaveFile(int save_id);
    176 
    177   // Help function for sending notification of canceling specific request.
    178   void SendCancelRequest(int save_id);
    179 
    180   // Notifications sent from the file thread and run on the UI thread.
    181 
    182   // Lookup the SaveManager for this WebContents' saving browser context and
    183   // inform it the saving job has been started.
    184   void OnStartSave(const SaveFileCreateInfo* info);
    185   // Update the SavePackage with the current state of a started saving job.
    186   // If the SavePackage for this saving job is gone, cancel the request.
    187   void OnUpdateSaveProgress(int save_id,
    188                             int64 bytes_so_far,
    189                             bool write_success);
    190   // Update the SavePackage with the finish state, and remove the request
    191   // tracking entries.
    192   void OnSaveFinished(int save_id, int64 bytes_so_far, bool is_success);
    193   // For those requests that do not have valid save id, use
    194   // map:(url, SavePackage) to find the request and remove it.
    195   void OnErrorFinished(const GURL& save_url, int contents_id);
    196   // Notifies SavePackage that the whole page saving job is finished.
    197   void OnFinishSavePageJob(int render_process_id,
    198                            int render_view_id,
    199                            int save_package_id);
    200 
    201   // Notifications sent from the UI thread and run on the file thread.
    202 
    203   // Deletes a specified file on the file thread.
    204   void OnDeleteDirectoryOrFile(const base::FilePath& full_path, bool is_dir);
    205 
    206   // Notifications sent from the UI thread and run on the IO thread
    207 
    208   // Initiates a request for URL to be saved.
    209   void OnSaveURL(const GURL& url,
    210                  const Referrer& referrer,
    211                  int render_process_host_id,
    212                  int render_view_id,
    213                  ResourceContext* context);
    214   // Handler for a notification sent to the IO thread for generating save id.
    215   void OnRequireSaveJobFromOtherSource(SaveFileCreateInfo* info);
    216   // Call ResourceDispatcherHostImpl's CancelRequest method to execute cancel
    217   // action in the IO thread.
    218   void ExecuteCancelSaveRequest(int render_process_id, int request_id);
    219 
    220   // Unique ID for the next SaveFile object.
    221   int next_id_;
    222 
    223   // A map of all saving jobs by using save id.
    224   typedef base::hash_map<int, SaveFile*> SaveFileMap;
    225   SaveFileMap save_file_map_;
    226 
    227   // Tracks which SavePackage to send data to, called only on UI thread.
    228   // SavePackageMap maps save IDs to their SavePackage.
    229   typedef base::hash_map<int, SavePackage*> SavePackageMap;
    230   SavePackageMap packages_;
    231 
    232   // There is a gap between after calling SaveURL() and before calling
    233   // StartSave(). In this gap, each request does not have save id for tracking.
    234   // But sometimes users might want to stop saving job or ResourceDispatcherHost
    235   // calls SaveFinished with save id -1 for network error. We name the requests
    236   // as starting requests. For tracking those starting requests, we need to
    237   // have some data structure.
    238   // First we use a hashmap to map the request URL to SavePackage, then we use a
    239   // hashmap to map the contents id (we actually use render_process_id) to the
    240   // hashmap since it is possible to save the same URL in different contents at
    241   // same time.
    242   typedef base::hash_map<std::string, SavePackage*> StartingRequestsMap;
    243   typedef base::hash_map<int, StartingRequestsMap>
    244       ContentsToStartingRequestsMap;
    245   ContentsToStartingRequestsMap contents_starting_requests_;
    246 
    247   DISALLOW_COPY_AND_ASSIGN(SaveFileManager);
    248 };
    249 
    250 }  // namespace content
    251 
    252 #endif  // CONTENT_BROWSER_DOWNLOAD_SAVE_FILE_MANAGER_H_
    253