diff options
author | apavlov@chromium.org <apavlov@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-08 20:04:02 +0000 |
---|---|---|
committer | apavlov@chromium.org <apavlov@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-08 20:04:02 +0000 |
commit | 93e0babab8dc046ae83a1d836fb2fe5eed09f2f1 (patch) | |
tree | 2f1ed7cf89cdc3c0fc609a4a08b93483b5d16d5a /chrome/browser | |
parent | ff8cae509ede97ba7231f3ba5233db49aaa18f0c (diff) | |
download | chromium_src-93e0babab8dc046ae83a1d836fb2fe5eed09f2f1.zip chromium_src-93e0babab8dc046ae83a1d836fb2fe5eed09f2f1.tar.gz chromium_src-93e0babab8dc046ae83a1d836fb2fe5eed09f2f1.tar.bz2 |
DevTools: Forward whitelisted unhandled shortcuts from inspected page into DevTools frontend
This will allow to freeze the inspected page,
so that the focus loss will not alter its state.
This is the Chromium part of the change.
R=pfeldman
BUG=160510
Review URL: https://codereview.chromium.org/225973003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@262492 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/devtools/devtools_embedder_message_dispatcher.cc | 2 | ||||
-rw-r--r-- | chrome/browser/devtools/devtools_embedder_message_dispatcher.h | 1 | ||||
-rw-r--r-- | chrome/browser/devtools/devtools_window.cc | 140 | ||||
-rw-r--r-- | chrome/browser/devtools/devtools_window.h | 14 | ||||
-rw-r--r-- | chrome/browser/ui/browser.cc | 9 |
5 files changed, 165 insertions, 1 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); }; diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc index 31bd25f..ea8e8dc 100644 --- a/chrome/browser/ui/browser.cc +++ b/chrome/browser/ui/browser.cc @@ -1149,7 +1149,14 @@ bool Browser::PreHandleKeyboardEvent(content::WebContents* source, void Browser::HandleKeyboardEvent(content::WebContents* source, const NativeWebKeyboardEvent& event) { - window()->HandleKeyboardEvent(event); + DevToolsWindow* devtools_window = + DevToolsWindow::GetInstanceForInspectedWebContents(source); + bool handled = false; + if (devtools_window) + handled = devtools_window->ForwardKeyboardEvent(event); + + if (!handled) + window()->HandleKeyboardEvent(event); } bool Browser::TabsNeedBeforeUnloadFired() { |