Convert WebContents::LastActiveTime to base::Time
TimeTicks should only be used to measure local duration (same machine, same process) and not absolute time. TimeTicks may not increment during process suspension (this is platform dependent) and so TimeTicks created at different time do not share a common reference. As a consequence, it is not possible to convert them to absolute times. WebContents::LastActiveTime is intended to represent the date of the last activation time, that will be persisted and sent to sync. Because it uses TimeTicks, this field is incorrectly synced for WebContents created on Mac or ChromeOS machines. Convert the field to a base::Time to fix it. Convert the field to a base::Time to fix it. Bug: 349542284 Change-Id: Iba85b1579f8ee9ec22d60219c8f8f444eef3336d Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5735384 Commit-Queue: Olivier Robin <olivierrobin@chromium.org> Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org> Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com> Reviewed-by: Scott Violet <sky@chromium.org> Reviewed-by: Sylvain Defresne <sdefresne@chromium.org> Cr-Commit-Position: refs/heads/main@{#1338463}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
be5d0586ca
commit
da292fb29d
chrome/browser
resource_coordinator
sessions
session_restore.ccsession_restore_stats_collector_unittest.ccsession_service_base.ccsession_service_base.h
ui
browser.ccbrowser_live_tab_context.ccbrowser_tabrestore.ccbrowser_tabrestore.hbrowser_tabrestore_browsertest.cc
sync
visited_url_ranking
components/sessions/core
content
browser
public
test
@ -490,6 +490,7 @@ void TabLifecycleUnitSource::TabLifecycleUnit::FinishDiscard(
|
||||
old_contents->GetVisibility() == content::Visibility::HIDDEN;
|
||||
create_params.desired_renderer_state =
|
||||
content::WebContents::CreateParams::kNoRendererProcess;
|
||||
create_params.last_active_time = old_contents->GetLastActiveTime();
|
||||
create_params.last_active_time_ticks = old_contents->GetLastActiveTimeTicks();
|
||||
std::unique_ptr<content::WebContents> null_contents =
|
||||
content::WebContents::Create(create_params);
|
||||
|
@ -333,8 +333,9 @@ class SessionRestoreImpl : public BrowserListObserver {
|
||||
browser, tab.navigations, tab_index, selected_index,
|
||||
tab.extension_app_id, std::nullopt,
|
||||
disposition == WindowOpenDisposition::NEW_FOREGROUND_TAB, // selected
|
||||
tab.pinned, base::TimeTicks(), nullptr, tab.user_agent_override,
|
||||
tab.extra_data, /*from_session_restore=*/true,
|
||||
tab.pinned, base::TimeTicks(), base::Time(), nullptr,
|
||||
tab.user_agent_override, tab.extra_data,
|
||||
/*from_session_restore=*/true,
|
||||
/*is_active_browser=*/std::nullopt);
|
||||
// Start loading the tab immediately.
|
||||
web_contents->GetController().LoadIfNecessary();
|
||||
@ -878,7 +879,7 @@ class SessionRestoreImpl : public BrowserListObserver {
|
||||
int tab_index = i + initial_tab_count;
|
||||
RestoreTab(tab, browser, is_active_browser, restored_tabs, new_group_ids,
|
||||
tab_index, is_selected_tab, last_active_time_ticks,
|
||||
did_show_browser);
|
||||
tab.last_active_time, did_show_browser);
|
||||
}
|
||||
}
|
||||
|
||||
@ -895,6 +896,7 @@ class SessionRestoreImpl : public BrowserListObserver {
|
||||
const int tab_index,
|
||||
bool is_selected_tab,
|
||||
base::TimeTicks last_active_time_ticks,
|
||||
base::Time last_active_time,
|
||||
bool& did_show_browser) {
|
||||
// It's possible (particularly for foreign sessions) to receive a tab
|
||||
// without valid navigations. In that case, just skip it.
|
||||
@ -932,9 +934,9 @@ class SessionRestoreImpl : public BrowserListObserver {
|
||||
WebContents* web_contents = chrome::AddRestoredTab(
|
||||
browser, tab.navigations, tab_index, selected_index,
|
||||
tab.extension_app_id, new_group, is_selected_tab, tab.pinned,
|
||||
last_active_time_ticks, session_storage_namespace.get(),
|
||||
tab.user_agent_override, tab.extra_data,
|
||||
true /* from_session_restore */, is_active_browser);
|
||||
last_active_time_ticks, last_active_time,
|
||||
session_storage_namespace.get(), tab.user_agent_override,
|
||||
tab.extra_data, true /* from_session_restore */, is_active_browser);
|
||||
DCHECK(web_contents);
|
||||
|
||||
RestoredTab restored_tab(web_contents, is_selected_tab,
|
||||
|
@ -175,8 +175,8 @@ class SessionRestoreStatsCollectorTest : public testing::Test {
|
||||
contents->GetController().Restore(0, content::RestoreType::kRestored,
|
||||
&entries);
|
||||
// Create a last active time in the past.
|
||||
content::WebContentsTester::For(contents)->SetLastActiveTimeTicks(
|
||||
base::TimeTicks::Now() - base::Minutes(1));
|
||||
content::WebContentsTester::For(contents)->SetLastActiveTime(
|
||||
base::Time::Now() - base::Minutes(1));
|
||||
restored_tabs_.push_back(
|
||||
RestoredTab(contents, is_active, false, false, std::nullopt));
|
||||
if (is_active)
|
||||
|
@ -312,7 +312,7 @@ void SessionServiceBase::SetTabExtensionAppID(
|
||||
|
||||
void SessionServiceBase::SetLastActiveTime(SessionID window_id,
|
||||
SessionID tab_id,
|
||||
base::TimeTicks last_active_time) {
|
||||
base::Time last_active_time) {
|
||||
if (!ShouldTrackChangesToWindow(window_id))
|
||||
return;
|
||||
|
||||
@ -532,7 +532,7 @@ void SessionServiceBase::BuildCommandsForTab(
|
||||
|
||||
command_storage_manager()->AppendRebuildCommand(
|
||||
sessions::CreateLastActiveTimeCommand(session_id,
|
||||
tab->GetLastActiveTimeTicks()));
|
||||
tab->GetLastActiveTime()));
|
||||
|
||||
// TODO(stahon@microsoft.com) This might be movable to SessionService
|
||||
// when Chrome OS uses AppSessionService for app restores.
|
||||
|
@ -129,7 +129,7 @@ class SessionServiceBase : public sessions::CommandStorageManagerDelegate,
|
||||
// Sets the last active time of the tab.
|
||||
void SetLastActiveTime(SessionID window_id,
|
||||
SessionID tab_id,
|
||||
base::TimeTicks last_active_time);
|
||||
base::Time last_active_time);
|
||||
|
||||
// Fetches the contents of the last session, notifying the callback when
|
||||
// done. If the callback is supplied an empty vector of SessionWindows
|
||||
|
@ -2856,7 +2856,7 @@ void Browser::OnActiveTabChanged(WebContents* old_contents,
|
||||
sessions::SessionTabHelper* session_tab_helper =
|
||||
sessions::SessionTabHelper::FromWebContents(new_contents);
|
||||
service->SetLastActiveTime(session_id(), session_tab_helper->session_id(),
|
||||
base::TimeTicks::Now());
|
||||
base::Time::Now());
|
||||
}
|
||||
|
||||
SearchTabHelper::FromWebContents(new_contents)->OnTabActivated();
|
||||
|
@ -235,7 +235,8 @@ sessions::LiveTab* BrowserLiveTabContext::AddRestoredTab(
|
||||
web_contents = chrome::AddRestoredTab(
|
||||
browser_, tab.navigations, tab_index, tab.normalized_navigation_index(),
|
||||
tab.extension_app_id, group_id, select, tab.pinned, base::TimeTicks(),
|
||||
storage_namespace, tab.user_agent_override, tab.extra_data,
|
||||
base::Time(), storage_namespace, tab.user_agent_override,
|
||||
tab.extra_data,
|
||||
/*from_session_restore=*/false, /*is_active_browser=*/std::nullopt);
|
||||
|
||||
if (is_grouped_tab_unsaved || group_deleted_from_model) {
|
||||
@ -285,8 +286,8 @@ sessions::LiveTab* BrowserLiveTabContext::AddRestoredTab(
|
||||
web_contents = chrome::AddRestoredTab(
|
||||
browser_, tab.navigations, tab_index,
|
||||
tab.normalized_navigation_index(), tab.extension_app_id, group_id,
|
||||
select, tab.pinned, base::TimeTicks(), storage_namespace,
|
||||
tab.user_agent_override, tab.extra_data,
|
||||
select, tab.pinned, base::TimeTicks(), base::Time(),
|
||||
storage_namespace, tab.user_agent_override, tab.extra_data,
|
||||
/*from_session_restore=*/false, /*is_active_browser=*/std::nullopt);
|
||||
} else {
|
||||
// Do nothing if the tab wasn't added to the group.
|
||||
|
@ -52,6 +52,7 @@ std::unique_ptr<WebContents> CreateRestoredTab(
|
||||
int selected_navigation,
|
||||
const std::string& extension_app_id,
|
||||
base::TimeTicks last_active_time_ticks,
|
||||
base::Time last_active_time,
|
||||
content::SessionStorageNamespace* session_storage_namespace,
|
||||
const sessions::SerializedUserAgentOverride& user_agent_override,
|
||||
const std::map<std::string, std::string>& extra_data,
|
||||
@ -73,6 +74,7 @@ std::unique_ptr<WebContents> CreateRestoredTab(
|
||||
create_params.desired_renderer_state =
|
||||
WebContents::CreateParams::kNoRendererProcess;
|
||||
create_params.last_active_time_ticks = last_active_time_ticks;
|
||||
create_params.last_active_time = last_active_time;
|
||||
std::unique_ptr<WebContents> web_contents =
|
||||
WebContents::CreateWithSessionStorage(create_params,
|
||||
session_storage_namespace_map);
|
||||
@ -264,7 +266,8 @@ WebContents* AddRestoredTab(
|
||||
std::optional<tab_groups::TabGroupId> group,
|
||||
bool select,
|
||||
bool pin,
|
||||
base::TimeTicks last_active_time,
|
||||
base::TimeTicks last_active_time_ticks,
|
||||
base::Time last_active_time,
|
||||
content::SessionStorageNamespace* session_storage_namespace,
|
||||
const sessions::SerializedUserAgentOverride& user_agent_override,
|
||||
const std::map<std::string, std::string>& extra_data,
|
||||
@ -273,8 +276,8 @@ WebContents* AddRestoredTab(
|
||||
const bool initially_hidden = !select || browser->window()->IsMinimized();
|
||||
std::unique_ptr<WebContents> web_contents = CreateRestoredTab(
|
||||
browser, navigations, selected_navigation, extension_app_id,
|
||||
last_active_time, session_storage_namespace, user_agent_override,
|
||||
extra_data, initially_hidden, from_session_restore);
|
||||
last_active_time_ticks, last_active_time, session_storage_namespace,
|
||||
user_agent_override, extra_data, initially_hidden, from_session_restore);
|
||||
|
||||
return AddRestoredTabImpl(std::move(web_contents), browser, tab_index, group,
|
||||
select, pin, from_session_restore,
|
||||
@ -292,8 +295,8 @@ WebContents* ReplaceRestoredTab(
|
||||
bool from_session_restore) {
|
||||
std::unique_ptr<WebContents> web_contents = CreateRestoredTab(
|
||||
browser, navigations, selected_navigation, extension_app_id,
|
||||
base::TimeTicks(), session_storage_namespace, user_agent_override,
|
||||
extra_data, false, from_session_restore);
|
||||
base::TimeTicks(), base::Time(), session_storage_namespace,
|
||||
user_agent_override, extra_data, false, from_session_restore);
|
||||
WebContents* raw_web_contents = web_contents.get();
|
||||
|
||||
// ReplaceWebContentsAt won't animate in the restoration, so manually do the
|
||||
|
@ -52,6 +52,7 @@ content::WebContents* AddRestoredTab(
|
||||
bool select,
|
||||
bool pin,
|
||||
base::TimeTicks last_active_time_ticks,
|
||||
base::Time last_active_time,
|
||||
content::SessionStorageNamespace* storage_namespace,
|
||||
const sessions::SerializedUserAgentOverride& user_agent_override,
|
||||
const std::map<std::string, std::string>& extra_data,
|
||||
|
@ -131,7 +131,8 @@ IN_PROC_BROWSER_TEST_F(BrowserTabRestoreTest,
|
||||
browser(), navigations, /* tab_index=*/1, /* selected_navigation=*/0,
|
||||
/* extension_app_id=*/std::string(), /* group=*/std::nullopt,
|
||||
/* select=*/true, /* pin=*/false,
|
||||
/* last_active_time=*/base::TimeTicks::Now(),
|
||||
/* last_active_time_ticks=*/base::TimeTicks::Now(),
|
||||
/* last_active_time=*/base::Time::Now(),
|
||||
/* storage_namespace=*/nullptr,
|
||||
/* user_agent_override=*/sessions::SerializedUserAgentOverride(),
|
||||
/* extra_data*/ std::map<std::string, std::string>(),
|
||||
@ -155,7 +156,8 @@ IN_PROC_BROWSER_TEST_F(BrowserTabRestoreTest,
|
||||
browser(), navigations, /* tab_index=*/1, /* selected_navigation=*/0,
|
||||
/* extension_app_id=*/std::string(), /* group=*/std::nullopt,
|
||||
/* select=*/false, /* pin=*/false,
|
||||
/* last_active_time=*/base::TimeTicks::Now(),
|
||||
/* last_active_time_ticks=*/base::TimeTicks::Now(),
|
||||
/* last_active_time=*/base::Time::Now(),
|
||||
/* storage_namespace=*/nullptr,
|
||||
/* user_agent_override=*/sessions::SerializedUserAgentOverride(),
|
||||
/* extra_data*/ std::map<std::string, std::string>(),
|
||||
|
@ -53,20 +53,18 @@ void TabContentsSyncedTabDelegate::ResetCachedLastActiveTime() {
|
||||
}
|
||||
|
||||
base::Time TabContentsSyncedTabDelegate::GetLastActiveTime() {
|
||||
// Use the TimeDelta common ground between the two units to make the
|
||||
// conversion.
|
||||
const base::TimeDelta delta_since_epoch =
|
||||
web_contents_->GetLastActiveTimeTicks() - base::TimeTicks::UnixEpoch();
|
||||
const base::Time converted_time = base::Time::UnixEpoch() + delta_since_epoch;
|
||||
const base::Time last_active_time = web_contents_->GetLastActiveTime();
|
||||
if (base::FeatureList::IsEnabled(syncer::kSyncSessionOnVisibilityChanged)) {
|
||||
const base::TimeTicks last_active_time_ticks =
|
||||
web_contents_->GetLastActiveTimeTicks();
|
||||
if (cached_last_active_time_.has_value() &&
|
||||
converted_time - cached_last_active_time_.value() <
|
||||
last_active_time_ticks - cached_last_active_time_.value().first <
|
||||
syncer::kSyncSessionOnVisibilityChangedTimeThreshold.Get()) {
|
||||
return cached_last_active_time_.value();
|
||||
return cached_last_active_time_.value().second;
|
||||
}
|
||||
cached_last_active_time_ = converted_time;
|
||||
cached_last_active_time_ = {last_active_time_ticks, last_active_time};
|
||||
}
|
||||
return converted_time;
|
||||
return last_active_time;
|
||||
}
|
||||
|
||||
bool TabContentsSyncedTabDelegate::IsBeingDestroyed() const {
|
||||
|
@ -67,9 +67,10 @@ class TabContentsSyncedTabDelegate : public sync_sessions::SyncedTabDelegate {
|
||||
|
||||
raw_ptr<content::WebContents, DanglingUntriaged> web_contents_ = nullptr;
|
||||
|
||||
// Cached value of last_active_time, sometimes returned instead of the
|
||||
// last_active_time from the WebContents.
|
||||
std::optional<base::Time> cached_last_active_time_;
|
||||
// Cached value of last_active_time_ticks and last_active_time, sometimes
|
||||
// returned instead of the last_active_time from the WebContents.
|
||||
std::optional<std::pair<base::TimeTicks, base::Time>>
|
||||
cached_last_active_time_;
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_UI_SYNC_TAB_CONTENTS_SYNCED_TAB_DELEGATE_H_
|
||||
|
@ -19,12 +19,6 @@
|
||||
|
||||
namespace {
|
||||
|
||||
base::Time ConvertLastActiveTime(base::TimeTicks time_to_convert) {
|
||||
const base::TimeDelta delta_since_epoch =
|
||||
time_to_convert - base::TimeTicks::UnixEpoch();
|
||||
return base::Time::UnixEpoch() + delta_since_epoch;
|
||||
}
|
||||
|
||||
class TestSyncedTabDelegate : public TabContentsSyncedTabDelegate {
|
||||
public:
|
||||
explicit TestSyncedTabDelegate(content::WebContents* web_contents) {
|
||||
@ -124,7 +118,9 @@ TEST_F(TabContentsSyncedTabDelegateTest, CachedLastActiveTime) {
|
||||
delegate.GetWindowId());
|
||||
|
||||
base::TimeTicks original_time_ticks = base::TimeTicks::Now();
|
||||
base::Time original_time = ConvertLastActiveTime(original_time_ticks);
|
||||
base::Time original_time = base::Time() + base::Seconds(1);
|
||||
content::WebContentsTester::For(web_contents.get())
|
||||
->SetLastActiveTime(original_time);
|
||||
content::WebContentsTester::For(web_contents.get())
|
||||
->SetLastActiveTimeTicks(original_time_ticks);
|
||||
|
||||
@ -133,16 +129,21 @@ TEST_F(TabContentsSyncedTabDelegateTest, CachedLastActiveTime) {
|
||||
// If not enough time has passed, the cached time should be returned.
|
||||
base::TimeTicks before_threshold_ticks =
|
||||
original_time_ticks + threshold - base::Minutes(1);
|
||||
base::Time before_threshold = base::Time() + base::Seconds(2);
|
||||
content::WebContentsTester::For(web_contents.get())
|
||||
->SetLastActiveTimeTicks(before_threshold_ticks);
|
||||
content::WebContentsTester::For(web_contents.get())
|
||||
->SetLastActiveTime(before_threshold);
|
||||
EXPECT_EQ(original_time, delegate.GetLastActiveTime());
|
||||
|
||||
// After the threshold has passed, the new value should be returned.
|
||||
base::TimeTicks after_threshold_ticks =
|
||||
original_time_ticks + threshold + base::Minutes(1);
|
||||
base::Time after_threshold = ConvertLastActiveTime(after_threshold_ticks);
|
||||
base::Time after_threshold = base::Time() + base::Seconds(3);
|
||||
content::WebContentsTester::For(web_contents.get())
|
||||
->SetLastActiveTimeTicks(after_threshold_ticks);
|
||||
content::WebContentsTester::For(web_contents.get())
|
||||
->SetLastActiveTime(after_threshold);
|
||||
EXPECT_EQ(after_threshold, delegate.GetLastActiveTime());
|
||||
}
|
||||
|
||||
@ -165,20 +166,24 @@ TEST_F(TabContentsSyncedTabDelegateTest, ResetCachedLastActiveTime) {
|
||||
delegate.GetWindowId());
|
||||
|
||||
base::TimeTicks original_time_ticks = base::TimeTicks::Now();
|
||||
base::Time original_time = ConvertLastActiveTime(original_time_ticks);
|
||||
base::Time original_time = base::Time() + base::Seconds(1);
|
||||
content::WebContentsTester::For(web_contents.get())
|
||||
->SetLastActiveTimeTicks(original_time_ticks);
|
||||
content::WebContentsTester::For(web_contents.get())
|
||||
->SetLastActiveTime(original_time);
|
||||
|
||||
EXPECT_EQ(original_time, delegate.GetLastActiveTime());
|
||||
|
||||
delegate.ResetCachedLastActiveTime();
|
||||
|
||||
// If not enough time has passed, the cached time should be returned.
|
||||
// Even if not enough time has passed, the cached time should not be returned.
|
||||
base::TimeTicks before_threshold_ticks =
|
||||
original_time_ticks + threshold - base::Minutes(1);
|
||||
base::Time before_threshold = ConvertLastActiveTime(before_threshold_ticks);
|
||||
base::Time before_threshold = base::Time() + base::Seconds(2);
|
||||
content::WebContentsTester::For(web_contents.get())
|
||||
->SetLastActiveTimeTicks(before_threshold_ticks);
|
||||
content::WebContentsTester::For(web_contents.get())
|
||||
->SetLastActiveTime(before_threshold);
|
||||
EXPECT_EQ(before_threshold, delegate.GetLastActiveTime());
|
||||
}
|
||||
|
||||
|
@ -42,14 +42,6 @@ URLVisitAggregate::Tab MakeAggregateTabFromWebContents(
|
||||
return tab;
|
||||
}
|
||||
|
||||
base::Time GetLastActiveTime(content::WebContents* web_contents) {
|
||||
// Use the TimeDelta common ground between the two units to make the
|
||||
// conversion.
|
||||
const base::TimeDelta delta_since_epoch =
|
||||
web_contents->GetLastActiveTimeTicks() - base::TimeTicks::UnixEpoch();
|
||||
return base::Time::UnixEpoch() + delta_since_epoch;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
DesktopTabModelURLVisitDataFetcher::DesktopTabModelURLVisitDataFetcher(
|
||||
@ -87,7 +79,7 @@ void DesktopTabModelURLVisitDataFetcher::FetchURLVisitData(
|
||||
auto it = url_visit_tab_data_map.find(url_key);
|
||||
bool tab_data_map_already_has_url_entry =
|
||||
(it != url_visit_tab_data_map.end());
|
||||
base::Time tab_entry_last_active = GetLastActiveTime(web_contents);
|
||||
base::Time tab_entry_last_active = web_contents->GetLastActiveTime();
|
||||
if (!tab_data_map_already_has_url_entry) {
|
||||
auto tab_data = URLVisitAggregate::TabData(
|
||||
MakeAggregateTabFromWebContents(web_contents));
|
||||
|
@ -1090,16 +1090,11 @@ std::unique_ptr<SessionCommand> CreateSetActiveWindowCommand(
|
||||
|
||||
std::unique_ptr<SessionCommand> CreateLastActiveTimeCommand(
|
||||
SessionID tab_id,
|
||||
base::TimeTicks last_active_time) {
|
||||
base::Time last_active_time) {
|
||||
LastActiveTimePayload payload = {0};
|
||||
payload.tab_id = tab_id.id();
|
||||
|
||||
// Convert the last_active_time from TimeTicks to Time.
|
||||
base::TimeDelta delta_since_epoch =
|
||||
last_active_time - base::TimeTicks::UnixEpoch();
|
||||
base::Time converted_time = base::Time::UnixEpoch() + delta_since_epoch;
|
||||
payload.last_active_time =
|
||||
converted_time.ToDeltaSinceWindowsEpoch().InMicroseconds();
|
||||
last_active_time.ToDeltaSinceWindowsEpoch().InMicroseconds();
|
||||
|
||||
return CreateSessionCommandForPayload(kCommandLastActiveTime, payload);
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ SESSIONS_EXPORT std::unique_ptr<SessionCommand> CreateSetWindowUserTitleCommand(
|
||||
const std::string& user_title);
|
||||
SESSIONS_EXPORT std::unique_ptr<SessionCommand> CreateLastActiveTimeCommand(
|
||||
SessionID tab_id,
|
||||
base::TimeTicks last_active_time);
|
||||
base::Time last_active_time);
|
||||
|
||||
SESSIONS_EXPORT std::unique_ptr<SessionCommand> CreateSetWindowWorkspaceCommand(
|
||||
SessionID window_id,
|
||||
|
@ -1192,6 +1192,7 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
|
||||
dialog_manager_(nullptr),
|
||||
is_showing_before_unload_dialog_(false),
|
||||
last_active_time_ticks_(base::TimeTicks::Now()),
|
||||
last_active_time_(base::Time::Now()),
|
||||
closed_by_user_gesture_(false),
|
||||
minimum_zoom_percent_(
|
||||
static_cast<int>(blink::kMinimumBrowserZoomFactor * 100)),
|
||||
@ -2748,6 +2749,10 @@ base::TimeTicks WebContentsImpl::GetLastActiveTimeTicks() {
|
||||
return last_active_time_ticks_;
|
||||
}
|
||||
|
||||
base::Time WebContentsImpl::GetLastActiveTime() {
|
||||
return last_active_time_;
|
||||
}
|
||||
|
||||
void WebContentsImpl::WasShown() {
|
||||
TRACE_EVENT0("content", "WebContentsImpl::WasShown");
|
||||
UpdateVisibilityAndNotifyPageAndView(Visibility::VISIBLE);
|
||||
@ -3595,6 +3600,9 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params,
|
||||
if (!params.last_active_time_ticks.is_null()) {
|
||||
last_active_time_ticks_ = params.last_active_time_ticks;
|
||||
}
|
||||
if (!params.last_active_time.is_null()) {
|
||||
last_active_time_ = params.last_active_time;
|
||||
}
|
||||
|
||||
scoped_refptr<SiteInstanceImpl> site_instance =
|
||||
static_cast<SiteInstanceImpl*>(params.site_instance.get());
|
||||
@ -4350,6 +4358,7 @@ void WebContentsImpl::UpdateVisibilityAndNotifyPageAndView(
|
||||
if (new_visibility == Visibility::VISIBLE) {
|
||||
if (is_activity) {
|
||||
last_active_time_ticks_ = base::TimeTicks::Now();
|
||||
last_active_time_ = base::Time::Now();
|
||||
}
|
||||
SetVisibilityAndNotifyObservers(new_visibility);
|
||||
}
|
||||
|
@ -458,6 +458,7 @@ class CONTENT_EXPORT WebContentsImpl
|
||||
void NotifyNavigationStateChanged(InvalidateTypes changed_flags) override;
|
||||
void OnAudioStateChanged() override;
|
||||
base::TimeTicks GetLastActiveTimeTicks() override;
|
||||
base::Time GetLastActiveTime() override;
|
||||
void WasShown() override;
|
||||
void WasHidden() override;
|
||||
void WasOccluded() override;
|
||||
@ -2220,9 +2221,13 @@ class CONTENT_EXPORT WebContentsImpl
|
||||
// Settings that get passed to the renderer process.
|
||||
blink::RendererPreferences renderer_preferences_;
|
||||
|
||||
// The time ticks that this WebContents was last made active. The initial
|
||||
// value is the WebContents creation time.
|
||||
base::TimeTicks last_active_time_ticks_;
|
||||
|
||||
// The time that this WebContents was last made active. The initial value is
|
||||
// the WebContents creation time.
|
||||
base::TimeTicks last_active_time_ticks_;
|
||||
base::Time last_active_time_;
|
||||
|
||||
// The most recent time that this WebContents was interacted with. Currently,
|
||||
// this counts:
|
||||
|
@ -2034,15 +2034,16 @@ TEST_F(WebContentsImplTest, NonActivityCaptureDoesNotCountAsActivity) {
|
||||
// This is done because the clock in these tests is frozen,
|
||||
// so recording the value and comparing against it later is meaningless.
|
||||
contents()->last_active_time_ticks_ = base::TimeTicks();
|
||||
contents()->last_active_time_ = base::Time();
|
||||
|
||||
auto handle = contents()->IncrementCapturerCount(
|
||||
gfx::Size(), /*stay_hidden=*/true,
|
||||
/*stay_awake=*/true, /*is_activity=*/false);
|
||||
ASSERT_TRUE(rwhv->is_showing());
|
||||
|
||||
// The value returned by GetLastActiveTimeTicks() should not have been
|
||||
// updated.
|
||||
// The value returned by GetLastActiveTime() should not have been updated.
|
||||
EXPECT_TRUE(contents()->GetLastActiveTimeTicks().is_null());
|
||||
EXPECT_TRUE(contents()->GetLastActiveTime().is_null());
|
||||
}
|
||||
|
||||
// Tests that GetLastActiveTimeTicks starts with a real, non-zero time and
|
||||
@ -2060,10 +2061,13 @@ TEST_F(WebContentsImplTest, GetLastActiveTimeTicks) {
|
||||
// so recording the value and comparing against it later is meaningless.
|
||||
contents()->last_active_time_ticks_ = base::TimeTicks();
|
||||
ASSERT_TRUE(contents()->GetLastActiveTimeTicks().is_null());
|
||||
contents()->last_active_time_ = base::Time();
|
||||
ASSERT_TRUE(contents()->GetLastActiveTime().is_null());
|
||||
|
||||
// Simulate activating the WebContents. The active time should update.
|
||||
contents()->WasShown();
|
||||
EXPECT_FALSE(contents()->GetLastActiveTimeTicks().is_null());
|
||||
EXPECT_FALSE(contents()->GetLastActiveTime().is_null());
|
||||
}
|
||||
|
||||
class ContentsZoomChangedDelegate : public WebContentsDelegate {
|
||||
|
@ -265,6 +265,12 @@ class WebContents : public PageNavigator, public base::SupportsUserData {
|
||||
// creation time.
|
||||
base::TimeTicks last_active_time_ticks;
|
||||
|
||||
// Value used to set the last time the WebContents was made active, this is
|
||||
// the value that'll be returned by GetLastActiveTime(). If this is left
|
||||
// default initialized then the value is not passed on to the WebContents
|
||||
// and GetLastActiveTime() will return the WebContents' creation time.
|
||||
base::Time last_active_time;
|
||||
|
||||
// Code location responsible for creating the CreateParams. This is used
|
||||
// mostly for debugging (e.g. to help attribute specific scenarios or
|
||||
// invariant violations to a particular flavor of WebContents).
|
||||
@ -848,9 +854,17 @@ class WebContents : public PageNavigator, public base::SupportsUserData {
|
||||
// directly to determine its aggregate audio state.
|
||||
virtual void OnAudioStateChanged() = 0;
|
||||
|
||||
// Get/Set the last time ticks that the WebContents was made active (either
|
||||
// when it was created or shown with WasShown()). Note: GetLastActiveTimeTicks
|
||||
// and GetLastActiveTime can get desynced if the process is suspended or if
|
||||
// the clock is adjusted.
|
||||
virtual base::TimeTicks GetLastActiveTimeTicks() = 0;
|
||||
|
||||
// Get/Set the last time that the WebContents was made active (either when it
|
||||
// was created or shown with WasShown()).
|
||||
virtual base::TimeTicks GetLastActiveTimeTicks() = 0;
|
||||
// Note: GetLastActiveTimeTicks and GetLastActiveTime can get desynced if the
|
||||
// process is suspended or if the clock is adjusted.
|
||||
virtual base::Time GetLastActiveTime() = 0;
|
||||
|
||||
// Invoked when the WebContents becomes shown/hidden. A hidden WebContents
|
||||
// isn't painted on the screen.
|
||||
|
@ -161,10 +161,13 @@ class WebContentsTester {
|
||||
// Resets the state around PauseSubresourceLoadingCalled.
|
||||
virtual void ResetPauseSubresourceLoadingCalled() = 0;
|
||||
|
||||
// Sets the last active time.
|
||||
// Sets the last active time ticks.
|
||||
virtual void SetLastActiveTimeTicks(
|
||||
base::TimeTicks last_active_time_ticks) = 0;
|
||||
|
||||
// Sets the last active time.
|
||||
virtual void SetLastActiveTime(base::Time last_active_time) = 0;
|
||||
|
||||
// Increments/decrements the number of frames with connected USB devices.
|
||||
virtual void TestIncrementUsbActiveFrameCount() = 0;
|
||||
virtual void TestDecrementUsbActiveFrameCount() = 0;
|
||||
|
@ -407,6 +407,10 @@ void TestWebContents::SetLastActiveTimeTicks(
|
||||
last_active_time_ticks_ = last_active_time_ticks;
|
||||
}
|
||||
|
||||
void TestWebContents::SetLastActiveTime(base::Time last_active_time) {
|
||||
last_active_time_ = last_active_time;
|
||||
}
|
||||
|
||||
void TestWebContents::TestIncrementUsbActiveFrameCount() {
|
||||
IncrementUsbActiveFrameCount();
|
||||
}
|
||||
|
@ -133,6 +133,7 @@ class TestWebContents : public WebContentsImpl, public WebContentsTester {
|
||||
void ResetPauseSubresourceLoadingCalled() override;
|
||||
|
||||
void SetLastActiveTimeTicks(base::TimeTicks last_active_time_ticks) override;
|
||||
void SetLastActiveTime(base::Time last_active_time) override;
|
||||
|
||||
void TestIncrementUsbActiveFrameCount() override;
|
||||
void TestDecrementUsbActiveFrameCount() override;
|
||||
|
Reference in New Issue
Block a user