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

Side by Side Diff: chrome/browser/android/data_usage/data_use_tab_model.cc

Issue 1443683002: Notify DataUseTabModel of navigations and tab closures (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addressed sclittle comments Created 5 years 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
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/android/data_usage/data_use_tab_model.h" 5 #include "chrome/browser/android/data_usage/data_use_tab_model.h"
6 6
7 #include "base/metrics/histogram_macros.h" 7 #include "base/metrics/histogram_macros.h"
8 #include "base/single_thread_task_runner.h"
8 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
9 #include "base/time/time.h" 10 #include "base/time/time.h"
10 #include "chrome/browser/android/data_usage/external_data_use_observer.h" 11 #include "chrome/browser/android/data_usage/external_data_use_observer.h"
11 #include "chrome/browser/android/data_usage/tab_data_use_entry.h" 12 #include "components/data_usage/core/data_use.h"
12 #include "components/variations/variations_associated_data.h" 13 #include "components/variations/variations_associated_data.h"
13 14
14 namespace { 15 namespace {
15 16
16 // Indicates the default maximum number of tabs to maintain session information 17 // Indicates the default maximum number of tabs to maintain session information
17 // about. May be overridden by the field trial. 18 // about. May be overridden by the field trial.
18 const size_t kDefaultMaxTabEntries = 200; 19 const size_t kDefaultMaxTabEntries = 200;
19 20
20 const char kUMAExpiredInactiveTabEntryRemovalDurationSecondsHistogram[] = 21 const char kUMAExpiredInactiveTabEntryRemovalDurationSecondsHistogram[] =
21 "DataUse.TabModel.ExpiredInactiveTabEntryRemovalDuration"; 22 "DataUse.TabModel.ExpiredInactiveTabEntryRemovalDuration";
22 const char kUMAExpiredActiveTabEntryRemovalDurationHoursHistogram[] = 23 const char kUMAExpiredActiveTabEntryRemovalDurationHoursHistogram[] =
23 "DataUse.TabModel.ExpiredActiveTabEntryRemovalDuration"; 24 "DataUse.TabModel.ExpiredActiveTabEntryRemovalDuration";
24 const char kUMAUnexpiredTabEntryRemovalDurationMinutesHistogram[] = 25 const char kUMAUnexpiredTabEntryRemovalDurationMinutesHistogram[] =
25 "DataUse.TabModel.UnexpiredTabEntryRemovalDuration"; 26 "DataUse.TabModel.UnexpiredTabEntryRemovalDuration";
26 27
27 // Returns true if |tab_id| is a valid tab ID. 28 // Returns true if |tab_id| is a valid tab ID.
28 bool IsValidTabID(int32_t tab_id) { 29 bool IsValidTabID(SessionID::id_type tab_id) {
29 return tab_id >= 0; 30 return tab_id >= 0;
30 } 31 }
31 32
32 // Returns various parameters from the values specified in the field trial. 33 // Returns various parameters from the values specified in the field trial.
33 size_t GetMaxTabEntries() { 34 size_t GetMaxTabEntries() {
34 size_t max_tab_entries = -1; 35 size_t max_tab_entries = -1;
35 std::string variation_value = variations::GetVariationParamValue( 36 std::string variation_value = variations::GetVariationParamValue(
36 chrome::android::ExternalDataUseObserver:: 37 chrome::android::ExternalDataUseObserver::
37 kExternalDataUseObserverFieldTrial, 38 kExternalDataUseObserverFieldTrial,
38 "max_tab_entries"); 39 "max_tab_entries");
39 if (!variation_value.empty() && 40 if (!variation_value.empty() &&
40 base::StringToSizeT(variation_value, &max_tab_entries)) { 41 base::StringToSizeT(variation_value, &max_tab_entries)) {
41 return max_tab_entries; 42 return max_tab_entries;
42 } 43 }
43 return kDefaultMaxTabEntries; 44 return kDefaultMaxTabEntries;
44 } 45 }
45 46
46 } // namespace 47 } // namespace
47 48
48 namespace chrome { 49 namespace chrome {
49 50
50 namespace android { 51 namespace android {
51 52
52 DataUseTabModel::DataUseTabModel( 53 DataUseTabModel::DataUseTabModel(
53 const ExternalDataUseObserver* data_use_observer, 54 const ExternalDataUseObserver* data_use_observer,
54 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) 55 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
55 : data_use_observer_(data_use_observer), 56 : data_use_observer_(data_use_observer),
56 observer_list_(new base::ObserverListThreadSafe<TabDataUseObserver>),
57 max_tab_entries_(GetMaxTabEntries()), 57 max_tab_entries_(GetMaxTabEntries()),
58 weak_factory_(this) {} 58 ui_task_runner_(ui_task_runner),
59 weak_factory_(this) {
60 DCHECK(ui_task_runner_);
61 }
59 62
60 DataUseTabModel::~DataUseTabModel() { 63 DataUseTabModel::~DataUseTabModel() {
61 DCHECK(thread_checker_.CalledOnValidThread()); 64 DCHECK(thread_checker_.CalledOnValidThread());
62 } 65 }
63 66
64 base::WeakPtr<DataUseTabModel> DataUseTabModel::GetWeakPtr() { 67 base::WeakPtr<DataUseTabModel> DataUseTabModel::GetWeakPtr() {
65 DCHECK(thread_checker_.CalledOnValidThread()); 68 DCHECK(thread_checker_.CalledOnValidThread());
66 return weak_factory_.GetWeakPtr(); 69 return weak_factory_.GetWeakPtr();
67 } 70 }
68 71
69 void DataUseTabModel::OnNavigationEvent(int32_t tab_id, 72 void DataUseTabModel::OnNavigationEvent(SessionID::id_type tab_id,
70 TransitionType transition, 73 TransitionType transition,
71 const GURL& url, 74 const GURL& url,
72 const std::string& package) { 75 const std::string& package) {
73 DCHECK(thread_checker_.CalledOnValidThread()); 76 DCHECK(thread_checker_.CalledOnValidThread());
74 DCHECK(IsValidTabID(tab_id)); 77 DCHECK(IsValidTabID(tab_id));
75 78
76 switch (transition) { 79 switch (transition) {
77 case TRANSITION_OMNIBOX_SEARCH: 80 case TRANSITION_OMNIBOX_SEARCH:
81 case TRANSITION_OMNIBOX_NAVIGATION:
78 case TRANSITION_FROM_EXTERNAL_APP: { 82 case TRANSITION_FROM_EXTERNAL_APP: {
79 // Enter events. 83 // Enter events.
80 bool start_tracking = false; 84 bool start_tracking = false;
81 std::string label; 85 std::string label;
82 TabEntryMap::const_iterator tab_entry_iterator = 86 TabEntryMap::const_iterator tab_entry_iterator =
83 active_tabs_.find(tab_id); 87 active_tabs_.find(tab_id);
84 if (tab_entry_iterator != active_tabs_.end() && 88 if (tab_entry_iterator != active_tabs_.end() &&
85 tab_entry_iterator->second.IsTrackingDataUse()) { 89 tab_entry_iterator->second.IsTrackingDataUse()) {
86 break; 90 break;
87 } 91 }
88 if (transition == TRANSITION_FROM_EXTERNAL_APP) { 92 if (transition == TRANSITION_FROM_EXTERNAL_APP) {
89 // Package name should match, for transitions from external app. 93 // Package name should match, for transitions from external app.
90 if (!package.empty() && 94 if (!package.empty() &&
91 data_use_observer_->MatchesAppPackageName(package, &label)) { 95 data_use_observer_->MatchesAppPackageName(package, &label)) {
92 DCHECK(!label.empty()); 96 DCHECK(!label.empty());
93 start_tracking = true; 97 start_tracking = true;
94 } 98 }
95 } 99 }
96 if (!start_tracking && !url.is_empty() && 100 if (!start_tracking && !url.is_empty() &&
97 data_use_observer_->Matches(url, &label)) { 101 data_use_observer_->Matches(url, &label)) {
98 DCHECK(!label.empty()); 102 DCHECK(!label.empty());
99 start_tracking = true; 103 start_tracking = true;
100 } 104 }
101 if (start_tracking) 105 if (start_tracking)
102 StartTrackingDataUse(tab_id, label); 106 StartTrackingDataUse(tab_id, label);
103 break; 107 break;
104 } 108 }
105 109
106 case TRANSITION_FROM_NAVSUGGEST:
107 case TRANSITION_OMNIBOX_NAVIGATION:
108 case TRANSITION_BOOKMARK: 110 case TRANSITION_BOOKMARK:
109 case TRANSITION_HISTORY_ITEM: 111 case TRANSITION_HISTORY_ITEM:
110 case TRANSITION_TO_EXTERNAL_APP:
111 // Exit events. 112 // Exit events.
112 EndTrackingDataUse(tab_id); 113 EndTrackingDataUse(tab_id);
113 break; 114 break;
114 115
115 default: 116 default:
116 NOTREACHED(); 117 NOTREACHED();
117 break; 118 break;
118 } 119 }
119 } 120 }
120 121
121 void DataUseTabModel::OnTabCloseEvent(int32_t tab_id) { 122 void DataUseTabModel::OnTabCloseEvent(SessionID::id_type tab_id) {
122 DCHECK(thread_checker_.CalledOnValidThread()); 123 DCHECK(thread_checker_.CalledOnValidThread());
123 DCHECK(IsValidTabID(tab_id)); 124 DCHECK(IsValidTabID(tab_id));
124 125
125 TabEntryMap::iterator tab_entry_iterator = active_tabs_.find(tab_id); 126 TabEntryMap::iterator tab_entry_iterator = active_tabs_.find(tab_id);
126 if (tab_entry_iterator == active_tabs_.end()) 127 if (tab_entry_iterator == active_tabs_.end())
127 return; 128 return;
128 129
129 TabDataUseEntry& tab_entry = tab_entry_iterator->second; 130 TabDataUseEntry& tab_entry = tab_entry_iterator->second;
130 if (tab_entry.IsTrackingDataUse()) 131 if (tab_entry.IsTrackingDataUse())
131 tab_entry.EndTracking(); 132 tab_entry.EndTracking();
(...skipping 20 matching lines...) Expand all
152 TabEntryMap::const_iterator tab_entry_iterator = 153 TabEntryMap::const_iterator tab_entry_iterator =
153 active_tabs_.find(data_use.tab_id); 154 active_tabs_.find(data_use.tab_id);
154 if (tab_entry_iterator != active_tabs_.end()) { 155 if (tab_entry_iterator != active_tabs_.end()) {
155 return tab_entry_iterator->second.GetLabel(data_use.request_start, 156 return tab_entry_iterator->second.GetLabel(data_use.request_start,
156 output_label); 157 output_label);
157 } 158 }
158 159
159 return false; // Tab session not found. 160 return false; // Tab session not found.
160 } 161 }
161 162
162 void DataUseTabModel::AddObserver(TabDataUseObserver* observer) { 163 void DataUseTabModel::AddObserver(
163 observer_list_->AddObserver(observer); 164 const TabDataUseObserver* observer,
165 const base::WeakPtr<TabDataUseObserver> weak_ptr_observer) {
sclittle 2015/11/24 04:11:50 There's no point in making this const, since WeakP
tbansal1 2015/11/24 20:01:12 const qualifier prevents something like weak_ptr_o
166 DCHECK(thread_checker_.CalledOnValidThread());
167 observers_.insert(ObserverMap::value_type(observer, weak_ptr_observer));
sclittle 2015/11/24 04:11:50 DCHECK that the observer isn't already in the map.
tbansal1 2015/11/24 20:01:12 Good point. Done similar to https://code.google.co
168 DCHECK_LT(0U, observers_.size());
164 } 169 }
165 170
166 void DataUseTabModel::RemoveObserver(TabDataUseObserver* observer) { 171 void DataUseTabModel::RemoveObserver(const TabDataUseObserver* observer) {
167 observer_list_->RemoveObserver(observer); 172 DCHECK(thread_checker_.CalledOnValidThread());
173 observers_.erase(observer);
sclittle 2015/11/24 04:11:50 DCHECK that the observer is in the map.
tbansal1 2015/11/24 20:01:12 Done.
168 } 174 }
169 175
170 base::TimeTicks DataUseTabModel::Now() const { 176 base::TimeTicks DataUseTabModel::Now() const {
171 return base::TimeTicks::Now(); 177 return base::TimeTicks::Now();
172 } 178 }
173 179
174 void DataUseTabModel::NotifyObserversOfTrackingStarting(int32_t tab_id) { 180 void DataUseTabModel::NotifyObserversOfTrackingStarting(
175 observer_list_->Notify(FROM_HERE, &TabDataUseObserver::NotifyTrackingStarting, 181 SessionID::id_type tab_id) {
176 tab_id); 182 DCHECK(thread_checker_.CalledOnValidThread());
183 DCHECK(ui_task_runner_);
184 for (const auto& it : observers_) {
185 ui_task_runner_->PostTask(
186 FROM_HERE, base::Bind(&TabDataUseObserver::NotifyTrackingStarting,
187 it.second, tab_id));
188 }
177 } 189 }
178 190
179 void DataUseTabModel::NotifyObserversOfTrackingEnding(int32_t tab_id) { 191 void DataUseTabModel::NotifyObserversOfTrackingEnding(
180 observer_list_->Notify(FROM_HERE, &TabDataUseObserver::NotifyTrackingEnding, 192 SessionID::id_type tab_id) {
181 tab_id); 193 DCHECK(thread_checker_.CalledOnValidThread());
194 DCHECK(ui_task_runner_);
195 for (const auto& it : observers_) {
196 ui_task_runner_->PostTask(
197 FROM_HERE, base::Bind(&TabDataUseObserver::NotifyTrackingEnding,
198 it.second, tab_id));
199 }
182 } 200 }
183 201
184 void DataUseTabModel::StartTrackingDataUse(int32_t tab_id, 202 void DataUseTabModel::StartTrackingDataUse(SessionID::id_type tab_id,
185 const std::string& label) { 203 const std::string& label) {
186 // TODO(rajendrant): Explore ability to handle changes in label for current 204 // TODO(rajendrant): Explore ability to handle changes in label for current
187 // session. 205 // session.
188 bool new_tab_entry_added = false; 206 bool new_tab_entry_added = false;
189 TabEntryMap::iterator tab_entry_iterator = active_tabs_.find(tab_id); 207 TabEntryMap::iterator tab_entry_iterator = active_tabs_.find(tab_id);
190 if (tab_entry_iterator == active_tabs_.end()) { 208 if (tab_entry_iterator == active_tabs_.end()) {
191 auto new_entry = 209 auto new_entry =
192 active_tabs_.insert(TabEntryMap::value_type(tab_id, TabDataUseEntry())); 210 active_tabs_.insert(TabEntryMap::value_type(tab_id, TabDataUseEntry()));
193 tab_entry_iterator = new_entry.first; 211 tab_entry_iterator = new_entry.first;
194 DCHECK(tab_entry_iterator != active_tabs_.end()); 212 DCHECK(tab_entry_iterator != active_tabs_.end());
195 DCHECK(!tab_entry_iterator->second.IsTrackingDataUse()); 213 DCHECK(!tab_entry_iterator->second.IsTrackingDataUse());
196 new_tab_entry_added = true; 214 new_tab_entry_added = true;
197 } 215 }
198 if (tab_entry_iterator->second.StartTracking(label)) 216 if (tab_entry_iterator->second.StartTracking(label))
199 NotifyObserversOfTrackingStarting(tab_id); 217 NotifyObserversOfTrackingStarting(tab_id);
200 218
201 if (new_tab_entry_added) 219 if (new_tab_entry_added)
202 CompactTabEntries(); // Keep total number of tab entries within limit. 220 CompactTabEntries(); // Keep total number of tab entries within limit.
203 } 221 }
204 222
205 void DataUseTabModel::EndTrackingDataUse(int32_t tab_id) { 223 void DataUseTabModel::EndTrackingDataUse(SessionID::id_type tab_id) {
206 TabEntryMap::iterator tab_entry_iterator = active_tabs_.find(tab_id); 224 TabEntryMap::iterator tab_entry_iterator = active_tabs_.find(tab_id);
207 if (tab_entry_iterator != active_tabs_.end() && 225 if (tab_entry_iterator != active_tabs_.end() &&
208 tab_entry_iterator->second.EndTracking()) { 226 tab_entry_iterator->second.EndTracking()) {
209 NotifyObserversOfTrackingEnding(tab_id); 227 NotifyObserversOfTrackingEnding(tab_id);
210 } 228 }
211 } 229 }
212 230
213 void DataUseTabModel::CompactTabEntries() { 231 void DataUseTabModel::CompactTabEntries() {
214 // Remove expired tab entries. 232 // Remove expired tab entries.
215 for (TabEntryMap::iterator tab_entry_iterator = active_tabs_.begin(); 233 for (TabEntryMap::iterator tab_entry_iterator = active_tabs_.begin();
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 kUMAUnexpiredTabEntryRemovalDurationMinutesHistogram, 273 kUMAUnexpiredTabEntryRemovalDurationMinutesHistogram,
256 Now() - oldest_tab_entry_iterator->second.GetLatestStartOrEndTime(), 274 Now() - oldest_tab_entry_iterator->second.GetLatestStartOrEndTime(),
257 base::TimeDelta::FromMinutes(1), base::TimeDelta::FromHours(1), 50); 275 base::TimeDelta::FromMinutes(1), base::TimeDelta::FromHours(1), 50);
258 active_tabs_.erase(oldest_tab_entry_iterator); 276 active_tabs_.erase(oldest_tab_entry_iterator);
259 } 277 }
260 } 278 }
261 279
262 } // namespace android 280 } // namespace android
263 281
264 } // namespace chrome 282 } // namespace chrome
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698