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.
5 #ifndef CONTENT_TEST_DOWNLOAD_TEST_OBSERVER_H_
6 #define CONTENT_TEST_DOWNLOAD_TEST_OBSERVER_H_
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"
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
{
25 typedef base::Callback
<bool(DownloadItem
*)> EventFilter
;
27 // The filter passed may be called multiple times, even after it
29 DownloadUpdatedObserver(DownloadItem
* item
, EventFilter filter
);
30 virtual ~DownloadUpdatedObserver();
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
39 // DownloadItem::Observer
40 virtual void OnDownloadUpdated(DownloadItem
* item
) OVERRIDE
;
41 virtual void OnDownloadDestroyed(DownloadItem
* item
) OVERRIDE
;
48 DISALLOW_COPY_AND_ASSIGN(DownloadUpdatedObserver
);
51 // Detects changes to the downloads after construction.
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.
58 // Callers may either probe for the finished state, or wait on it.
59 class DownloadTestObserver
: public DownloadManager::Observer
,
60 public DownloadItem::Observer
{
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.
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
,
75 DangerousDownloadAction dangerous_download_action
);
77 virtual ~DownloadTestObserver();
79 // Wait for one of the finish conditions.
80 void WaitForFinished();
82 // Return true if we reached one of the finish conditions.
83 bool IsFinished() const;
85 // DownloadItem::Observer
86 virtual void OnDownloadUpdated(DownloadItem
* download
) OVERRIDE
;
87 virtual void OnDownloadDestroyed(DownloadItem
* download
) OVERRIDE
;
89 // DownloadManager::Observer
90 virtual void OnDownloadCreated(
91 DownloadManager
* manager
, DownloadItem
* item
) OVERRIDE
;
92 virtual void ManagerGoingDown(DownloadManager
* manager
) OVERRIDE
;
94 size_t NumDangerousDownloadsSeen() const;
96 size_t NumDownloadsSeenInState(DownloadItem::DownloadState state
) const;
99 // Only to be called by derived classes' constructors.
102 // Called to see if a download item is in a final state.
103 virtual bool IsDownloadInFinalState(DownloadItem
* download
) = 0;
106 typedef std::set
<DownloadItem
*> DownloadSet
;
108 // Maps states to the number of times they have been encountered
109 typedef std::map
<DownloadItem::DownloadState
, size_t> StateMap
;
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
);
117 void SignalIfFinished();
119 // Fake user click on "Accept".
120 void AcceptDangerousDownload(uint32 download_id
);
122 // Fake user click on "Deny".
123 void DenyDangerousDownload(uint32 download_id
);
125 // The observed download manager.
126 DownloadManager
* download_manager_
;
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_
;
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_
;
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_
;
144 // The number of downloads to wait on completing.
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
154 int finished_downloads_at_construction_
;
156 // Whether an internal message loop has been started and must be quit upon
157 // all downloads completing.
160 // Action to take if a dangerous download is encountered.
161 DangerousDownloadAction dangerous_download_action_
;
163 // Holds the download ids which were dangerous.
164 std::set
<uint32
> dangerous_downloads_seen_
;
166 base::WeakPtrFactory
<DownloadTestObserver
> weak_factory_
;
168 DISALLOW_COPY_AND_ASSIGN(DownloadTestObserver
);
171 class DownloadTestObserverTerminal
: public DownloadTestObserver
{
173 // Create an object that will be considered finished when |wait_count|
174 // download items have entered a terminal state (DownloadItem::IsDone() is
176 DownloadTestObserverTerminal(
177 DownloadManager
* download_manager
,
179 DangerousDownloadAction dangerous_download_action
);
181 virtual ~DownloadTestObserverTerminal();
184 virtual bool IsDownloadInFinalState(DownloadItem
* download
) OVERRIDE
;
186 DISALLOW_COPY_AND_ASSIGN(DownloadTestObserverTerminal
);
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
{
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
);
201 virtual ~DownloadTestObserverInProgress();
204 virtual bool IsDownloadInFinalState(DownloadItem
* download
) OVERRIDE
;
206 DISALLOW_COPY_AND_ASSIGN(DownloadTestObserverInProgress
);
209 class DownloadTestObserverInterrupted
: public DownloadTestObserver
{
211 // Create an object that will be considered finished when |wait_count|
212 // download items are interrupted.
213 DownloadTestObserverInterrupted(
214 DownloadManager
* download_manager
,
216 DangerousDownloadAction dangerous_download_action
);
218 virtual ~DownloadTestObserverInterrupted();
221 virtual bool IsDownloadInFinalState(DownloadItem
* download
) OVERRIDE
;
223 DISALLOW_COPY_AND_ASSIGN(DownloadTestObserverInterrupted
);
226 // The WaitForFlush() method on this class returns after:
227 // * There are no IN_PROGRESS download items remaining on the
229 // * There have been two round trip messages through the file and
231 // This almost certainly means that a Download cancel has propagated through
233 class DownloadTestFlushObserver
234 : public DownloadManager::Observer
,
235 public DownloadItem::Observer
,
236 public base::RefCountedThreadSafe
<DownloadTestFlushObserver
> {
238 explicit DownloadTestFlushObserver(DownloadManager
* download_manager
);
242 // DownloadsManager observer methods.
243 virtual void OnDownloadCreated(
244 DownloadManager
* manager
,
245 DownloadItem
* item
) OVERRIDE
;
247 // DownloadItem observer methods.
248 virtual void OnDownloadUpdated(DownloadItem
* download
) OVERRIDE
;
249 virtual void OnDownloadDestroyed(DownloadItem
* download
) OVERRIDE
;
252 friend class base::RefCountedThreadSafe
<DownloadTestFlushObserver
>;
254 virtual ~DownloadTestFlushObserver();
257 typedef std::set
<DownloadItem
*> DownloadSet
;
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
);
264 void PingFileThread(int cycle
);
266 void PingIOThread(int cycle
);
268 DownloadManager
* download_manager_
;
269 DownloadSet downloads_observed_
;
270 bool waiting_for_zero_inprogress_
;
272 DISALLOW_COPY_AND_ASSIGN(DownloadTestFlushObserver
);
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
> {
280 DownloadTestItemCreationObserver();
282 void WaitForDownloadItemCreation();
284 uint32
download_id() const { return download_id_
; }
285 DownloadInterruptReason
interrupt_reason() const { return interrupt_reason_
; }
286 bool started() const { return called_back_count_
> 0; }
287 bool succeeded() const {
288 return started() && interrupt_reason_
== DOWNLOAD_INTERRUPT_REASON_NONE
;
291 const DownloadUrlParameters::OnStartedCallback
callback();
294 friend class base::RefCountedThreadSafe
<DownloadTestItemCreationObserver
>;
296 ~DownloadTestItemCreationObserver();
298 void DownloadItemCreationCallback(DownloadItem
* item
,
299 DownloadInterruptReason interrupt_reason
);
301 // The download creation information we received.
303 DownloadInterruptReason interrupt_reason_
;
305 // Count of callbacks.
306 size_t called_back_count_
;
308 // We are in the message loop.
311 DISALLOW_COPY_AND_ASSIGN(DownloadTestItemCreationObserver
);
314 } // namespace content`
316 #endif // CONTENT_TEST_DOWNLOAD_TEST_OBSERVER_H_