summaryrefslogtreecommitdiffstats
path: root/chromium/chrome/browser/ui/webui/downloads/downloads_list_tracker.h
blob: a54c75f995c1dc6d009ed48e068f192cc9535891 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_WEBUI_DOWNLOADS_DOWNLOADS_LIST_TRACKER_H_
#define CHROME_BROWSER_UI_WEBUI_DOWNLOADS_DOWNLOADS_LIST_TRACKER_H_

#include <stddef.h>

#include <memory>
#include <set>

#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "base/values.h"
#include "chrome/browser/ui/webui/downloads/downloads.mojom.h"
#include "components/download/content/public/all_download_item_notifier.h"
#include "components/download/public/common/download_item.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"

namespace content {
class DownloadManager;
}

// A class that tracks all downloads activity and keeps a sorted representation
// of the downloads as chrome://downloads wants to display them.
class DownloadsListTracker
    : public download::AllDownloadItemNotifier::Observer {
 public:
  DownloadsListTracker(content::DownloadManager* download_manager,
                       mojo::PendingRemote<downloads::mojom::Page> page);
  ~DownloadsListTracker() override;

  // Clears all downloads on the page if currently sending updates and resets
  // chunk tracking data.
  void Reset();

  // This class only cares about downloads that match |search_terms|.
  // An empty list shows all downloads (the default). Returns true if
  // |search_terms| differ from the current ones.
  bool SetSearchTerms(const std::vector<std::string>& search_terms);

  // Starts sending updates and sends a capped amount of downloads. Tracks which
  // downloads have been sent. Re-call this to send more.
  void StartAndSendChunk();

  // Stops sending updates to the page.
  void Stop();

  content::DownloadManager* GetMainNotifierManager() const;
  content::DownloadManager* GetOriginalNotifierManager() const;

  // AllDownloadItemNotifier::Observer:
  void OnDownloadCreated(content::DownloadManager* manager,
                         download::DownloadItem* download_item) override;
  void OnDownloadUpdated(content::DownloadManager* manager,
                         download::DownloadItem* download_item) override;
  void OnDownloadRemoved(content::DownloadManager* manager,
                         download::DownloadItem* download_item) override;

 protected:
  // Testing constructor.
  DownloadsListTracker(content::DownloadManager* download_manager,
                       mojo::PendingRemote<downloads::mojom::Page> page,
                       base::Callback<bool(const download::DownloadItem&)>);

  // Creates a dictionary value that's sent to the page as JSON.
  virtual downloads::mojom::DataPtr CreateDownloadData(
      download::DownloadItem* item) const;

  // Exposed for testing.
  bool IsIncognito(const download::DownloadItem& item) const;

  const download::DownloadItem* GetItemForTesting(size_t index) const;

  void SetChunkSizeForTesting(size_t chunk_size);

 private:
  struct StartTimeComparator {
    bool operator()(const download::DownloadItem* a,
                    const download::DownloadItem* b) const;
  };
  using SortedSet = std::set<download::DownloadItem*, StartTimeComparator>;

  // Called by both constructors to initialize common state.
  void Init();

  // Clears and re-inserts all downloads items into |sorted_items_|.
  void RebuildSortedItems();

  // Whether |item| should show on the current page.
  bool ShouldShow(const download::DownloadItem& item) const;

  // Returns the index of |item| in |sorted_items_|.
  size_t GetIndex(const SortedSet::iterator& item) const;

  // Calls "insertItems" if sending updates and the page knows about |insert|.
  void InsertItem(const SortedSet::iterator& insert);

  // Calls "updateItem" if sending updates and the page knows about |update|.
  void UpdateItem(const SortedSet::iterator& update);

  // Removes the item that corresponds to |remove| and sends "removeItems"
  // if sending updates.
  void RemoveItem(const SortedSet::iterator& remove);

  download::AllDownloadItemNotifier main_notifier_;
  std::unique_ptr<download::AllDownloadItemNotifier> original_notifier_;

  mojo::Remote<downloads::mojom::Page> page_;

  // Callback used to determine if an item should show on the page. Set to
  // |ShouldShow()| in default constructor, passed in while testing.
  base::Callback<bool(const download::DownloadItem&)> should_show_;

  // When this is true, all changes to downloads that affect the page are sent
  // via JavaScript.
  bool sending_updates_ = false;

  SortedSet sorted_items_;

  // The number of items sent to the page so far.
  size_t sent_to_page_ = 0u;

  // The maximum number of items sent to the page at a time.
  size_t chunk_size_ = 20u;

  // Current search terms.
  std::vector<base::string16> search_terms_;

  DISALLOW_COPY_AND_ASSIGN(DownloadsListTracker);
};

#endif  // CHROME_BROWSER_UI_WEBUI_DOWNLOADS_DOWNLOADS_LIST_TRACKER_H_