| 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 |