Index: chrome/browser/devtools/devtools_window.cc |
diff --git a/chrome/browser/devtools/devtools_window.cc b/chrome/browser/devtools/devtools_window.cc |
index dce7133ed3df102a99d8b65cbe60eb275df79805..538039c19f4a4427eebb1eb28a78363908f24e76 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); |
+} |