Commit 6634b7db authored by scottmg@chromium.org's avatar scottmg@chromium.org

Send WM_DEVICECHANGE message through SystemMonitor

WM_DEVICECHANGE is sent when there's been a change to devices or the computer;
specifically when a USB device is connected or disconnected. This is intended
for use in support of Gamepads for more performant polling and
connect/disconnect testing. Currently only on Windows, though seems reasonable
to add for other platforms in the future.

BUG=79050


Review URL: http://codereview.chromium.org/8523021

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@109960 0039d316-1c4b-4281-b951-d872f2087c98
parent 950067dd
...@@ -19,7 +19,9 @@ static int kDelayedBatteryCheckMs = 10 * 1000; ...@@ -19,7 +19,9 @@ static int kDelayedBatteryCheckMs = 10 * 1000;
#endif // defined(ENABLE_BATTERY_MONITORING) #endif // defined(ENABLE_BATTERY_MONITORING)
SystemMonitor::SystemMonitor() SystemMonitor::SystemMonitor()
: observer_list_(new ObserverListThreadSafe<PowerObserver>()), : power_observer_list_(new ObserverListThreadSafe<PowerObserver>()),
devices_changed_observer_list_(
new ObserverListThreadSafe<DevicesChangedObserver>()),
battery_in_use_(false), battery_in_use_(false),
suspended_(false) { suspended_(false) {
DCHECK(!g_system_monitor); DCHECK(!g_system_monitor);
...@@ -77,28 +79,47 @@ void SystemMonitor::ProcessPowerMessage(PowerEvent event_id) { ...@@ -77,28 +79,47 @@ void SystemMonitor::ProcessPowerMessage(PowerEvent event_id) {
} }
} }
void SystemMonitor::AddObserver(PowerObserver* obs) { void SystemMonitor::ProcessDevicesChanged() {
observer_list_->AddObserver(obs); NotifyDevicesChanged();
} }
void SystemMonitor::RemoveObserver(PowerObserver* obs) { void SystemMonitor::AddPowerObserver(PowerObserver* obs) {
observer_list_->RemoveObserver(obs); power_observer_list_->AddObserver(obs);
}
void SystemMonitor::RemovePowerObserver(PowerObserver* obs) {
power_observer_list_->RemoveObserver(obs);
}
void SystemMonitor::AddDevicesChangedObserver(DevicesChangedObserver* obs) {
devices_changed_observer_list_->AddObserver(obs);
}
void SystemMonitor::RemoveDevicesChangedObserver(DevicesChangedObserver* obs) {
devices_changed_observer_list_->RemoveObserver(obs);
}
void SystemMonitor::NotifyDevicesChanged() {
DVLOG(1) << "DevicesChanged";
devices_changed_observer_list_->Notify(
&DevicesChangedObserver::OnDevicesChanged);
} }
void SystemMonitor::NotifyPowerStateChange() { void SystemMonitor::NotifyPowerStateChange() {
DVLOG(1) << "PowerStateChange: " << (BatteryPower() ? "On" : "Off") DVLOG(1) << "PowerStateChange: " << (BatteryPower() ? "On" : "Off")
<< " battery"; << " battery";
observer_list_->Notify(&PowerObserver::OnPowerStateChange, BatteryPower()); power_observer_list_->Notify(&PowerObserver::OnPowerStateChange,
BatteryPower());
} }
void SystemMonitor::NotifySuspend() { void SystemMonitor::NotifySuspend() {
DVLOG(1) << "Power Suspending"; DVLOG(1) << "Power Suspending";
observer_list_->Notify(&PowerObserver::OnSuspend); power_observer_list_->Notify(&PowerObserver::OnSuspend);
} }
void SystemMonitor::NotifyResume() { void SystemMonitor::NotifyResume() {
DVLOG(1) << "Power Resuming"; DVLOG(1) << "Power Resuming";
observer_list_->Notify(&PowerObserver::OnResume); power_observer_list_->Notify(&PowerObserver::OnResume);
} }
void SystemMonitor::BatteryCheck() { void SystemMonitor::BatteryCheck() {
......
...@@ -90,15 +90,26 @@ class BASE_EXPORT SystemMonitor { ...@@ -90,15 +90,26 @@ class BASE_EXPORT SystemMonitor {
virtual ~PowerObserver() {} virtual ~PowerObserver() {}
}; };
class BASE_EXPORT DevicesChangedObserver {
public:
// Notification that the devices connected to the system have changed.
virtual void OnDevicesChanged() {}
protected:
virtual ~DevicesChangedObserver() {}
};
// Add a new observer. // Add a new observer.
// Can be called from any thread. // Can be called from any thread.
// Must not be called from within a notification callback. // Must not be called from within a notification callback.
void AddObserver(PowerObserver* obs); void AddPowerObserver(PowerObserver* obs);
void AddDevicesChangedObserver(DevicesChangedObserver* obs);
// Remove an existing observer. // Remove an existing observer.
// Can be called from any thread. // Can be called from any thread.
// Must not be called from within a notification callback. // Must not be called from within a notification callback.
void RemoveObserver(PowerObserver* obs); void RemovePowerObserver(PowerObserver* obs);
void RemoveDevicesChangedObserver(DevicesChangedObserver* obs);
#if defined(OS_WIN) #if defined(OS_WIN)
// Windows-specific handling of a WM_POWERBROADCAST message. // Windows-specific handling of a WM_POWERBROADCAST message.
...@@ -110,6 +121,9 @@ class BASE_EXPORT SystemMonitor { ...@@ -110,6 +121,9 @@ class BASE_EXPORT SystemMonitor {
// Cross-platform handling of a power event. // Cross-platform handling of a power event.
void ProcessPowerMessage(PowerEvent event_id); void ProcessPowerMessage(PowerEvent event_id);
// Cross-platform handling of a device change event.
void ProcessDevicesChanged();
private: private:
#if defined(OS_MACOSX) #if defined(OS_MACOSX)
void PlatformInit(); void PlatformInit();
...@@ -126,11 +140,14 @@ class BASE_EXPORT SystemMonitor { ...@@ -126,11 +140,14 @@ class BASE_EXPORT SystemMonitor {
void BatteryCheck(); void BatteryCheck();
// Functions to trigger notifications. // Functions to trigger notifications.
void NotifyDevicesChanged();
void NotifyPowerStateChange(); void NotifyPowerStateChange();
void NotifySuspend(); void NotifySuspend();
void NotifyResume(); void NotifyResume();
scoped_refptr<ObserverListThreadSafe<PowerObserver> > observer_list_; scoped_refptr<ObserverListThreadSafe<PowerObserver> > power_observer_list_;
scoped_refptr<ObserverListThreadSafe<DevicesChangedObserver> >
devices_changed_observer_list_;
bool battery_in_use_; bool battery_in_use_;
bool suspended_; bool suspended_;
......
...@@ -55,7 +55,7 @@ TEST(SystemMonitor, PowerNotifications) { ...@@ -55,7 +55,7 @@ TEST(SystemMonitor, PowerNotifications) {
SystemMonitor system_monitor; SystemMonitor system_monitor;
PowerTest test[kObservers]; PowerTest test[kObservers];
for (int index = 0; index < kObservers; ++index) for (int index = 0; index < kObservers; ++index)
system_monitor.AddObserver(&test[index]); system_monitor.AddPowerObserver(&test[index]);
// Send a bunch of power changes. Since the battery power hasn't // Send a bunch of power changes. Since the battery power hasn't
// actually changed, we shouldn't get notifications. // actually changed, we shouldn't get notifications.
...@@ -90,4 +90,49 @@ TEST(SystemMonitor, PowerNotifications) { ...@@ -90,4 +90,49 @@ TEST(SystemMonitor, PowerNotifications) {
EXPECT_EQ(test[0].resumes(), 1); EXPECT_EQ(test[0].resumes(), 1);
} }
class DevicesChangedTest : public SystemMonitor::DevicesChangedObserver {
public:
DevicesChangedTest()
: changes_(0) {
}
// DevicesChangedObserver callbacks.
virtual void OnDevicesChanged() OVERRIDE {
changes_++;
}
// Test status counts.
int changes() const { return changes_; }
private:
int changes_; // Count of OnDevicesChanged notifications.
DISALLOW_COPY_AND_ASSIGN(DevicesChangedTest);
};
TEST(SystemMonitor, DeviceChangeNotifications) {
const int kObservers = 5;
// Initialize a message loop for this to run on.
MessageLoop loop;
#if defined(OS_MACOSX)
SystemMonitor::AllocateSystemIOPorts();
#endif
SystemMonitor system_monitor;
DevicesChangedTest test[kObservers];
for (int index = 0; index < kObservers; ++index)
system_monitor.AddDevicesChangedObserver(&test[index]);
system_monitor.ProcessDevicesChanged();
loop.RunAllPending();
EXPECT_EQ(1, test[0].changes());
system_monitor.ProcessDevicesChanged();
system_monitor.ProcessDevicesChanged();
loop.RunAllPending();
EXPECT_EQ(3, test[0].changes());
}
} // namespace base } // namespace base
...@@ -33,6 +33,7 @@ ...@@ -33,6 +33,7 @@
#include <ole2.h> #include <ole2.h>
#include <shellapi.h> #include <shellapi.h>
#include "content/browser/system_message_window_win.h"
#include "ui/base/l10n/l10n_util_win.h" #include "ui/base/l10n/l10n_util_win.h"
#include "net/base/winsock_init.h" #include "net/base/winsock_init.h"
#endif #endif
...@@ -256,6 +257,10 @@ void BrowserMainLoop::MainMessageLoopStart() { ...@@ -256,6 +257,10 @@ void BrowserMainLoop::MainMessageLoopStart() {
network_change_notifier_.reset(net::NetworkChangeNotifier::Create()); network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
#if defined(OS_WIN)
system_message_window_.reset(new SystemMessageWindowWin);
#endif
for (size_t i = 0; i < parts_list_.size(); ++i) for (size_t i = 0; i < parts_list_.size(); ++i)
parts_list_[i]->PostMainMessageLoopStart(); parts_list_[i]->PostMainMessageLoopStart();
} }
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
class CommandLine; class CommandLine;
class HighResolutionTimerManager; class HighResolutionTimerManager;
class MessageLoop; class MessageLoop;
class SystemMessageWindowWin;
namespace base { namespace base {
class SystemMonitor; class SystemMonitor;
...@@ -64,6 +65,9 @@ class BrowserMainLoop { ...@@ -64,6 +65,9 @@ class BrowserMainLoop {
scoped_ptr<base::SystemMonitor> system_monitor_; scoped_ptr<base::SystemMonitor> system_monitor_;
scoped_ptr<HighResolutionTimerManager> hi_res_timer_manager_; scoped_ptr<HighResolutionTimerManager> hi_res_timer_manager_;
scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_; scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
#if defined(OS_WIN)
scoped_ptr<SystemMessageWindowWin> system_message_window_;
#endif
scoped_ptr<BrowserThreadImpl> main_thread_; scoped_ptr<BrowserThreadImpl> main_thread_;
DISALLOW_COPY_AND_ASSIGN(BrowserMainLoop); DISALLOW_COPY_AND_ASSIGN(BrowserMainLoop);
......
// Copyright (c) 2011 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 "content/browser/system_message_window_win.h"
#include <windows.h>
#include <dbt.h>
#include "base/system_monitor/system_monitor.h"
#include "base/win/wrapped_window_proc.h"
static const wchar_t* const WindowClassName = L"Chrome_SystemMessageWindow";
SystemMessageWindowWin::SystemMessageWindowWin() {
HINSTANCE hinst = GetModuleHandle(NULL);
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(wc);
wc.lpfnWndProc =
base::win::WrappedWindowProc<&SystemMessageWindowWin::WndProcThunk>;
wc.hInstance = hinst;
wc.lpszClassName = WindowClassName;
ATOM clazz = RegisterClassEx(&wc);
DCHECK(clazz);
window_ = CreateWindow(WindowClassName,
0, 0, 0, 0, 0, 0, 0, 0, hinst, 0);
SetWindowLongPtr(window_, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
}
SystemMessageWindowWin::~SystemMessageWindowWin() {
if (window_) {
DestroyWindow(window_);
UnregisterClass(WindowClassName, GetModuleHandle(NULL));
}
}
LRESULT SystemMessageWindowWin::OnDeviceChange(UINT event_type, DWORD data) {
base::SystemMonitor* monitor = base::SystemMonitor::Get();
if (monitor && event_type == DBT_DEVNODES_CHANGED)
monitor->ProcessDevicesChanged();
return TRUE;
}
LRESULT CALLBACK SystemMessageWindowWin::WndProc(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam) {
switch (message) {
case WM_DEVICECHANGE:
return OnDeviceChange(static_cast<UINT>(wparam),
static_cast<DWORD>(lparam));
default:
break;
}
return ::DefWindowProc(hwnd, message, wparam, lparam);
}
// Copyright (c) 2011 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 CONTENT_BROWSER_SYSTEM_MESSAGE_WINDOW_WIN_H_
#define CONTENT_BROWSER_SYSTEM_MESSAGE_WINDOW_WIN_H_
#pragma once
#include "build/build_config.h"
#include <windows.h>
#include "base/basictypes.h"
#include "content/common/content_export.h"
class CONTENT_EXPORT SystemMessageWindowWin {
public:
SystemMessageWindowWin();
virtual ~SystemMessageWindowWin();
virtual LRESULT OnDeviceChange(UINT event_type, DWORD data);
private:
LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wparam, LPARAM lparam);
static LRESULT CALLBACK WndProcThunk(HWND hwnd,
UINT message,
WPARAM wparam,
LPARAM lparam) {
SystemMessageWindowWin* msg_wnd = reinterpret_cast<SystemMessageWindowWin*>(
GetWindowLongPtr(hwnd, GWLP_USERDATA));
if (msg_wnd)
return msg_wnd->WndProc(hwnd, message, wparam, lparam);
return ::DefWindowProc(hwnd, message, wparam, lparam);
}
HWND window_;
DISALLOW_COPY_AND_ASSIGN(SystemMessageWindowWin);
};
#endif // CONTENT_BROWSER_SYSTEM_MESSAGE_WINDOW_WIN_H_
...@@ -9,12 +9,12 @@ ...@@ -9,12 +9,12 @@
HighResolutionTimerManager::HighResolutionTimerManager() HighResolutionTimerManager::HighResolutionTimerManager()
: hi_res_clock_available_(false) { : hi_res_clock_available_(false) {
base::SystemMonitor* system_monitor = base::SystemMonitor::Get(); base::SystemMonitor* system_monitor = base::SystemMonitor::Get();
system_monitor->AddObserver(this); system_monitor->AddPowerObserver(this);
UseHiResClock(!system_monitor->BatteryPower()); UseHiResClock(!system_monitor->BatteryPower());
} }
HighResolutionTimerManager::~HighResolutionTimerManager() { HighResolutionTimerManager::~HighResolutionTimerManager() {
base::SystemMonitor::Get()->RemoveObserver(this); base::SystemMonitor::Get()->RemovePowerObserver(this);
UseHiResClock(false); UseHiResClock(false);
} }
......
...@@ -511,6 +511,8 @@ ...@@ -511,6 +511,8 @@
'browser/ssl/ssl_policy_backend.h', 'browser/ssl/ssl_policy_backend.h',
'browser/ssl/ssl_request_info.cc', 'browser/ssl/ssl_request_info.cc',
'browser/ssl/ssl_request_info.h', 'browser/ssl/ssl_request_info.h',
'browser/system_message_window_win.cc',
'browser/system_message_window_win.h',
'browser/tab_contents/drag_utils_gtk.cc', 'browser/tab_contents/drag_utils_gtk.cc',
'browser/tab_contents/drag_utils_gtk.h', 'browser/tab_contents/drag_utils_gtk.h',
'browser/tab_contents/interstitial_page.cc', 'browser/tab_contents/interstitial_page.cc',
......
...@@ -34,7 +34,7 @@ URLRequestJob::URLRequestJob(URLRequest* request) ...@@ -34,7 +34,7 @@ URLRequestJob::URLRequestJob(URLRequest* request)
ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) { ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)) {
base::SystemMonitor* system_monitor = base::SystemMonitor::Get(); base::SystemMonitor* system_monitor = base::SystemMonitor::Get();
if (system_monitor) if (system_monitor)
base::SystemMonitor::Get()->AddObserver(this); base::SystemMonitor::Get()->AddPowerObserver(this);
} }
void URLRequestJob::SetUpload(UploadData* upload) { void URLRequestJob::SetUpload(UploadData* upload) {
...@@ -219,7 +219,7 @@ void URLRequestJob::NotifyURLRequestDestroyed() { ...@@ -219,7 +219,7 @@ void URLRequestJob::NotifyURLRequestDestroyed() {
URLRequestJob::~URLRequestJob() { URLRequestJob::~URLRequestJob() {
base::SystemMonitor* system_monitor = base::SystemMonitor::Get(); base::SystemMonitor* system_monitor = base::SystemMonitor::Get();
if (system_monitor) if (system_monitor)
base::SystemMonitor::Get()->RemoveObserver(this); base::SystemMonitor::Get()->RemovePowerObserver(this);
} }
void URLRequestJob::NotifyCertificateRequested( void URLRequestJob::NotifyCertificateRequested(
......
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