| // Copyright 2013 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/network_time/navigation_time_helper.h" |
| |
| #include "chrome/browser/network_time/network_time_service.h" |
| #include "chrome/browser/network_time/network_time_service_factory.h" |
| #include "content/public/browser/navigation_entry.h" |
| #include "content/public/browser/notification_service.h" |
| #include "content/public/browser/notification_types.h" |
| |
| DEFINE_WEB_CONTENTS_USER_DATA_KEY(NavigationTimeHelper); |
| |
| NavigationTimeHelper::NavigationTimeHelper() |
| : web_contents_(NULL) {} |
| |
| NavigationTimeHelper::NavigationTimeHelper(content::WebContents* web_contents) |
| : web_contents_(web_contents) { |
| registrar_.Add(this, content::NOTIFICATION_NAV_LIST_PRUNED, |
| content::NotificationService::AllSources()); |
| } |
| |
| NavigationTimeHelper::~NavigationTimeHelper() {} |
| |
| base::Time NavigationTimeHelper::GetNavigationTime( |
| const content::NavigationEntry* entry) { |
| const void* entry_key = entry; |
| base::Time local_time = entry->GetTimestamp(); |
| |
| NavigationTimeCache::iterator iter = time_cache_.find(entry_key); |
| if (iter == time_cache_.end() || iter->second.local_time != local_time) { |
| // Calculate navigation time for new entry or existing entry that has new |
| // navigation. |
| base::Time navigation_time = GetNetworkTime(local_time); |
| |
| if (iter == time_cache_.end()) { |
| time_cache_.insert(std::make_pair(entry_key, |
| NavigationTimeInfo(local_time, |
| navigation_time))); |
| } else { |
| iter->second = NavigationTimeInfo(local_time, navigation_time); |
| } |
| |
| return navigation_time; |
| } else { |
| // Use the navigation time calculated before for unchanged entry. |
| return iter->second.network_time; |
| } |
| } |
| |
| void NavigationTimeHelper::Observe( |
| int type, |
| const content::NotificationSource& source, |
| const content::NotificationDetails& details) { |
| DCHECK_EQ(type, content::NOTIFICATION_NAV_LIST_PRUNED); |
| |
| // Drop pruned entries from cache. |
| const content::NavigationController& controller = |
| web_contents_->GetController(); |
| NavigationTimeCache new_cache; |
| for (int i = 0; i < controller.GetEntryCount(); ++i) { |
| const void* entry_key = controller.GetEntryAtIndex(i); |
| NavigationTimeCache::const_iterator iter = time_cache_.find(entry_key); |
| if (iter != time_cache_.end()) { |
| new_cache.insert(std::make_pair(entry_key, iter->second)); |
| } |
| } |
| time_cache_.swap(new_cache); |
| } |
| |
| base::Time NavigationTimeHelper::GetNetworkTime(base::Time local_time) { |
| Profile* profile = |
| Profile::FromBrowserContext(web_contents_->GetBrowserContext()); |
| return NetworkTimeServiceFactory::GetForProfile(profile)-> |
| GetNetworkTime(local_time); |
| } |