OLD | NEW |
| (Empty) |
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 CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TEST_OBSERVER_H_ | |
6 #define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TEST_OBSERVER_H_ | |
7 | |
8 #include <set> | |
9 #include <vector> | |
10 | |
11 #include "base/basictypes.h" | |
12 #include "base/memory/ref_counted.h" | |
13 #include "content/public/browser/download_item.h" | |
14 #include "content/public/browser/download_manager.h" | |
15 #include "content/public/browser/download_url_parameters.h" | |
16 #include "net/base/net_errors.h" | |
17 | |
18 namespace internal { | |
19 class MockFileChooserDownloadManagerDelegate; | |
20 } | |
21 | |
22 class Profile; | |
23 | |
24 // Detects changes to the downloads after construction. | |
25 // Finishes when one of the following happens: | |
26 // - A specified number of downloads change to a terminal state (defined | |
27 // in derived classes). | |
28 // - Specific events, such as a select file dialog. | |
29 // Callers may either probe for the finished state, or wait on it. | |
30 // | |
31 // TODO(rdsmith): Detect manager going down, remove pointer to | |
32 // DownloadManager, transition to finished. (For right now we | |
33 // just use a scoped_refptr<> to keep it around, but that may cause | |
34 // timeouts on waiting if a DownloadManager::Shutdown() occurs which | |
35 // cancels our in-progress downloads.) | |
36 class DownloadTestObserver : public content::DownloadManager::Observer, | |
37 public content::DownloadItem::Observer { | |
38 public: | |
39 // Action an observer should take if a dangerous download is encountered. | |
40 enum DangerousDownloadAction { | |
41 ON_DANGEROUS_DOWNLOAD_ACCEPT, // Accept the download | |
42 ON_DANGEROUS_DOWNLOAD_DENY, // Deny the download | |
43 ON_DANGEROUS_DOWNLOAD_FAIL // Fail if a dangerous download is seen | |
44 }; | |
45 | |
46 // Create an object that will be considered finished when |wait_count| | |
47 // download items have entered a terminal state. | |
48 DownloadTestObserver( | |
49 content::DownloadManager* download_manager, | |
50 size_t wait_count, | |
51 DangerousDownloadAction dangerous_download_action); | |
52 | |
53 virtual ~DownloadTestObserver(); | |
54 | |
55 // Wait for the requested number of downloads to enter a terminal state. | |
56 void WaitForFinished(); | |
57 | |
58 // Return true if everything's happened that we're configured for. | |
59 bool IsFinished() const; | |
60 | |
61 // content::DownloadItem::Observer | |
62 virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE; | |
63 virtual void OnDownloadDestroyed(content::DownloadItem* download) OVERRIDE; | |
64 | |
65 // content::DownloadManager::Observer | |
66 virtual void ModelChanged(content::DownloadManager* manager) OVERRIDE; | |
67 | |
68 size_t NumDangerousDownloadsSeen() const; | |
69 | |
70 size_t NumDownloadsSeenInState( | |
71 content::DownloadItem::DownloadState state) const; | |
72 | |
73 protected: | |
74 // Only to be called by derived classes' constructors. | |
75 virtual void Init(); | |
76 | |
77 // Called to see if a download item is in a final state. | |
78 virtual bool IsDownloadInFinalState(content::DownloadItem* download) = 0; | |
79 | |
80 private: | |
81 typedef std::set<content::DownloadItem*> DownloadSet; | |
82 | |
83 // Maps states to the number of times they have been encountered | |
84 typedef std::map<content::DownloadItem::DownloadState, size_t> StateMap; | |
85 | |
86 // Called when we know that a download item is in a final state. | |
87 // Note that this is not the same as it first transitioning in to the | |
88 // final state; multiple notifications may occur once the item is in | |
89 // that state. So we keep our own track of transitions into final. | |
90 void DownloadInFinalState(content::DownloadItem* download); | |
91 | |
92 void SignalIfFinished(); | |
93 | |
94 // The observed download manager. | |
95 scoped_refptr<content::DownloadManager> download_manager_; | |
96 | |
97 // The set of DownloadItem's that have transitioned to their finished state | |
98 // since construction of this object. When the size of this array | |
99 // reaches wait_count_, we're done. | |
100 DownloadSet finished_downloads_; | |
101 | |
102 // The set of DownloadItem's we are currently observing. Generally there | |
103 // won't be any overlap with the above; once we see the final state | |
104 // on a DownloadItem, we'll stop observing it. | |
105 DownloadSet downloads_observed_; | |
106 | |
107 // The map of states to the number of times they have been observed since | |
108 // we started looking. | |
109 // Recorded at the time downloads_observed_ is recorded, but cleared in the | |
110 // constructor to exclude pre-existing states. | |
111 StateMap states_observed_; | |
112 | |
113 // The number of downloads to wait on completing. | |
114 size_t wait_count_; | |
115 | |
116 // The number of downloads entered in final state in initial | |
117 // ModelChanged(). We use |finished_downloads_| to track the incoming | |
118 // transitions to final state we should ignore, and to track the | |
119 // number of final state transitions that occurred between | |
120 // construction and return from wait. But some downloads may be in our | |
121 // final state (and thus be entered into |finished_downloads_|) when we | |
122 // construct this class. We don't want to count those in our transition | |
123 // to finished. | |
124 int finished_downloads_at_construction_; | |
125 | |
126 // Whether an internal message loop has been started and must be quit upon | |
127 // all downloads completing. | |
128 bool waiting_; | |
129 | |
130 // Action to take if a dangerous download is encountered. | |
131 DangerousDownloadAction dangerous_download_action_; | |
132 | |
133 // Holds the download ids which were dangerous. | |
134 std::set<int32> dangerous_downloads_seen_; | |
135 | |
136 DISALLOW_COPY_AND_ASSIGN(DownloadTestObserver); | |
137 }; | |
138 | |
139 class DownloadTestObserverTerminal : public DownloadTestObserver { | |
140 public: | |
141 // Create an object that will be considered finished when |wait_count| | |
142 // download items have entered a terminal state (any but IN_PROGRESS). | |
143 // If |finish_on_select_file| is true, the object will also be | |
144 // considered finished if the DownloadManager raises a | |
145 // SelectFileDialogDisplayed() notification. | |
146 DownloadTestObserverTerminal( | |
147 content::DownloadManager* download_manager, | |
148 size_t wait_count, | |
149 DangerousDownloadAction dangerous_download_action); | |
150 | |
151 virtual ~DownloadTestObserverTerminal(); | |
152 | |
153 private: | |
154 virtual bool IsDownloadInFinalState(content::DownloadItem* download) OVERRIDE; | |
155 | |
156 DISALLOW_COPY_AND_ASSIGN(DownloadTestObserverTerminal); | |
157 }; | |
158 | |
159 // Detects changes to the downloads after construction. | |
160 // Finishes when a specified number of downloads change to the | |
161 // IN_PROGRESS state, or a Select File Dialog has appeared. | |
162 // Dangerous downloads are accepted. | |
163 // Callers may either probe for the finished state, or wait on it. | |
164 class DownloadTestObserverInProgress : public DownloadTestObserver { | |
165 public: | |
166 // Create an object that will be considered finished when |wait_count| | |
167 // download items have entered state |IN_PROGRESS|. | |
168 // If |finish_on_select_file| is true, the object will also be | |
169 // considered finished if the DownloadManager raises a | |
170 // SelectFileDialogDisplayed() notification. | |
171 DownloadTestObserverInProgress( | |
172 content::DownloadManager* download_manager, | |
173 size_t wait_count); | |
174 | |
175 virtual ~DownloadTestObserverInProgress(); | |
176 | |
177 private: | |
178 virtual bool IsDownloadInFinalState(content::DownloadItem* download) OVERRIDE; | |
179 | |
180 DISALLOW_COPY_AND_ASSIGN(DownloadTestObserverInProgress); | |
181 }; | |
182 | |
183 // The WaitForFlush() method on this class returns after: | |
184 // * There are no IN_PROGRESS download items remaining on the | |
185 // DownloadManager. | |
186 // * There have been two round trip messages through the file and | |
187 // IO threads. | |
188 // This almost certainly means that a Download cancel has propagated through | |
189 // the system. | |
190 class DownloadTestFlushObserver | |
191 : public content::DownloadManager::Observer, | |
192 public content::DownloadItem::Observer, | |
193 public base::RefCountedThreadSafe<DownloadTestFlushObserver> { | |
194 public: | |
195 explicit DownloadTestFlushObserver( | |
196 content::DownloadManager* download_manager); | |
197 | |
198 void WaitForFlush(); | |
199 | |
200 // DownloadsManager observer methods. | |
201 virtual void ModelChanged(content::DownloadManager* manager) OVERRIDE; | |
202 | |
203 // DownloadItem observer methods. | |
204 virtual void OnDownloadUpdated(content::DownloadItem* download) OVERRIDE; | |
205 virtual void OnDownloadDestroyed(content::DownloadItem* download) OVERRIDE; | |
206 | |
207 protected: | |
208 friend class base::RefCountedThreadSafe<DownloadTestFlushObserver>; | |
209 | |
210 virtual ~DownloadTestFlushObserver(); | |
211 | |
212 private: | |
213 typedef std::set<content::DownloadItem*> DownloadSet; | |
214 | |
215 // If we're waiting for that flush point, check the number | |
216 // of downloads in the IN_PROGRESS state and take appropriate | |
217 // action. If requested, also observes all downloads while iterating. | |
218 void CheckDownloadsInProgress(bool observe_downloads); | |
219 | |
220 void PingFileThread(int cycle); | |
221 | |
222 void PingIOThread(int cycle); | |
223 | |
224 content::DownloadManager* download_manager_; | |
225 DownloadSet downloads_observed_; | |
226 bool waiting_for_zero_inprogress_; | |
227 | |
228 DISALLOW_COPY_AND_ASSIGN(DownloadTestFlushObserver); | |
229 }; | |
230 | |
231 // Waits for a callback indicating that the DownloadItem is about to be created, | |
232 // or that an error occurred and it won't be created. | |
233 class DownloadTestItemCreationObserver | |
234 : public base::RefCountedThreadSafe<DownloadTestItemCreationObserver> { | |
235 public: | |
236 DownloadTestItemCreationObserver(); | |
237 | |
238 void WaitForDownloadItemCreation(); | |
239 | |
240 content::DownloadId download_id() const { return download_id_; } | |
241 net::Error error() const { return error_; } | |
242 bool started() const { return called_back_count_ > 0; } | |
243 bool succeeded() const { return started() && (error_ == net::OK); } | |
244 | |
245 const content::DownloadUrlParameters::OnStartedCallback callback(); | |
246 | |
247 private: | |
248 friend class base::RefCountedThreadSafe<DownloadTestItemCreationObserver>; | |
249 | |
250 ~DownloadTestItemCreationObserver(); | |
251 | |
252 void DownloadItemCreationCallback(content::DownloadId download_id, | |
253 net::Error error); | |
254 | |
255 // The download creation information we received. | |
256 content::DownloadId download_id_; | |
257 | |
258 net::Error error_; | |
259 | |
260 // Count of callbacks. | |
261 size_t called_back_count_; | |
262 | |
263 // We are in the message loop. | |
264 bool waiting_; | |
265 | |
266 DISALLOW_COPY_AND_ASSIGN(DownloadTestItemCreationObserver); | |
267 }; | |
268 | |
269 // Observes and overrides file chooser activity for a profile. By default, once | |
270 // attached to a profile, this class overrides the default file chooser by | |
271 // replacing the ChromeDownloadManagerDelegate associated with |profile|. | |
272 // NOTE: Again, this overrides the ChromeDownloadManagerDelegate for |profile|. | |
273 class DownloadTestFileChooserObserver { | |
274 public: | |
275 // Attaches to |profile|. By default file chooser dialogs will be disabled | |
276 // once attached. Call EnableFileChooser() to re-enable. | |
277 explicit DownloadTestFileChooserObserver(Profile* profile); | |
278 ~DownloadTestFileChooserObserver(); | |
279 | |
280 // Sets whether the file chooser dialog is enabled. If |enable| is false, any | |
281 // attempt to display a file chooser dialog will cause the download to be | |
282 // canceled. Otherwise, attempting to display a file chooser dialog will | |
283 // result in the download continuing with the suggested path. | |
284 void EnableFileChooser(bool enable); | |
285 | |
286 // Returns true if a file chooser dialog was displayed since the last time | |
287 // this method was called. | |
288 bool TestAndResetDidShowFileChooser(); | |
289 | |
290 private: | |
291 scoped_refptr<internal::MockFileChooserDownloadManagerDelegate> | |
292 test_delegate_; | |
293 }; | |
294 | |
295 #endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_TEST_OBSERVER_H_ | |
OLD | NEW |