| 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 |