• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • 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 #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_interrupt_reasons.h"
15 #include "content/public/browser/download_item.h"
16 #include "content/public/browser/download_manager.h"
17 #include "content/public/browser/download_url_parameters.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 
download_id()284   uint32 download_id() const { return download_id_; }
interrupt_reason()285   DownloadInterruptReason interrupt_reason() const { return interrupt_reason_; }
started()286   bool started() const { return called_back_count_ > 0; }
succeeded()287   bool succeeded() const {
288     return started() && interrupt_reason_ == DOWNLOAD_INTERRUPT_REASON_NONE;
289   }
290 
291   const DownloadUrlParameters::OnStartedCallback callback();
292 
293  private:
294   friend class base::RefCountedThreadSafe<DownloadTestItemCreationObserver>;
295 
296   ~DownloadTestItemCreationObserver();
297 
298   void DownloadItemCreationCallback(DownloadItem* item,
299                                     DownloadInterruptReason interrupt_reason);
300 
301   // The download creation information we received.
302   uint32 download_id_;
303   DownloadInterruptReason interrupt_reason_;
304 
305   // Count of callbacks.
306   size_t called_back_count_;
307 
308   // We are in the message loop.
309   bool waiting_;
310 
311   DISALLOW_COPY_AND_ASSIGN(DownloadTestItemCreationObserver);
312 };
313 
314 }  // namespace content`
315 
316 #endif  // CONTENT_TEST_DOWNLOAD_TEST_OBSERVER_H_
317