- Add keyboard and focus notifications (issue #508).

- Add CefDOMNode::IsEditable method.
- List interfaces alphabetically in CefClient.
- Correct error checking for code and command input.

git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@680 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt
2012-06-11 15:52:49 +00:00
parent 3715c23777
commit d8caf27e3b
60 changed files with 1940 additions and 408 deletions

View File

@@ -269,6 +269,15 @@ void ClientApp::OnContextReleased(CefRefPtr<CefBrowser> browser,
}
}
void ClientApp::OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) {
// Execute delegate callbacks.
RenderDelegateSet::iterator it = render_delegates_.begin();
for (; it != render_delegates_.end(); ++it)
(*it)->OnFocusedNodeChanged(this, browser, frame, node);
}
bool ClientApp::OnProcessMessageRecieved(
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,

View File

@@ -43,6 +43,13 @@ class ClientApp : public CefApp,
CefRefPtr<CefV8Context> context) {
};
// Called when the focused node in a frame has changed.
virtual void OnFocusedNodeChanged(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) {
}
// Called when a process message is received. Return true if the message was
// handled and should not be passed on to other handlers. RenderDelegates
// should check for unique message names to avoid interfering with each
@@ -112,6 +119,9 @@ class ClientApp : public CefApp,
virtual void OnContextReleased(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefV8Context> context) OVERRIDE;
virtual void OnFocusedNodeChanged(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) OVERRIDE;
virtual bool OnProcessMessageRecieved(
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,

View File

@@ -3,11 +3,13 @@
// can be found in the LICENSE file.
#include "cefclient/client_app.h"
#include "cefclient/client_renderer.h"
#include "cefclient/dom_test.h"
#include "cefclient/scheme_test.h"
// static
void ClientApp::CreateRenderDelegates(RenderDelegateSet& delegates) {
client_renderer::CreateRenderDelegates(delegates);
dom_test::CreateRenderDelegates(delegates);
}

View File

@@ -11,6 +11,7 @@
#include "include/wrapper/cef_stream_resource_handler.h"
#include "cefclient/binding_test.h"
#include "cefclient/cefclient.h"
#include "cefclient/client_renderer.h"
#include "cefclient/dom_test.h"
#include "cefclient/resource_util.h"
#include "cefclient/string_util.h"
@@ -34,7 +35,7 @@ ClientHandler::ClientHandler()
m_ForwardHwnd(NULL),
m_StopHwnd(NULL),
m_ReloadHwnd(NULL),
m_bFormElementHasFocus(false) {
m_bFocusOnEditableField(false) {
CreateProcessMessageDelegates(process_message_delegates_);
CreateRequestDelegates(request_delegates_);
}
@@ -46,6 +47,17 @@ bool ClientHandler::OnProcessMessageRecieved(
CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) {
// Check for messages from the client renderer.
std::string message_name = message->GetName();
if (message_name == client_renderer::kFocusedNodeChangedMessage) {
// A message is sent from ClientRenderDelegate to tell us whether the
// currently focused DOM node is editable. Use of |m_bFocusOnEditableField|
// is redundant with CefKeyEvent.focus_on_editable_field in OnPreKeyEvent
// but is useful for demonstration purposes.
m_bFocusOnEditableField = message->GetArgumentList()->GetBool(0);
return true;
}
bool handled = false;
// Execute delegate callbacks.
@@ -58,6 +70,129 @@ bool ClientHandler::OnProcessMessageRecieved(
return handled;
}
void ClientHandler::OnBeforeContextMenu(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model) {
if ((params->GetTypeFlags() & (CM_TYPEFLAG_PAGE | CM_TYPEFLAG_FRAME)) != 0) {
// Add a separator if the menu already has items.
if (model->GetCount() > 0)
model->AddSeparator();
// Add a "Show DevTools" item to all context menus.
model->AddItem(CLIENT_ID_SHOW_DEVTOOLS, "&Show DevTools");
CefString devtools_url = browser->GetHost()->GetDevToolsURL(true);
if (devtools_url.empty() ||
m_OpenDevToolsURLs.find(devtools_url) != m_OpenDevToolsURLs.end()) {
// Disable the menu option if DevTools isn't enabled or if a window is
// already open for the current URL.
model->SetEnabled(CLIENT_ID_SHOW_DEVTOOLS, false);
}
// Test context menu features.
BuildTestMenu(model);
}
}
bool ClientHandler::OnContextMenuCommand(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
int command_id,
EventFlags event_flags) {
switch (command_id) {
case CLIENT_ID_SHOW_DEVTOOLS:
ShowDevTools(browser);
return true;
default: // Allow default handling, if any.
return ExecuteTestMenu(command_id);
}
}
void ClientHandler::OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
bool isLoading,
bool canGoBack,
bool canGoForward) {
REQUIRE_UI_THREAD();
SetLoading(isLoading);
SetNavState(canGoBack, canGoForward);
}
bool ClientHandler::OnConsoleMessage(CefRefPtr<CefBrowser> browser,
const CefString& message,
const CefString& source,
int line) {
REQUIRE_UI_THREAD();
bool first_message;
std::string logFile;
{
AutoLock lock_scope(this);
first_message = m_LogFile.empty();
if (first_message) {
std::stringstream ss;
ss << AppGetWorkingDirectory();
#if defined(OS_WIN)
ss << "\\";
#else
ss << "/";
#endif
ss << "console.log";
m_LogFile = ss.str();
}
logFile = m_LogFile;
}
FILE* file = fopen(logFile.c_str(), "a");
if (file) {
std::stringstream ss;
ss << "Message: " << std::string(message) << "\r\nSource: " <<
std::string(source) << "\r\nLine: " << line <<
"\r\n-----------------------\r\n";
fputs(ss.str().c_str(), file);
fclose(file);
if (first_message)
SendNotification(NOTIFY_CONSOLE_MESSAGE);
}
return false;
}
void ClientHandler::OnRequestGeolocationPermission(
CefRefPtr<CefBrowser> browser,
const CefString& requesting_url,
int request_id,
CefRefPtr<CefGeolocationCallback> callback) {
// Allow geolocation access from all websites.
callback->Continue(true);
}
bool ClientHandler::OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent& event,
CefEventHandle os_event,
bool* is_keyboard_shortcut) {
ASSERT(m_bFocusOnEditableField == event.focus_on_editable_field);
if (!event.focus_on_editable_field && event.windows_key_code == 0x20) {
// Special handling for the space character when an input element does not
// have focus. Handling the event in OnPreKeyEvent() keeps the event from
// being processed in the renderer. If we instead handled the event in the
// OnKeyEvent() method the space key would cause the window to scroll in
// addition to showing the alert box.
if (event.type == KEYEVENT_RAWKEYDOWN) {
browser->GetMainFrame()->ExecuteJavaScript(
"alert('You pressed the space bar!');", "", 0);
}
return true;
}
return false;
}
void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
REQUIRE_UI_THREAD();
@@ -194,108 +329,6 @@ CefRefPtr<CefResourceHandler> ClientHandler::GetResourceHandler(
return handler;
}
void ClientHandler::OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
bool isLoading,
bool canGoBack,
bool canGoForward) {
REQUIRE_UI_THREAD();
SetLoading(isLoading);
SetNavState(canGoBack, canGoForward);
}
bool ClientHandler::OnConsoleMessage(CefRefPtr<CefBrowser> browser,
const CefString& message,
const CefString& source,
int line) {
REQUIRE_UI_THREAD();
bool first_message;
std::string logFile;
{
AutoLock lock_scope(this);
first_message = m_LogFile.empty();
if (first_message) {
std::stringstream ss;
ss << AppGetWorkingDirectory();
#if defined(OS_WIN)
ss << "\\";
#else
ss << "/";
#endif
ss << "console.log";
m_LogFile = ss.str();
}
logFile = m_LogFile;
}
FILE* file = fopen(logFile.c_str(), "a");
if (file) {
std::stringstream ss;
ss << "Message: " << std::string(message) << "\r\nSource: " <<
std::string(source) << "\r\nLine: " << line <<
"\r\n-----------------------\r\n";
fputs(ss.str().c_str(), file);
fclose(file);
if (first_message)
SendNotification(NOTIFY_CONSOLE_MESSAGE);
}
return false;
}
void ClientHandler::OnRequestGeolocationPermission(
CefRefPtr<CefBrowser> browser,
const CefString& requesting_url,
int request_id,
CefRefPtr<CefGeolocationCallback> callback) {
// Allow geolocation access from all websites.
callback->Continue(true);
}
void ClientHandler::OnBeforeContextMenu(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model) {
if ((params->GetTypeFlags() & (CM_TYPEFLAG_PAGE | CM_TYPEFLAG_FRAME)) != 0) {
// Add a separator if the menu already has items.
if (model->GetCount() > 0)
model->AddSeparator();
// Add a "Show DevTools" item to all context menus.
model->AddItem(CLIENT_ID_SHOW_DEVTOOLS, "&Show DevTools");
CefString devtools_url = browser->GetHost()->GetDevToolsURL(true);
if (devtools_url.empty() ||
m_OpenDevToolsURLs.find(devtools_url) != m_OpenDevToolsURLs.end()) {
// Disable the menu option if DevTools isn't enabled or if a window is
// already open for the current URL.
model->SetEnabled(CLIENT_ID_SHOW_DEVTOOLS, false);
}
// Test context menu features.
BuildTestMenu(model);
}
}
bool ClientHandler::OnContextMenuCommand(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
int command_id,
EventFlags event_flags) {
switch (command_id) {
case CLIENT_ID_SHOW_DEVTOOLS:
ShowDevTools(browser);
return true;
default: // Allow default handling, if any.
return ExecuteTestMenu(command_id);
}
}
void ClientHandler::SetMainHwnd(CefWindowHandle hwnd) {
AutoLock lock_scope(this);
m_MainHwnd = hwnd;

View File

@@ -20,12 +20,13 @@
// ClientHandler implementation.
class ClientHandler : public CefClient,
public CefLifeSpanHandler,
public CefLoadHandler,
public CefRequestHandler,
public CefContextMenuHandler,
public CefDisplayHandler,
public CefGeolocationHandler,
public CefContextMenuHandler {
public CefKeyboardHandler,
public CefLifeSpanHandler,
public CefLoadHandler,
public CefRequestHandler {
public:
// Interface for process message delegates. Do not perform work in the
// RenderDelegate constructor.
@@ -67,6 +68,18 @@ class ClientHandler : public CefClient,
virtual ~ClientHandler();
// CefClient methods
virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefGeolocationHandler> GetGeolocationHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() OVERRIDE {
return this;
}
@@ -76,48 +89,21 @@ class ClientHandler : public CefClient,
virtual CefRefPtr<CefRequestHandler> GetRequestHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefDisplayHandler> GetDisplayHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefGeolocationHandler> GetGeolocationHandler() OVERRIDE {
return this;
}
virtual CefRefPtr<CefContextMenuHandler> GetContextMenuHandler() OVERRIDE {
return this;
}
virtual bool OnProcessMessageRecieved(CefRefPtr<CefBrowser> browser,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message)
OVERRIDE;
// CefLifeSpanHandler methods
virtual bool OnBeforePopup(CefRefPtr<CefBrowser> parentBrowser,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
const CefString& url,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) OVERRIDE;
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
// CefLoadHandler methods
virtual void OnLoadStart(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame) OVERRIDE;
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) OVERRIDE;
virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) OVERRIDE;
// CefRequestHandler methods
virtual CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) OVERRIDE;
// CefContextMenuHandler methods
virtual void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model) OVERRIDE;
virtual bool OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
int command_id,
EventFlags event_flags) OVERRIDE;
// CefDisplayHandler methods
virtual void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
@@ -141,16 +127,34 @@ class ClientHandler : public CefClient,
int request_id,
CefRefPtr<CefGeolocationCallback> callback) OVERRIDE;
// CefContextMenuHandler methods
virtual void OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
CefRefPtr<CefMenuModel> model) OVERRIDE;
virtual bool OnContextMenuCommand(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefContextMenuParams> params,
int command_id,
EventFlags event_flags) OVERRIDE;
// CefKeyboardHandler methods
virtual bool OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
const CefKeyEvent& event,
CefEventHandle os_event,
bool* is_keyboard_shortcut) OVERRIDE;
// CefLifeSpanHandler methods
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
virtual void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
// CefLoadHandler methods
virtual void OnLoadStart(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame) OVERRIDE;
virtual void OnLoadEnd(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int httpStatusCode) OVERRIDE;
virtual void OnLoadError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
ErrorCode errorCode,
const CefString& errorText,
const CefString& failedUrl) OVERRIDE;
// CefRequestHandler methods
virtual CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) OVERRIDE;
void SetMainHwnd(CefWindowHandle hwnd);
CefWindowHandle GetMainHwnd() { return m_MainHwnd; }
@@ -224,8 +228,8 @@ class ClientHandler : public CefClient,
// Support for downloading files.
std::string m_LastDownloadFile;
// True if a form element currently has focus
bool m_bFormElementHasFocus;
// True if an editable field currently has focus.
bool m_bFocusOnEditableField;
// Registered delegates.
ProcessMessageDelegateSet process_message_delegates_;

