diff options
Diffstat (limited to 'chrome/browser/devtools')
4 files changed, 157 insertions, 0 deletions
diff --git a/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc b/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc index d4d532c..120d9a6 100644 --- a/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc +++ b/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc @@ -259,6 +259,8 @@ DevToolsEmbedderMessageDispatcher* d->RegisterHandler("indexPath", &Delegate::IndexPath, delegate); d->RegisterHandler("stopIndexing", &Delegate::StopIndexing, delegate); d->RegisterHandler("searchInPath", &Delegate::SearchInPath, delegate); + d->RegisterHandler("setWhitelistedShortcuts", + &Delegate::SetWhitelistedShortcuts, delegate); d->RegisterHandler("zoomIn", &Delegate::ZoomIn, delegate); d->RegisterHandler("zoomOut", &Delegate::ZoomOut, delegate); d->RegisterHandler("resetZoom", &Delegate::ResetZoom, delegate); diff --git a/chrome/browser/devtools/devtools_embedder_message_dispatcher.h b/chrome/browser/devtools/devtools_embedder_message_dispatcher.h index 7398a16..9c1d664 100644 --- a/chrome/browser/devtools/devtools_embedder_message_dispatcher.h +++ b/chrome/browser/devtools/devtools_embedder_message_dispatcher.h @@ -54,6 +54,7 @@ class DevToolsEmbedderMessageDispatcher { virtual void SearchInPath(int request_id, const std::string& file_system_path, const std::string& query) = 0; + virtual void SetWhitelistedShortcuts(const std::string& message) = 0; virtual void ZoomIn() = 0; virtual void ZoomOut() = 0; virtual void ResetZoom() = 0; diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc index dce7133..538039c 100644 --- a/chrome/browser/devtools/devtools_window.cc +++ b/chrome/browser/devtools/devtools_window.cc @@ -55,6 +55,7 @@ #include "content/public/browser/devtools_manager.h" #include "content/public/browser/favicon_status.h" #include "content/public/browser/load_notification_details.h" +#include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/navigation_controller.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/notification_source.h" @@ -76,8 +77,10 @@ #include "grit/generated_resources.h" #include "third_party/WebKit/public/web/WebInputEvent.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/events/keycodes/keyboard_codes.h" using base::DictionaryValue; +using blink::WebInputEvent; using content::BrowserThread; using content::DevToolsAgentHost; @@ -159,6 +162,123 @@ bool DevToolsConfirmInfoBarDelegate::Cancel() { return true; } +// DevToolsEventForwarder ----------------------------------------------------- + +namespace { + +static const char kKeyUpEventName[] = "keyup"; +static const char kKeyDownEventName[] = "keydown"; + +} // namespace + +class DevToolsEventForwarder { + public: + explicit DevToolsEventForwarder(DevToolsWindow* window) + : devtools_window_(window) {} + + // Registers whitelisted shortcuts with the forwarder. + // Only registered keys will be forwarded to the DevTools frontend. + void SetWhitelistedShortcuts(const std::string& message); + + // Forwards a keyboard event to the DevTools frontend if it is whitelisted. + // Returns |true| if the event has been forwarded, |false| otherwise. + bool ForwardEvent(const content::NativeWebKeyboardEvent& event); + + private: + static int VirtualKeyCodeWithoutLocation(int key_code); + static bool KeyWhitelistingAllowed(int key_code, int modifiers); + static int CombineKeyCodeAndModifiers(int key_code, int modifiers); + + DevToolsWindow* devtools_window_; + std::set<int> whitelisted_keys_; + + DISALLOW_COPY_AND_ASSIGN(DevToolsEventForwarder); +}; + +void DevToolsEventForwarder::SetWhitelistedShortcuts( + const std::string& message) { + scoped_ptr<base::Value> parsed_message(base::JSONReader::Read(message)); + base::ListValue* shortcut_list; + if (!parsed_message->GetAsList(&shortcut_list)) + return; + base::ListValue::iterator it = shortcut_list->begin(); + for (; it != shortcut_list->end(); ++it) { + base::DictionaryValue* dictionary; + if (!(*it)->GetAsDictionary(&dictionary)) + continue; + int key_code = 0; + dictionary->GetInteger("keyCode", &key_code); + if (key_code == 0) + continue; + int modifiers = 0; + dictionary->GetInteger("modifiers", &modifiers); + if (!KeyWhitelistingAllowed(key_code, modifiers)) { + LOG(WARNING) << "Key whitelisting forbidden: " + << "(" << key_code << "," << modifiers << ")"; + continue; + } + whitelisted_keys_.insert(CombineKeyCodeAndModifiers(key_code, modifiers)); + } +} + +bool DevToolsEventForwarder::ForwardEvent( + const content::NativeWebKeyboardEvent& event) { + std::string event_type; + switch (event.type) { + case WebInputEvent::KeyDown: + case WebInputEvent::RawKeyDown: + event_type = kKeyDownEventName; + break; + case WebInputEvent::KeyUp: + event_type = kKeyUpEventName; + break; + default: + return false; + } + + int key_code = VirtualKeyCodeWithoutLocation(event.windowsKeyCode); + int key = CombineKeyCodeAndModifiers(key_code, event.modifiers); + if (whitelisted_keys_.find(key) == whitelisted_keys_.end()) + return false; + + base::DictionaryValue event_data; + event_data.SetString("type", event_type); + event_data.SetString("keyIdentifier", event.keyIdentifier); + event_data.SetInteger("keyCode", key_code); + event_data.SetInteger("modifiers", event.modifiers); + devtools_window_->CallClientFunction( + "InspectorFrontendAPI.keyEventUnhandled", &event_data, NULL, NULL); + return true; +} + +int DevToolsEventForwarder::CombineKeyCodeAndModifiers(int key_code, + int modifiers) { + return key_code | (modifiers << 16); +} + +bool DevToolsEventForwarder::KeyWhitelistingAllowed(int key_code, + int modifiers) { + return (ui::VKEY_F1 <= key_code && key_code <= ui::VKEY_F12) || + modifiers != 0; +} + +// Mapping copied from Blink's KeyboardEvent.cpp. +int DevToolsEventForwarder::VirtualKeyCodeWithoutLocation(int key_code) +{ + switch (key_code) { + case ui::VKEY_LCONTROL: + case ui::VKEY_RCONTROL: + return ui::VKEY_CONTROL; + case ui::VKEY_LSHIFT: + case ui::VKEY_RSHIFT: + return ui::VKEY_SHIFT; + case ui::VKEY_LMENU: + case ui::VKEY_RMENU: + return ui::VKEY_MENU; + default: + return key_code; + } +} // DevToolsWindow::InspectedWebContentsObserver ------------------------------- @@ -346,6 +466,15 @@ DevToolsWindow* DevToolsWindow::GetInstanceForInspectedRenderViewHost( } // static +DevToolsWindow* DevToolsWindow::GetInstanceForInspectedWebContents( + content::WebContents* inspected_web_contents) { + if (!inspected_web_contents) + return NULL; + return GetInstanceForInspectedRenderViewHost( + inspected_web_contents->GetRenderViewHost()); +} + +// static bool DevToolsWindow::IsDevToolsWindow(content::RenderViewHost* window_rvh) { return AsDevToolsWindow(window_rvh) != NULL; } @@ -704,6 +833,7 @@ DevToolsWindow::DevToolsWindow(Profile* profile, embedder_message_dispatcher_.reset( DevToolsEmbedderMessageDispatcher::createForDevToolsFrontend(this)); + event_forwarder_.reset(new DevToolsEventForwarder(this)); } // static @@ -1543,3 +1673,13 @@ void DevToolsWindow::SetLoadCompletedCallback(const base::Closure& closure) { } load_completed_callback_ = closure; } + +void DevToolsWindow::SetWhitelistedShortcuts( + const std::string& message) { + event_forwarder_->SetWhitelistedShortcuts(message); +} + +bool DevToolsWindow::ForwardKeyboardEvent( + const content::NativeWebKeyboardEvent& event) { + return event_forwarder_->ForwardEvent(event); +} diff --git a/chrome/browser/devtools/devtools_window.h b/chrome/browser/devtools/devtools_window.h index fd7f430..f89786c 100644 --- a/chrome/browser/devtools/devtools_window.h +++ b/chrome/browser/devtools/devtools_window.h @@ -27,6 +27,7 @@ class Browser; class BrowserWindow; class DevToolsControllerTest; +class DevToolsEventForwarder; class Profile; namespace base { @@ -37,6 +38,7 @@ namespace content { class DevToolsAgentHost; class DevToolsClientHost; struct FileChooserParams; +struct NativeWebKeyboardEvent; class RenderViewHost; class WebContents; } @@ -68,6 +70,11 @@ class DevToolsWindow : private content::NotificationObserver, static DevToolsWindow* GetInstanceForInspectedRenderViewHost( content::RenderViewHost* inspected_rvh); + // Return the DevToolsWindow for the given WebContents if one exists, + // otherwise NULL. + static DevToolsWindow* GetInstanceForInspectedWebContents( + content::WebContents* inspected_web_contents); + // Return the DevToolsWindow for the given WebContents if one exists and is // docked, otherwise NULL. This method will return only fully initialized // window ready to be presented in UI. @@ -133,6 +140,9 @@ class DevToolsWindow : private content::NotificationObserver, // closure immediately. void SetLoadCompletedCallback(const base::Closure& closure); + // Forwards an unhandled keyboard event to the DevTools frontend. + bool ForwardKeyboardEvent(const content::NativeWebKeyboardEvent& event); + // BeforeUnload interception //////////////////////////////////////////////// // In order to preserve any edits the user may have made in devtools, the @@ -326,6 +336,7 @@ class DevToolsWindow : private content::NotificationObserver, virtual void SearchInPath(int request_id, const std::string& file_system_path, const std::string& query) OVERRIDE; + virtual void SetWhitelistedShortcuts(const std::string& message) OVERRIDE; virtual void ZoomIn() OVERRIDE; virtual void ZoomOut() OVERRIDE; virtual void ResetZoom() OVERRIDE; @@ -399,6 +410,9 @@ class DevToolsWindow : private content::NotificationObserver, scoped_ptr<DevToolsEmbedderMessageDispatcher> embedder_message_dispatcher_; base::WeakPtrFactory<DevToolsWindow> weak_factory_; base::TimeTicks inspect_element_start_time_; + scoped_ptr<DevToolsEventForwarder> event_forwarder_; + + friend class DevToolsEventForwarder; DISALLOW_COPY_AND_ASSIGN(DevToolsWindow); }; |