Create a pipeline from render frame host to VibrationManager
Design doc: go/crca-cspp-ping-vibration-api Change-Id: I7b34c92559fcca9f650240b4b7afab3c76f9a7da Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5490193 Reviewed-by: Ken Buchanan <kenrb@chromium.org> Commit-Queue: Seung Jae Lim <andysjlim@chromium.org> Reviewed-by: Matt Reynolds <mattreynolds@chromium.org> Cr-Commit-Position: refs/heads/main@{#1299589}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
9bbe7a89ec
commit
c16c5e138a
content
browser
back_forward_cache_features_browsertest.ccbrowser_interface_binders.ccbrowser_interface_binders.h
renderer_host
vibration_browsertest.ccweb_contents
public
browser
services/device
@ -3443,7 +3443,8 @@ class TestVibrationManager : public device::mojom::VibrationManager {
|
||||
}
|
||||
|
||||
void BindVibrationManager(
|
||||
mojo::PendingReceiver<device::mojom::VibrationManager> receiver) {
|
||||
mojo::PendingReceiver<device::mojom::VibrationManager> receiver,
|
||||
mojo::PendingRemote<device::mojom::VibrationManagerListener> listener) {
|
||||
receiver_.Bind(std::move(receiver));
|
||||
}
|
||||
|
||||
|
@ -701,12 +701,15 @@ VibrationManagerBinder& GetVibrationManagerBinderOverride() {
|
||||
}
|
||||
|
||||
void BindVibrationManager(
|
||||
RenderFrameHostImpl* frame,
|
||||
mojo::PendingReceiver<device::mojom::VibrationManager> receiver) {
|
||||
const auto& binder = GetVibrationManagerBinderOverride();
|
||||
if (binder)
|
||||
binder.Run(std::move(receiver));
|
||||
else
|
||||
GetDeviceService().BindVibrationManager(std::move(receiver));
|
||||
if (binder) {
|
||||
binder.Run(std::move(receiver), frame->CreateVibrationManagerListener());
|
||||
} else {
|
||||
GetDeviceService().BindVibrationManager(
|
||||
std::move(receiver), frame->CreateVibrationManagerListener());
|
||||
}
|
||||
}
|
||||
|
||||
void BindMediaPlayerObserverClientHandler(
|
||||
@ -914,7 +917,7 @@ void PopulateFrameBinders(RenderFrameHostImpl* host, mojo::BinderMap* map) {
|
||||
&RenderFrameHostImpl::GetSensorProvider, base::Unretained(host)));
|
||||
|
||||
map->Add<device::mojom::VibrationManager>(
|
||||
base::BindRepeating(&BindVibrationManager));
|
||||
base::BindRepeating(&BindVibrationManager, base::Unretained(host)));
|
||||
|
||||
map->Add<payments::mojom::PaymentManager>(base::BindRepeating(
|
||||
&RenderFrameHostImpl::CreatePaymentManager, base::Unretained(host)));
|
||||
|
@ -79,7 +79,8 @@ CONTENT_EXPORT void OverrideBatteryMonitorBinderForTesting(
|
||||
|
||||
// Allows tests to override how frame hosts bind VibrationManager receivers.
|
||||
using VibrationManagerBinder = base::RepeatingCallback<void(
|
||||
mojo::PendingReceiver<device::mojom::VibrationManager>)>;
|
||||
mojo::PendingReceiver<device::mojom::VibrationManager>,
|
||||
mojo::PendingRemote<device::mojom::VibrationManagerListener>)>;
|
||||
CONTENT_EXPORT void OverrideVibrationManagerBinderForTesting(
|
||||
VibrationManagerBinder binder);
|
||||
|
||||
|
@ -80,7 +80,7 @@ namespace mojom {
|
||||
class DisplayCutoutHost;
|
||||
class FullscreenOptions;
|
||||
class WindowFeatures;
|
||||
}
|
||||
} // namespace mojom
|
||||
class PageState;
|
||||
namespace web_pref {
|
||||
struct WebPreferences;
|
||||
@ -101,7 +101,7 @@ namespace ui {
|
||||
class ClipboardFormatType;
|
||||
struct AXUpdatesAndEvents;
|
||||
struct AXLocationChanges;
|
||||
}
|
||||
} // namespace ui
|
||||
|
||||
namespace content {
|
||||
class FrameTreeNode;
|
||||
@ -627,6 +627,7 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
|
||||
RenderFrameHostImpl* render_frame_host,
|
||||
blink::mojom::StorageTypeAccessed storage_type,
|
||||
bool blocked) {}
|
||||
virtual void OnVibrate(RenderFrameHostImpl* render_frame_host) {}
|
||||
|
||||
// Notified that the renderer responded after calling GetSavableResourceLinks.
|
||||
virtual void SavableResourceLinksResponse(
|
||||
|
@ -16347,6 +16347,14 @@ RenderFrameHostImpl::CreateSharedDictionaryAccessObserver() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
mojo::PendingRemote<device::mojom::VibrationManagerListener>
|
||||
RenderFrameHostImpl::CreateVibrationManagerListener() {
|
||||
mojo::PendingRemote<device::mojom::VibrationManagerListener> remote;
|
||||
vibration_manager_listeners_.Add(this,
|
||||
remote.InitWithNewPipeAndPassReceiver());
|
||||
return remote;
|
||||
}
|
||||
|
||||
#if BUILDFLAG(ENABLE_MDNS)
|
||||
void RenderFrameHostImpl::CreateMdnsResponder(
|
||||
mojo::PendingReceiver<network::mojom::MdnsResponder> receiver) {
|
||||
@ -16404,6 +16412,10 @@ void RenderFrameHostImpl::OnSharedDictionaryAccessed(
|
||||
delegate_->OnSharedDictionaryAccessed(this, *details);
|
||||
}
|
||||
|
||||
void RenderFrameHostImpl::OnVibrate() {
|
||||
delegate_->OnVibrate(this);
|
||||
}
|
||||
|
||||
void RenderFrameHostImpl::SetEmbeddingToken(
|
||||
const base::UnguessableToken& embedding_token) {
|
||||
// Everything in this method depends on whether the embedding token has
|
||||
|
@ -112,6 +112,7 @@
|
||||
#include "net/cookies/cookie_setting_override.h"
|
||||
#include "net/net_buildflags.h"
|
||||
#include "ppapi/buildflags/buildflags.h"
|
||||
#include "services/device/public/mojom/vibration_manager.mojom.h"
|
||||
#include "services/metrics/public/cpp/ukm_source_id.h"
|
||||
#include "services/network/public/cpp/attribution_reporting_runtime_features.h"
|
||||
#include "services/network/public/cpp/cross_origin_embedder_policy.h"
|
||||
@ -317,6 +318,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
|
||||
public blink::mojom::NonAssociatedLocalFrameHost,
|
||||
public blink::mojom::LocalMainFrameHost,
|
||||
public ui::AXActionHandlerBase,
|
||||
public device::mojom::VibrationManagerListener,
|
||||
public network::mojom::CookieAccessObserver,
|
||||
public network::mojom::TrustTokenAccessObserver,
|
||||
public network::mojom::SharedDictionaryAccessObserver,
|
||||
@ -2627,6 +2629,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
|
||||
mojo::PendingRemote<network::mojom::SharedDictionaryAccessObserver>
|
||||
CreateSharedDictionaryAccessObserver();
|
||||
|
||||
mojo::PendingRemote<device::mojom::VibrationManagerListener>
|
||||
CreateVibrationManagerListener();
|
||||
|
||||
// network::mojom::CookieAccessObserver:
|
||||
void OnCookiesAccessed(std::vector<network::mojom::CookieAccessDetailsPtr>
|
||||
details_vector) override;
|
||||
@ -2639,6 +2644,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
|
||||
void OnSharedDictionaryAccessed(
|
||||
network::mojom::SharedDictionaryAccessDetailsPtr details) override;
|
||||
|
||||
// device::mojom::VibrationManagerListener:
|
||||
void OnVibrate() override;
|
||||
|
||||
void GetSavableResourceLinksFromRenderer();
|
||||
|
||||
// Helper for checking if a navigation to an error page should be excluded
|
||||
@ -4980,6 +4988,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
|
||||
mojo::ReceiverSet<network::mojom::SharedDictionaryAccessObserver>
|
||||
shared_dictionary_observers_;
|
||||
|
||||
mojo::ReceiverSet<device::mojom::VibrationManagerListener>
|
||||
vibration_manager_listeners_;
|
||||
|
||||
// Indicates whether this frame is an outer delegate frame for some other
|
||||
// RenderFrameHost. This will be a valid ID if so, and
|
||||
// `kFrameTreeNodeInvalidId` otherwise.
|
||||
|
@ -11,18 +11,43 @@
|
||||
#include "content/browser/browser_interface_binders.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/browser/web_contents_observer.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_utils.h"
|
||||
#include "content/shell/browser/shell.h"
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "services/device/public/mojom/vibration_manager.mojom.h"
|
||||
|
||||
namespace content {
|
||||
|
||||
namespace {
|
||||
|
||||
class VibrationObserver : public WebContentsObserver {
|
||||
public:
|
||||
explicit VibrationObserver(WebContents* web_contents)
|
||||
: WebContentsObserver(web_contents) {}
|
||||
|
||||
void VibrationRequested() override {
|
||||
did_vibrate_ = true;
|
||||
run_loop_.Quit();
|
||||
}
|
||||
|
||||
void Wait() {
|
||||
if (!did_vibrate_) {
|
||||
run_loop_.Run();
|
||||
}
|
||||
}
|
||||
|
||||
bool DidVibrate() { return did_vibrate_; }
|
||||
|
||||
private:
|
||||
bool did_vibrate_ = false;
|
||||
base::RunLoop run_loop_;
|
||||
};
|
||||
|
||||
class VibrationTest : public ContentBrowserTest,
|
||||
public device::mojom::VibrationManager {
|
||||
public:
|
||||
@ -39,8 +64,10 @@ class VibrationTest : public ContentBrowserTest,
|
||||
}
|
||||
|
||||
void BindVibrationManager(
|
||||
mojo::PendingReceiver<device::mojom::VibrationManager> receiver) {
|
||||
mojo::PendingReceiver<device::mojom::VibrationManager> receiver,
|
||||
mojo::PendingRemote<device::mojom::VibrationManagerListener> listener) {
|
||||
receiver_.Bind(std::move(receiver));
|
||||
listener_.Bind(std::move(listener));
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -61,12 +88,14 @@ class VibrationTest : public ContentBrowserTest,
|
||||
vibrate_milliseconds_ = milliseconds;
|
||||
std::move(callback).Run();
|
||||
std::move(vibrate_done_).Run();
|
||||
listener_->OnVibrate();
|
||||
}
|
||||
void Cancel(CancelCallback callback) override { std::move(callback).Run(); }
|
||||
|
||||
int64_t vibrate_milliseconds_ = -1;
|
||||
base::OnceClosure vibrate_done_;
|
||||
mojo::Receiver<device::mojom::VibrationManager> receiver_{this};
|
||||
mojo::Remote<device::mojom::VibrationManagerListener> listener_;
|
||||
};
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(VibrationTest, Vibrate) {
|
||||
@ -80,6 +109,19 @@ IN_PROC_BROWSER_TEST_F(VibrationTest, Vibrate) {
|
||||
ASSERT_EQ(1234, vibrate_milliseconds());
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(VibrationTest, VibrateNotifiesListener) {
|
||||
VibrationObserver observer(shell()->web_contents());
|
||||
EXPECT_FALSE(observer.DidVibrate());
|
||||
|
||||
ASSERT_TRUE(NavigateToURL(shell(), GetTestUrl(".", "simple_page.html")));
|
||||
base::RunLoop run_loop;
|
||||
|
||||
TriggerVibrate(1234, run_loop.QuitClosure());
|
||||
run_loop.Run();
|
||||
observer.Wait();
|
||||
EXPECT_TRUE(observer.DidVibrate());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace content
|
||||
|
@ -3475,6 +3475,12 @@ void WebContentsImpl::NotifyStorageAccessed(
|
||||
storage_type, blocked);
|
||||
}
|
||||
|
||||
void WebContentsImpl::OnVibrate(RenderFrameHostImpl* rfh) {
|
||||
OPTIONAL_TRACE_EVENT1("content", "WebContentsImpl::OnVibrate",
|
||||
"render_frame_host", rfh);
|
||||
observers_.NotifyObservers(&WebContentsObserver::VibrationRequested);
|
||||
}
|
||||
|
||||
std::optional<blink::ParsedPermissionsPolicy>
|
||||
WebContentsImpl::GetPermissionsPolicyForIsolatedWebApp(
|
||||
RenderFrameHostImpl* source) {
|
||||
|
@ -778,6 +778,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
|
||||
void NotifyStorageAccessed(RenderFrameHostImpl*,
|
||||
blink::mojom::StorageTypeAccessed storage_type,
|
||||
bool blocked) override;
|
||||
void OnVibrate(RenderFrameHostImpl*) override;
|
||||
|
||||
std::optional<blink::ParsedPermissionsPolicy>
|
||||
GetPermissionsPolicyForIsolatedWebApp(RenderFrameHostImpl* source) override;
|
||||
|
||||
|
@ -919,6 +919,9 @@ class CONTENT_EXPORT WebContentsObserver : public base::CheckedObserver {
|
||||
// Called when WebContents received a request to lock the pointer.
|
||||
virtual void PointerLockRequested() {}
|
||||
|
||||
// Called when WebContents received a request to vibrate the page.
|
||||
virtual void VibrationRequested() {}
|
||||
|
||||
WebContents* web_contents() const;
|
||||
|
||||
protected:
|
||||
|
@ -47,6 +47,7 @@ source_set("lib") {
|
||||
"//services/device/screen_orientation",
|
||||
"//services/device/time_zone_monitor",
|
||||
"//services/device/usb/mojo",
|
||||
"//services/device/vibration",
|
||||
"//services/device/wake_lock",
|
||||
"//services/service_manager/public/cpp",
|
||||
"//ui/gfx",
|
||||
@ -65,7 +66,6 @@ source_set("lib") {
|
||||
deps += [
|
||||
"//services/device/battery",
|
||||
"//services/device/hid",
|
||||
"//services/device/vibration",
|
||||
]
|
||||
}
|
||||
|
||||
@ -187,6 +187,7 @@ source_set("tests") {
|
||||
"//services/device/public/cpp/power_monitor",
|
||||
"//services/device/public/mojom",
|
||||
"//services/device/public/mojom:geolocation_internals",
|
||||
"//services/device/vibration",
|
||||
"//services/device/wake_lock",
|
||||
"//services/network:test_support",
|
||||
"//testing/gmock",
|
||||
@ -257,10 +258,7 @@ source_set("tests") {
|
||||
"geolocation/network_location_provider_unittest.cc",
|
||||
"geolocation/wifi_data_provider_common_unittest.cc",
|
||||
]
|
||||
deps += [
|
||||
":device_service_jni_headers",
|
||||
"//services/device/vibration/android:vibration_jni_headers",
|
||||
]
|
||||
deps += [ ":device_service_jni_headers" ]
|
||||
} else {
|
||||
sources += [
|
||||
"battery/battery_monitor_impl_unittest.cc",
|
||||
@ -272,7 +270,6 @@ source_set("tests") {
|
||||
"//components/variations:test_support",
|
||||
"//services/device/battery",
|
||||
"//services/device/hid",
|
||||
"//services/device/vibration",
|
||||
]
|
||||
|
||||
if ((!is_linux && !is_chromeos) || use_udev) {
|
||||
|
@ -10,10 +10,8 @@ import org.jni_zero.JNINamespace;
|
||||
import org.chromium.device.battery.BatteryMonitorFactory;
|
||||
import org.chromium.device.mojom.BatteryMonitor;
|
||||
import org.chromium.device.mojom.NfcProvider;
|
||||
import org.chromium.device.mojom.VibrationManager;
|
||||
import org.chromium.device.nfc.NfcDelegate;
|
||||
import org.chromium.device.nfc.NfcProviderImpl;
|
||||
import org.chromium.device.vibration.VibrationManagerImpl;
|
||||
import org.chromium.mojo.system.impl.CoreImpl;
|
||||
import org.chromium.services.service_manager.InterfaceRegistry;
|
||||
|
||||
@ -30,6 +28,5 @@ class InterfaceRegistrar {
|
||||
.toMessagePipeHandle());
|
||||
registry.addInterface(BatteryMonitor.MANAGER, new BatteryMonitorFactory());
|
||||
registry.addInterface(NfcProvider.MANAGER, new NfcProviderImpl.Factory(nfcDelegate));
|
||||
registry.addInterface(VibrationManager.MANAGER, new VibrationManagerImpl.Factory());
|
||||
}
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "services/device/public/mojom/battery_monitor.mojom.h"
|
||||
#include "services/device/serial/serial_port_manager_impl.h"
|
||||
#include "services/device/time_zone_monitor/time_zone_monitor.h"
|
||||
#include "services/device/vibration/vibration_manager_impl.h"
|
||||
#include "services/device/wake_lock/wake_lock_provider.h"
|
||||
#include "services/network/public/cpp/shared_url_loader_factory.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
@ -35,11 +36,11 @@
|
||||
#include "base/android/jni_android.h"
|
||||
#include "services/device/device_service_jni_headers/InterfaceRegistrar_jni.h"
|
||||
#include "services/device/screen_orientation/screen_orientation_listener_android.h"
|
||||
#include "services/device/vibration/vibration_manager_android.h"
|
||||
#else
|
||||
#include "services/device/battery/battery_monitor_impl.h"
|
||||
#include "services/device/battery/battery_status_service.h"
|
||||
#include "services/device/hid/hid_manager_impl.h"
|
||||
#include "services/device/vibration/vibration_manager_impl.h"
|
||||
#endif
|
||||
|
||||
#if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)) && defined(USE_UDEV)
|
||||
@ -214,11 +215,12 @@ void DeviceService::BindNFCProvider(
|
||||
#endif
|
||||
|
||||
void DeviceService::BindVibrationManager(
|
||||
mojo::PendingReceiver<mojom::VibrationManager> receiver) {
|
||||
mojo::PendingReceiver<mojom::VibrationManager> receiver,
|
||||
mojo::PendingRemote<mojom::VibrationManagerListener> listener) {
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
GetJavaInterfaceProvider()->GetInterface(std::move(receiver));
|
||||
VibrationManagerAndroid::Create(std::move(receiver), std::move(listener));
|
||||
#else
|
||||
VibrationManagerImpl::Create(std::move(receiver));
|
||||
VibrationManagerImpl::Create(std::move(receiver), std::move(listener));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -174,7 +174,8 @@ class DeviceService : public mojom::DeviceService {
|
||||
#endif
|
||||
|
||||
void BindVibrationManager(
|
||||
mojo::PendingReceiver<mojom::VibrationManager> receiver) override;
|
||||
mojo::PendingReceiver<mojom::VibrationManager> receiver,
|
||||
mojo::PendingRemote<mojom::VibrationManagerListener> listener) override;
|
||||
|
||||
#if !BUILDFLAG(IS_ANDROID)
|
||||
void BindHidManager(
|
||||
|
@ -67,8 +67,9 @@ interface DeviceService {
|
||||
[EnableIf=is_android]
|
||||
BindNFCProvider(pending_receiver<NFCProvider> receiver);
|
||||
|
||||
// Binds a VibrationManager endpoint.
|
||||
BindVibrationManager(pending_receiver<VibrationManager> receiver);
|
||||
// Binds a VibrationManager endpoint and a VibrationManagerListener endpoint.
|
||||
BindVibrationManager(pending_receiver<VibrationManager> receiver,
|
||||
pending_remote<VibrationManagerListener> listener);
|
||||
|
||||
// Binds a HidManager endpoint.
|
||||
[EnableIf=enable_hid]
|
||||
|
@ -4,8 +4,20 @@
|
||||
|
||||
module device.mojom;
|
||||
|
||||
// Responsible for handling the device vibration, if applicable. Desktop devices
|
||||
// currently do not support this but Android does. There are separate
|
||||
// implementations to handle this under vibration_manager_impl.cc.
|
||||
interface VibrationManager {
|
||||
// TODO(mvanouwerkerk): Add something like StructTraits to validate arguments.
|
||||
Vibrate(int64 milliseconds) => ();
|
||||
// Cancels the vibration after the VibrationManager vibrates the device.
|
||||
Cancel() => ();
|
||||
};
|
||||
|
||||
// Listens when the VibrationManager implementation calls Vibrate function.
|
||||
// Currently, this mojo connection exists to connect between the RenderFrameHost
|
||||
// and the device directory VibrationManagerImpl in the device service.
|
||||
interface VibrationManagerListener {
|
||||
// Called when VibrationManager calls Vibrate.
|
||||
OnVibrate();
|
||||
};
|
||||
|
@ -5,26 +5,36 @@
|
||||
import("//build/config/features.gni")
|
||||
import("//mojo/public/tools/bindings/mojom.gni")
|
||||
|
||||
# On android, VibrationManager mojo interface is implemented directly in Java.
|
||||
if (!is_android) {
|
||||
source_set("vibration") {
|
||||
visibility = [
|
||||
"//services/device:lib",
|
||||
"//services/device:tests",
|
||||
if (is_android) {
|
||||
import("//build/config/android/rules.gni")
|
||||
import("//third_party/jni_zero/jni_zero.gni")
|
||||
}
|
||||
|
||||
source_set("vibration") {
|
||||
visibility = [
|
||||
"//services/device:lib",
|
||||
"//services/device:tests",
|
||||
]
|
||||
sources = [
|
||||
"vibration_manager_impl.cc",
|
||||
"vibration_manager_impl.h",
|
||||
]
|
||||
|
||||
configs += [ "//build/config/compiler:wexit_time_destructors" ]
|
||||
|
||||
public_deps = [ "//services/device/public/mojom" ]
|
||||
|
||||
deps = [
|
||||
"//base",
|
||||
"//mojo/public/cpp/bindings",
|
||||
]
|
||||
|
||||
if (is_android) {
|
||||
sources += [
|
||||
"vibration_manager_android.cc",
|
||||
"vibration_manager_android.h",
|
||||
]
|
||||
|
||||
sources = [
|
||||
"vibration_manager_impl.h",
|
||||
"vibration_manager_impl_default.cc",
|
||||
]
|
||||
|
||||
configs += [ "//build/config/compiler:wexit_time_destructors" ]
|
||||
|
||||
public_deps = [ "//services/device/public/mojom" ]
|
||||
|
||||
deps = [
|
||||
"//base",
|
||||
"//mojo/public/cpp/bindings",
|
||||
]
|
||||
deps += [ "//services/device/vibration/android:vibration_jni_headers" ]
|
||||
}
|
||||
}
|
||||
|
@ -8,14 +8,14 @@ import("//third_party/jni_zero/jni_zero.gni")
|
||||
|
||||
generate_jni("vibration_jni_headers") {
|
||||
sources =
|
||||
[ "java/src/org/chromium/device/vibration/VibrationManagerImpl.java" ]
|
||||
[ "java/src/org/chromium/device/vibration/VibrationManagerAndroid.java" ]
|
||||
}
|
||||
|
||||
android_library("vibration_manager_java") {
|
||||
visibility = [ "//services/device:*" ]
|
||||
|
||||
sources =
|
||||
[ "java/src/org/chromium/device/vibration/VibrationManagerImpl.java" ]
|
||||
[ "java/src/org/chromium/device/vibration/VibrationManagerAndroid.java" ]
|
||||
|
||||
deps = [
|
||||
"//base:base_java",
|
||||
|
@ -8,25 +8,15 @@ import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Vibrator;
|
||||
|
||||
import org.jni_zero.CalledByNative;
|
||||
import org.jni_zero.CalledByNativeForTesting;
|
||||
import org.jni_zero.JNINamespace;
|
||||
|
||||
import org.chromium.base.ContextUtils;
|
||||
import org.chromium.base.Log;
|
||||
import org.chromium.base.ResettersForTesting;
|
||||
import org.chromium.device.mojom.VibrationManager;
|
||||
import org.chromium.mojo.system.MojoException;
|
||||
import org.chromium.services.service_manager.InterfaceFactory;
|
||||
import org.jni_zero.CalledByNative;
|
||||
import org.jni_zero.JNINamespace;
|
||||
|
||||
/**
|
||||
* Android implementation of the VibrationManager interface defined in
|
||||
* services/device/public/mojom/vibration_manager.mojom.
|
||||
*/
|
||||
/** Android implementation details for device::VibrationManagerAndroid. */
|
||||
@JNINamespace("device")
|
||||
public class VibrationManagerImpl implements VibrationManager {
|
||||
private static final String TAG = "VibrationManagerImpl";
|
||||
public class VibrationManagerAndroid {
|
||||
private static final String TAG = "VibrationManager";
|
||||
|
||||
private static final long MINIMUM_VIBRATION_DURATION_MS = 1; // 1 millisecond
|
||||
private static final long MAXIMUM_VIBRATION_DURATION_MS = 10000; // 10 seconds
|
||||
@ -35,10 +25,7 @@ public class VibrationManagerImpl implements VibrationManager {
|
||||
private final Vibrator mVibrator;
|
||||
private final boolean mHasVibratePermission;
|
||||
|
||||
private static long sVibrateMilliSecondsForTesting = -1;
|
||||
private static boolean sVibrateCancelledForTesting;
|
||||
|
||||
public VibrationManagerImpl() {
|
||||
public VibrationManagerAndroid() {
|
||||
Context appContext = ContextUtils.getApplicationContext();
|
||||
mAudioManager = (AudioManager) appContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
mVibrator = (Vibrator) appContext.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
@ -51,14 +38,13 @@ public class VibrationManagerImpl implements VibrationManager {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {}
|
||||
@CalledByNative
|
||||
static VibrationManagerAndroid getInstance() {
|
||||
return new VibrationManagerAndroid();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConnectionError(MojoException e) {}
|
||||
|
||||
@Override
|
||||
public void vibrate(long milliseconds, Vibrate_Response callback) {
|
||||
@CalledByNative
|
||||
public void vibrate(long milliseconds) {
|
||||
// Though the Blink implementation already sanitizes vibration times, don't
|
||||
// trust any values passed from the client.
|
||||
long sanitizedMilliseconds =
|
||||
@ -70,37 +56,12 @@ public class VibrationManagerImpl implements VibrationManager {
|
||||
&& mHasVibratePermission) {
|
||||
mVibrator.vibrate(sanitizedMilliseconds);
|
||||
}
|
||||
sVibrateMilliSecondsForTesting = sanitizedMilliseconds;
|
||||
callback.call();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(Cancel_Response callback) {
|
||||
if (mHasVibratePermission) {
|
||||
mVibrator.cancel();
|
||||
}
|
||||
sVibrateCancelledForTesting = true;
|
||||
ResettersForTesting.register(() -> sVibrateCancelledForTesting = false);
|
||||
callback.call();
|
||||
}
|
||||
|
||||
/** A factory for implementations of the VibrationManager interface. */
|
||||
public static class Factory implements InterfaceFactory<VibrationManager> {
|
||||
public Factory() {}
|
||||
|
||||
@Override
|
||||
public VibrationManager createImpl() {
|
||||
return new VibrationManagerImpl();
|
||||
}
|
||||
}
|
||||
|
||||
@CalledByNative
|
||||
static long getVibrateMilliSecondsForTesting() {
|
||||
return sVibrateMilliSecondsForTesting;
|
||||
}
|
||||
|
||||
@CalledByNativeForTesting
|
||||
static boolean getVibrateCancelledForTesting() {
|
||||
return sVibrateCancelledForTesting;
|
||||
public void cancel() {
|
||||
if (mHasVibratePermission) {
|
||||
mVibrator.cancel();
|
||||
}
|
||||
}
|
||||
}
|
39
services/device/vibration/vibration_manager_android.cc
Normal file
39
services/device/vibration/vibration_manager_android.cc
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "services/device/vibration/vibration_manager_android.h"
|
||||
|
||||
#include "base/android/jni_android.h"
|
||||
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
|
||||
#include "services/device/vibration/android/vibration_jni_headers/VibrationManagerAndroid_jni.h"
|
||||
|
||||
namespace device {
|
||||
|
||||
VibrationManagerAndroid::VibrationManagerAndroid(
|
||||
mojo::PendingRemote<mojom::VibrationManagerListener> listener)
|
||||
: VibrationManagerImpl(std::move(listener)) {
|
||||
impl_.Reset(Java_VibrationManagerAndroid_getInstance(
|
||||
base::android::AttachCurrentThread()));
|
||||
}
|
||||
VibrationManagerAndroid::~VibrationManagerAndroid() = default;
|
||||
|
||||
void VibrationManagerAndroid::PlatformVibrate(int64_t milliseconds) {
|
||||
Java_VibrationManagerAndroid_vibrate(base::android::AttachCurrentThread(),
|
||||
impl_, milliseconds);
|
||||
}
|
||||
|
||||
void VibrationManagerAndroid::PlatformCancel() {
|
||||
Java_VibrationManagerAndroid_cancel(base::android::AttachCurrentThread(),
|
||||
impl_);
|
||||
}
|
||||
|
||||
void VibrationManagerAndroid::Create(
|
||||
mojo::PendingReceiver<mojom::VibrationManager> receiver,
|
||||
mojo::PendingRemote<mojom::VibrationManagerListener> listener) {
|
||||
mojo::MakeSelfOwnedReceiver(
|
||||
std::make_unique<VibrationManagerAndroid>(std::move(listener)),
|
||||
std::move(receiver));
|
||||
}
|
||||
|
||||
} // namespace device
|
38
services/device/vibration/vibration_manager_android.h
Normal file
38
services/device/vibration/vibration_manager_android.h
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef SERVICES_DEVICE_VIBRATION_VIBRATION_MANAGER_ANDROID_H_
|
||||
#define SERVICES_DEVICE_VIBRATION_VIBRATION_MANAGER_ANDROID_H_
|
||||
|
||||
#include <jni.h>
|
||||
|
||||
#include "base/android/scoped_java_ref.h"
|
||||
#include "services/device/vibration/vibration_manager_impl.h"
|
||||
|
||||
namespace device {
|
||||
|
||||
class VibrationManagerAndroid : public VibrationManagerImpl {
|
||||
public:
|
||||
static void Create(
|
||||
mojo::PendingReceiver<mojom::VibrationManager> receiver,
|
||||
mojo::PendingRemote<mojom::VibrationManagerListener> listener);
|
||||
|
||||
explicit VibrationManagerAndroid(
|
||||
mojo::PendingRemote<mojom::VibrationManagerListener> listener);
|
||||
VibrationManagerAndroid(const VibrationManagerAndroid&) = delete;
|
||||
VibrationManagerAndroid& operator=(const VibrationManagerAndroid&) = delete;
|
||||
~VibrationManagerAndroid() override;
|
||||
|
||||
protected:
|
||||
// VibrationManagerImpl:
|
||||
void PlatformVibrate(int64_t milliseconds) override;
|
||||
void PlatformCancel() override;
|
||||
|
||||
private:
|
||||
base::android::ScopedJavaGlobalRef<jobject> impl_;
|
||||
};
|
||||
|
||||
} // namespace device
|
||||
|
||||
#endif // SERVICES_DEVICE_VIBRATION_VIBRATION_MANAGER_ANDROID_H_
|
54
services/device/vibration/vibration_manager_impl.cc
Normal file
54
services/device/vibration/vibration_manager_impl.cc
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2014 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "services/device/vibration/vibration_manager_impl.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
|
||||
|
||||
namespace device {
|
||||
|
||||
int64_t VibrationManagerImpl::milli_seconds_for_testing_ = -1;
|
||||
bool VibrationManagerImpl::cancelled_for_testing_ = false;
|
||||
|
||||
VibrationManagerImpl::VibrationManagerImpl(
|
||||
mojo::PendingRemote<mojom::VibrationManagerListener> listener) {
|
||||
CHECK(!listener_);
|
||||
listener_.Bind(std::move(listener));
|
||||
}
|
||||
VibrationManagerImpl::~VibrationManagerImpl() = default;
|
||||
|
||||
void VibrationManagerImpl::Vibrate(int64_t milliseconds,
|
||||
VibrateCallback callback) {
|
||||
PlatformVibrate(milliseconds);
|
||||
VibrationManagerImpl::milli_seconds_for_testing_ = milliseconds;
|
||||
if (listener_) {
|
||||
listener_->OnVibrate();
|
||||
}
|
||||
|
||||
std::move(callback).Run();
|
||||
}
|
||||
|
||||
void VibrationManagerImpl::Cancel(CancelCallback callback) {
|
||||
VibrationManagerImpl::cancelled_for_testing_ = true;
|
||||
std::move(callback).Run();
|
||||
}
|
||||
|
||||
void VibrationManagerImpl::PlatformVibrate(int64_t milliseconds) {}
|
||||
void VibrationManagerImpl::PlatformCancel() {}
|
||||
|
||||
// static
|
||||
|
||||
void VibrationManagerImpl::Create(
|
||||
mojo::PendingReceiver<mojom::VibrationManager> receiver,
|
||||
mojo::PendingRemote<mojom::VibrationManagerListener> listener) {
|
||||
mojo::MakeSelfOwnedReceiver(
|
||||
std::make_unique<VibrationManagerImpl>(std::move(listener)),
|
||||
std::move(receiver));
|
||||
}
|
||||
|
||||
} // namespace device
|
@ -5,17 +5,41 @@
|
||||
#ifndef SERVICES_DEVICE_VIBRATION_VIBRATION_MANAGER_IMPL_H_
|
||||
#define SERVICES_DEVICE_VIBRATION_VIBRATION_MANAGER_IMPL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "services/device/public/mojom/vibration_manager.mojom.h"
|
||||
|
||||
namespace device {
|
||||
|
||||
class VibrationManagerImpl {
|
||||
class VibrationManagerImpl : public mojom::VibrationManager {
|
||||
public:
|
||||
static void Create(mojo::PendingReceiver<mojom::VibrationManager> receiver);
|
||||
static void Create(
|
||||
mojo::PendingReceiver<mojom::VibrationManager> receiver,
|
||||
mojo::PendingRemote<mojom::VibrationManagerListener> listener);
|
||||
|
||||
// Sets the listener that listens for any Vibrate calls from this class. The
|
||||
// listener is currently set from the RenderFrameHostImpl.
|
||||
explicit VibrationManagerImpl(
|
||||
mojo::PendingRemote<mojom::VibrationManagerListener> listener);
|
||||
VibrationManagerImpl(const VibrationManagerImpl&) = delete;
|
||||
VibrationManagerImpl& operator=(const VibrationManagerImpl&) = delete;
|
||||
~VibrationManagerImpl() override;
|
||||
|
||||
// mojom::VibrationManager
|
||||
void Vibrate(int64_t milliseconds, VibrateCallback callback) override;
|
||||
void Cancel(CancelCallback callback) override;
|
||||
|
||||
static int64_t milli_seconds_for_testing_;
|
||||
static bool cancelled_for_testing_;
|
||||
|
||||
protected:
|
||||
virtual void PlatformVibrate(int64_t milliseconds);
|
||||
virtual void PlatformCancel();
|
||||
|
||||
mojo::Remote<mojom::VibrationManagerListener> listener_;
|
||||
};
|
||||
|
||||
} // namespace device
|
||||
|
@ -1,44 +0,0 @@
|
||||
// Copyright 2014 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "services/device/vibration/vibration_manager_impl.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <utility>
|
||||
|
||||
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
|
||||
|
||||
namespace device {
|
||||
|
||||
int64_t VibrationManagerImpl::milli_seconds_for_testing_ = -1;
|
||||
bool VibrationManagerImpl::cancelled_for_testing_ = false;
|
||||
|
||||
namespace {
|
||||
|
||||
class VibrationManagerEmptyImpl : public mojom::VibrationManager {
|
||||
public:
|
||||
VibrationManagerEmptyImpl() {}
|
||||
~VibrationManagerEmptyImpl() override {}
|
||||
|
||||
void Vibrate(int64_t milliseconds, VibrateCallback callback) override {
|
||||
VibrationManagerImpl::milli_seconds_for_testing_ = milliseconds;
|
||||
std::move(callback).Run();
|
||||
}
|
||||
|
||||
void Cancel(CancelCallback callback) override {
|
||||
VibrationManagerImpl::cancelled_for_testing_ = true;
|
||||
std::move(callback).Run();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
void VibrationManagerImpl::Create(
|
||||
mojo::PendingReceiver<mojom::VibrationManager> receiver) {
|
||||
mojo::MakeSelfOwnedReceiver(std::make_unique<VibrationManagerEmptyImpl>(),
|
||||
std::move(receiver));
|
||||
}
|
||||
|
||||
} // namespace device
|
@ -2,24 +2,23 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "services/device/vibration/vibration_manager_impl.h"
|
||||
|
||||
#include "base/run_loop.h"
|
||||
#include "build/build_config.h"
|
||||
#include "base/test/gmock_callback_support.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "services/device/device_service_test_base.h"
|
||||
#include "services/device/public/mojom/vibration_manager.mojom.h"
|
||||
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
#include "base/android/jni_android.h"
|
||||
#include "services/device/vibration/android/vibration_jni_headers/VibrationManagerImpl_jni.h"
|
||||
#else
|
||||
#include "services/device/vibration/vibration_manager_impl.h"
|
||||
#endif
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
|
||||
namespace device {
|
||||
|
||||
using ::base::test::RunClosure;
|
||||
|
||||
namespace {
|
||||
|
||||
class VibrationManagerImplTest : public DeviceServiceTestBase {
|
||||
class VibrationManagerImplTest : public DeviceServiceTestBase,
|
||||
public mojom::VibrationManagerListener {
|
||||
public:
|
||||
VibrationManagerImplTest() = default;
|
||||
|
||||
@ -32,8 +31,10 @@ class VibrationManagerImplTest : public DeviceServiceTestBase {
|
||||
void SetUp() override {
|
||||
DeviceServiceTestBase::SetUp();
|
||||
|
||||
mojo::PendingRemote<device::mojom::VibrationManagerListener> remote;
|
||||
listener_.Bind(remote.InitWithNewPipeAndPassReceiver());
|
||||
device_service()->BindVibrationManager(
|
||||
vibration_manager_.BindNewPipeAndPassReceiver());
|
||||
vibration_manager_.BindNewPipeAndPassReceiver(), std::move(remote));
|
||||
}
|
||||
|
||||
void Vibrate(int64_t milliseconds) {
|
||||
@ -49,25 +50,18 @@ class VibrationManagerImplTest : public DeviceServiceTestBase {
|
||||
}
|
||||
|
||||
int64_t GetVibrationMilliSeconds() {
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
return Java_VibrationManagerImpl_getVibrateMilliSecondsForTesting(
|
||||
base::android::AttachCurrentThread());
|
||||
#else
|
||||
return VibrationManagerImpl::milli_seconds_for_testing_;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GetVibrationCancelled() {
|
||||
#if BUILDFLAG(IS_ANDROID)
|
||||
return Java_VibrationManagerImpl_getVibrateCancelledForTesting(
|
||||
base::android::AttachCurrentThread());
|
||||
#else
|
||||
return VibrationManagerImpl::cancelled_for_testing_;
|
||||
#endif
|
||||
}
|
||||
|
||||
MOCK_METHOD(void, OnVibrate, (), (override));
|
||||
|
||||
private:
|
||||
mojo::Remote<mojom::VibrationManager> vibration_manager_;
|
||||
mojo::Receiver<mojom::VibrationManagerListener> listener_{this};
|
||||
};
|
||||
|
||||
TEST_F(VibrationManagerImplTest, VibrateThenCancel) {
|
||||
@ -80,6 +74,14 @@ TEST_F(VibrationManagerImplTest, VibrateThenCancel) {
|
||||
EXPECT_TRUE(GetVibrationCancelled());
|
||||
}
|
||||
|
||||
TEST_F(VibrationManagerImplTest, VibrateNotifiesListener) {
|
||||
base::RunLoop loop;
|
||||
EXPECT_CALL(*this, OnVibrate)
|
||||
.WillOnce(base::test::RunClosure(loop.QuitClosure()));
|
||||
Vibrate(10000);
|
||||
loop.Run();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
} // namespace device
|
||||
|
Reference in New Issue
Block a user