blob: 5db921f97b1012b34c87a5f9f5ebf902b07c6c91 [file] [log] [blame]
// Copyright 2014 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 <utility>
#include "base/callback_list.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/test/content_browser_test.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 "content/shell/browser/shell_content_browser_client.h"
#include "device/battery/battery_monitor.mojom.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/service_manager/public/cpp/interface_registry.h"
// These tests run against a dummy implementation of the BatteryMonitor service.
// That is, they verify that the service implementation is correctly exposed to
// the renderer, whatever the implementation is.
namespace content {
namespace {
typedef base::CallbackList<void(const device::BatteryStatus&)>
BatteryUpdateCallbackList;
typedef BatteryUpdateCallbackList::Subscription BatteryUpdateSubscription;
// Global battery state used in the tests.
device::BatteryStatus g_battery_status;
// Global list of test battery monitors to notify when |g_battery_status|
// changes.
base::LazyInstance<BatteryUpdateCallbackList>::Leaky g_callback_list =
LAZY_INSTANCE_INITIALIZER;
// Updates the global battery state and notifies existing test monitors.
void UpdateBattery(const device::BatteryStatus& battery_status) {
g_battery_status = battery_status;
g_callback_list.Get().Notify(battery_status);
}
class FakeBatteryMonitor : public device::BatteryMonitor {
public:
FakeBatteryMonitor() {}
~FakeBatteryMonitor() override {}
static void Create(mojo::InterfaceRequest<BatteryMonitor> request) {
mojo::MakeStrongBinding(base::MakeUnique<FakeBatteryMonitor>(),
std::move(request));
}
private:
void QueryNextStatus(const QueryNextStatusCallback& callback) override {
// We don't expect overlapped calls to QueryNextStatus.
DCHECK(callback_.is_null());
callback_ = callback;
if (!subscription_) {
subscription_ =
g_callback_list.Get().Add(base::Bind(&FakeBatteryMonitor::DidChange,
base::Unretained(this)));
// Report initial value.
DidChange(g_battery_status);
}
}
void DidChange(const device::BatteryStatus& battery_status) {
if (!callback_.is_null()) {
callback_.Run(battery_status.Clone());
callback_.Reset();
}
}
std::unique_ptr<BatteryUpdateSubscription> subscription_;
QueryNextStatusCallback callback_;
};
// Overrides the default service implementation with the test implementation
// declared above.
class TestContentBrowserClient : public ContentBrowserClient {
public:
void ExposeInterfacesToRenderer(
service_manager::InterfaceRegistry* registry,
RenderProcessHost* render_process_host) override {
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner =
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI);
registry->AddInterface(base::Bind(&FakeBatteryMonitor::Create),
ui_task_runner);
}
void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
int child_process_id) override {
// Necessary for passing kIsolateSitesForTesting flag to the renderer.
ShellContentBrowserClient::Get()->AppendExtraCommandLineSwitches(
command_line, child_process_id);
}
#if defined(OS_ANDROID)
void GetAdditionalMappedFilesForChildProcess(
const base::CommandLine& command_line,
int child_process_id,
FileDescriptorInfo* mappings) override {
ShellContentBrowserClient::Get()->GetAdditionalMappedFilesForChildProcess(
command_line, child_process_id, mappings);
}
#endif // defined(OS_ANDROID)
};
class BatteryMonitorIntegrationTest : public ContentBrowserTest {
public:
BatteryMonitorIntegrationTest() {}
void SetUpOnMainThread() override {
old_client_ = SetBrowserClientForTesting(&test_client_);
}
void TearDownOnMainThread() override {
SetBrowserClientForTesting(old_client_);
}
private:
TestContentBrowserClient test_client_;
ContentBrowserClient* old_client_;
DISALLOW_COPY_AND_ASSIGN(BatteryMonitorIntegrationTest);
};
IN_PROC_BROWSER_TEST_F(BatteryMonitorIntegrationTest, DefaultValues) {
// From JavaScript request a promise for the battery status information and
// once it resolves check the default values and navigate to #pass.
UpdateBattery(device::BatteryStatus());
GURL test_url =
GetTestUrl("battery_status", "battery_status_default_test.html");
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
}
IN_PROC_BROWSER_TEST_F(BatteryMonitorIntegrationTest, ResolvePromise) {
// Set the fake battery monitor to return predefined battery status values.
// From JavaScript request a promise for the battery status information and
// once it resolves check the values and navigate to #pass.
device::BatteryStatus status;
status.charging = true;
status.charging_time = 100;
status.discharging_time = std::numeric_limits<double>::infinity();
status.level = 0.5;
UpdateBattery(status);
GURL test_url = GetTestUrl("battery_status",
"battery_status_promise_resolution_test.html");
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 2);
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
}
IN_PROC_BROWSER_TEST_F(BatteryMonitorIntegrationTest, EventListener) {
// Set the fake battery monitor to return default battery status values.
// 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::BatteryStatus status;
UpdateBattery(status);
TestNavigationObserver same_tab_observer(shell()->web_contents(), 2);
GURL test_url =
GetTestUrl("battery_status", "battery_status_event_listener_test.html");
shell()->LoadURL(test_url);
same_tab_observer.Wait();
EXPECT_EQ("resolved", shell()->web_contents()->GetLastCommittedURL().ref());
TestNavigationObserver same_tab_observer2(shell()->web_contents(), 1);
status.level = 0.6;
UpdateBattery(status);
same_tab_observer2.Wait();
EXPECT_EQ("pass", shell()->web_contents()->GetLastCommittedURL().ref());
}
} // namespace
} // namespace content