View File

@@ -8,18 +8,6 @@
#include "include/cef_browser.h"
#include "include/cef_frame.h"
// ClientHandler::ClientLifeSpanHandler implementation
bool ClientHandler::OnBeforePopup(CefRefPtr<CefBrowser> parentBrowser,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
const CefString& url,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
REQUIRE_UI_THREAD();
return false;
}
void ClientHandler::OnAddressChange(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& url) {

View File

@@ -9,19 +9,6 @@
#include "include/cef_frame.h"
#include "cefclient/cefclient.h"
// ClientHandler::ClientLifeSpanHandler implementation
bool ClientHandler::OnBeforePopup(CefRefPtr<CefBrowser> parentBrowser,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
const CefString& url,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
REQUIRE_UI_THREAD();
return false;
}
void ClientHandler::OnAddressChange(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& url) {

View File

@@ -8,17 +8,6 @@
#include "include/cef_frame.h"
#include "cefclient/resource.h"
bool ClientHandler::OnBeforePopup(CefRefPtr<CefBrowser> parentBrowser,
const CefPopupFeatures& popupFeatures,
CefWindowInfo& windowInfo,
const CefString& url,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings) {
REQUIRE_UI_THREAD();
return false;
}
void ClientHandler::OnAddressChange(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const CefString& url) {

View File

@@ -0,0 +1,52 @@
// Copyright (c) 2012 The Chromium Embedded Framework 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 "cefclient/client_renderer.h"
#include <sstream>
#include <string>
#include "include/cef_dom.h"
#include "cefclient/util.h"
namespace client_renderer {
const char kFocusedNodeChangedMessage[] = "ClientRenderer.FocusedNodeChanged";
namespace {
class ClientRenderDelegate : public ClientApp::RenderDelegate {
public:
ClientRenderDelegate()
: last_node_is_editable_(false) {
}
virtual void OnFocusedNodeChanged(CefRefPtr<ClientApp> app,
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefDOMNode> node) OVERRIDE {
bool is_editable = (node.get() && node->IsEditable());
if (is_editable != last_node_is_editable_) {
// Notify the browser of the change in focused element type.
last_node_is_editable_ = is_editable;
CefRefPtr<CefProcessMessage> message =
CefProcessMessage::Create(kFocusedNodeChangedMessage);
message->GetArgumentList()->SetBool(0, is_editable);
browser->SendProcessMessage(PID_BROWSER, message);
}
}
private:
bool last_node_is_editable_;
IMPLEMENT_REFCOUNTING(ClientRenderDelegate);
};
} // namespace
void CreateRenderDelegates(ClientApp::RenderDelegateSet& delegates) {
delegates.insert(new ClientRenderDelegate);
}
} // namespace client_renderer

View File

@@ -0,0 +1,22 @@
// Copyright (c) 2012 The Chromium Embedded Framework 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 CEF_TESTS_CEFCLIENT_CLIENT_RENDERER_H_
#define CEF_TESTS_CEFCLIENT_CLIENT_RENDERER_H_
#pragma once
#include "include/cef_base.h"
#include "cefclient/client_app.h"
namespace client_renderer {
// Message sent when the focused node changes.
extern const char kFocusedNodeChangedMessage[];
// Create the render delegate.
void CreateRenderDelegates(ClientApp::RenderDelegateSet& delegates);
} // namespace client_renderer
#endif // CEF_TESTS_CEFCLIENT_CLIENT_RENDERER_H_