Home | History | Annotate | Download | only in test
      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 #ifndef CONTENT_TEST_DOWNLOAD_TEST_OBSERVER_H_
      6 #define CONTENT_TEST_DOWNLOAD_TEST_OBSERVER_H_
      7 
      8 #include <set>
      9 #include <vector>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/callback_forward.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "content/public/browser/download_item.h"
     15 #include "content/public/browser/download_manager.h"
     16 #include "content/public/browser/download_url_parameters.h"
     17 #include "net/base/net_errors.h"
     18 
     19 namespace content {
     20 
     21 // Detects an arbitrary change on a download item.
     22 // TODO: Rewrite other observers to use this (or be replaced by it).
     23 class DownloadUpdatedObserver : public DownloadItem::Observer {
     24  public:
     25   typedef base::Callback<bool(DownloadItem*)> EventFilter;
     26 
     27   // The filter passed may be called multiple times, even after it
     28   // returns true.
     29   DownloadUpdatedObserver(DownloadItem* item, EventFilter filter);
     30   virtual ~DownloadUpdatedObserver();
     31 
     32   // Returns when either the event has been seen (at least once since
     33   // object construction) or the item is destroyed.  Return value indicates
     34   // if the wait ended because the item was seen (true) or the object
     35   // destroyed (false).
     36   bool WaitForEvent();
     37 
     38  private:
     39   // DownloadItem::Observer
     40   virtual void OnDownloadUpdated(DownloadItem* item) OVERRIDE;
     41   virtual void OnDownloadDestroyed(DownloadItem* item) OVERRIDE;
     42 
     43   DownloadItem* item_;
     44   EventFilter filter_;
     45   bool waiting_;
     46   bool event_seen_;
     47 
     48   DISALLOW_COPY_AND_ASSIGN(DownloadUpdatedObserver);
     49 };
     50 
     51 // Detects changes to the downloads after construction.
     52 //
     53 // Finishes when one of the following happens:
     54 //   - A specified number of downloads change to a terminal state (defined
     55 //     in derived classes).
     56 //   - The download manager was shutdown.
     57 //
     58 // Callers may either probe for the finished state, or wait on it.
     59 class DownloadTestObserver : public DownloadManager::Observer,
     60                              public DownloadItem::Observer {
     61  public:
     62   // Action an observer should take if a dangerous download is encountered.
     63   enum DangerousDownloadAction {
     64     ON_DANGEROUS_DOWNLOAD_ACCEPT,  // Accept the download
     65     ON_DANGEROUS_DOWNLOAD_DENY,    // Deny the download
     66     ON_DANGEROUS_DOWNLOAD_FAIL,    // Fail if a dangerous download is seen
     67     ON_DANGEROUS_DOWNLOAD_IGNORE,  // Make it the callers problem.
     68     ON_DANGEROUS_DOWNLOAD_QUIT     // Will set final state without decision.
     69   };
     70 
     71   // Create an object that will be considered finished when |wait_count|
     72   // download items have entered a terminal state.
     73   DownloadTestObserver(DownloadManager* download_manager,
     74                        size_t wait_count,
     75                        DangerousDownloadAction dangerous_download_action);
     76 
     77   virtual ~DownloadTestObserver();
     78 
     79   // Wait for one of the finish conditions.
     80   void WaitForFinished();
     81 
     82   // Return true if we reached one of the finish conditions.
     83   bool IsFinished() const;
     84 
     85   // DownloadItem::Observer
     86   virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE;
     87   virtual void OnDownloadDestroyed(DownloadItem* download) OVERRIDE;
     88 
     89   // DownloadManager::Observer
     90   virtual void OnDownloadCreated(
     91       DownloadManager* manager, DownloadItem* item) OVERRIDE;
     92   virtual void ManagerGoingDown(DownloadManager* manager) OVERRIDE;
     93 
     94   size_t NumDangerousDownloadsSeen() const;
     95 
     96   size_t NumDownloadsSeenInState(DownloadItem::DownloadState state) const;
     97 
     98  protected:
     99   // Only to be called by derived classes' constructors.
    100   virtual void Init();
    101 
    102   // Called to see if a download item is in a final state.
    103   virtual bool IsDownloadInFinalState(DownloadItem* download) = 0;
    104 
    105  private:
    106   typedef std::set<DownloadItem*> DownloadSet;
    107 
    108   // Maps states to the number of times they have been encountered
    109   typedef std::map<DownloadItem::DownloadState, size_t> StateMap;
    110 
    111   // Called when we know that a download item is in a final state.
    112   // Note that this is not the same as it first transitioning in to the
    113   // final state; multiple notifications may occur once the item is in
    114   // that state.  So we keep our own track of transitions into final.
    115   void DownloadInFinalState(DownloadItem* download);
    116 
    117   void SignalIfFinished();
    118 
    119   // Fake user click on "Accept".
    120   void AcceptDangerousDownload(uint32 download_id);
    121 
    122   // Fake user click on "Deny".
    123   void DenyDangerousDownload(uint32 download_id);
    124 
    125   // The observed download manager.
    126   DownloadManager* download_manager_;
    127 
    128   // The set of DownloadItem's that have transitioned to their finished state
    129   // since construction of this object.  When the size of this array
    130   // reaches wait_count_, we're done.
    131   DownloadSet finished_downloads_;
    132 
    133   // The set of DownloadItem's we are currently observing.  Generally there
    134   // won't be any overlap with the above; once we see the final state
    135   // on a DownloadItem, we'll stop observing it.
    136   DownloadSet downloads_observed_;
    137 
    138   // The map of states to the number of times they have been observed since
    139   // we started looking.
    140   // Recorded at the time downloads_observed_ is recorded, but cleared in the
    141   // constructor to exclude pre-existing states.
    142   StateMap states_observed_;
    143 
    144   // The number of downloads to wait on completing.
    145   size_t wait_count_;
    146 
    147   // The number of downloads entered in final state in Init().  We use
    148   // |finished_downloads_| to track the incoming transitions to final state we
    149   // should ignore, and to track the number of final state transitions that
    150   // occurred between construction and return from wait.  But some downloads may
    151   // be in our final state (and thus be entered into |finished_downloads_|) when
    152   // we construct this class.  We don't want to count those in our transition to
    153   // finished.
    154   int finished_downloads_at_construction_;
    155 
    156   // Whether an internal message loop has been started and must be quit upon
    157   // all downloads completing.
    158   bool waiting_;
    159 
    160   // Action to take if a dangerous download is encountered.
    161   DangerousDownloadAction dangerous_download_action_;
    162 
    163   // Holds the download ids which were dangerous.
    164   std::set<uint32> dangerous_downloads_seen_;
    165 
    166   base::WeakPtrFactory<DownloadTestObserver> weak_factory_;
    167 
    168   DISALLOW_COPY_AND_ASSIGN(DownloadTestObserver);
    169 };
    170 
    171 class DownloadTestObserverTerminal : public DownloadTestObserver {
    172  public:
    173   // Create an object that will be considered finished when |wait_count|
    174   // download items have entered a terminal state (DownloadItem::IsDone() is
    175   // true).
    176   DownloadTestObserverTerminal(
    177       DownloadManager* download_manager,
    178       size_t wait_count,
    179       DangerousDownloadAction dangerous_download_action);
    180 
    181   virtual ~DownloadTestObserverTerminal();
    182 
    183  private:
    184   virtual bool IsDownloadInFinalState(DownloadItem* download) OVERRIDE;
    185 
    186   DISALLOW_COPY_AND_ASSIGN(DownloadTestObserverTerminal);
    187 };
    188 
    189 // Detects changes to the downloads after construction.
    190 // Finishes when a specified number of downloads change to the
    191 // IN_PROGRESS state, or when the download manager is destroyed.
    192 // Dangerous downloads are accepted.
    193 // Callers may either probe for the finished state, or wait on it.
    194 class DownloadTestObserverInProgress : public DownloadTestObserver {
    195  public:
    196   // Create an object that will be considered finished when |wait_count|
    197   // download items have entered state |IN_PROGRESS|.
    198   DownloadTestObserverInProgress(
    199       DownloadManager* download_manager, size_t wait_count);
    200 
    201   virtual ~DownloadTestObserverInProgress();
    202 
    203  private:
    204   virtual bool IsDownloadInFinalState(DownloadItem* download) OVERRIDE;
    205 
    206   DISALLOW_COPY_AND_ASSIGN(DownloadTestObserverInProgress);
    207 };
    208 
    209 class DownloadTestObserverInterrupted : public DownloadTestObserver {
    210  public:
    211   // Create an object that will be considered finished when |wait_count|
    212   // download items are interrupted.
    213   DownloadTestObserverInterrupted(
    214       DownloadManager* download_manager,
    215       size_t wait_count,
    216       DangerousDownloadAction dangerous_download_action);
    217 
    218   virtual ~DownloadTestObserverInterrupted();
    219 
    220  private:
    221   virtual bool IsDownloadInFinalState(DownloadItem* download) OVERRIDE;
    222 
    223   DISALLOW_COPY_AND_ASSIGN(DownloadTestObserverInterrupted);
    224 };
    225 
    226 // The WaitForFlush() method on this class returns after:
    227 //      * There are no IN_PROGRESS download items remaining on the
    228 //        DownloadManager.
    229 //      * There have been two round trip messages through the file and
    230 //        IO threads.
    231 // This almost certainly means that a Download cancel has propagated through
    232 // the system.
    233 class DownloadTestFlushObserver
    234     : public DownloadManager::Observer,
    235       public DownloadItem::Observer,
    236       public base::RefCountedThreadSafe<DownloadTestFlushObserver> {
    237  public:
    238   explicit DownloadTestFlushObserver(DownloadManager* download_manager);
    239 
    240   void WaitForFlush();
    241 
    242   // DownloadsManager observer methods.
    243   virtual void OnDownloadCreated(
    244       DownloadManager* manager,
    245       DownloadItem* item) OVERRIDE;
    246 
    247   // DownloadItem observer methods.
    248   virtual void OnDownloadUpdated(DownloadItem* download) OVERRIDE;
    249   virtual void OnDownloadDestroyed(DownloadItem* download) OVERRIDE;
    250 
    251  protected:
    252   friend class base::RefCountedThreadSafe<DownloadTestFlushObserver>;
    253 
    254   virtual ~DownloadTestFlushObserver();
    255 
    256  private:
    257   typedef std::set<DownloadItem*> DownloadSet;
    258 
    259   // If we're waiting for that flush point, check the number
    260   // of downloads in the IN_PROGRESS state and take appropriate
    261   // action.  If requested, also observes all downloads while iterating.
    262   void CheckDownloadsInProgress(bool observe_downloads);
    263 
    264   void PingFileThread(int cycle);
    265 
    266   void PingIOThread(int cycle);
    267 
    268   DownloadManager* download_manager_;
    269   DownloadSet downloads_observed_;
    270   bool waiting_for_zero_inprogress_;
    271 
    272   DISALLOW_COPY_AND_ASSIGN(DownloadTestFlushObserver);
    273 };
    274 
    275 // Waits for a callback indicating that the DownloadItem is about to be created,
    276 // or that an error occurred and it won't be created.
    277 class DownloadTestItemCreationObserver
    278     : public base::RefCountedThreadSafe<DownloadTestItemCreationObserver> {
    279  public:
    280   DownloadTestItemCreationObserver();
    281 
    282   void WaitForDownloadItemCreation();
    283 
    284   uint32 download_id() const { return download_id_; }
    285   net::Error error() const { return error_; }
    286   bool started() const { return called_back_count_ > 0; }
    287   bool succeeded() const { return started() && (error_ == net::OK); }
    288 
    289   const DownloadUrlParameters::OnStartedCallback callback();
    290 
    291  private:
    292   friend class base::RefCountedThreadSafe<DownloadTestItemCreationObserver>;
    293 
    294   ~DownloadTestItemCreationObserver();
    295 
    296   void DownloadItemCreationCallback(DownloadItem* item, net::Error error);
    297 
    298   // The download creation information we received.
    299   uint32 download_id_;
    300   net::Error error_;
    301 
    302   // Count of callbacks.
    303   size_t called_back_count_;
    304 
    305   // We are in the message loop.
    306   bool waiting_;
    307 
    308   DISALLOW_COPY_AND_ASSIGN(DownloadTestItemCreationObserver);
    309 };
    310 
    311 }  // namespace content`
    312 
    313 #endif  // CONTENT_TEST_DOWNLOAD_TEST_OBSERVER_H_
    314