Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1087)

Side by Side Diff: media/blink/url_index.cc

Issue 1399603003: Tie multibuffers to URLs (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@media_cache
Patch Set: comments addressed Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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 #include <set>
6 #include <utility>
7
8 #include "base/bind.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/time/time.h"
11 #include "media/blink/resource_multibuffer_data_provider.h"
12 #include "media/blink/url_index.h"
13
14 namespace media {
15
16 const int kBlockSizeShift = 15; // 1<<15 == 32kb
17 const int kUrlMappingTimeoutSeconds = 300;
18
19 ResourceMultiBuffer::ResourceMultiBuffer(UrlData* url_data)
20 : MultiBuffer(kBlockSizeShift, url_data->url_index_->lru_),
21 url_data_(url_data) {}
22
23 ResourceMultiBuffer::~ResourceMultiBuffer() {}
24
25 scoped_ptr<MultiBuffer::DataProvider> ResourceMultiBuffer::CreateWriter(
26 const MultiBufferBlockId& pos) {
27 ResourceMultiBufferDataProvider* ret =
28 new ResourceMultiBufferDataProvider(url_data_, pos);
29 ret->Start();
30 return scoped_ptr<MultiBuffer::DataProvider>(ret);
31 }
32
33 bool ResourceMultiBuffer::RangeSupported() const {
34 return url_data_->range_supported_;
35 }
36
37 void ResourceMultiBuffer::OnEmpty() {
38 url_data_->OnEmpty();
liberato (no reviews please) 2015/11/23 19:07:10 i'm not a big fan of self-deleters, especially sin
hubbe 2015/11/23 20:17:30 Agreed, updated UrlData::OnEmpty()
39 }
40
41 UrlData::UrlData(const GURL& url,
42 CORSMode cors_mode,
43 const base::WeakPtr<UrlIndex>& url_index)
44 : url_(url),
45 cors_mode_(cors_mode),
46 url_index_(url_index),
47 length_(kPositionNotSpecified),
48 range_supported_(false),
49 cacheable_(false),
50 last_used_(),
51 multibuffer_(this) {}
52
53 UrlData::~UrlData() {
54 if (url_index_)
55 url_index_->RemoveUrlData(this);
liberato (no reviews please) 2015/11/23 19:07:10 how would this happen? urlindex has a strong ref
hubbe 2015/11/23 20:17:30 I was thinking that UrlData might not be in the in
56 }
57
58 std::pair<GURL, UrlData::CORSMode> UrlData::key() const {
59 DCHECK(thread_checker_.CalledOnValidThread());
60 return std::make_pair(url(), cors_mode());
61 }
62
63 void UrlData::set_valid_until(base::TimeTicks valid_until) {
64 DCHECK(thread_checker_.CalledOnValidThread());
65 valid_until_ = valid_until;
66 }
67
68 void UrlData::MergeFrom(const scoped_refptr<UrlData>& other) {
69 // We're merging from another UrlData that refers to the *same*
70 // resource, so when we merge the metadata, we can use the most
71 // optimistic values.
72 DCHECK(thread_checker_.CalledOnValidThread());
73 valid_until_ = std::max(valid_until_, other->valid_until_);
74 // set_length() will not override the length if already known.
75 set_length(other->length_);
76 cacheable_ |= other->cacheable_;
77 range_supported_ |= other->range_supported_;
78 if (last_modified_.is_null()) {
79 last_modified_ = other->last_modified_;
80 }
81 multibuffer()->MergeFrom(other->multibuffer());
82 }
83
84 void UrlData::set_cacheable(bool cacheable) {
85 DCHECK(thread_checker_.CalledOnValidThread());
86 cacheable_ = cacheable;
87 }
88
89 void UrlData::set_length(int64 length) {
90 DCHECK(thread_checker_.CalledOnValidThread());
91 if (length != kPositionNotSpecified) {
92 length_ = length;
93 }
94 }
95
96 void UrlData::RedirectTo(const scoped_refptr<UrlData>& url_data) {
97 DCHECK(thread_checker_.CalledOnValidThread());
98 // Copy any cached data over to the new location.
99 url_data->multibuffer()->MergeFrom(multibuffer());
100
101 std::vector<RedirectCB> redirect_callbacks;
102 redirect_callbacks.swap(redirect_callbacks_);
103 for (const RedirectCB& cb : redirect_callbacks) {
104 cb.Run(url_data);
105 }
106 }
107
108 void UrlData::Fail() {
109 DCHECK(thread_checker_.CalledOnValidThread());
110 // Handled similar to a redirect.
111 std::vector<RedirectCB> redirect_callbacks;
112 redirect_callbacks.swap(redirect_callbacks_);
113 for (const RedirectCB& cb : redirect_callbacks) {
114 cb.Run(nullptr);
115 }
116 }
117
118 void UrlData::OnRedirect(const RedirectCB& cb) {
119 DCHECK(thread_checker_.CalledOnValidThread());
120 redirect_callbacks_.push_back(cb);
121 }
122
123 void UrlData::Use() {
124 DCHECK(thread_checker_.CalledOnValidThread());
125 last_used_ = base::TimeTicks::Now();
126 }
127
128 void UrlData::OnEmpty() {
129 DCHECK(thread_checker_.CalledOnValidThread());
130 if (url_index_)
131 url_index_->RemoveUrlData(this);
132 }
133
134 bool UrlData::Valid() const {
135 DCHECK(thread_checker_.CalledOnValidThread());
136 base::TimeTicks now = base::TimeTicks::Now();
137 if (!range_supported_)
138 return false;
139 // When ranges are not supported, we cannot re-use cached data.
140 if (valid_until_ > now)
141 return true;
142 if (now - last_used_ <
143 base::TimeDelta::FromSeconds(kUrlMappingTimeoutSeconds))
144 return true;
145 return false;
146 }
147
148 void UrlData::set_last_modified(base::Time last_modified) {
149 DCHECK(thread_checker_.CalledOnValidThread());
150 last_modified_ = last_modified;
151 }
152
153 void UrlData::set_range_supported() {
154 DCHECK(thread_checker_.CalledOnValidThread());
155 range_supported_ = true;
156 }
157
158 ResourceMultiBuffer* UrlData::multibuffer() {
159 DCHECK(thread_checker_.CalledOnValidThread());
160 return &multibuffer_;
161 }
162
163 size_t UrlData::CachedSize() {
164 DCHECK(thread_checker_.CalledOnValidThread());
165 return multibuffer()->map().size();
166 }
167
168 UrlIndex::UrlIndex(blink::WebFrame* frame)
169 : frame_(frame), lru_(new MultiBuffer::GlobalLRU()), weak_factory_(this) {}
170
171 UrlIndex::~UrlIndex() {}
172
173 void UrlIndex::RemoveUrlData(const UrlData* url_data) {
174 auto i = by_url_.find(url_data->key());
175 if (i != by_url_.end() && i->second == url_data)
176 by_url_.erase(i);
177 }
178
179 scoped_refptr<UrlData> UrlIndex::GetByUrl(const GURL& gurl,
180 UrlData::CORSMode cors_mode) {
181 auto i = by_url_.find(std::make_pair(gurl, cors_mode));
182 if (i != by_url_.end() && i->second->Valid()) {
183 return i->second;
184 }
185 return NewUrlData(gurl, cors_mode);
186 }
187
188 scoped_refptr<UrlData> UrlIndex::NewUrlData(const GURL& url,
189 UrlData::CORSMode cors_mode) {
190 return new UrlData(url, cors_mode, weak_factory_.GetWeakPtr());
191 }
192
193 scoped_refptr<UrlData> UrlIndex::TryInsert(
194 const scoped_refptr<UrlData>& url_data) {
195 scoped_refptr<UrlData>* by_url_slot;
196 bool urldata_valid = url_data->Valid();
197 if (urldata_valid) {
198 by_url_slot = &by_url_.insert(std::make_pair(url_data->key(), url_data))
199 .first->second;
200 } else {
201 std::map<UrlData::KeyType, scoped_refptr<UrlData>>::iterator iter;
202 iter = by_url_.find(url_data->key());
203 if (iter == by_url_.end())
204 return url_data;
205 by_url_slot = &iter->second;
206 }
207 if (*by_url_slot == url_data)
208 return url_data;
209
210 // TODO(hubbe): Support etag validation.
211 if (!url_data->last_modified().is_null()) {
212 if ((*by_url_slot)->last_modified() != url_data->last_modified()) {
213 if (urldata_valid)
214 *by_url_slot = url_data;
215 return url_data;
216 }
217 }
218 // Check if we should replace the in-cache url data with our url data.
219 if (urldata_valid) {
220 if ((!(*by_url_slot)->Valid() ||
221 url_data->CachedSize() > (*by_url_slot)->CachedSize())) {
222 *by_url_slot = url_data;
223 } else {
224 (*by_url_slot)->MergeFrom(url_data);
225 }
226 }
227 return *by_url_slot;
228 }
229
230 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698