Commit 9f6594c0 authored by Roman Aleksandrov's avatar Roman Aleksandrov Committed by Commit Bot

Update relaunch title after laptop wake up

Add WallClockTimer implementation to proper update relaunch titles for both - desktop and ChromeOS.

Bug: 906689
Change-Id: Ic31766bc6566e935762cb4a1afcaf0967e6ed142
Reviewed-on: https://chromium-review.googlesource.com/c/1356706
Commit-Queue: Roman Aleksandrov <raleksandrov@google.com>
Reviewed-by: default avatarGreg Thompson <grt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#619917}
parent 30cd990c
......@@ -2732,6 +2732,8 @@ jumbo_split_static_library("ui") {
"views/relaunch_notification/relaunch_required_timer.h",
"views/relaunch_notification/relaunch_required_timer_internal.cc",
"views/relaunch_notification/relaunch_required_timer_internal.h",
"views/relaunch_notification/wall_clock_timer.cc",
"views/relaunch_notification/wall_clock_timer.h",
"views/sad_tab_view.cc",
"views/sad_tab_view.h",
"views/safe_browsing/password_reuse_modal_warning_dialog.cc",
......
......@@ -8,7 +8,7 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/ui/views/relaunch_notification/wall_clock_timer.h"
// Timer that handles notification title refresh for relaunch recommended
// notification. Created either by RelaunchRecommendedBubbleView for Chrome
......@@ -42,7 +42,7 @@ class RelaunchRecommendedTimer {
const base::TimeTicks upgrade_detected_time_;
// A timer with which title refreshes are scheduled.
base::OneShotTimer refresh_timer_;
WallClockTimer refresh_timer_;
// Callback which triggers the actual title update, which differs on Chrome
// for desktop vs for Chrome OS.
......
......@@ -8,7 +8,7 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "chrome/browser/ui/views/relaunch_notification/wall_clock_timer.h"
// Timer that handles notification title refresh for relaunch required
// notification. Created either by RelaunchRequiredDialogView for Chrome
......@@ -44,7 +44,7 @@ class RelaunchRequiredTimer {
base::TimeTicks deadline_;
// A timer with which title refreshes are scheduled.
base::OneShotTimer refresh_timer_;
WallClockTimer refresh_timer_;
// Callback which triggers the actual title update, which differs on Chrome
// for desktop vs for Chrome OS.
......
// Copyright 2018 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/ui/views/relaunch_notification/wall_clock_timer.h"
#include <utility>
#include "base/power_monitor/power_monitor.h"
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "base/time/default_tick_clock.h"
#include "base/time/tick_clock.h"
WallClockTimer::WallClockTimer() : WallClockTimer(nullptr, nullptr) {}
WallClockTimer::WallClockTimer(const base::Clock* clock,
const base::TickClock* tick_clock)
: timer_(tick_clock),
clock_(clock ? clock : base::DefaultClock::GetInstance()) {}
WallClockTimer::~WallClockTimer() {
RemoveObserver();
}
void WallClockTimer::Start(const base::Location& posted_from,
base::TimeDelta delay,
base::OnceClosure user_task) {
user_task_ = std::move(user_task);
posted_from_ = posted_from;
delay_ = delay;
desired_run_time_ = Now() + delay_;
AddObserver();
timer_.Start(posted_from_, delay, this, &WallClockTimer::RunUserTask);
}
base::Time WallClockTimer::Now() const {
return clock_->Now();
}
void WallClockTimer::Stop() {
timer_.Stop();
user_task_.Reset();
RemoveObserver();
}
bool WallClockTimer::IsRunning() {
return timer_.IsRunning();
}
void WallClockTimer::RunUserTask() {
DCHECK(user_task_);
base::OnceClosure task = std::move(user_task_);
std::move(task).Run();
RemoveObserver();
}
void WallClockTimer::OnResume() {
// This will actually restart timer with smaller delay
timer_.Start(posted_from_, desired_run_time_ - Now(), this,
&WallClockTimer::RunUserTask);
}
void WallClockTimer::AddObserver() {
if (!observer_added_) {
base::PowerMonitor::Get()->AddObserver(this);
observer_added_ = true;
}
}
void WallClockTimer::RemoveObserver() {
if (observer_added_) {
base::PowerMonitor::Get()->RemoveObserver(this);
observer_added_ = false;
}
}
// Copyright 2018 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.
#ifndef CHROME_BROWSER_UI_VIEWS_RELAUNCH_NOTIFICATION_WALL_CLOCK_TIMER_H_
#define CHROME_BROWSER_UI_VIEWS_RELAUNCH_NOTIFICATION_WALL_CLOCK_TIMER_H_
#include "base/bind.h"
#include "base/callback.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/power_monitor/power_observer.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
namespace base {
class Clock;
class TickClock;
} // namespace base
// WallClockTimer is based on OneShotTimer and provides a simple timer API
// which is mostly similar to OneShotTimer's API. The main difference is that
// WallClockTimer is using Time (which is system-dependent) to schedule task.
// WallClockTimer calls you back once scheduled time has come.
//
// Comparison with OneShotTimer: WallClockTimer runs |user_task_| after |delay_|
// expires according to usual time, while OneShotTimer runs |user_task_| after
// |delay_| expires according to TimeTicks which freezes when power suspends
// (desktop falls asleep).
//
// The API is not thread safe. All methods must be called from the same
// sequence (not necessarily the construction sequence), except for the
// destructor.
// - The destructor may be called from any sequence when the timer is not
// running and there is no scheduled task active.
class WallClockTimer : public base::PowerObserver {
public:
WallClockTimer();
WallClockTimer(const base::Clock* clock, const base::TickClock* tick_clock);
~WallClockTimer() override;
// Start the timer to run at the given |delay| from now. If the timer is
// already running, it will be replaced to call the given |user_task|.
virtual void Start(const base::Location& posted_from,
base::TimeDelta delay,
base::OnceClosure user_task);
// Start the timer to run at the given |delay| from now. If the timer is
// already running, it will be replaced to call a task formed from
// |reviewer->*method|.
template <class Receiver>
void Start(const base::Location& posted_from,
base::TimeDelta delay,
Receiver* receiver,
void (Receiver::*method)()) {
Start(posted_from, delay,
base::BindOnce(method, base::Unretained(receiver)));
}
void Stop();
bool IsRunning();
// base::PowerObserver:
void OnResume() override;
base::Time desired_run_time() const { return desired_run_time_; }
private:
void AddObserver();
void RemoveObserver();
// Actually run scheduled task
void RunUserTask();
// Returns the current time count.
base::Time Now() const;
bool observer_added_ = false;
// Location in user code.
base::Location posted_from_;
// Delay requested by user.
base::TimeDelta delay_;
// The desired run time of |user_task_|.
base::Time desired_run_time_;
base::OnceClosure user_task_;
// Timer which should notify to run task in the period while system awake
base::OneShotTimer timer_;
// The clock used to calculate the run time for scheduled tasks.
const base::Clock* const clock_;
DISALLOW_COPY_AND_ASSIGN(WallClockTimer);
};
#endif // CHROME_BROWSER_UI_VIEWS_RELAUNCH_NOTIFICATION_WALL_CLOCK_TIMER_H_
// Copyright 2018 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/ui/views/relaunch_notification/wall_clock_timer.h"
#include <memory>
#include <utility>
#include "base/macros.h"
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_monitor_source.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/simple_test_clock.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
class StubPowerMonitorSource : public base::PowerMonitorSource {
public:
// Use this method to send a power resume event.
void Resume() { ProcessPowerEvent(RESUME_EVENT); }
// Use this method to send a power suspend event.
void Suspend() { ProcessPowerEvent(SUSPEND_EVENT); }
// base::PowerMonitorSource:
void Shutdown() override {}
bool IsOnBatteryPowerImpl() override { return false; }
};
} // namespace
class WallClockTimerTest : public ::testing::Test {
protected:
WallClockTimerTest()
: task_environment_(
base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {
auto mock_power_monitor_source = std::make_unique<StubPowerMonitorSource>();
mock_power_monitor_source_ = mock_power_monitor_source.get();
power_monitor_ = std::make_unique<base::PowerMonitor>(
std::move(mock_power_monitor_source));
}
std::unique_ptr<base::PowerMonitor> power_monitor_;
// Owned by power_monitor_. Use this to simulate a power suspend and resume.
StubPowerMonitorSource* mock_power_monitor_source_ = nullptr;
base::test::ScopedTaskEnvironment task_environment_;
private:
DISALLOW_COPY_AND_ASSIGN(WallClockTimerTest);
};
TEST_F(WallClockTimerTest, PowerResume) {
::testing::StrictMock<base::MockCallback<base::OnceClosure>> callback;
base::SimpleTestClock clock;
// Set up a WallClockTimer that will fire in one minute.
WallClockTimer wall_clock_timer(&clock, task_environment_.GetMockTickClock());
auto delay = base::TimeDelta::FromMinutes(1);
auto start_time = base::Time::Now();
clock.SetNow(start_time);
wall_clock_timer.Start(FROM_HERE, delay, callback.Get());
EXPECT_EQ(wall_clock_timer.desired_run_time(), start_time + delay);
mock_power_monitor_source_->Suspend();
// Pretend that time jumps forward 30 seconds while the machine is suspended.
auto past_time = base::TimeDelta::FromSeconds(30);
clock.SetNow(start_time + past_time);
mock_power_monitor_source_->Resume();
task_environment_.RunUntilIdle();
// Ensure that the timer has not yet fired.
::testing::Mock::VerifyAndClearExpectations(&callback);
EXPECT_EQ(wall_clock_timer.desired_run_time(), start_time + delay);
// Expect that the timer fires at the desired run time.
EXPECT_CALL(callback, Run());
// Both Time::Now() and |task_environment_| MockTickClock::Now()
// go forward by (|delay| - |past_time|):
clock.SetNow(start_time + delay);
task_environment_.FastForwardBy(delay - past_time);
::testing::Mock::VerifyAndClearExpectations(&callback);
EXPECT_FALSE(wall_clock_timer.IsRunning());
}
......@@ -4356,6 +4356,7 @@ test("unit_tests") {
"../browser/ui/views/payments/view_stack_unittest.cc",
"../browser/ui/views/relaunch_notification/relaunch_notification_controller_unittest.cc",
"../browser/ui/views/relaunch_notification/relaunch_required_timer_internal_unittest.cc",
"../browser/ui/views/relaunch_notification/wall_clock_timer_unittest.cc",
"../browser/ui/views/status_icons/status_tray_win_unittest.cc",
"../browser/ui/views/sync/bubble_sync_promo_view_unittest.cc",
"../browser/ui/views/tab_contents/chrome_web_contents_view_delegate_views_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment