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
|
// Copyright 2019 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.
#include "chrome/browser/ui/webui/tab_strip/thumbnail_tracker.h"
#include <memory>
#include <utility>
#include "base/scoped_observer.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/thumbnails/thumbnail_image.h"
#include "chrome/browser/ui/thumbnails/thumbnail_tab_helper.h"
#include "content/public/browser/web_contents_observer.h"
// Handles requests for a given tab's thumbnail and watches for thumbnail
// updates for the lifetime of the tab.
class ThumbnailTracker::ContentsData : public content::WebContentsObserver,
public ThumbnailImage::Observer {
public:
ContentsData(ThumbnailTracker* parent, content::WebContents* contents)
: content::WebContentsObserver(contents),
parent_(parent),
observer_(this) {
thumbnail_ = parent_->thumbnail_getter_.Run(contents);
if (thumbnail_)
observer_.Add(thumbnail_.get());
}
void RequestThumbnail() {
if (thumbnail_)
thumbnail_->RequestThumbnailImage();
}
// content::WebContents:
void WebContentsDestroyed() override {
// We must un-observe each ThumbnailImage when the WebContents it came from
// closes.
if (thumbnail_) {
observer_.Remove(thumbnail_.get());
thumbnail_.reset();
}
// Destroy ourself. After this call, |this| doesn't exist!
parent_->ContentsClosed(web_contents());
}
// ThumbnailImage::Observer:
void OnThumbnailImageAvailable(gfx::ImageSkia thumbnail_image) override {
parent_->ThumbnailUpdated(web_contents(), thumbnail_image);
}
private:
ThumbnailTracker* parent_;
scoped_refptr<ThumbnailImage> thumbnail_;
ScopedObserver<ThumbnailImage, ContentsData> observer_;
};
ThumbnailTracker::ThumbnailTracker(ThumbnailUpdatedCallback callback)
: ThumbnailTracker(std::move(callback),
base::Bind(GetThumbnailFromTabHelper)) {}
ThumbnailTracker::ThumbnailTracker(ThumbnailUpdatedCallback callback,
GetThumbnailCallback thumbnail_getter)
: thumbnail_getter_(std::move(thumbnail_getter)),
callback_(std::move(callback)) {}
ThumbnailTracker::~ThumbnailTracker() = default;
void ThumbnailTracker::WatchTab(content::WebContents* contents) {
auto data_it = contents_data_.find(contents);
if (data_it == contents_data_.end()) {
data_it = contents_data_.emplace_hint(
data_it, contents, std::make_unique<ContentsData>(this, contents));
}
data_it->second->RequestThumbnail();
}
void ThumbnailTracker::ThumbnailUpdated(content::WebContents* contents,
gfx::ImageSkia image) {
callback_.Run(contents, image);
}
void ThumbnailTracker::ContentsClosed(content::WebContents* contents) {
contents_data_.erase(contents);
}
// static
scoped_refptr<ThumbnailImage> ThumbnailTracker::GetThumbnailFromTabHelper(
content::WebContents* contents) {
ThumbnailTabHelper* thumbnail_helper =
ThumbnailTabHelper::FromWebContents(contents);
// Gracefully handle when ThumbnailTabHelper isn't available.
if (thumbnail_helper) {
auto thumbnail = thumbnail_helper->thumbnail();
DCHECK(thumbnail);
return thumbnail;
} else {
DVLOG(1) << "ThumbnailTabHelper doesn't exist for tab";
return nullptr;
}
}
|