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