OLD | NEW |
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" |
| 14 #include "url/gurl.h" |
13 | 15 |
14 namespace { | 16 namespace { |
15 | 17 |
16 // Indicates the default maximum number of tabs to maintain session information | 18 // Indicates the default maximum number of tabs to maintain session information |
17 // about. May be overridden by the field trial. | 19 // about. May be overridden by the field trial. |
18 const size_t kDefaultMaxTabEntries = 200; | 20 const size_t kDefaultMaxTabEntries = 200; |
19 | 21 |
20 const char kUMAExpiredInactiveTabEntryRemovalDurationSecondsHistogram[] = | 22 const char kUMAExpiredInactiveTabEntryRemovalDurationSecondsHistogram[] = |
21 "DataUse.TabModel.ExpiredInactiveTabEntryRemovalDuration"; | 23 "DataUse.TabModel.ExpiredInactiveTabEntryRemovalDuration"; |
22 const char kUMAExpiredActiveTabEntryRemovalDurationHoursHistogram[] = | 24 const char kUMAExpiredActiveTabEntryRemovalDurationHoursHistogram[] = |
23 "DataUse.TabModel.ExpiredActiveTabEntryRemovalDuration"; | 25 "DataUse.TabModel.ExpiredActiveTabEntryRemovalDuration"; |
24 const char kUMAUnexpiredTabEntryRemovalDurationMinutesHistogram[] = | 26 const char kUMAUnexpiredTabEntryRemovalDurationMinutesHistogram[] = |
25 "DataUse.TabModel.UnexpiredTabEntryRemovalDuration"; | 27 "DataUse.TabModel.UnexpiredTabEntryRemovalDuration"; |
26 | 28 |
27 // Returns true if |tab_id| is a valid tab ID. | 29 // Returns true if |tab_id| is a valid tab ID. |
28 bool IsValidTabID(int32_t tab_id) { | 30 bool IsValidTabID(SessionID::id_type tab_id) { |
29 return tab_id >= 0; | 31 return tab_id >= 0; |
30 } | 32 } |
31 | 33 |
32 // Returns various parameters from the values specified in the field trial. | 34 // Returns various parameters from the values specified in the field trial. |
33 size_t GetMaxTabEntries() { | 35 size_t GetMaxTabEntries() { |
34 size_t max_tab_entries = -1; | 36 size_t max_tab_entries = -1; |
35 std::string variation_value = variations::GetVariationParamValue( | 37 std::string variation_value = variations::GetVariationParamValue( |
36 chrome::android::ExternalDataUseObserver:: | 38 chrome::android::ExternalDataUseObserver:: |
37 kExternalDataUseObserverFieldTrial, | 39 kExternalDataUseObserverFieldTrial, |
38 "max_tab_entries"); | 40 "max_tab_entries"); |
39 if (!variation_value.empty() && | 41 if (!variation_value.empty() && |
40 base::StringToSizeT(variation_value, &max_tab_entries)) { | 42 base::StringToSizeT(variation_value, &max_tab_entries)) { |
41 return max_tab_entries; | 43 return max_tab_entries; |
42 } | 44 } |
43 return kDefaultMaxTabEntries; | 45 return kDefaultMaxTabEntries; |
44 } | 46 } |
45 | 47 |
46 } // namespace | 48 } // namespace |
47 | 49 |
48 namespace chrome { | 50 namespace chrome { |
49 | 51 |
50 namespace android { | 52 namespace android { |
51 | 53 |
52 DataUseTabModel::DataUseTabModel( | 54 DataUseTabModel::DataUseTabModel( |
53 const ExternalDataUseObserver* data_use_observer, | 55 const ExternalDataUseObserver* data_use_observer, |
54 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) | 56 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) |
55 : data_use_observer_(data_use_observer), | 57 : data_use_observer_(data_use_observer), |
56 observer_list_(new base::ObserverListThreadSafe<TabDataUseObserver>), | |
57 max_tab_entries_(GetMaxTabEntries()), | 58 max_tab_entries_(GetMaxTabEntries()), |
58 weak_factory_(this) {} | 59 ui_task_runner_(ui_task_runner), |
| 60 weak_factory_(this) { |
| 61 DCHECK(ui_task_runner_); |
| 62 } |
59 | 63 |
60 DataUseTabModel::~DataUseTabModel() { | 64 DataUseTabModel::~DataUseTabModel() { |
61 DCHECK(thread_checker_.CalledOnValidThread()); | 65 DCHECK(thread_checker_.CalledOnValidThread()); |
62 } | 66 } |
63 | 67 |
64 base::WeakPtr<DataUseTabModel> DataUseTabModel::GetWeakPtr() { | 68 base::WeakPtr<DataUseTabModel> DataUseTabModel::GetWeakPtr() { |
65 DCHECK(thread_checker_.CalledOnValidThread()); | 69 DCHECK(thread_checker_.CalledOnValidThread()); |
66 return weak_factory_.GetWeakPtr(); | 70 return weak_factory_.GetWeakPtr(); |
67 } | 71 } |
68 | 72 |
69 void DataUseTabModel::OnNavigationEvent(int32_t tab_id, | 73 void DataUseTabModel::OnNavigationEvent(SessionID::id_type tab_id, |
70 TransitionType transition, | 74 TransitionType transition, |
71 const GURL& url, | 75 const GURL& url, |
72 const std::string& package) { | 76 const std::string& package) { |
73 DCHECK(thread_checker_.CalledOnValidThread()); | 77 DCHECK(thread_checker_.CalledOnValidThread()); |
74 DCHECK(IsValidTabID(tab_id)); | 78 DCHECK(IsValidTabID(tab_id)); |
75 | 79 |
76 switch (transition) { | 80 switch (transition) { |
77 case TRANSITION_OMNIBOX_SEARCH: | 81 case TRANSITION_OMNIBOX_SEARCH: |
| 82 case TRANSITION_OMNIBOX_NAVIGATION: |
78 case TRANSITION_FROM_EXTERNAL_APP: { | 83 case TRANSITION_FROM_EXTERNAL_APP: { |
79 // Enter events. | 84 // Enter events. |
80 bool start_tracking = false; | 85 bool start_tracking = false; |
81 std::string label; | 86 std::string label; |
82 TabEntryMap::const_iterator tab_entry_iterator = | 87 TabEntryMap::const_iterator tab_entry_iterator = |
83 active_tabs_.find(tab_id); | 88 active_tabs_.find(tab_id); |
84 if (tab_entry_iterator != active_tabs_.end() && | 89 if (tab_entry_iterator != active_tabs_.end() && |
85 tab_entry_iterator->second.IsTrackingDataUse()) { | 90 tab_entry_iterator->second.IsTrackingDataUse()) { |
86 break; | 91 break; |
87 } | 92 } |
88 if (transition == TRANSITION_FROM_EXTERNAL_APP) { | 93 if (transition == TRANSITION_FROM_EXTERNAL_APP) { |
89 // Package name should match, for transitions from external app. | 94 // Package name should match, for transitions from external app. |
90 if (!package.empty() && | 95 if (!package.empty() && |
91 data_use_observer_->MatchesAppPackageName(package, &label)) { | 96 data_use_observer_->MatchesAppPackageName(package, &label)) { |
92 DCHECK(!label.empty()); | 97 DCHECK(!label.empty()); |
93 start_tracking = true; | 98 start_tracking = true; |
94 } | 99 } |
95 } | 100 } |
96 if (!start_tracking && !url.is_empty() && | 101 if (!start_tracking && !url.is_empty() && |
97 data_use_observer_->Matches(url, &label)) { | 102 data_use_observer_->Matches(url, &label)) { |
98 DCHECK(!label.empty()); | 103 DCHECK(!label.empty()); |
99 start_tracking = true; | 104 start_tracking = true; |
100 } | 105 } |
101 if (start_tracking) | 106 if (start_tracking) |
102 StartTrackingDataUse(tab_id, label); | 107 StartTrackingDataUse(tab_id, label); |
103 break; | 108 break; |
104 } | 109 } |
105 | 110 |
106 case TRANSITION_FROM_NAVSUGGEST: | |
107 case TRANSITION_OMNIBOX_NAVIGATION: | |
108 case TRANSITION_BOOKMARK: | 111 case TRANSITION_BOOKMARK: |
109 case TRANSITION_HISTORY_ITEM: | 112 case TRANSITION_HISTORY_ITEM: |
110 case TRANSITION_TO_EXTERNAL_APP: | |
111 // Exit events. | 113 // Exit events. |
112 EndTrackingDataUse(tab_id); | 114 EndTrackingDataUse(tab_id); |
113 break; | 115 break; |
114 | 116 |
115 default: | 117 default: |
116 NOTREACHED(); | 118 NOTREACHED(); |
117 break; | 119 break; |
118 } | 120 } |
119 } | 121 } |
120 | 122 |
121 void DataUseTabModel::OnTabCloseEvent(int32_t tab_id) { | 123 void DataUseTabModel::OnTabCloseEvent(SessionID::id_type tab_id) { |
122 DCHECK(thread_checker_.CalledOnValidThread()); | 124 DCHECK(thread_checker_.CalledOnValidThread()); |
123 DCHECK(IsValidTabID(tab_id)); | 125 DCHECK(IsValidTabID(tab_id)); |
124 | 126 |
125 TabEntryMap::iterator tab_entry_iterator = active_tabs_.find(tab_id); | 127 TabEntryMap::iterator tab_entry_iterator = active_tabs_.find(tab_id); |
126 if (tab_entry_iterator == active_tabs_.end()) | 128 if (tab_entry_iterator == active_tabs_.end()) |
127 return; | 129 return; |
128 | 130 |
129 TabDataUseEntry& tab_entry = tab_entry_iterator->second; | 131 TabDataUseEntry& tab_entry = tab_entry_iterator->second; |
130 if (tab_entry.IsTrackingDataUse()) | 132 if (tab_entry.IsTrackingDataUse()) |
131 tab_entry.EndTracking(); | 133 tab_entry.EndTracking(); |
(...skipping 20 matching lines...) Expand all Loading... |
152 TabEntryMap::const_iterator tab_entry_iterator = | 154 TabEntryMap::const_iterator tab_entry_iterator = |
153 active_tabs_.find(data_use.tab_id); | 155 active_tabs_.find(data_use.tab_id); |
154 if (tab_entry_iterator != active_tabs_.end()) { | 156 if (tab_entry_iterator != active_tabs_.end()) { |
155 return tab_entry_iterator->second.GetLabel(data_use.request_start, | 157 return tab_entry_iterator->second.GetLabel(data_use.request_start, |
156 output_label); | 158 output_label); |
157 } | 159 } |
158 | 160 |
159 return false; // Tab session not found. | 161 return false; // Tab session not found. |
160 } | 162 } |
161 | 163 |
162 void DataUseTabModel::AddObserver(TabDataUseObserver* observer) { | 164 void DataUseTabModel::AddObserver(base::WeakPtr<TabDataUseObserver> observer) { |
163 observer_list_->AddObserver(observer); | 165 DCHECK(thread_checker_.CalledOnValidThread()); |
164 } | 166 observers_.push_back(observer); |
165 | |
166 void DataUseTabModel::RemoveObserver(TabDataUseObserver* observer) { | |
167 observer_list_->RemoveObserver(observer); | |
168 } | 167 } |
169 | 168 |
170 base::TimeTicks DataUseTabModel::Now() const { | 169 base::TimeTicks DataUseTabModel::Now() const { |
171 return base::TimeTicks::Now(); | 170 return base::TimeTicks::Now(); |
172 } | 171 } |
173 | 172 |
174 void DataUseTabModel::NotifyObserversOfTrackingStarting(int32_t tab_id) { | 173 void DataUseTabModel::NotifyObserversOfTrackingStarting( |
175 observer_list_->Notify(FROM_HERE, &TabDataUseObserver::NotifyTrackingStarting, | 174 SessionID::id_type tab_id) { |
176 tab_id); | 175 DCHECK(thread_checker_.CalledOnValidThread()); |
| 176 DCHECK(ui_task_runner_); |
| 177 for (const auto& observer : observers_) { |
| 178 ui_task_runner_->PostTask( |
| 179 FROM_HERE, base::Bind(&TabDataUseObserver::NotifyTrackingStarting, |
| 180 observer, tab_id)); |
| 181 } |
177 } | 182 } |
178 | 183 |
179 void DataUseTabModel::NotifyObserversOfTrackingEnding(int32_t tab_id) { | 184 void DataUseTabModel::NotifyObserversOfTrackingEnding( |
180 observer_list_->Notify(FROM_HERE, &TabDataUseObserver::NotifyTrackingEnding, | 185 SessionID::id_type tab_id) { |
181 tab_id); | 186 DCHECK(thread_checker_.CalledOnValidThread()); |
| 187 DCHECK(ui_task_runner_); |
| 188 for (const auto& observer : observers_) { |
| 189 ui_task_runner_->PostTask( |
| 190 FROM_HERE, base::Bind(&TabDataUseObserver::NotifyTrackingEnding, |
| 191 observer, tab_id)); |
| 192 } |
182 } | 193 } |
183 | 194 |
184 void DataUseTabModel::StartTrackingDataUse(int32_t tab_id, | 195 void DataUseTabModel::StartTrackingDataUse(SessionID::id_type tab_id, |
185 const std::string& label) { | 196 const std::string& label) { |
186 // TODO(rajendrant): Explore ability to handle changes in label for current | 197 // TODO(rajendrant): Explore ability to handle changes in label for current |
187 // session. | 198 // session. |
188 bool new_tab_entry_added = false; | 199 bool new_tab_entry_added = false; |
189 TabEntryMap::iterator tab_entry_iterator = active_tabs_.find(tab_id); | 200 TabEntryMap::iterator tab_entry_iterator = active_tabs_.find(tab_id); |
190 if (tab_entry_iterator == active_tabs_.end()) { | 201 if (tab_entry_iterator == active_tabs_.end()) { |
191 auto new_entry = | 202 auto new_entry = |
192 active_tabs_.insert(TabEntryMap::value_type(tab_id, TabDataUseEntry())); | 203 active_tabs_.insert(TabEntryMap::value_type(tab_id, TabDataUseEntry())); |
193 tab_entry_iterator = new_entry.first; | 204 tab_entry_iterator = new_entry.first; |
194 DCHECK(tab_entry_iterator != active_tabs_.end()); | 205 DCHECK(tab_entry_iterator != active_tabs_.end()); |
195 DCHECK(!tab_entry_iterator->second.IsTrackingDataUse()); | 206 DCHECK(!tab_entry_iterator->second.IsTrackingDataUse()); |
196 new_tab_entry_added = true; | 207 new_tab_entry_added = true; |
197 } | 208 } |
198 if (tab_entry_iterator->second.StartTracking(label)) | 209 if (tab_entry_iterator->second.StartTracking(label)) |
199 NotifyObserversOfTrackingStarting(tab_id); | 210 NotifyObserversOfTrackingStarting(tab_id); |
200 | 211 |
201 if (new_tab_entry_added) | 212 if (new_tab_entry_added) |
202 CompactTabEntries(); // Keep total number of tab entries within limit. | 213 CompactTabEntries(); // Keep total number of tab entries within limit. |
203 } | 214 } |
204 | 215 |
205 void DataUseTabModel::EndTrackingDataUse(int32_t tab_id) { | 216 void DataUseTabModel::EndTrackingDataUse(SessionID::id_type tab_id) { |
206 TabEntryMap::iterator tab_entry_iterator = active_tabs_.find(tab_id); | 217 TabEntryMap::iterator tab_entry_iterator = active_tabs_.find(tab_id); |
207 if (tab_entry_iterator != active_tabs_.end() && | 218 if (tab_entry_iterator != active_tabs_.end() && |
208 tab_entry_iterator->second.EndTracking()) { | 219 tab_entry_iterator->second.EndTracking()) { |
209 NotifyObserversOfTrackingEnding(tab_id); | 220 NotifyObserversOfTrackingEnding(tab_id); |
210 } | 221 } |
211 } | 222 } |
212 | 223 |
213 void DataUseTabModel::CompactTabEntries() { | 224 void DataUseTabModel::CompactTabEntries() { |
214 // Remove expired tab entries. | 225 // Remove expired tab entries. |
215 for (TabEntryMap::iterator tab_entry_iterator = active_tabs_.begin(); | 226 for (TabEntryMap::iterator tab_entry_iterator = active_tabs_.begin(); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 kUMAUnexpiredTabEntryRemovalDurationMinutesHistogram, | 266 kUMAUnexpiredTabEntryRemovalDurationMinutesHistogram, |
256 Now() - oldest_tab_entry_iterator->second.GetLatestStartOrEndTime(), | 267 Now() - oldest_tab_entry_iterator->second.GetLatestStartOrEndTime(), |
257 base::TimeDelta::FromMinutes(1), base::TimeDelta::FromHours(1), 50); | 268 base::TimeDelta::FromMinutes(1), base::TimeDelta::FromHours(1), 50); |
258 active_tabs_.erase(oldest_tab_entry_iterator); | 269 active_tabs_.erase(oldest_tab_entry_iterator); |
259 } | 270 } |
260 } | 271 } |
261 | 272 |
262 } // namespace android | 273 } // namespace android |
263 | 274 |
264 } // namespace chrome | 275 } // namespace chrome |
OLD | NEW |