blob: 481157950860dad0c78d4010f9766fb04162ce40 [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <utility>
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "content/browser/browser_interface_binders.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_content_browser_client.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "mojo/public/cpp/bindings/binder_map.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "services/device/public/mojom/battery_monitor.mojom.h"
#include "services/device/public/mojom/battery_status.mojom.h"
namespace content {
namespace {
class MockBatteryMonitor : public device::mojom::BatteryMonitor {
public:
MockBatteryMonitor() = default;
MockBatteryMonitor(const MockBatteryMonitor&) = delete;
MockBatteryMonitor& operator=(const MockBatteryMonitor&) = delete;
~MockBatteryMonitor() override = default;
void Bind(mojo::PendingReceiver<device::mojom::BatteryMonitor> receiver) {
DCHECK(!receiver_.is_bound());
receiver_.Bind(std::move(receiver));
}
void DidChange(const device::mojom::BatteryStatus& battery_status) {
status_ = battery_status;
status_to_report_ = true;
if (!callback_.is_null())
ReportStatus();
}
private:
// mojom::BatteryMonitor methods:
void QueryNextStatus(QueryNextStatusCallback callback) override {
if (!callback_.is_null()) {
DVLOG(1) << "Overlapped call to QueryNextStatus!";
receiver_.reset();
return;
}
callback_ = std::move(callback);
if (status_to_report_)
ReportStatus();
}
void ReportStatus() {
std::move(callback_).Run(status_.Clone());
status_to_report_ = false;
}
QueryNextStatusCallback callback_;
device::mojom::BatteryStatus status_;
bool status_to_report_ = false;
mojo::Receiver<device::mojom::BatteryMonitor> receiver_{this};
};
class TestBatteryMonitorContentBrowserClient
: public ContentBrowserTestContentBrowserClient {
public:
TestBatteryMonitorContentBrowserClient() = default;
~TestBatteryMonitorContentBrowserClient() override = default;
void RegisterBrowserInterfaceBindersForFrame(
content::RenderFrameHost* render_frame_host,
mojo::BinderMapWithContext<content::RenderFrameHost*>* map) override {
ContentBrowserTestContentBrowserClient::
RegisterBrowserInterfaceBindersForFrame(render_frame_host, map);
map->Add<device::mojom::BatteryMonitor>(
base::BindRepeating(&TestBatteryMonitorContentBrowserClient::Bind,
weak_factory_.GetWeakPtr()));
}
MockBatteryMonitor& mock_battery_monitor() { return mock_battery_monitor_; }
private:
void Bind(content::RenderFrameHost* render_frame_host,
mojo::PendingReceiver<device::mojom::BatteryMonitor> receiver) {
mock_battery_monitor_.Bind(std::move(receiver));
}
MockBatteryMonitor mock_battery_monitor_;
base::WeakPtrFactory<TestBatteryMonitorContentBrowserClient> weak_factory_{
this};
};
class BatteryMonitorTest : public ContentBrowserTest {
public:
BatteryMonitorTest() = default;
void SetUpOnMainThread() override {
ContentBrowserTest::SetUpOnMainThread();
browser_client_ =
std::make_unique<TestBatteryMonitorContentBrowserClient>();
// Create a new renderer now that RegisterBrowserInterfaceBindersForFrame
// is overridden.
RecreateWindow();
}
BatteryMonitorTest(const BatteryMonitorTest&) = delete;
BatteryMonitorTest& operator=(const BatteryMonitorTest&) = delete;
~BatteryMonitorTest() override = default;
protected:
MockBatteryMonitor& mock_battery_monitor() {
return browser_client_->mock_battery_monitor();
}
private:
std::unique_ptr<TestBatteryMonitorContentBrowserClient> browser_client_;
};
IN_PROC_BROWSER_TEST_F(BatteryMonitorTest, NavigatorGetBatteryInfo) {
// From JavaScript request a promise for the battery status information and
// once it resolves check the values and navigate to #pass.
device::mojom::BatteryStatus status;
status.charging = true;
status.charging_time = 100;
status.discharging_time = std::numeric_limits<double>::infinity();
status.level = 0.5;
mock_battery_monitor().DidChange(status);
GURL test_url = GetTestUrl("battery_monitor",
"battery_status_promise_resolution_test.html");
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().GetRef());
}
IN_PROC_BROWSER_TEST_F(BatteryMonitorTest, NavigatorGetBatteryListenChange) {
// From JavaScript request a promise for the battery status information.
// Once it resolves add an event listener for battery level change. Set
// battery level to 0.6 and invoke update. Check that the event listener
// is invoked with the correct value for level and navigate to #pass.
device::mojom::BatteryStatus status;
mock_battery_monitor().DidChange(status);
TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);
GURL test_url =
GetTestUrl("battery_monitor", "battery_status_event_listener_test.html");
shell()->LoadURL(test_url);
same_tab_observer.Wait();
EXPECT_EQ("resolved",
shell()->web_contents()->GetLastCommittedURL().GetRef());
TestNavigationObserver same_tab_observer2(shell()->web_contents(), 1);
status.level = 0.6;
mock_battery_monitor().DidChange(status);
same_tab_observer2.Wait();
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().GetRef());
}
} // namespace
} // namespace content