mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
- Factor platform-specific code out of CefBrowserHostImpl (issue #1749).
- Introduce native/ and osr/ folders for native (non-platform-agnostic) and osr (windowless) code respectively. - Introduce CefBrowserPlatformDelegate for abstracting platform-specific implementations of browser host functionality. - Move dialog and menu code to separate manager and platform-specific runner implementations exposed via CefBrowserPlatformDelegate. - Standardize focus-handling behavior between windowed and windowless implementations. CefFocusHandler::OnSetFocus() will now also be called for osr focus changes. - Support multiple simultaneous popups (issue #1289).
This commit is contained in:
89
cef.gyp
89
cef.gyp
@ -958,12 +958,17 @@
|
|||||||
'libcef/browser/browser_host_impl.h',
|
'libcef/browser/browser_host_impl.h',
|
||||||
'libcef/browser/browser_info.cc',
|
'libcef/browser/browser_info.cc',
|
||||||
'libcef/browser/browser_info.h',
|
'libcef/browser/browser_info.h',
|
||||||
|
'libcef/browser/browser_info_manager.cc',
|
||||||
|
'libcef/browser/browser_info_manager.h',
|
||||||
'libcef/browser/browser_main.cc',
|
'libcef/browser/browser_main.cc',
|
||||||
'libcef/browser/browser_main.h',
|
'libcef/browser/browser_main.h',
|
||||||
'libcef/browser/browser_message_filter.cc',
|
'libcef/browser/browser_message_filter.cc',
|
||||||
'libcef/browser/browser_message_filter.h',
|
'libcef/browser/browser_message_filter.h',
|
||||||
'libcef/browser/browser_message_loop.cc',
|
'libcef/browser/browser_message_loop.cc',
|
||||||
'libcef/browser/browser_message_loop.h',
|
'libcef/browser/browser_message_loop.h',
|
||||||
|
'libcef/browser/browser_platform_delegate.cc',
|
||||||
|
'libcef/browser/browser_platform_delegate.h',
|
||||||
|
'libcef/browser/browser_platform_delegate_create.cc',
|
||||||
'libcef/browser/browser_urlrequest_impl.cc',
|
'libcef/browser/browser_urlrequest_impl.cc',
|
||||||
'libcef/browser/browser_urlrequest_impl.h',
|
'libcef/browser/browser_urlrequest_impl.h',
|
||||||
'libcef/browser/chrome_browser_process_stub.cc',
|
'libcef/browser/chrome_browser_process_stub.cc',
|
||||||
@ -1022,26 +1027,42 @@
|
|||||||
'libcef/browser/extensions/pdf_web_contents_helper_client.h',
|
'libcef/browser/extensions/pdf_web_contents_helper_client.h',
|
||||||
'libcef/browser/extensions/url_request_util.cc',
|
'libcef/browser/extensions/url_request_util.cc',
|
||||||
'libcef/browser/extensions/url_request_util.h',
|
'libcef/browser/extensions/url_request_util.h',
|
||||||
|
'libcef/browser/file_dialog_runner.h',
|
||||||
|
'libcef/browser/file_dialog_manager.cc',
|
||||||
|
'libcef/browser/file_dialog_manager.h',
|
||||||
'libcef/browser/frame_host_impl.cc',
|
'libcef/browser/frame_host_impl.cc',
|
||||||
'libcef/browser/frame_host_impl.h',
|
'libcef/browser/frame_host_impl.h',
|
||||||
'libcef/browser/geolocation_impl.cc',
|
'libcef/browser/geolocation_impl.cc',
|
||||||
'libcef/browser/internal_scheme_handler.cc',
|
'libcef/browser/internal_scheme_handler.cc',
|
||||||
'libcef/browser/internal_scheme_handler.h',
|
'libcef/browser/internal_scheme_handler.h',
|
||||||
'libcef/browser/javascript_dialog.h',
|
'libcef/browser/javascript_dialog_runner.h',
|
||||||
'libcef/browser/javascript_dialog_manager.cc',
|
'libcef/browser/javascript_dialog_manager.cc',
|
||||||
'libcef/browser/javascript_dialog_manager.h',
|
'libcef/browser/javascript_dialog_manager.h',
|
||||||
'libcef/browser/media_capture_devices_dispatcher.cc',
|
'libcef/browser/media_capture_devices_dispatcher.cc',
|
||||||
'libcef/browser/media_capture_devices_dispatcher.h',
|
'libcef/browser/media_capture_devices_dispatcher.h',
|
||||||
'libcef/browser/menu_creator.cc',
|
'libcef/browser/menu_manager.cc',
|
||||||
'libcef/browser/menu_creator.h',
|
'libcef/browser/menu_manager.h',
|
||||||
'libcef/browser/menu_model_impl.cc',
|
'libcef/browser/menu_model_impl.cc',
|
||||||
'libcef/browser/menu_model_impl.h',
|
'libcef/browser/menu_model_impl.h',
|
||||||
|
'libcef/browser/menu_runner.h',
|
||||||
|
'libcef/browser/native/browser_platform_delegate_native.cc',
|
||||||
|
'libcef/browser/native/browser_platform_delegate_native.h',
|
||||||
'libcef/browser/navigate_params.cc',
|
'libcef/browser/navigate_params.cc',
|
||||||
'libcef/browser/navigate_params.h',
|
'libcef/browser/navigate_params.h',
|
||||||
'libcef/browser/navigation_entry_impl.cc',
|
'libcef/browser/navigation_entry_impl.cc',
|
||||||
'libcef/browser/navigation_entry_impl.h',
|
'libcef/browser/navigation_entry_impl.h',
|
||||||
'libcef/browser/origin_whitelist_impl.cc',
|
'libcef/browser/origin_whitelist_impl.cc',
|
||||||
'libcef/browser/origin_whitelist_impl.h',
|
'libcef/browser/origin_whitelist_impl.h',
|
||||||
|
'libcef/browser/osr/browser_platform_delegate_osr.cc',
|
||||||
|
'libcef/browser/osr/browser_platform_delegate_osr.h',
|
||||||
|
'libcef/browser/osr/osr_util.cc',
|
||||||
|
'libcef/browser/osr/osr_util.h',
|
||||||
|
'libcef/browser/osr/render_widget_host_view_osr.cc',
|
||||||
|
'libcef/browser/osr/render_widget_host_view_osr.h',
|
||||||
|
'libcef/browser/osr/software_output_device_osr.cc',
|
||||||
|
'libcef/browser/osr/software_output_device_osr.h',
|
||||||
|
'libcef/browser/osr/web_contents_view_osr.cc',
|
||||||
|
'libcef/browser/osr/web_contents_view_osr.h',
|
||||||
'libcef/browser/path_util_impl.cc',
|
'libcef/browser/path_util_impl.cc',
|
||||||
'libcef/browser/pepper/browser_pepper_host_factory.cc',
|
'libcef/browser/pepper/browser_pepper_host_factory.cc',
|
||||||
'libcef/browser/pepper/browser_pepper_host_factory.h',
|
'libcef/browser/pepper/browser_pepper_host_factory.h',
|
||||||
@ -1074,8 +1095,6 @@
|
|||||||
'libcef/browser/printing/print_view_manager_base.h',
|
'libcef/browser/printing/print_view_manager_base.h',
|
||||||
'libcef/browser/process_util_impl.cc',
|
'libcef/browser/process_util_impl.cc',
|
||||||
'libcef/browser/proxy_stubs.cc',
|
'libcef/browser/proxy_stubs.cc',
|
||||||
'libcef/browser/render_widget_host_view_osr.cc',
|
|
||||||
'libcef/browser/render_widget_host_view_osr.h',
|
|
||||||
'libcef/browser/resource_context.cc',
|
'libcef/browser/resource_context.cc',
|
||||||
'libcef/browser/resource_context.h',
|
'libcef/browser/resource_context.h',
|
||||||
'libcef/browser/resource_dispatcher_host_delegate.cc',
|
'libcef/browser/resource_dispatcher_host_delegate.cc',
|
||||||
@ -1087,8 +1106,6 @@
|
|||||||
'libcef/browser/scheme_handler.cc',
|
'libcef/browser/scheme_handler.cc',
|
||||||
'libcef/browser/scheme_handler.h',
|
'libcef/browser/scheme_handler.h',
|
||||||
'libcef/browser/scheme_impl.cc',
|
'libcef/browser/scheme_impl.cc',
|
||||||
'libcef/browser/software_output_device_osr.cc',
|
|
||||||
'libcef/browser/software_output_device_osr.h',
|
|
||||||
'libcef/browser/speech_recognition_manager_delegate.cc',
|
'libcef/browser/speech_recognition_manager_delegate.cc',
|
||||||
'libcef/browser/speech_recognition_manager_delegate.h',
|
'libcef/browser/speech_recognition_manager_delegate.h',
|
||||||
'libcef/browser/ssl_cert_principal_impl.cc',
|
'libcef/browser/ssl_cert_principal_impl.cc',
|
||||||
@ -1121,8 +1138,6 @@
|
|||||||
'libcef/browser/url_request_interceptor.h',
|
'libcef/browser/url_request_interceptor.h',
|
||||||
'libcef/browser/url_request_user_data.cc',
|
'libcef/browser/url_request_user_data.cc',
|
||||||
'libcef/browser/url_request_user_data.h',
|
'libcef/browser/url_request_user_data.h',
|
||||||
'libcef/browser/web_contents_view_osr.cc',
|
|
||||||
'libcef/browser/web_contents_view_osr.h',
|
|
||||||
'libcef/browser/web_plugin_impl.cc',
|
'libcef/browser/web_plugin_impl.cc',
|
||||||
'libcef/browser/web_plugin_impl.h',
|
'libcef/browser/web_plugin_impl.h',
|
||||||
'libcef/browser/xml_reader_impl.cc',
|
'libcef/browser/xml_reader_impl.cc',
|
||||||
@ -1398,12 +1413,18 @@
|
|||||||
['OS=="win"', {
|
['OS=="win"', {
|
||||||
'sources': [
|
'sources': [
|
||||||
'<@(includes_win)',
|
'<@(includes_win)',
|
||||||
'libcef/browser/browser_host_impl_win.cc',
|
|
||||||
'libcef/browser/browser_main_win.cc',
|
'libcef/browser/browser_main_win.cc',
|
||||||
'libcef/browser/javascript_dialog_win.cc',
|
'libcef/browser/native/browser_platform_delegate_native_win.cc',
|
||||||
'libcef/browser/menu_creator_runner_win.cc',
|
'libcef/browser/native/browser_platform_delegate_native_win.h',
|
||||||
'libcef/browser/menu_creator_runner_win.h',
|
'libcef/browser/native/file_dialog_runner_win.cc',
|
||||||
'libcef/browser/render_widget_host_view_osr_win.cc',
|
'libcef/browser/native/file_dialog_runner_win.h',
|
||||||
|
'libcef/browser/native/javascript_dialog_runner_win.cc',
|
||||||
|
'libcef/browser/native/javascript_dialog_runner_win.h',
|
||||||
|
'libcef/browser/native/menu_runner_win.cc',
|
||||||
|
'libcef/browser/native/menu_runner_win.h',
|
||||||
|
'libcef/browser/osr/browser_platform_delegate_osr_win.cc',
|
||||||
|
'libcef/browser/osr/browser_platform_delegate_osr_win.h',
|
||||||
|
'libcef/browser/osr/render_widget_host_view_osr_win.cc',
|
||||||
# Include sources for printing using PDF.
|
# Include sources for printing using PDF.
|
||||||
'libcef/utility/printing_handler.cc',
|
'libcef/utility/printing_handler.cc',
|
||||||
'libcef/utility/printing_handler.h',
|
'libcef/utility/printing_handler.h',
|
||||||
@ -1418,13 +1439,19 @@
|
|||||||
[ 'OS=="mac"', {
|
[ 'OS=="mac"', {
|
||||||
'sources': [
|
'sources': [
|
||||||
'<@(includes_mac)',
|
'<@(includes_mac)',
|
||||||
'libcef/browser/browser_host_impl_mac.mm',
|
'libcef/browser/native/browser_platform_delegate_native_mac.h',
|
||||||
'libcef/browser/javascript_dialog_mac.mm',
|
'libcef/browser/native/browser_platform_delegate_native_mac.mm',
|
||||||
'libcef/browser/menu_creator_runner_mac.h',
|
'libcef/browser/native/file_dialog_runner_mac.h',
|
||||||
'libcef/browser/menu_creator_runner_mac.mm',
|
'libcef/browser/native/file_dialog_runner_mac.mm',
|
||||||
'libcef/browser/render_widget_host_view_osr_mac.mm',
|
'libcef/browser/native/javascript_dialog_runner_mac.h',
|
||||||
'libcef/browser/text_input_client_osr_mac.mm',
|
'libcef/browser/native/javascript_dialog_runner_mac.mm',
|
||||||
'libcef/browser/text_input_client_osr_mac.h',
|
'libcef/browser/native/menu_runner_mac.h',
|
||||||
|
'libcef/browser/native/menu_runner_mac.mm',
|
||||||
|
'libcef/browser/osr/browser_platform_delegate_osr_mac.h',
|
||||||
|
'libcef/browser/osr/browser_platform_delegate_osr_mac.mm',
|
||||||
|
'libcef/browser/osr/render_widget_host_view_osr_mac.mm',
|
||||||
|
'libcef/browser/osr/text_input_client_osr_mac.mm',
|
||||||
|
'libcef/browser/osr/text_input_client_osr_mac.h',
|
||||||
'libcef/common/util_mac.h',
|
'libcef/common/util_mac.h',
|
||||||
'libcef/common/util_mac.mm',
|
'libcef/common/util_mac.mm',
|
||||||
# Include sources for spell checking support.
|
# Include sources for spell checking support.
|
||||||
@ -1442,15 +1469,17 @@
|
|||||||
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
|
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
|
||||||
'sources': [
|
'sources': [
|
||||||
'<@(includes_linux)',
|
'<@(includes_linux)',
|
||||||
'libcef/browser/browser_host_impl_linux.cc',
|
'libcef/browser/native/browser_platform_delegate_native_linux.cc',
|
||||||
'libcef/browser/javascript_dialog_linux.cc',
|
'libcef/browser/native/browser_platform_delegate_native_linux.h',
|
||||||
'libcef/browser/menu_creator_runner_linux.cc',
|
'libcef/browser/native/menu_runner_linux.cc',
|
||||||
'libcef/browser/menu_creator_runner_linux.h',
|
'libcef/browser/native/menu_runner_linux.h',
|
||||||
|
'libcef/browser/osr/browser_platform_delegate_osr_linux.cc',
|
||||||
|
'libcef/browser/osr/browser_platform_delegate_osr_linux.h',
|
||||||
|
'libcef/browser/osr/render_widget_host_view_osr_linux.cc',
|
||||||
'libcef/browser/printing/print_dialog_linux.cc',
|
'libcef/browser/printing/print_dialog_linux.cc',
|
||||||
'libcef/browser/printing/print_dialog_linux.h',
|
'libcef/browser/printing/print_dialog_linux.h',
|
||||||
'libcef/browser/render_widget_host_view_osr_linux.cc',
|
'libcef/browser/native/window_x11.cc',
|
||||||
'libcef/browser/window_x11.cc',
|
'libcef/browser/native/window_x11.h',
|
||||||
'libcef/browser/window_x11.h',
|
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
['os_posix == 1 and OS != "mac"', {
|
['os_posix == 1 and OS != "mac"', {
|
||||||
@ -1469,8 +1498,8 @@
|
|||||||
'<(DEPTH)/ui/views/views.gyp:views',
|
'<(DEPTH)/ui/views/views.gyp:views',
|
||||||
],
|
],
|
||||||
'sources': [
|
'sources': [
|
||||||
'libcef/browser/window_delegate_view.cc',
|
'libcef/browser/native/window_delegate_view.cc',
|
||||||
'libcef/browser/window_delegate_view.h',
|
'libcef/browser/native/window_delegate_view.h',
|
||||||
'<(DEPTH)/ui/views/test/desktop_test_views_delegate.h',
|
'<(DEPTH)/ui/views/test/desktop_test_views_delegate.h',
|
||||||
'<(DEPTH)/ui/views/test/desktop_test_views_delegate_aura.cc',
|
'<(DEPTH)/ui/views/test/desktop_test_views_delegate_aura.cc',
|
||||||
'<(DEPTH)/ui/views/test/test_views_delegate.h',
|
'<(DEPTH)/ui/views/test/test_views_delegate.h',
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -16,9 +16,11 @@
|
|||||||
#include "include/cef_client.h"
|
#include "include/cef_client.h"
|
||||||
#include "include/cef_frame.h"
|
#include "include/cef_frame.h"
|
||||||
#include "libcef/browser/browser_info.h"
|
#include "libcef/browser/browser_info.h"
|
||||||
|
#include "libcef/browser/browser_platform_delegate.h"
|
||||||
|
#include "libcef/browser/file_dialog_manager.h"
|
||||||
#include "libcef/browser/frame_host_impl.h"
|
#include "libcef/browser/frame_host_impl.h"
|
||||||
#include "libcef/browser/javascript_dialog_manager.h"
|
#include "libcef/browser/javascript_dialog_manager.h"
|
||||||
#include "libcef/browser/menu_creator.h"
|
#include "libcef/browser/menu_manager.h"
|
||||||
#include "libcef/common/response_manager.h"
|
#include "libcef/common/response_manager.h"
|
||||||
|
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "base/memory/scoped_ptr.h"
|
||||||
@ -29,42 +31,11 @@
|
|||||||
#include "content/public/browser/web_contents.h"
|
#include "content/public/browser/web_contents.h"
|
||||||
#include "content/public/browser/web_contents_delegate.h"
|
#include "content/public/browser/web_contents_delegate.h"
|
||||||
#include "content/public/browser/web_contents_observer.h"
|
#include "content/public/browser/web_contents_observer.h"
|
||||||
#include "content/public/common/file_chooser_params.h"
|
|
||||||
|
|
||||||
#if defined(USE_AURA)
|
|
||||||
#include "third_party/WebKit/public/platform/WebCursorInfo.h"
|
|
||||||
#include "ui/base/cursor/cursor.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_X11)
|
|
||||||
#include "ui/base/x/x11_util.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace content {
|
|
||||||
struct NativeWebKeyboardEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace blink {
|
|
||||||
class WebMouseEvent;
|
|
||||||
class WebMouseWheelEvent;
|
|
||||||
class WebInputEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace net {
|
namespace net {
|
||||||
class DirectoryLister;
|
|
||||||
class URLRequest;
|
class URLRequest;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USE_AURA)
|
|
||||||
namespace views {
|
|
||||||
class Widget;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_X11)
|
|
||||||
class CefWindowX11;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct Cef_DraggableRegion_Params;
|
struct Cef_DraggableRegion_Params;
|
||||||
struct Cef_Request_Params;
|
struct Cef_Request_Params;
|
||||||
struct Cef_Response_Params;
|
struct Cef_Response_Params;
|
||||||
@ -100,18 +71,6 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
virtual void OnResponse(const std::string& response) =0;
|
virtual void OnResponse(const std::string& response) =0;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Extend content::FileChooserParams with some options unique to CEF.
|
|
||||||
struct FileChooserParams : public content::FileChooserParams {
|
|
||||||
// 0-based index of the selected value in |accept_types|.
|
|
||||||
int selected_accept_filter = 0;
|
|
||||||
|
|
||||||
// True if the Save dialog should prompt before overwriting files.
|
|
||||||
bool overwriteprompt = true;
|
|
||||||
|
|
||||||
// True if read-only files should be hidden.
|
|
||||||
bool hidereadonly = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
~CefBrowserHostImpl() override;
|
~CefBrowserHostImpl() override;
|
||||||
|
|
||||||
// Create a new CefBrowserHostImpl instance.
|
// Create a new CefBrowserHostImpl instance.
|
||||||
@ -120,7 +79,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
CefRefPtr<CefClient> client,
|
CefRefPtr<CefClient> client,
|
||||||
const CefString& url,
|
const CefString& url,
|
||||||
const CefBrowserSettings& settings,
|
const CefBrowserSettings& settings,
|
||||||
CefWindowHandle opener,
|
CefRefPtr<CefBrowserHostImpl> opener,
|
||||||
bool is_popup,
|
bool is_popup,
|
||||||
CefRefPtr<CefRequestContext> request_context);
|
CefRefPtr<CefRequestContext> request_context);
|
||||||
|
|
||||||
@ -239,8 +198,6 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
|
|
||||||
// Returns true if windowless rendering is enabled.
|
// Returns true if windowless rendering is enabled.
|
||||||
bool IsWindowless() const;
|
bool IsWindowless() const;
|
||||||
// Returns true if transparent painting is enabled.
|
|
||||||
bool IsTransparent() const;
|
|
||||||
|
|
||||||
// Called when the OS window hosting the browser is destroyed.
|
// Called when the OS window hosting the browser is destroyed.
|
||||||
void WindowDestroyed();
|
void WindowDestroyed();
|
||||||
@ -252,11 +209,11 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
// Cancel display of the context menu, if any.
|
// Cancel display of the context menu, if any.
|
||||||
void CancelContextMenu();
|
void CancelContextMenu();
|
||||||
|
|
||||||
// Returns the native view for the WebContents.
|
#if defined(USE_AURA)
|
||||||
gfx::NativeView GetContentView() const;
|
// Returns the Widget owner for the browser window. Only used with windowed
|
||||||
|
// rendering.
|
||||||
// Returns a pointer to the WebContents.
|
views::Widget* GetWindowWidget() const;
|
||||||
content::WebContents* GetWebContents() const;
|
#endif
|
||||||
|
|
||||||
// Returns the frame associated with the specified URLRequest.
|
// Returns the frame associated with the specified URLRequest.
|
||||||
CefRefPtr<CefFrame> GetFrameForRequest(net::URLRequest* request);
|
CefRefPtr<CefFrame> GetFrameForRequest(net::URLRequest* request);
|
||||||
@ -293,7 +250,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
bool user_initiated);
|
bool user_initiated);
|
||||||
|
|
||||||
// Open the specified text in the default text editor.
|
// Open the specified text in the default text editor.
|
||||||
bool ViewText(const std::string& text);
|
void ViewText(const std::string& text);
|
||||||
|
|
||||||
// Handler for URLs involving external protocols.
|
// Handler for URLs involving external protocols.
|
||||||
void HandleExternalProtocol(const GURL& url);
|
void HandleExternalProtocol(const GURL& url);
|
||||||
@ -301,39 +258,23 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
// Set the frame that currently has focus.
|
// Set the frame that currently has focus.
|
||||||
void SetFocusedFrame(int64 frame_id);
|
void SetFocusedFrame(int64 frame_id);
|
||||||
|
|
||||||
|
// Convert from view coordinates to screen coordinates.
|
||||||
|
gfx::Point GetScreenPoint(const gfx::Point& view) const;
|
||||||
|
|
||||||
// Thread safe accessors.
|
// Thread safe accessors.
|
||||||
const CefBrowserSettings& settings() const { return settings_; }
|
const CefBrowserSettings& settings() const { return settings_; }
|
||||||
CefRefPtr<CefClient> client() const { return client_; }
|
CefRefPtr<CefClient> client() const { return client_; }
|
||||||
scoped_refptr<CefBrowserInfo> browser_info() const { return browser_info_; }
|
scoped_refptr<CefBrowserInfo> browser_info() const { return browser_info_; }
|
||||||
int browser_id() const;
|
int browser_id() const;
|
||||||
|
|
||||||
#if defined(USE_AURA)
|
|
||||||
views::Widget* window_widget() const { return window_widget_; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_X11)
|
|
||||||
CefWindowX11* window_x11() const { return window_x11_; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
static void RegisterWindowClass();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(USE_AURA)
|
|
||||||
ui::PlatformCursor GetPlatformCursor(blink::WebCursorInfo::Type type);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void OnSetFocus(cef_focus_source_t source);
|
void OnSetFocus(cef_focus_source_t source);
|
||||||
|
|
||||||
// The argument vector will be empty if the dialog was cancelled.
|
|
||||||
typedef base::Callback<void(int, const std::vector<base::FilePath>&)>
|
|
||||||
RunFileChooserCallback;
|
|
||||||
|
|
||||||
// Run the file chooser dialog specified by |params|. Only a single dialog may
|
// Run the file chooser dialog specified by |params|. Only a single dialog may
|
||||||
// be pending at any given time. |callback| will be executed asynchronously
|
// be pending at any given time. |callback| will be executed asynchronously
|
||||||
// after the dialog is dismissed or if another dialog is already pending.
|
// after the dialog is dismissed or if another dialog is already pending.
|
||||||
void RunFileChooser(const FileChooserParams& params,
|
void RunFileChooser(
|
||||||
const RunFileChooserCallback& callback);
|
const CefFileDialogRunner::FileChooserParams& params,
|
||||||
|
const CefFileDialogRunner::RunFileChooserCallback& callback);
|
||||||
|
|
||||||
bool HandleContextMenu(
|
bool HandleContextMenu(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
@ -345,15 +286,6 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
// Otherwise, the browser's WebContents will be returned.
|
// Otherwise, the browser's WebContents will be returned.
|
||||||
content::WebContents* GetActionableWebContents();
|
content::WebContents* GetActionableWebContents();
|
||||||
|
|
||||||
// Used when creating a new popup window.
|
|
||||||
struct PendingPopupInfo {
|
|
||||||
CefWindowInfo window_info;
|
|
||||||
CefBrowserSettings settings;
|
|
||||||
CefRefPtr<CefClient> client;
|
|
||||||
};
|
|
||||||
// Returns false if a popup is already pending.
|
|
||||||
bool SetPendingPopupInfo(scoped_ptr<PendingPopupInfo> info);
|
|
||||||
|
|
||||||
enum DestructionState {
|
enum DestructionState {
|
||||||
DESTRUCTION_STATE_NONE = 0,
|
DESTRUCTION_STATE_NONE = 0,
|
||||||
DESTRUCTION_STATE_PENDING,
|
DESTRUCTION_STATE_PENDING,
|
||||||
@ -488,13 +420,13 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
class DevToolsWebContentsObserver;
|
class DevToolsWebContentsObserver;
|
||||||
|
|
||||||
static CefRefPtr<CefBrowserHostImpl> CreateInternal(
|
static CefRefPtr<CefBrowserHostImpl> CreateInternal(
|
||||||
const CefWindowInfo& window_info,
|
|
||||||
const CefBrowserSettings& settings,
|
const CefBrowserSettings& settings,
|
||||||
CefRefPtr<CefClient> client,
|
CefRefPtr<CefClient> client,
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
scoped_refptr<CefBrowserInfo> browser_info,
|
scoped_refptr<CefBrowserInfo> browser_info,
|
||||||
CefWindowHandle opener,
|
CefRefPtr<CefBrowserHostImpl> opener,
|
||||||
CefRefPtr<CefRequestContext> request_context);
|
CefRefPtr<CefRequestContext> request_context,
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegate> platform_delegate);
|
||||||
|
|
||||||
// content::WebContentsObserver::OnMessageReceived() message handlers.
|
// content::WebContentsObserver::OnMessageReceived() message handlers.
|
||||||
void OnFrameIdentified(int64 frame_id,
|
void OnFrameIdentified(int64 frame_id,
|
||||||
@ -516,13 +448,16 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
const content::NotificationSource& source,
|
const content::NotificationSource& source,
|
||||||
const content::NotificationDetails& details) override;
|
const content::NotificationDetails& details) override;
|
||||||
|
|
||||||
CefBrowserHostImpl(const CefWindowInfo& window_info,
|
CefBrowserHostImpl(const CefBrowserSettings& settings,
|
||||||
const CefBrowserSettings& settings,
|
|
||||||
CefRefPtr<CefClient> client,
|
CefRefPtr<CefClient> client,
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
scoped_refptr<CefBrowserInfo> browser_info,
|
scoped_refptr<CefBrowserInfo> browser_info,
|
||||||
CefWindowHandle opener,
|
CefRefPtr<CefBrowserHostImpl> opener,
|
||||||
CefRefPtr<CefRequestContext> request_context);
|
CefRefPtr<CefRequestContext> request_context,
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegate> platform_delegate);
|
||||||
|
|
||||||
|
// Give the platform delegate an opportunity to create the host window.
|
||||||
|
bool CreateHostWindow();
|
||||||
|
|
||||||
// Updates and returns an existing frame or creates a new frame. Pass
|
// Updates and returns an existing frame or creates a new frame. Pass
|
||||||
// CefFrameHostImpl::kUnspecifiedFrameId for |parent_frame_id| if unknown.
|
// CefFrameHostImpl::kUnspecifiedFrameId for |parent_frame_id| if unknown.
|
||||||
@ -534,59 +469,6 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
// Remove the references to all frames and mark them as detached.
|
// Remove the references to all frames and mark them as detached.
|
||||||
void DetachAllFrames();
|
void DetachAllFrames();
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
static LPCTSTR GetWndClass();
|
|
||||||
static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
|
||||||
WPARAM wParam, LPARAM lParam);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Create the window.
|
|
||||||
bool PlatformCreateWindow();
|
|
||||||
// Sends a message via the OS to close the native browser window.
|
|
||||||
// DestroyBrowser will be called after the native window has closed.
|
|
||||||
void PlatformCloseWindow();
|
|
||||||
// Resize the window to the given dimensions.
|
|
||||||
void PlatformSizeTo(int width, int height);
|
|
||||||
// Set or remove focus from the window.
|
|
||||||
void PlatformSetFocus(bool focus);
|
|
||||||
#if defined(OS_MACOSX)
|
|
||||||
// Set or remove window visibility.
|
|
||||||
void PlatformSetWindowVisibility(bool visible);
|
|
||||||
#endif
|
|
||||||
// Return the handle for this window.
|
|
||||||
CefWindowHandle PlatformGetWindowHandle();
|
|
||||||
// Open the specified text in the default text editor.
|
|
||||||
bool PlatformViewText(const std::string& text);
|
|
||||||
// Forward the keyboard event to the application or frame window to allow
|
|
||||||
// processing of shortcut keys.
|
|
||||||
void PlatformHandleKeyboardEvent(
|
|
||||||
const content::NativeWebKeyboardEvent& event);
|
|
||||||
// Invoke platform specific handling for the external protocol.
|
|
||||||
void PlatformHandleExternalProtocol(const GURL& url);
|
|
||||||
// Invoke platform specific file chooser dialog.
|
|
||||||
void PlatformRunFileChooser(const FileChooserParams& params,
|
|
||||||
RunFileChooserCallback callback);
|
|
||||||
|
|
||||||
void PlatformTranslateKeyEvent(content::NativeWebKeyboardEvent& native_event,
|
|
||||||
const CefKeyEvent& key_event);
|
|
||||||
void PlatformTranslateClickEvent(blink::WebMouseEvent& web_event,
|
|
||||||
const CefMouseEvent& mouse_event,
|
|
||||||
CefBrowserHost::MouseButtonType type,
|
|
||||||
bool mouseUp, int clickCount);
|
|
||||||
void PlatformTranslateMoveEvent(blink::WebMouseEvent& web_event,
|
|
||||||
const CefMouseEvent& mouse_event,
|
|
||||||
bool mouseLeave);
|
|
||||||
void PlatformTranslateWheelEvent(blink::WebMouseWheelEvent& web_event,
|
|
||||||
const CefMouseEvent& mouse_event,
|
|
||||||
int deltaX, int deltaY);
|
|
||||||
void PlatformTranslateMouseEvent(blink::WebMouseEvent& web_event,
|
|
||||||
const CefMouseEvent& mouse_event);
|
|
||||||
|
|
||||||
void PlatformNotifyMoveOrResizeStarted();
|
|
||||||
|
|
||||||
int TranslateModifiers(uint32 cefKeyStates);
|
|
||||||
void SendMouseEvent(const blink::WebMouseEvent& web_event);
|
|
||||||
|
|
||||||
void OnAddressChange(CefRefPtr<CefFrame> frame,
|
void OnAddressChange(CefRefPtr<CefFrame> frame,
|
||||||
const GURL& url);
|
const GURL& url);
|
||||||
void OnLoadStart(CefRefPtr<CefFrame> frame,
|
void OnLoadStart(CefRefPtr<CefFrame> frame,
|
||||||
@ -602,44 +484,18 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
void OnFullscreenModeChange(bool fullscreen);
|
void OnFullscreenModeChange(bool fullscreen);
|
||||||
void OnTitleChange(const base::string16& title);
|
void OnTitleChange(const base::string16& title);
|
||||||
|
|
||||||
// Continuation from RunFileChooser.
|
|
||||||
void RunFileChooserOnUIThread(const FileChooserParams& params,
|
|
||||||
const RunFileChooserCallback& callback);
|
|
||||||
|
|
||||||
// Used with RunFileChooser to clear the |file_chooser_pending_| flag.
|
|
||||||
void OnRunFileChooserCallback(const RunFileChooserCallback& callback,
|
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<base::FilePath>& file_paths);
|
|
||||||
|
|
||||||
// Used with WebContentsDelegate::RunFileChooser when mode is
|
|
||||||
// content::FileChooserParams::UploadFolder.
|
|
||||||
void OnRunFileChooserUploadFolderDelegateCallback(
|
|
||||||
content::WebContents* web_contents,
|
|
||||||
const content::FileChooserParams::Mode mode,
|
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<base::FilePath>& file_paths);
|
|
||||||
|
|
||||||
// Used with WebContentsDelegate::RunFileChooser to notify the WebContents.
|
|
||||||
void OnRunFileChooserDelegateCallback(
|
|
||||||
content::WebContents* web_contents,
|
|
||||||
content::FileChooserParams::Mode mode,
|
|
||||||
int selected_accept_filter,
|
|
||||||
const std::vector<base::FilePath>& file_paths);
|
|
||||||
|
|
||||||
void OnDevToolsWebContentsDestroyed();
|
void OnDevToolsWebContentsDestroyed();
|
||||||
|
|
||||||
CefWindowInfo window_info_;
|
// Create the CefFileDialogManager if it doesn't already exist.
|
||||||
|
void EnsureFileDialogManager();
|
||||||
|
|
||||||
CefBrowserSettings settings_;
|
CefBrowserSettings settings_;
|
||||||
CefRefPtr<CefClient> client_;
|
CefRefPtr<CefClient> client_;
|
||||||
scoped_ptr<content::WebContents> web_contents_;
|
scoped_ptr<content::WebContents> web_contents_;
|
||||||
scoped_refptr<CefBrowserInfo> browser_info_;
|
scoped_refptr<CefBrowserInfo> browser_info_;
|
||||||
CefWindowHandle opener_;
|
CefWindowHandle opener_;
|
||||||
CefRefPtr<CefRequestContext> request_context_;
|
CefRefPtr<CefRequestContext> request_context_;
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegate> platform_delegate_;
|
||||||
// Pending popup information. Access must be protected by
|
|
||||||
// |pending_popup_info_lock_|.
|
|
||||||
base::Lock pending_popup_info_lock_;
|
|
||||||
scoped_ptr<PendingPopupInfo> pending_popup_info_;
|
|
||||||
|
|
||||||
// Volatile state information. All access must be protected by the state lock.
|
// Volatile state information. All access must be protected by the state lock.
|
||||||
base::Lock state_lock_;
|
base::Lock state_lock_;
|
||||||
@ -694,11 +550,14 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
// Manages response registrations.
|
// Manages response registrations.
|
||||||
scoped_ptr<CefResponseManager> response_manager_;
|
scoped_ptr<CefResponseManager> response_manager_;
|
||||||
|
|
||||||
|
// Used for creating and managing file dialogs.
|
||||||
|
scoped_ptr<CefFileDialogManager> file_dialog_manager_;
|
||||||
|
|
||||||
// Used for creating and managing JavaScript dialogs.
|
// Used for creating and managing JavaScript dialogs.
|
||||||
scoped_ptr<CefJavaScriptDialogManager> dialog_manager_;
|
scoped_ptr<CefJavaScriptDialogManager> javascript_dialog_manager_;
|
||||||
|
|
||||||
// Used for creating and managing context menus.
|
// Used for creating and managing context menus.
|
||||||
scoped_ptr<CefMenuCreator> menu_creator_;
|
scoped_ptr<CefMenuManager> menu_manager_;
|
||||||
|
|
||||||
// Track the lifespan of the frontend WebContents associated with this
|
// Track the lifespan of the frontend WebContents associated with this
|
||||||
// browser.
|
// browser.
|
||||||
@ -707,24 +566,8 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||||||
// destroyed.
|
// destroyed.
|
||||||
CefDevToolsFrontend* devtools_frontend_;
|
CefDevToolsFrontend* devtools_frontend_;
|
||||||
|
|
||||||
// True if a file chooser is currently pending.
|
|
||||||
bool file_chooser_pending_;
|
|
||||||
|
|
||||||
// Used for asynchronously listing directory contents.
|
|
||||||
scoped_ptr<net::DirectoryLister> lister_;
|
|
||||||
|
|
||||||
#if defined(USE_AURA)
|
|
||||||
// Widget hosting the web contents. It will be deleted automatically when the
|
|
||||||
// associated root window is destroyed.
|
|
||||||
views::Widget* window_widget_;
|
|
||||||
#endif // defined(USE_AURA)
|
|
||||||
#if defined(USE_X11)
|
|
||||||
CefWindowX11* window_x11_;
|
|
||||||
scoped_ptr<ui::XScopedCursor> invisible_cursor_;
|
|
||||||
#endif // defined(USE_X11)
|
|
||||||
|
|
||||||
IMPLEMENT_REFCOUNTING(CefBrowserHostImpl);
|
IMPLEMENT_REFCOUNTING(CefBrowserHostImpl);
|
||||||
DISALLOW_EVIL_CONSTRUCTORS(CefBrowserHostImpl);
|
DISALLOW_COPY_AND_ASSIGN(CefBrowserHostImpl);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_BROWSER_HOST_IMPL_H_
|
#endif // CEF_LIBCEF_BROWSER_BROWSER_HOST_IMPL_H_
|
||||||
|
@ -1,946 +0,0 @@
|
|||||||
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
|
||||||
// Portions 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 "libcef/browser/browser_host_impl.h"
|
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
#import <CoreServices/CoreServices.h>
|
|
||||||
|
|
||||||
#include "libcef/browser/render_widget_host_view_osr.h"
|
|
||||||
#include "libcef/browser/text_input_client_osr_mac.h"
|
|
||||||
#include "libcef/browser/thread_util.h"
|
|
||||||
|
|
||||||
#include "base/files/file_util.h"
|
|
||||||
#include "base/mac/mac_util.h"
|
|
||||||
#include "base/mac/scoped_nsautorelease_pool.h"
|
|
||||||
#include "base/strings/string_split.h"
|
|
||||||
#include "base/strings/string_util.h"
|
|
||||||
#include "base/strings/sys_string_conversions.h"
|
|
||||||
#include "base/strings/utf_string_conversions.h"
|
|
||||||
#include "base/threading/thread_restrictions.h"
|
|
||||||
#include "content/public/browser/native_web_keyboard_event.h"
|
|
||||||
#include "content/public/browser/render_widget_host_view.h"
|
|
||||||
#include "content/public/browser/web_contents.h"
|
|
||||||
#include "content/public/common/file_chooser_params.h"
|
|
||||||
#include "grit/cef_strings.h"
|
|
||||||
#include "grit/ui_strings.h"
|
|
||||||
#include "net/base/mime_util.h"
|
|
||||||
#include "third_party/WebKit/public/web/WebInputEvent.h"
|
|
||||||
#import "ui/base/cocoa/underlay_opengl_hosting_window.h"
|
|
||||||
#include "ui/base/l10n/l10n_util.h"
|
|
||||||
#include "ui/events/keycodes/keyboard_codes_posix.h"
|
|
||||||
#include "ui/gfx/geometry/rect.h"
|
|
||||||
|
|
||||||
// Wrapper NSView for the native view. Necessary to destroy the browser when
|
|
||||||
// the view is deleted.
|
|
||||||
@interface CefBrowserHostView : NSView {
|
|
||||||
@private
|
|
||||||
CefBrowserHostImpl* browser_; // weak
|
|
||||||
}
|
|
||||||
|
|
||||||
@property (nonatomic, assign) CefBrowserHostImpl* browser;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation CefBrowserHostView
|
|
||||||
|
|
||||||
@synthesize browser = browser_;
|
|
||||||
|
|
||||||
- (void) dealloc {
|
|
||||||
if (browser_) {
|
|
||||||
// Force the browser to be destroyed and release the reference added in
|
|
||||||
// PlatformCreateWindow().
|
|
||||||
browser_->WindowDestroyed();
|
|
||||||
}
|
|
||||||
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
// Receives notifications from the browser window. Will delete itself when done.
|
|
||||||
@interface CefWindowDelegate : NSObject <NSWindowDelegate> {
|
|
||||||
@private
|
|
||||||
CefBrowserHostImpl* browser_; // weak
|
|
||||||
NSWindow* window_;
|
|
||||||
}
|
|
||||||
- (id)initWithWindow:(NSWindow*)window andBrowser:(CefBrowserHostImpl*)browser;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation CefWindowDelegate
|
|
||||||
|
|
||||||
- (id)initWithWindow:(NSWindow*)window andBrowser:(CefBrowserHostImpl*)browser {
|
|
||||||
if (self = [super init]) {
|
|
||||||
window_ = window;
|
|
||||||
browser_ = browser;
|
|
||||||
|
|
||||||
[window_ setDelegate:self];
|
|
||||||
|
|
||||||
// Register for application hide/unhide notifications.
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
|
||||||
addObserver:self
|
|
||||||
selector:@selector(applicationDidHide:)
|
|
||||||
name:NSApplicationDidHideNotification
|
|
||||||
object:nil];
|
|
||||||
[[NSNotificationCenter defaultCenter]
|
|
||||||
addObserver:self
|
|
||||||
selector:@selector(applicationDidUnhide:)
|
|
||||||
name:NSApplicationDidUnhideNotification
|
|
||||||
object:nil];
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)dealloc {
|
|
||||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
||||||
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when we are activated (when we gain focus).
|
|
||||||
- (void)windowDidBecomeKey:(NSNotification*)notification {
|
|
||||||
if (browser_)
|
|
||||||
browser_->SetFocus(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when we are deactivated (when we lose focus).
|
|
||||||
- (void)windowDidResignKey:(NSNotification*)notification {
|
|
||||||
if (browser_)
|
|
||||||
browser_->SetFocus(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when we have been minimized.
|
|
||||||
- (void)windowDidMiniaturize:(NSNotification *)notification {
|
|
||||||
if (browser_)
|
|
||||||
browser_->SetWindowVisibility(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when we have been unminimized.
|
|
||||||
- (void)windowDidDeminiaturize:(NSNotification *)notification {
|
|
||||||
if (browser_)
|
|
||||||
browser_->SetWindowVisibility(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when the application has been hidden.
|
|
||||||
- (void)applicationDidHide:(NSNotification *)notification {
|
|
||||||
// If the window is miniaturized then nothing has really changed.
|
|
||||||
if (![window_ isMiniaturized]) {
|
|
||||||
if (browser_)
|
|
||||||
browser_->SetWindowVisibility(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when the application has been unhidden.
|
|
||||||
- (void)applicationDidUnhide:(NSNotification *)notification {
|
|
||||||
// If the window is miniaturized then nothing has really changed.
|
|
||||||
if (![window_ isMiniaturized]) {
|
|
||||||
if (browser_)
|
|
||||||
browser_->SetWindowVisibility(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)windowShouldClose:(id)window {
|
|
||||||
// Protect against multiple requests to close while the close is pending.
|
|
||||||
if (browser_ && browser_->destruction_state() <=
|
|
||||||
CefBrowserHostImpl::DESTRUCTION_STATE_PENDING) {
|
|
||||||
if (browser_->destruction_state() ==
|
|
||||||
CefBrowserHostImpl::DESTRUCTION_STATE_NONE) {
|
|
||||||
// Request that the browser close.
|
|
||||||
browser_->CloseBrowser(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cancel the close.
|
|
||||||
return NO;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean ourselves up after clearing the stack of anything that might have the
|
|
||||||
// window on it.
|
|
||||||
[self performSelectorOnMainThread:@selector(cleanup:)
|
|
||||||
withObject:window
|
|
||||||
waitUntilDone:NO];
|
|
||||||
|
|
||||||
// Allow the close.
|
|
||||||
return YES;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)cleanup:(id)window {
|
|
||||||
[self release];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
base::string16 GetDescriptionFromMimeType(const std::string& mime_type) {
|
|
||||||
// Check for wild card mime types and return an appropriate description.
|
|
||||||
static const struct {
|
|
||||||
const char* mime_type;
|
|
||||||
int string_id;
|
|
||||||
} kWildCardMimeTypes[] = {
|
|
||||||
{ "audio", IDS_APP_AUDIO_FILES },
|
|
||||||
{ "image", IDS_APP_IMAGE_FILES },
|
|
||||||
{ "text", IDS_APP_TEXT_FILES },
|
|
||||||
{ "video", IDS_APP_VIDEO_FILES },
|
|
||||||
};
|
|
||||||
|
|
||||||
for (size_t i = 0; i < arraysize(kWildCardMimeTypes); ++i) {
|
|
||||||
if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*")
|
|
||||||
return l10n_util::GetStringUTF16(kWildCardMimeTypes[i].string_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return base::string16();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddFilters(NSPopUpButton *button,
|
|
||||||
const std::vector<base::string16>& accept_filters,
|
|
||||||
bool include_all_files,
|
|
||||||
std::vector<std::vector<base::string16> >* all_extensions) {
|
|
||||||
for (size_t i = 0; i < accept_filters.size(); ++i) {
|
|
||||||
const base::string16& filter = accept_filters[i];
|
|
||||||
if (filter.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
std::vector<base::string16> extensions;
|
|
||||||
base::string16 description;
|
|
||||||
|
|
||||||
size_t sep_index = filter.find('|');
|
|
||||||
if (sep_index != std::string::npos) {
|
|
||||||
// Treat as a filter of the form "Filter Name|.ext1;.ext2;.ext3".
|
|
||||||
description = filter.substr(0, sep_index);
|
|
||||||
|
|
||||||
const std::vector<base::string16>& ext =
|
|
||||||
base::SplitString(filter.substr(sep_index + 1),
|
|
||||||
base::ASCIIToUTF16(";"),
|
|
||||||
base::TRIM_WHITESPACE,
|
|
||||||
base::SPLIT_WANT_NONEMPTY);
|
|
||||||
for (size_t x = 0; x < ext.size(); ++x) {
|
|
||||||
const base::string16& file_ext = ext[x];
|
|
||||||
if (!file_ext.empty() && file_ext[0] == '.')
|
|
||||||
extensions.push_back(file_ext);
|
|
||||||
}
|
|
||||||
} else if (filter[0] == '.') {
|
|
||||||
// Treat as an extension beginning with the '.' character.
|
|
||||||
extensions.push_back(filter);
|
|
||||||
} else {
|
|
||||||
// Otherwise convert mime type to one or more extensions.
|
|
||||||
const std::string& ascii = base::UTF16ToASCII(filter);
|
|
||||||
std::vector<base::FilePath::StringType> ext;
|
|
||||||
net::GetExtensionsForMimeType(ascii, &ext);
|
|
||||||
if (!ext.empty()) {
|
|
||||||
for (size_t x = 0; x < ext.size(); ++x)
|
|
||||||
extensions.push_back(base::ASCIIToUTF16("." + ext[x]));
|
|
||||||
description = GetDescriptionFromMimeType(ascii);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extensions.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Don't display a crazy number of extensions since the NSPopUpButton width
|
|
||||||
// will keep growing.
|
|
||||||
const size_t kMaxExtensions = 10;
|
|
||||||
|
|
||||||
base::string16 ext_str;
|
|
||||||
for (size_t x = 0; x < std::min(kMaxExtensions, extensions.size()); ++x) {
|
|
||||||
const base::string16& pattern = base::ASCIIToUTF16("*") + extensions[x];
|
|
||||||
if (x != 0)
|
|
||||||
ext_str += base::ASCIIToUTF16(";");
|
|
||||||
ext_str += pattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (extensions.size() > kMaxExtensions)
|
|
||||||
ext_str += base::ASCIIToUTF16(";...");
|
|
||||||
|
|
||||||
if (description.empty()) {
|
|
||||||
description = ext_str;
|
|
||||||
} else {
|
|
||||||
description +=
|
|
||||||
base::ASCIIToUTF16(" (") + ext_str + base::ASCIIToUTF16(")");
|
|
||||||
}
|
|
||||||
|
|
||||||
[button addItemWithTitle:base::SysUTF16ToNSString(description)];
|
|
||||||
|
|
||||||
all_extensions->push_back(extensions);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add the *.* filter, but only if we have added other filters (otherwise it
|
|
||||||
// is implied).
|
|
||||||
if (include_all_files && !all_extensions->empty()) {
|
|
||||||
[button addItemWithTitle:base::SysUTF8ToNSString("All Files (*)")];
|
|
||||||
all_extensions->push_back(std::vector<base::string16>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// Used to manage the file type filter in the NSSavePanel/NSOpenPanel.
|
|
||||||
@interface CefFilterDelegate : NSObject {
|
|
||||||
@private
|
|
||||||
NSSavePanel* panel_;
|
|
||||||
std::vector<std::vector<base::string16> > extensions_;
|
|
||||||
int selected_index_;
|
|
||||||
}
|
|
||||||
- (id)initWithPanel:(NSSavePanel*)panel
|
|
||||||
andAcceptFilters:(const std::vector<base::string16>&)accept_filters
|
|
||||||
andFilterIndex:(int)index;
|
|
||||||
- (void)setFilter:(int)index;
|
|
||||||
- (int)filter;
|
|
||||||
- (void)filterSelectionChanged:(id)sender;
|
|
||||||
- (void)setFileExtension;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation CefFilterDelegate
|
|
||||||
|
|
||||||
- (id)initWithPanel:(NSSavePanel*)panel
|
|
||||||
andAcceptFilters:(const std::vector<base::string16>&)accept_filters
|
|
||||||
andFilterIndex:(int)index {
|
|
||||||
if (self = [super init]) {
|
|
||||||
DCHECK(panel);
|
|
||||||
panel_ = panel;
|
|
||||||
selected_index_ = 0;
|
|
||||||
|
|
||||||
NSPopUpButton *button = [[NSPopUpButton alloc] init];
|
|
||||||
AddFilters(button, accept_filters, true, &extensions_);
|
|
||||||
[button sizeToFit];
|
|
||||||
[button setTarget:self];
|
|
||||||
[button setAction:@selector(filterSelectionChanged:)];
|
|
||||||
|
|
||||||
if (index < static_cast<int>(extensions_.size())) {
|
|
||||||
[button selectItemAtIndex:index];
|
|
||||||
[self setFilter:index];
|
|
||||||
}
|
|
||||||
|
|
||||||
[panel_ setAccessoryView:button];
|
|
||||||
}
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the current filter index.
|
|
||||||
- (void)setFilter:(int)index {
|
|
||||||
DCHECK(index >= 0 && index < static_cast<int>(extensions_.size()));
|
|
||||||
selected_index_ = index;
|
|
||||||
|
|
||||||
// Set the selectable file types. For open panels this limits the files that
|
|
||||||
// can be selected. For save panels this applies a default file extenion when
|
|
||||||
// the dialog is dismissed if none is already provided.
|
|
||||||
NSMutableArray* acceptArray = nil;
|
|
||||||
if (!extensions_[index].empty()) {
|
|
||||||
acceptArray = [[NSMutableArray alloc] init];
|
|
||||||
for (size_t i = 0; i < extensions_[index].size(); ++i) {
|
|
||||||
[acceptArray addObject:
|
|
||||||
base::SysUTF16ToNSString(extensions_[index][i].substr(1))];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
[panel_ setAllowedFileTypes:acceptArray];
|
|
||||||
|
|
||||||
if (![panel_ isKindOfClass:[NSOpenPanel class]]) {
|
|
||||||
// For save panels set the file extension.
|
|
||||||
[self setFileExtension];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the current filter index.
|
|
||||||
- (int)filter {
|
|
||||||
return selected_index_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when the selected filter is changed via the NSPopUpButton.
|
|
||||||
- (void)filterSelectionChanged:(id)sender {
|
|
||||||
NSPopUpButton *button = (NSPopUpButton*)sender;
|
|
||||||
[self setFilter:[button indexOfSelectedItem]];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the extension on the currently selected file name.
|
|
||||||
- (void)setFileExtension {
|
|
||||||
const std::vector<base::string16>& filter = extensions_[selected_index_];
|
|
||||||
if (filter.empty()) {
|
|
||||||
// All extensions are allowed so don't change anything.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
base::FilePath path(base::SysNSStringToUTF8([panel_ nameFieldStringValue]));
|
|
||||||
|
|
||||||
// If the file name currently includes an extension from |filter| then don't
|
|
||||||
// change anything.
|
|
||||||
base::string16 extension = base::UTF8ToUTF16(path.Extension());
|
|
||||||
if (!extension.empty()) {
|
|
||||||
for (size_t i = 0; i < filter.size(); ++i) {
|
|
||||||
if (filter[i] == extension)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Change the extension to the first value in |filter|.
|
|
||||||
path = path.ReplaceExtension(base::UTF16ToUTF8(filter[0]));
|
|
||||||
[panel_ setNameFieldStringValue:base::SysUTF8ToNSString(path.value())];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
void RunOpenFileDialog(const CefBrowserHostImpl::FileChooserParams& params,
|
|
||||||
NSView* view,
|
|
||||||
int* filter_index,
|
|
||||||
std::vector<base::FilePath>* files) {
|
|
||||||
NSOpenPanel* openPanel = [NSOpenPanel openPanel];
|
|
||||||
|
|
||||||
base::string16 title;
|
|
||||||
if (!params.title.empty()) {
|
|
||||||
title = params.title;
|
|
||||||
} else {
|
|
||||||
title = l10n_util::GetStringUTF16(
|
|
||||||
params.mode == content::FileChooserParams::Open ?
|
|
||||||
IDS_OPEN_FILE_DIALOG_TITLE :
|
|
||||||
(params.mode == content::FileChooserParams::OpenMultiple ?
|
|
||||||
IDS_OPEN_FILES_DIALOG_TITLE : IDS_SELECT_FOLDER_DIALOG_TITLE));
|
|
||||||
}
|
|
||||||
[openPanel setTitle:base::SysUTF16ToNSString(title)];
|
|
||||||
|
|
||||||
std::string filename, directory;
|
|
||||||
if (!params.default_file_name.empty()) {
|
|
||||||
if (params.mode == content::FileChooserParams::UploadFolder ||
|
|
||||||
params.default_file_name.EndsWithSeparator()) {
|
|
||||||
// The value is only a directory.
|
|
||||||
directory = params.default_file_name.value();
|
|
||||||
} else {
|
|
||||||
// The value is a file name and possibly a directory.
|
|
||||||
filename = params.default_file_name.BaseName().value();
|
|
||||||
directory = params.default_file_name.DirName().value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!filename.empty()) {
|
|
||||||
[openPanel setNameFieldStringValue:base::SysUTF8ToNSString(filename)];
|
|
||||||
}
|
|
||||||
if (!directory.empty()) {
|
|
||||||
[openPanel setDirectoryURL:
|
|
||||||
[NSURL fileURLWithPath:base::SysUTF8ToNSString(directory)]];
|
|
||||||
}
|
|
||||||
|
|
||||||
CefFilterDelegate* filter_delegate = nil;
|
|
||||||
if (params.mode != content::FileChooserParams::UploadFolder &&
|
|
||||||
!params.accept_types.empty()) {
|
|
||||||
// Add the file filter control.
|
|
||||||
filter_delegate =
|
|
||||||
[[CefFilterDelegate alloc] initWithPanel:openPanel
|
|
||||||
andAcceptFilters:params.accept_types
|
|
||||||
andFilterIndex:*filter_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Further panel configuration.
|
|
||||||
[openPanel setAllowsOtherFileTypes:YES];
|
|
||||||
[openPanel setAllowsMultipleSelection:
|
|
||||||
(params.mode == content::FileChooserParams::OpenMultiple)];
|
|
||||||
[openPanel setCanChooseFiles:
|
|
||||||
(params.mode != content::FileChooserParams::UploadFolder)];
|
|
||||||
[openPanel setCanChooseDirectories:
|
|
||||||
(params.mode == content::FileChooserParams::UploadFolder)];
|
|
||||||
[openPanel setShowsHiddenFiles:!params.hidereadonly];
|
|
||||||
|
|
||||||
// Show panel.
|
|
||||||
[openPanel beginSheetModalForWindow:[view window]
|
|
||||||
completionHandler:^(NSInteger returnCode) {
|
|
||||||
[NSApp stopModalWithCode:returnCode];
|
|
||||||
}];
|
|
||||||
NSInteger result = [NSApp runModalForWindow:[view window]];
|
|
||||||
if (result == NSFileHandlingPanelOKButton) {
|
|
||||||
NSArray *urls = [openPanel URLs];
|
|
||||||
int i, count = [urls count];
|
|
||||||
for (i=0; i<count; i++) {
|
|
||||||
NSURL* url = [urls objectAtIndex:i];
|
|
||||||
if ([url isFileURL])
|
|
||||||
files->push_back(base::FilePath(base::SysNSStringToUTF8([url path])));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter_delegate != nil)
|
|
||||||
*filter_index = [filter_delegate filter];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RunSaveFileDialog(const CefBrowserHostImpl::FileChooserParams& params,
|
|
||||||
NSView* view,
|
|
||||||
int* filter_index,
|
|
||||||
base::FilePath* file) {
|
|
||||||
NSSavePanel* savePanel = [NSSavePanel savePanel];
|
|
||||||
|
|
||||||
base::string16 title;
|
|
||||||
if (!params.title.empty())
|
|
||||||
title = params.title;
|
|
||||||
else
|
|
||||||
title = l10n_util::GetStringUTF16(IDS_SAVE_AS_DIALOG_TITLE);
|
|
||||||
[savePanel setTitle:base::SysUTF16ToNSString(title)];
|
|
||||||
|
|
||||||
std::string filename, directory;
|
|
||||||
if (!params.default_file_name.empty()) {
|
|
||||||
if (params.default_file_name.EndsWithSeparator()) {
|
|
||||||
// The value is only a directory.
|
|
||||||
directory = params.default_file_name.value();
|
|
||||||
} else {
|
|
||||||
// The value is a file name and possibly a directory.
|
|
||||||
filename = params.default_file_name.BaseName().value();
|
|
||||||
directory = params.default_file_name.DirName().value();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!filename.empty()) {
|
|
||||||
[savePanel setNameFieldStringValue:base::SysUTF8ToNSString(filename)];
|
|
||||||
}
|
|
||||||
if (!directory.empty()) {
|
|
||||||
[savePanel setDirectoryURL:
|
|
||||||
[NSURL fileURLWithPath:base::SysUTF8ToNSString(directory)]];
|
|
||||||
}
|
|
||||||
|
|
||||||
CefFilterDelegate* filter_delegate = nil;
|
|
||||||
if (!params.accept_types.empty()) {
|
|
||||||
// Add the file filter control.
|
|
||||||
filter_delegate =
|
|
||||||
[[CefFilterDelegate alloc] initWithPanel:savePanel
|
|
||||||
andAcceptFilters:params.accept_types
|
|
||||||
andFilterIndex:*filter_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
[savePanel setAllowsOtherFileTypes:YES];
|
|
||||||
[savePanel setShowsHiddenFiles:!params.hidereadonly];
|
|
||||||
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
// Show panel.
|
|
||||||
[savePanel beginSheetModalForWindow:[view window]
|
|
||||||
completionHandler:^(NSInteger resultCode) {
|
|
||||||
[NSApp stopModalWithCode:resultCode];
|
|
||||||
}];
|
|
||||||
NSInteger result = [NSApp runModalForWindow:[view window]];
|
|
||||||
if (result == NSFileHandlingPanelOKButton) {
|
|
||||||
NSURL* url = [savePanel URL];
|
|
||||||
NSString* path = [url path];
|
|
||||||
*file = base::FilePath([path UTF8String]);
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filter_delegate != nil)
|
|
||||||
*filter_index = [filter_delegate filter];
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
bool CefBrowserHostImpl::PlatformViewText(const std::string& text) {
|
|
||||||
NOTIMPLEMENTED();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CefTextInputContext CefBrowserHostImpl::GetNSTextInputContext() {
|
|
||||||
if (!IsWindowless()) {
|
|
||||||
NOTREACHED() << "Window rendering is not disabled";
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
||||||
NOTREACHED() << "Called on invalid thread";
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRenderWidgetHostViewOSR* rwhv = static_cast<CefRenderWidgetHostViewOSR*>(
|
|
||||||
GetWebContents()->GetRenderWidgetHostView());
|
|
||||||
|
|
||||||
return rwhv->GetNSTextInputContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::HandleKeyEventBeforeTextInputClient(
|
|
||||||
CefEventHandle keyEvent) {
|
|
||||||
if (!IsWindowless()) {
|
|
||||||
NOTREACHED() << "Window rendering is not disabled";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
||||||
NOTREACHED() << "Called on invalid thread";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRenderWidgetHostViewOSR* rwhv = static_cast<CefRenderWidgetHostViewOSR*>(
|
|
||||||
GetWebContents()->GetRenderWidgetHostView());
|
|
||||||
|
|
||||||
rwhv->HandleKeyEventBeforeTextInputClient(keyEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::HandleKeyEventAfterTextInputClient(
|
|
||||||
CefEventHandle keyEvent) {
|
|
||||||
if (!IsWindowless()) {
|
|
||||||
NOTREACHED() << "Window rendering is not disabled";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
|
||||||
NOTREACHED() << "Called on invalid thread";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRenderWidgetHostViewOSR* rwhv = static_cast<CefRenderWidgetHostViewOSR*>(
|
|
||||||
GetWebContents()->GetRenderWidgetHostView());
|
|
||||||
|
|
||||||
rwhv->HandleKeyEventAfterTextInputClient(keyEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CefBrowserHostImpl::PlatformCreateWindow() {
|
|
||||||
base::mac::ScopedNSAutoreleasePool autorelease_pool;
|
|
||||||
|
|
||||||
NSWindow* newWnd = nil;
|
|
||||||
|
|
||||||
NSView* parentView = window_info_.parent_view;
|
|
||||||
NSRect contentRect = {{window_info_.x, window_info_.y},
|
|
||||||
{window_info_.width, window_info_.height}};
|
|
||||||
if (parentView == nil) {
|
|
||||||
// Create a new window.
|
|
||||||
NSRect screen_rect = [[NSScreen mainScreen] visibleFrame];
|
|
||||||
NSRect window_rect = {{window_info_.x,
|
|
||||||
screen_rect.size.height - window_info_.y},
|
|
||||||
{window_info_.width, window_info_.height}};
|
|
||||||
if (window_rect.size.width == 0)
|
|
||||||
window_rect.size.width = 750;
|
|
||||||
if (window_rect.size.height == 0)
|
|
||||||
window_rect.size.height = 750;
|
|
||||||
|
|
||||||
contentRect.origin.x = 0;
|
|
||||||
contentRect.origin.y = 0;
|
|
||||||
contentRect.size.width = window_rect.size.width;
|
|
||||||
contentRect.size.height = window_rect.size.height;
|
|
||||||
|
|
||||||
newWnd = [[UnderlayOpenGLHostingWindow alloc]
|
|
||||||
initWithContentRect:window_rect
|
|
||||||
styleMask:(NSTitledWindowMask |
|
|
||||||
NSClosableWindowMask |
|
|
||||||
NSMiniaturizableWindowMask |
|
|
||||||
NSResizableWindowMask |
|
|
||||||
NSUnifiedTitleAndToolbarWindowMask )
|
|
||||||
backing:NSBackingStoreBuffered
|
|
||||||
defer:NO];
|
|
||||||
|
|
||||||
// Create the delegate for control and browser window events.
|
|
||||||
[[CefWindowDelegate alloc] initWithWindow:newWnd andBrowser:this];
|
|
||||||
|
|
||||||
parentView = [newWnd contentView];
|
|
||||||
window_info_.parent_view = parentView;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the content view for the window have a layer. This will make all
|
|
||||||
// sub-views have layers. This is necessary to ensure correct layer
|
|
||||||
// ordering of all child views and their layers.
|
|
||||||
[[[parentView window] contentView] setWantsLayer:YES];
|
|
||||||
|
|
||||||
// Add a reference that will be released in the dealloc handler.
|
|
||||||
AddRef();
|
|
||||||
|
|
||||||
// Create the browser view.
|
|
||||||
CefBrowserHostView* browser_view =
|
|
||||||
[[CefBrowserHostView alloc] initWithFrame:contentRect];
|
|
||||||
browser_view.browser = this;
|
|
||||||
[parentView addSubview:browser_view];
|
|
||||||
[browser_view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
|
|
||||||
[browser_view setNeedsDisplay:YES];
|
|
||||||
[browser_view release];
|
|
||||||
|
|
||||||
// Parent the TabContents to the browser view.
|
|
||||||
const NSRect bounds = [browser_view bounds];
|
|
||||||
NSView* native_view = web_contents_->GetNativeView();
|
|
||||||
[browser_view addSubview:native_view];
|
|
||||||
[native_view setFrame:bounds];
|
|
||||||
[native_view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
|
|
||||||
[native_view setNeedsDisplay:YES];
|
|
||||||
|
|
||||||
window_info_.view = browser_view;
|
|
||||||
|
|
||||||
if (newWnd != nil && !window_info_.hidden) {
|
|
||||||
// Show the window.
|
|
||||||
[newWnd makeKeyAndOrderFront: nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformCloseWindow() {
|
|
||||||
if (window_info_.view != nil) {
|
|
||||||
[[window_info_.view window]
|
|
||||||
performSelectorOnMainThread:@selector(performClose:)
|
|
||||||
withObject:nil
|
|
||||||
waitUntilDone:NO];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformSizeTo(int width, int height) {
|
|
||||||
// Not needed; subviews are bound.
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformSetFocus(bool focus) {
|
|
||||||
if (web_contents_) {
|
|
||||||
if (content::RenderWidgetHostView* view =
|
|
||||||
web_contents_->GetRenderWidgetHostView()) {
|
|
||||||
view->SetActive(focus);
|
|
||||||
|
|
||||||
if (focus && !IsWindowless()) {
|
|
||||||
// Give keyboard focus to the native view.
|
|
||||||
NSView* view = web_contents_->GetContentNativeView();
|
|
||||||
DCHECK([view canBecomeKeyView]);
|
|
||||||
[[view window] makeFirstResponder:view];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformSetWindowVisibility(bool visible) {
|
|
||||||
if (web_contents_) {
|
|
||||||
if (content::RenderWidgetHostView* view =
|
|
||||||
web_contents_->GetRenderWidgetHostView()) {
|
|
||||||
view->SetWindowVisibility(visible);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CefWindowHandle CefBrowserHostImpl::PlatformGetWindowHandle() {
|
|
||||||
return IsWindowless() ? window_info_.parent_view : window_info_.view;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformHandleKeyboardEvent(
|
|
||||||
const content::NativeWebKeyboardEvent& event) {
|
|
||||||
// Give the top level menu equivalents a chance to handle the event.
|
|
||||||
if ([event.os_event type] == NSKeyDown)
|
|
||||||
[[NSApp mainMenu] performKeyEquivalent:event.os_event];
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformRunFileChooser(
|
|
||||||
const FileChooserParams& params,
|
|
||||||
RunFileChooserCallback callback) {
|
|
||||||
std::vector<base::FilePath> files;
|
|
||||||
int filter_index = params.selected_accept_filter;
|
|
||||||
NSView* owner = PlatformGetWindowHandle();
|
|
||||||
|
|
||||||
if (params.mode == content::FileChooserParams::Open ||
|
|
||||||
params.mode == content::FileChooserParams::OpenMultiple ||
|
|
||||||
params.mode == content::FileChooserParams::UploadFolder) {
|
|
||||||
RunOpenFileDialog(params, owner, &filter_index, &files);
|
|
||||||
} else if (params.mode == content::FileChooserParams::Save) {
|
|
||||||
base::FilePath file;
|
|
||||||
if (RunSaveFileDialog(params, owner, &filter_index, &file)) {
|
|
||||||
files.push_back(file);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
NOTIMPLEMENTED();
|
|
||||||
}
|
|
||||||
|
|
||||||
callback.Run(filter_index, files);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {
|
|
||||||
}
|
|
||||||
|
|
||||||
static NSTimeInterval currentEventTimestamp() {
|
|
||||||
NSEvent* currentEvent = [NSApp currentEvent];
|
|
||||||
if (currentEvent)
|
|
||||||
return [currentEvent timestamp];
|
|
||||||
else {
|
|
||||||
// FIXME(API): In case there is no current event, the timestamp could be
|
|
||||||
// obtained by getting the time since the application started. This involves
|
|
||||||
// taking some more static functions from Chromium code.
|
|
||||||
// Another option is to have the timestamp as a field in CefEvent structures
|
|
||||||
// and let the client provide it.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static NSUInteger NativeModifiers(int cef_modifiers) {
|
|
||||||
NSUInteger native_modifiers = 0;
|
|
||||||
if (cef_modifiers & EVENTFLAG_SHIFT_DOWN)
|
|
||||||
native_modifiers |= NSShiftKeyMask;
|
|
||||||
if (cef_modifiers & EVENTFLAG_CONTROL_DOWN)
|
|
||||||
native_modifiers |= NSControlKeyMask;
|
|
||||||
if (cef_modifiers & EVENTFLAG_ALT_DOWN)
|
|
||||||
native_modifiers |= NSAlternateKeyMask;
|
|
||||||
if (cef_modifiers & EVENTFLAG_COMMAND_DOWN)
|
|
||||||
native_modifiers |= NSCommandKeyMask;
|
|
||||||
if (cef_modifiers & EVENTFLAG_CAPS_LOCK_ON)
|
|
||||||
native_modifiers |= NSAlphaShiftKeyMask;
|
|
||||||
if (cef_modifiers & EVENTFLAG_NUM_LOCK_ON)
|
|
||||||
native_modifiers |= NSNumericPadKeyMask;
|
|
||||||
|
|
||||||
return native_modifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformTranslateKeyEvent(
|
|
||||||
content::NativeWebKeyboardEvent& native_event,
|
|
||||||
const CefKeyEvent& key_event) {
|
|
||||||
// Use a synthetic NSEvent in order to obtain the windowsKeyCode member from
|
|
||||||
// the NativeWebKeyboardEvent constructor. This is the only member which can
|
|
||||||
// not be easily translated (without hardcoding keyCodes)
|
|
||||||
// Determining whether a modifier key is left or right seems to be done
|
|
||||||
// through the key code as well.
|
|
||||||
|
|
||||||
NSEventType event_type;
|
|
||||||
if (key_event.character == 0 && key_event.unmodified_character == 0) {
|
|
||||||
// Check if both character and unmodified_characther are empty to determine
|
|
||||||
// if this was a NSFlagsChanged event.
|
|
||||||
// A dead key will have an empty character, but a non-empty unmodified
|
|
||||||
// character
|
|
||||||
event_type = NSFlagsChanged;
|
|
||||||
} else {
|
|
||||||
switch (key_event.type) {
|
|
||||||
case KEYEVENT_RAWKEYDOWN:
|
|
||||||
case KEYEVENT_KEYDOWN:
|
|
||||||
case KEYEVENT_CHAR:
|
|
||||||
event_type = NSKeyDown;
|
|
||||||
break;
|
|
||||||
case KEYEVENT_KEYUP:
|
|
||||||
event_type = NSKeyUp;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NSString* charactersIgnoringModifiers = [[[NSString alloc]
|
|
||||||
initWithCharacters:&key_event.unmodified_character length:1]
|
|
||||||
autorelease];
|
|
||||||
NSString* characters = [[[NSString alloc]
|
|
||||||
initWithCharacters:&key_event.character length:1] autorelease];
|
|
||||||
|
|
||||||
NSEvent* synthetic_event =
|
|
||||||
[NSEvent keyEventWithType:event_type
|
|
||||||
location:NSMakePoint(0, 0)
|
|
||||||
modifierFlags:NativeModifiers(key_event.modifiers)
|
|
||||||
timestamp:currentEventTimestamp()
|
|
||||||
windowNumber:0
|
|
||||||
context:nil
|
|
||||||
characters:characters
|
|
||||||
charactersIgnoringModifiers:charactersIgnoringModifiers
|
|
||||||
isARepeat:NO
|
|
||||||
keyCode:key_event.native_key_code];
|
|
||||||
|
|
||||||
native_event = content::NativeWebKeyboardEvent(synthetic_event);
|
|
||||||
if (key_event.type == KEYEVENT_CHAR)
|
|
||||||
native_event.type = blink::WebInputEvent::Char;
|
|
||||||
|
|
||||||
native_event.isSystemKey = key_event.is_system_key;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformTranslateClickEvent(
|
|
||||||
blink::WebMouseEvent& result,
|
|
||||||
const CefMouseEvent& mouse_event,
|
|
||||||
MouseButtonType type,
|
|
||||||
bool mouseUp, int clickCount) {
|
|
||||||
PlatformTranslateMouseEvent(result, mouse_event);
|
|
||||||
|
|
||||||
switch (type) {
|
|
||||||
case MBT_LEFT:
|
|
||||||
result.type = mouseUp ? blink::WebInputEvent::MouseUp :
|
|
||||||
blink::WebInputEvent::MouseDown;
|
|
||||||
result.button = blink::WebMouseEvent::ButtonLeft;
|
|
||||||
break;
|
|
||||||
case MBT_MIDDLE:
|
|
||||||
result.type = mouseUp ? blink::WebInputEvent::MouseUp :
|
|
||||||
blink::WebInputEvent::MouseDown;
|
|
||||||
result.button = blink::WebMouseEvent::ButtonMiddle;
|
|
||||||
break;
|
|
||||||
case MBT_RIGHT:
|
|
||||||
result.type = mouseUp ? blink::WebInputEvent::MouseUp :
|
|
||||||
blink::WebInputEvent::MouseDown;
|
|
||||||
result.button = blink::WebMouseEvent::ButtonRight;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
NOTREACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
result.clickCount = clickCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformTranslateMoveEvent(
|
|
||||||
blink::WebMouseEvent& result,
|
|
||||||
const CefMouseEvent& mouse_event,
|
|
||||||
bool mouseLeave) {
|
|
||||||
PlatformTranslateMouseEvent(result, mouse_event);
|
|
||||||
|
|
||||||
if (!mouseLeave) {
|
|
||||||
result.type = blink::WebInputEvent::MouseMove;
|
|
||||||
if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON)
|
|
||||||
result.button = blink::WebMouseEvent::ButtonLeft;
|
|
||||||
else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON)
|
|
||||||
result.button = blink::WebMouseEvent::ButtonMiddle;
|
|
||||||
else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON)
|
|
||||||
result.button = blink::WebMouseEvent::ButtonRight;
|
|
||||||
else
|
|
||||||
result.button = blink::WebMouseEvent::ButtonNone;
|
|
||||||
} else {
|
|
||||||
result.type = blink::WebInputEvent::MouseLeave;
|
|
||||||
result.button = blink::WebMouseEvent::ButtonNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
result.clickCount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformTranslateWheelEvent(
|
|
||||||
blink::WebMouseWheelEvent& result,
|
|
||||||
const CefMouseEvent& mouse_event,
|
|
||||||
int deltaX, int deltaY) {
|
|
||||||
result = blink::WebMouseWheelEvent();
|
|
||||||
PlatformTranslateMouseEvent(result, mouse_event);
|
|
||||||
|
|
||||||
result.type = blink::WebInputEvent::MouseWheel;
|
|
||||||
|
|
||||||
static const double scrollbarPixelsPerCocoaTick = 40.0;
|
|
||||||
result.deltaX = deltaX;
|
|
||||||
result.deltaY = deltaY;
|
|
||||||
result.wheelTicksX = result.deltaX / scrollbarPixelsPerCocoaTick;
|
|
||||||
result.wheelTicksY = result.deltaY / scrollbarPixelsPerCocoaTick;
|
|
||||||
result.hasPreciseScrollingDeltas = true;
|
|
||||||
|
|
||||||
// Unless the phase and momentumPhase are passed in as parameters to this
|
|
||||||
// function, there is no way to know them
|
|
||||||
result.phase = blink::WebMouseWheelEvent::PhaseNone;
|
|
||||||
result.momentumPhase = blink::WebMouseWheelEvent::PhaseNone;
|
|
||||||
|
|
||||||
if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON)
|
|
||||||
result.button = blink::WebMouseEvent::ButtonLeft;
|
|
||||||
else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON)
|
|
||||||
result.button = blink::WebMouseEvent::ButtonMiddle;
|
|
||||||
else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON)
|
|
||||||
result.button = blink::WebMouseEvent::ButtonRight;
|
|
||||||
else
|
|
||||||
result.button = blink::WebMouseEvent::ButtonNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformTranslateMouseEvent(
|
|
||||||
blink::WebMouseEvent& result,
|
|
||||||
const CefMouseEvent& mouse_event) {
|
|
||||||
// position
|
|
||||||
result.x = mouse_event.x;
|
|
||||||
result.y = mouse_event.y;
|
|
||||||
result.windowX = result.x;
|
|
||||||
result.windowY = result.y;
|
|
||||||
result.globalX = result.x;
|
|
||||||
result.globalY = result.y;
|
|
||||||
|
|
||||||
if (IsWindowless()) {
|
|
||||||
CefRefPtr<CefRenderHandler> handler = client_->GetRenderHandler();
|
|
||||||
if (handler.get()) {
|
|
||||||
handler->GetScreenPoint(this, result.x, result.y, result.globalX,
|
|
||||||
result.globalY);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
NSView* view = window_info_.parent_view;
|
|
||||||
if (view) {
|
|
||||||
NSRect bounds = [view bounds];
|
|
||||||
NSPoint view_pt = {result.x, bounds.size.height - result.y};
|
|
||||||
NSPoint window_pt = [view convertPoint:view_pt toView:nil];
|
|
||||||
NSPoint screen_pt = [[view window] convertBaseToScreen:window_pt];
|
|
||||||
result.globalX = screen_pt.x;
|
|
||||||
result.globalY = screen_pt.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// modifiers
|
|
||||||
result.modifiers |= TranslateModifiers(mouse_event.modifiers);
|
|
||||||
|
|
||||||
// timestamp - Mac OSX specific
|
|
||||||
result.timeStampSeconds = currentEventTimestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformNotifyMoveOrResizeStarted() {
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -5,6 +5,7 @@
|
|||||||
#include "libcef/browser/browser_info.h"
|
#include "libcef/browser/browser_info.h"
|
||||||
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
#include "libcef/browser/thread_util.h"
|
||||||
|
|
||||||
#include "ipc/ipc_message.h"
|
#include "ipc/ipc_message.h"
|
||||||
|
|
||||||
@ -36,14 +37,14 @@ void CefBrowserInfo::RenderIDManager::remove_render_frame_id(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CefBrowserInfo::RenderIDManager::is_render_view_id_match(
|
bool CefBrowserInfo::RenderIDManager::is_render_view_id_match(
|
||||||
int render_process_id, int render_routing_id) {
|
int render_process_id, int render_routing_id) const {
|
||||||
return is_render_id_match(&render_view_id_set_,
|
return is_render_id_match(&render_view_id_set_,
|
||||||
render_process_id,
|
render_process_id,
|
||||||
render_routing_id);
|
render_routing_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefBrowserInfo::RenderIDManager::is_render_frame_id_match(
|
bool CefBrowserInfo::RenderIDManager::is_render_frame_id_match(
|
||||||
int render_process_id, int render_routing_id) {
|
int render_process_id, int render_routing_id) const {
|
||||||
return is_render_id_match(&render_frame_id_set_,
|
return is_render_id_match(&render_frame_id_set_,
|
||||||
render_process_id,
|
render_process_id,
|
||||||
render_routing_id);
|
render_routing_id);
|
||||||
@ -87,7 +88,7 @@ void CefBrowserInfo::RenderIDManager::remove_render_id(RenderIdSet* id_set,
|
|||||||
bool CefBrowserInfo::RenderIDManager::is_render_id_match(
|
bool CefBrowserInfo::RenderIDManager::is_render_id_match(
|
||||||
const RenderIdSet* id_set,
|
const RenderIdSet* id_set,
|
||||||
int render_process_id,
|
int render_process_id,
|
||||||
int render_routing_id) {
|
int render_routing_id) const {
|
||||||
base::AutoLock lock_scope(*lock_);
|
base::AutoLock lock_scope(*lock_);
|
||||||
|
|
||||||
if (id_set->empty())
|
if (id_set->empty())
|
||||||
@ -117,7 +118,7 @@ void CefBrowserInfo::set_windowless(bool windowless) {
|
|||||||
is_windowless_ = windowless;
|
is_windowless_ = windowless;
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRefPtr<CefBrowserHostImpl> CefBrowserInfo::browser() {
|
CefRefPtr<CefBrowserHostImpl> CefBrowserInfo::browser() const {
|
||||||
base::AutoLock lock_scope(lock_);
|
base::AutoLock lock_scope(lock_);
|
||||||
return browser_;
|
return browser_;
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,10 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
|
|||||||
void remove_render_frame_id(int render_process_id, int render_routing_id);
|
void remove_render_frame_id(int render_process_id, int render_routing_id);
|
||||||
|
|
||||||
// Returns true if this browser matches the specified ID pair.
|
// Returns true if this browser matches the specified ID pair.
|
||||||
bool is_render_view_id_match(int render_process_id, int render_routing_id);
|
bool is_render_view_id_match(int render_process_id,
|
||||||
bool is_render_frame_id_match(int render_process_id, int render_routing_id);
|
int render_routing_id) const;
|
||||||
|
bool is_render_frame_id_match(int render_process_id,
|
||||||
|
int render_routing_id)const ;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::set<std::pair<int, int> > RenderIdSet;
|
typedef std::set<std::pair<int, int> > RenderIdSet;
|
||||||
@ -50,9 +52,9 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
|
|||||||
int render_routing_id);
|
int render_routing_id);
|
||||||
bool is_render_id_match(const RenderIdSet* id_set,
|
bool is_render_id_match(const RenderIdSet* id_set,
|
||||||
int render_process_id,
|
int render_process_id,
|
||||||
int render_routing_id);
|
int render_routing_id) const;
|
||||||
|
|
||||||
base::Lock* lock_;
|
mutable base::Lock* lock_;
|
||||||
|
|
||||||
// The below members must be protected by |lock_|.
|
// The below members must be protected by |lock_|.
|
||||||
|
|
||||||
@ -88,7 +90,7 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
|
|||||||
return &guest_render_id_manager_;
|
return &guest_render_id_manager_;
|
||||||
}
|
}
|
||||||
|
|
||||||
CefRefPtr<CefBrowserHostImpl> browser();
|
CefRefPtr<CefBrowserHostImpl> browser() const;
|
||||||
void set_browser(CefRefPtr<CefBrowserHostImpl> browser);
|
void set_browser(CefRefPtr<CefBrowserHostImpl> browser);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -100,7 +102,7 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
|
|||||||
bool is_popup_;
|
bool is_popup_;
|
||||||
bool is_windowless_;
|
bool is_windowless_;
|
||||||
|
|
||||||
base::Lock lock_;
|
mutable base::Lock lock_;
|
||||||
|
|
||||||
// The below members must be protected by |lock_|.
|
// The below members must be protected by |lock_|.
|
||||||
|
|
||||||
|
556
libcef/browser/browser_info_manager.cc
Normal file
556
libcef/browser/browser_info_manager.cc
Normal file
@ -0,0 +1,556 @@
|
|||||||
|
// Copyright 2015 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 "libcef/browser/browser_info_manager.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_platform_delegate.h"
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
#include "libcef/browser/thread_util.h"
|
||||||
|
#include "libcef/common/cef_messages.h"
|
||||||
|
#include "libcef/common/extensions/extensions_util.h"
|
||||||
|
#include "libcef/browser/extensions/browser_extensions_util.h"
|
||||||
|
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "content/public/browser/render_frame_host.h"
|
||||||
|
#include "content/public/browser/render_process_host.h"
|
||||||
|
#include "content/public/browser/render_view_host.h"
|
||||||
|
#include "content/public/browser/web_contents.h"
|
||||||
|
#include "content/common/view_messages.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void TranslatePopupFeatures(const blink::WebWindowFeatures& webKitFeatures,
|
||||||
|
CefPopupFeatures& features) {
|
||||||
|
features.x = static_cast<int>(webKitFeatures.x);
|
||||||
|
features.xSet = webKitFeatures.xSet;
|
||||||
|
features.y = static_cast<int>(webKitFeatures.y);
|
||||||
|
features.ySet = webKitFeatures.ySet;
|
||||||
|
features.width = static_cast<int>(webKitFeatures.width);
|
||||||
|
features.widthSet = webKitFeatures.widthSet;
|
||||||
|
features.height = static_cast<int>(webKitFeatures.height);
|
||||||
|
features.heightSet = webKitFeatures.heightSet;
|
||||||
|
|
||||||
|
features.menuBarVisible = webKitFeatures.menuBarVisible;
|
||||||
|
features.statusBarVisible = webKitFeatures.statusBarVisible;
|
||||||
|
features.toolBarVisible = webKitFeatures.toolBarVisible;
|
||||||
|
features.locationBarVisible = webKitFeatures.locationBarVisible;
|
||||||
|
features.scrollbarsVisible = webKitFeatures.scrollbarsVisible;
|
||||||
|
features.resizable = webKitFeatures.resizable;
|
||||||
|
|
||||||
|
features.fullscreen = webKitFeatures.fullscreen;
|
||||||
|
features.dialog = webKitFeatures.dialog;
|
||||||
|
features.additionalFeatures = NULL;
|
||||||
|
if (webKitFeatures.additionalFeatures.size() > 0)
|
||||||
|
features.additionalFeatures = cef_string_list_alloc();
|
||||||
|
|
||||||
|
CefString str;
|
||||||
|
for (unsigned int i = 0; i < webKitFeatures.additionalFeatures.size(); ++i) {
|
||||||
|
str = base::string16(webKitFeatures.additionalFeatures[i]);
|
||||||
|
cef_string_list_append(features.additionalFeatures, str.GetStruct());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CefBrowserInfoManager* g_info_manager = nullptr;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
CefBrowserInfoManager::CefBrowserInfoManager()
|
||||||
|
: next_browser_id_(0) {
|
||||||
|
DCHECK(!g_info_manager);
|
||||||
|
g_info_manager = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CefBrowserInfoManager::~CefBrowserInfoManager() {
|
||||||
|
DCHECK(browser_info_list_.empty());
|
||||||
|
g_info_manager = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
CefBrowserInfoManager* CefBrowserInfoManager::GetInstance() {
|
||||||
|
return g_info_manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::CreateBrowserInfo(
|
||||||
|
bool is_popup,
|
||||||
|
bool is_windowless) {
|
||||||
|
base::AutoLock lock_scope(browser_info_lock_);
|
||||||
|
|
||||||
|
scoped_refptr<CefBrowserInfo> browser_info =
|
||||||
|
new CefBrowserInfo(++next_browser_id_, is_popup);
|
||||||
|
browser_info_list_.push_back(browser_info);
|
||||||
|
|
||||||
|
if (is_windowless)
|
||||||
|
browser_info->set_windowless(true);
|
||||||
|
|
||||||
|
return browser_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::CreatePopupBrowserInfo(
|
||||||
|
content::WebContents* new_contents,
|
||||||
|
bool is_windowless) {
|
||||||
|
base::AutoLock lock_scope(browser_info_lock_);
|
||||||
|
|
||||||
|
content::RenderViewHost* view_host = new_contents->GetRenderViewHost();
|
||||||
|
content::RenderFrameHost* main_frame_host = new_contents->GetMainFrame();
|
||||||
|
|
||||||
|
content::RenderProcessHost* host = view_host->GetProcess();
|
||||||
|
|
||||||
|
// The host processes may be different in the future with OOP iframes. When
|
||||||
|
// that happens re-visit the implementation of this class.
|
||||||
|
DCHECK_EQ(host, main_frame_host->GetProcess());
|
||||||
|
|
||||||
|
const int render_process_routing_id = host->GetID();
|
||||||
|
const int render_view_routing_id = view_host->GetRoutingID();
|
||||||
|
const int render_frame_routing_id = main_frame_host->GetRoutingID();
|
||||||
|
|
||||||
|
scoped_refptr<CefBrowserInfo> browser_info =
|
||||||
|
new CefBrowserInfo(++next_browser_id_, true);
|
||||||
|
browser_info->render_id_manager()->add_render_view_id(
|
||||||
|
render_process_routing_id, render_view_routing_id);
|
||||||
|
browser_info->render_id_manager()->add_render_frame_id(
|
||||||
|
render_process_routing_id, render_frame_routing_id);
|
||||||
|
browser_info_list_.push_back(browser_info);
|
||||||
|
|
||||||
|
if (is_windowless)
|
||||||
|
browser_info->set_windowless(true);
|
||||||
|
|
||||||
|
// Continue any pending NewBrowserInfo requests.
|
||||||
|
PendingNewBrowserInfoList::iterator it =
|
||||||
|
pending_new_browser_info_list_.begin();
|
||||||
|
for (; it != pending_new_browser_info_list_.end(); ++it) {
|
||||||
|
PendingNewBrowserInfo* info = *it;
|
||||||
|
if (info->host == host &&
|
||||||
|
info->render_view_routing_id == render_view_routing_id &&
|
||||||
|
info->render_frame_routing_id == render_frame_routing_id) {
|
||||||
|
SendNewBrowserInfoResponse(host, browser_info.get(), false,
|
||||||
|
info->reply_msg);
|
||||||
|
|
||||||
|
pending_new_browser_info_list_.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return browser_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserInfoManager::OnCreateWindow(
|
||||||
|
content::RenderProcessHost* host,
|
||||||
|
const ViewHostMsg_CreateWindow_Params& params) {
|
||||||
|
DCHECK_GT(params.opener_id, 0);
|
||||||
|
DCHECK_GT(params.opener_render_frame_id, 0);
|
||||||
|
DCHECK(!params.target_url.is_empty());
|
||||||
|
|
||||||
|
scoped_ptr<CefBrowserInfoManager::PendingPopup> pending_popup(
|
||||||
|
new CefBrowserInfoManager::PendingPopup);
|
||||||
|
pending_popup->step = CefBrowserInfoManager::PendingPopup::ON_CREATE_WINDOW;
|
||||||
|
pending_popup->opener_process_id = host->GetID();
|
||||||
|
pending_popup->opener_view_id = params.opener_id;
|
||||||
|
pending_popup->opener_frame_id = params.opener_render_frame_id;
|
||||||
|
pending_popup->target_url = params.target_url;
|
||||||
|
pending_popup->target_frame_name = params.frame_name;
|
||||||
|
PushPendingPopup(pending_popup.Pass());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefBrowserInfoManager::CanCreateWindow(
|
||||||
|
const GURL& target_url,
|
||||||
|
const content::Referrer& referrer,
|
||||||
|
WindowOpenDisposition disposition,
|
||||||
|
const blink::WebWindowFeatures& features,
|
||||||
|
bool user_gesture,
|
||||||
|
bool opener_suppressed,
|
||||||
|
int render_process_id,
|
||||||
|
int opener_render_view_id,
|
||||||
|
int opener_render_frame_id,
|
||||||
|
bool* no_javascript_access) {
|
||||||
|
scoped_ptr<CefBrowserInfoManager::PendingPopup> pending_popup =
|
||||||
|
PopPendingPopup(CefBrowserInfoManager::PendingPopup::ON_CREATE_WINDOW,
|
||||||
|
render_process_id, opener_render_view_id, target_url);
|
||||||
|
DCHECK(pending_popup.get());
|
||||||
|
DCHECK(!pending_popup->platform_delegate.get());
|
||||||
|
|
||||||
|
bool is_guest_view = false;
|
||||||
|
CefRefPtr<CefBrowserHostImpl> browser =
|
||||||
|
extensions::GetOwnerBrowserForView(
|
||||||
|
pending_popup->opener_process_id,
|
||||||
|
pending_popup->opener_view_id,
|
||||||
|
&is_guest_view);
|
||||||
|
DCHECK(browser.get());
|
||||||
|
if (!browser.get()) {
|
||||||
|
// Cancel the popup.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_guest_view) {
|
||||||
|
content::OpenURLParams params(target_url,
|
||||||
|
referrer,
|
||||||
|
disposition,
|
||||||
|
ui::PAGE_TRANSITION_LINK,
|
||||||
|
true);
|
||||||
|
params.user_gesture = user_gesture;
|
||||||
|
|
||||||
|
// Pass navigation to the owner browser.
|
||||||
|
CEF_POST_TASK(CEF_UIT,
|
||||||
|
base::Bind(base::IgnoreResult(&CefBrowserHostImpl::OpenURLFromTab),
|
||||||
|
browser.get(), nullptr, params));
|
||||||
|
|
||||||
|
// Cancel the popup.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CefRefPtr<CefClient> client = browser->GetClient();
|
||||||
|
bool allow = true;
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
pending_popup->window_info.SetAsPopup(NULL, CefString());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Start with the current browser's settings.
|
||||||
|
pending_popup->client = client;
|
||||||
|
pending_popup->settings = browser->settings();
|
||||||
|
|
||||||
|
if (client.get()) {
|
||||||
|
CefRefPtr<CefLifeSpanHandler> handler = client->GetLifeSpanHandler();
|
||||||
|
if (handler.get()) {
|
||||||
|
CefRefPtr<CefFrame> frame =
|
||||||
|
browser->GetFrame(pending_popup->opener_frame_id);
|
||||||
|
|
||||||
|
CefPopupFeatures cef_features;
|
||||||
|
TranslatePopupFeatures(features, cef_features);
|
||||||
|
|
||||||
|
#if (defined(OS_WIN) || defined(OS_MACOSX))
|
||||||
|
// Default to the size from the popup features.
|
||||||
|
if (cef_features.xSet)
|
||||||
|
pending_popup->window_info.x = cef_features.x;
|
||||||
|
if (cef_features.ySet)
|
||||||
|
pending_popup->window_info.y = cef_features.y;
|
||||||
|
if (cef_features.widthSet)
|
||||||
|
pending_popup->window_info.width = cef_features.width;
|
||||||
|
if (cef_features.heightSet)
|
||||||
|
pending_popup->window_info.height = cef_features.height;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
allow = !handler->OnBeforePopup(browser.get(),
|
||||||
|
frame,
|
||||||
|
pending_popup->target_url.spec(),
|
||||||
|
pending_popup->target_frame_name,
|
||||||
|
static_cast<cef_window_open_disposition_t>(disposition),
|
||||||
|
user_gesture,
|
||||||
|
cef_features,
|
||||||
|
pending_popup->window_info,
|
||||||
|
pending_popup->client,
|
||||||
|
pending_popup->settings,
|
||||||
|
no_javascript_access);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allow) {
|
||||||
|
pending_popup->platform_delegate =
|
||||||
|
CefBrowserPlatformDelegate::Create(pending_popup->window_info,
|
||||||
|
pending_popup->settings,
|
||||||
|
pending_popup->client);
|
||||||
|
CHECK(pending_popup->platform_delegate.get());
|
||||||
|
|
||||||
|
pending_popup->step =
|
||||||
|
CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW;
|
||||||
|
|
||||||
|
// Filtering needs to be done on the UI thread.
|
||||||
|
CEF_POST_TASK(CEF_UIT,
|
||||||
|
base::Bind(FilterPendingPopupURL, render_process_id,
|
||||||
|
base::Passed(&pending_popup)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return allow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserInfoManager::ShouldCreateWebContents(
|
||||||
|
content::WebContents* web_contents,
|
||||||
|
const GURL& target_url,
|
||||||
|
content::WebContentsView** view,
|
||||||
|
content::RenderViewHostDelegateView** delegate_view) {
|
||||||
|
scoped_ptr<CefBrowserInfoManager::PendingPopup> pending_popup =
|
||||||
|
PopPendingPopup(CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW,
|
||||||
|
web_contents->GetRenderViewHost()->GetProcess()->GetID(),
|
||||||
|
web_contents->GetRenderViewHost()->GetRoutingID(),
|
||||||
|
target_url);
|
||||||
|
DCHECK(pending_popup.get());
|
||||||
|
DCHECK(pending_popup->platform_delegate.get());
|
||||||
|
|
||||||
|
if (pending_popup->platform_delegate->IsWindowless()) {
|
||||||
|
pending_popup->platform_delegate->CreateViewForWebContents(view,
|
||||||
|
delegate_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
pending_popup->step =
|
||||||
|
CefBrowserInfoManager::PendingPopup::SHOULD_CREATE_WEB_CONTENTS;
|
||||||
|
PushPendingPopup(pending_popup.Pass());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserInfoManager::WebContentsCreated(
|
||||||
|
content::WebContents* source_contents,
|
||||||
|
const GURL& target_url,
|
||||||
|
content::WebContents* new_contents,
|
||||||
|
CefBrowserSettings& settings,
|
||||||
|
CefRefPtr<CefClient>& client,
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegate>& platform_delegate) {
|
||||||
|
DCHECK(source_contents);
|
||||||
|
DCHECK(new_contents);
|
||||||
|
|
||||||
|
scoped_ptr<CefBrowserInfoManager::PendingPopup> pending_popup =
|
||||||
|
PopPendingPopup(
|
||||||
|
CefBrowserInfoManager::PendingPopup::SHOULD_CREATE_WEB_CONTENTS,
|
||||||
|
source_contents->GetRenderViewHost()->GetProcess()->GetID(),
|
||||||
|
source_contents->GetRenderViewHost()->GetRoutingID(),
|
||||||
|
target_url);
|
||||||
|
DCHECK(pending_popup.get());
|
||||||
|
DCHECK(pending_popup->platform_delegate.get());
|
||||||
|
|
||||||
|
settings = pending_popup->settings;
|
||||||
|
client = pending_popup->client;
|
||||||
|
platform_delegate = pending_popup->platform_delegate.Pass();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserInfoManager::OnGetNewBrowserInfo(
|
||||||
|
content::RenderProcessHost* host,
|
||||||
|
int render_view_routing_id,
|
||||||
|
int render_frame_routing_id,
|
||||||
|
IPC::Message* reply_msg) {
|
||||||
|
DCHECK(host);
|
||||||
|
DCHECK_GT(render_view_routing_id, 0);
|
||||||
|
DCHECK_GT(render_frame_routing_id, 0);
|
||||||
|
DCHECK(reply_msg);
|
||||||
|
|
||||||
|
base::AutoLock lock_scope(browser_info_lock_);
|
||||||
|
|
||||||
|
const int render_process_routing_id = host->GetID();
|
||||||
|
bool is_guest_view = false;
|
||||||
|
|
||||||
|
scoped_refptr<CefBrowserInfo> browser_info = GetBrowserInfo(
|
||||||
|
render_process_routing_id, render_view_routing_id,
|
||||||
|
render_process_routing_id, render_frame_routing_id,
|
||||||
|
&is_guest_view);
|
||||||
|
|
||||||
|
if (browser_info.get()) {
|
||||||
|
// Send the response immediately.
|
||||||
|
SendNewBrowserInfoResponse(host, browser_info.get(), is_guest_view,
|
||||||
|
reply_msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// Verify that no request for the same route is currently queued.
|
||||||
|
{
|
||||||
|
PendingNewBrowserInfoList::const_iterator it =
|
||||||
|
pending_new_browser_info_list_.begin();
|
||||||
|
for (; it != pending_new_browser_info_list_.end(); ++it) {
|
||||||
|
PendingNewBrowserInfo* info = *it;
|
||||||
|
if (info->host == host &&
|
||||||
|
info->render_view_routing_id == render_view_routing_id &&
|
||||||
|
info->render_frame_routing_id == render_frame_routing_id) {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Queue the request.
|
||||||
|
scoped_ptr<PendingNewBrowserInfo> pending(new PendingNewBrowserInfo());
|
||||||
|
pending->host = host;
|
||||||
|
pending->render_view_routing_id = render_view_routing_id;
|
||||||
|
pending->render_frame_routing_id = render_frame_routing_id;
|
||||||
|
pending->reply_msg = reply_msg;
|
||||||
|
pending_new_browser_info_list_.push_back(pending.Pass());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserInfoManager::RemoveBrowserInfo(
|
||||||
|
scoped_refptr<CefBrowserInfo> browser_info) {
|
||||||
|
base::AutoLock lock_scope(browser_info_lock_);
|
||||||
|
|
||||||
|
BrowserInfoList::iterator it = browser_info_list_.begin();
|
||||||
|
for (; it != browser_info_list_.end(); ++it) {
|
||||||
|
if (*it == browser_info) {
|
||||||
|
browser_info_list_.erase(it);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserInfoManager::DestroyAllBrowsers() {
|
||||||
|
BrowserInfoList list;
|
||||||
|
|
||||||
|
{
|
||||||
|
base::AutoLock lock_scope(browser_info_lock_);
|
||||||
|
list = browser_info_list_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Destroy any remaining browser windows.
|
||||||
|
if (!list.empty()) {
|
||||||
|
BrowserInfoList::iterator it = list.begin();
|
||||||
|
for (; it != list.end(); ++it) {
|
||||||
|
CefRefPtr<CefBrowserHostImpl> browser = (*it)->browser();
|
||||||
|
DCHECK(browser.get());
|
||||||
|
if (browser.get()) {
|
||||||
|
// DestroyBrowser will call RemoveBrowserInfo.
|
||||||
|
browser->DestroyBrowser();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
{
|
||||||
|
// Verify that all browser windows have been destroyed.
|
||||||
|
base::AutoLock lock_scope(browser_info_lock_);
|
||||||
|
DCHECK(browser_info_list_.empty());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::GetBrowserInfoForView(
|
||||||
|
int render_process_id,
|
||||||
|
int render_routing_id,
|
||||||
|
bool* is_guest_view) {
|
||||||
|
base::AutoLock lock_scope(browser_info_lock_);
|
||||||
|
return GetBrowserInfo(render_process_id, render_routing_id, 0, 0,
|
||||||
|
is_guest_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::GetBrowserInfoForFrame(
|
||||||
|
int render_process_id,
|
||||||
|
int render_routing_id,
|
||||||
|
bool* is_guest_view) {
|
||||||
|
base::AutoLock lock_scope(browser_info_lock_);
|
||||||
|
return GetBrowserInfo(0, 0, render_process_id, render_routing_id,
|
||||||
|
is_guest_view);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserInfoManager::RenderProcessHostDestroyed(
|
||||||
|
content::RenderProcessHost* host) {
|
||||||
|
base::AutoLock lock_scope(browser_info_lock_);
|
||||||
|
|
||||||
|
// Remove all pending requests that reference the destroyed host.
|
||||||
|
PendingNewBrowserInfoList::iterator it =
|
||||||
|
pending_new_browser_info_list_.begin();
|
||||||
|
while (it != pending_new_browser_info_list_.end()) {
|
||||||
|
PendingNewBrowserInfo* info = *it;
|
||||||
|
if (info->host == host)
|
||||||
|
it = pending_new_browser_info_list_.erase(it);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserInfoManager::FilterPendingPopupURL(
|
||||||
|
int render_process_id,
|
||||||
|
scoped_ptr<CefBrowserInfoManager::PendingPopup> pending_popup) {
|
||||||
|
content::RenderProcessHost* rph =
|
||||||
|
content::RenderProcessHost::FromID(render_process_id);
|
||||||
|
DCHECK(rph);
|
||||||
|
rph->FilterURL(false, &pending_popup->target_url);
|
||||||
|
|
||||||
|
GetInstance()->PushPendingPopup(pending_popup.Pass());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserInfoManager::PushPendingPopup(scoped_ptr<PendingPopup> popup) {
|
||||||
|
base::AutoLock lock_scope(pending_popup_lock_);
|
||||||
|
pending_popup_list_.push_back(popup.Pass());
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<CefBrowserInfoManager::PendingPopup>
|
||||||
|
CefBrowserInfoManager::PopPendingPopup(
|
||||||
|
PendingPopup::Step step,
|
||||||
|
int opener_process_id,
|
||||||
|
int opener_view_id,
|
||||||
|
const GURL& target_url) {
|
||||||
|
DCHECK_GT(opener_process_id, 0);
|
||||||
|
DCHECK_GT(opener_view_id, 0);
|
||||||
|
DCHECK(!target_url.is_empty());
|
||||||
|
|
||||||
|
base::AutoLock lock_scope(pending_popup_lock_);
|
||||||
|
|
||||||
|
PendingPopupList::iterator it = pending_popup_list_.begin();
|
||||||
|
for (; it != pending_popup_list_.end(); ++it) {
|
||||||
|
PendingPopup* popup = *it;
|
||||||
|
if (popup->step == step &&
|
||||||
|
popup->opener_process_id == opener_process_id &&
|
||||||
|
popup->opener_view_id == opener_view_id &&
|
||||||
|
popup->target_url == target_url) {
|
||||||
|
pending_popup_list_.weak_erase(it);
|
||||||
|
return make_scoped_ptr(popup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_refptr<CefBrowserInfo> CefBrowserInfoManager::GetBrowserInfo(
|
||||||
|
int render_view_process_id,
|
||||||
|
int render_view_routing_id,
|
||||||
|
int render_frame_process_id,
|
||||||
|
int render_frame_routing_id,
|
||||||
|
bool* is_guest_view) {
|
||||||
|
browser_info_lock_.AssertAcquired();
|
||||||
|
|
||||||
|
if (is_guest_view)
|
||||||
|
*is_guest_view = false;
|
||||||
|
|
||||||
|
const bool valid_view_ids = render_view_process_id > 0 &&
|
||||||
|
render_view_routing_id > 0;
|
||||||
|
const bool valid_frame_ids = render_frame_process_id > 0 &&
|
||||||
|
render_frame_routing_id > 0;
|
||||||
|
|
||||||
|
BrowserInfoList::const_iterator it = browser_info_list_.begin();
|
||||||
|
for (; it != browser_info_list_.end(); ++it) {
|
||||||
|
const scoped_refptr<CefBrowserInfo>& browser_info = *it;
|
||||||
|
if (valid_view_ids &&
|
||||||
|
browser_info->render_id_manager()->is_render_view_id_match(
|
||||||
|
render_view_process_id, render_view_routing_id)) {
|
||||||
|
if (valid_frame_ids) {
|
||||||
|
// Make sure the frame id is also registered.
|
||||||
|
browser_info->render_id_manager()->add_render_frame_id(
|
||||||
|
render_frame_process_id, render_frame_routing_id);
|
||||||
|
}
|
||||||
|
return browser_info;
|
||||||
|
}
|
||||||
|
if (valid_frame_ids &&
|
||||||
|
browser_info->render_id_manager()->is_render_frame_id_match(
|
||||||
|
render_frame_process_id, render_frame_routing_id)) {
|
||||||
|
if (valid_view_ids) {
|
||||||
|
// Make sure the view id is also registered.
|
||||||
|
browser_info->render_id_manager()->add_render_view_id(
|
||||||
|
render_view_process_id, render_view_routing_id);
|
||||||
|
}
|
||||||
|
return browser_info;
|
||||||
|
}
|
||||||
|
if (extensions::ExtensionsEnabled() &&
|
||||||
|
((valid_view_ids &&
|
||||||
|
browser_info->guest_render_id_manager()->is_render_view_id_match(
|
||||||
|
render_view_process_id, render_view_routing_id)) ||
|
||||||
|
(valid_frame_ids &&
|
||||||
|
browser_info->guest_render_id_manager()->is_render_frame_id_match(
|
||||||
|
render_frame_process_id, render_frame_routing_id)))) {
|
||||||
|
if (is_guest_view)
|
||||||
|
*is_guest_view = true;
|
||||||
|
return browser_info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void CefBrowserInfoManager::SendNewBrowserInfoResponse(
|
||||||
|
content::RenderProcessHost* host,
|
||||||
|
CefBrowserInfo* browser_info,
|
||||||
|
bool is_guest_view,
|
||||||
|
IPC::Message* reply_msg) {
|
||||||
|
CefProcessHostMsg_GetNewBrowserInfo_Params params;
|
||||||
|
params.browser_id = browser_info->browser_id();
|
||||||
|
params.is_windowless = browser_info->is_windowless();
|
||||||
|
params.is_popup = browser_info->is_popup();
|
||||||
|
params.is_guest_view = is_guest_view;
|
||||||
|
|
||||||
|
CefProcessHostMsg_GetNewBrowserInfo::WriteReplyParams(reply_msg, params);
|
||||||
|
host->Send(reply_msg);
|
||||||
|
}
|
239
libcef/browser/browser_info_manager.h
Normal file
239
libcef/browser/browser_info_manager.h
Normal file
@ -0,0 +1,239 @@
|
|||||||
|
// Copyright 2015 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_LIBCEF_BROWSER_BROWSER_INFO_MANAGER_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_BROWSER_INFO_MANAGER_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "include/cef_client.h"
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_info.h"
|
||||||
|
|
||||||
|
#include "base/memory/scoped_vector.h"
|
||||||
|
#include "base/synchronization/lock.h"
|
||||||
|
#include "content/public/browser/render_process_host_observer.h"
|
||||||
|
#include "ui/base/window_open_disposition.h"
|
||||||
|
#include "url/gurl.h"
|
||||||
|
|
||||||
|
namespace blink {
|
||||||
|
struct WebWindowFeatures;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace content {
|
||||||
|
struct Referrer;
|
||||||
|
class RenderViewHostDelegateView;
|
||||||
|
class WebContents;
|
||||||
|
class WebContentsView;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace IPC {
|
||||||
|
class Message;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CefBrowserPlatformDelegate;
|
||||||
|
struct ViewHostMsg_CreateWindow_Params;
|
||||||
|
|
||||||
|
// Singleton object for managing BrowserInfo instances.
|
||||||
|
class CefBrowserInfoManager : public content::RenderProcessHostObserver {
|
||||||
|
public:
|
||||||
|
CefBrowserInfoManager();
|
||||||
|
~CefBrowserInfoManager() override;
|
||||||
|
|
||||||
|
// Returns this singleton instance of this class.
|
||||||
|
static CefBrowserInfoManager* GetInstance();
|
||||||
|
|
||||||
|
// Called from CefBrowserHostImpl::Create when a new browser is being created
|
||||||
|
// directly. In this case |is_popup| will be true only for DevTools browsers.
|
||||||
|
scoped_refptr<CefBrowserInfo> CreateBrowserInfo(bool is_popup,
|
||||||
|
bool is_windowless);
|
||||||
|
|
||||||
|
// Called from CefBrowserHostImpl::WebContentsCreated when a new browser is
|
||||||
|
// being created for a traditional popup (e.g. window.open() or targeted
|
||||||
|
// link). If any OnGetNewBrowserInfo requests are pending for the popup the
|
||||||
|
// response will be sent when this method is called.
|
||||||
|
scoped_refptr<CefBrowserInfo> CreatePopupBrowserInfo(
|
||||||
|
content::WebContents* new_contents,
|
||||||
|
bool is_windowless);
|
||||||
|
|
||||||
|
// Called from CefBrowserMessageFilter::OnCreateWindow. See comments on
|
||||||
|
// PendingPopup for more information.
|
||||||
|
void OnCreateWindow(content::RenderProcessHost* host,
|
||||||
|
const ViewHostMsg_CreateWindow_Params& params);
|
||||||
|
|
||||||
|
// Called from CefContentBrowserClient::CanCreateWindow. See comments on
|
||||||
|
// PendingPopup for more information.
|
||||||
|
bool CanCreateWindow(
|
||||||
|
const GURL& target_url,
|
||||||
|
const content::Referrer& referrer,
|
||||||
|
WindowOpenDisposition disposition,
|
||||||
|
const blink::WebWindowFeatures& features,
|
||||||
|
bool user_gesture,
|
||||||
|
bool opener_suppressed,
|
||||||
|
int render_process_id,
|
||||||
|
int opener_render_view_id,
|
||||||
|
int opener_render_frame_id,
|
||||||
|
bool* no_javascript_access);
|
||||||
|
|
||||||
|
// Called from CefBrowserHostImpl::ShouldCreateWebContents. See comments on
|
||||||
|
// PendingPopup for more information.
|
||||||
|
void ShouldCreateWebContents(
|
||||||
|
content::WebContents* web_contents,
|
||||||
|
const GURL& target_url,
|
||||||
|
content::WebContentsView** view,
|
||||||
|
content::RenderViewHostDelegateView** delegate_view);
|
||||||
|
|
||||||
|
// Called from CefBrowserHostImpl::WebContentsCreated. See comments on
|
||||||
|
// PendingPopup for more information.
|
||||||
|
void WebContentsCreated(
|
||||||
|
content::WebContents* source_contents,
|
||||||
|
const GURL& target_url,
|
||||||
|
content::WebContents* new_contents,
|
||||||
|
CefBrowserSettings& settings,
|
||||||
|
CefRefPtr<CefClient>& client,
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegate>& platform_delegate);
|
||||||
|
|
||||||
|
// Called from CefBrowserMessageFilter::OnGetNewBrowserInfo for delivering
|
||||||
|
// browser info to the renderer process. If the browser info already exists
|
||||||
|
// the response will be sent immediately. Otherwise, the response will be sent
|
||||||
|
// when CreatePopupBrowserInfo creates the browser info. The info will already
|
||||||
|
// exist for explicitly created browsers and guest views. It may sometimes
|
||||||
|
// already exist for traditional popup browsers depending on timing. See
|
||||||
|
// comments on PendingPopup for more information.
|
||||||
|
void OnGetNewBrowserInfo(
|
||||||
|
content::RenderProcessHost* host,
|
||||||
|
int render_view_routing_id,
|
||||||
|
int render_frame_routing_id,
|
||||||
|
IPC::Message* reply_msg);
|
||||||
|
|
||||||
|
// Called from CefBrowserHostImpl::DestroyBrowser() when a browser is
|
||||||
|
// destroyed.
|
||||||
|
void RemoveBrowserInfo(scoped_refptr<CefBrowserInfo> browser_info);
|
||||||
|
|
||||||
|
// Called from CefContext::FinishShutdownOnUIThread() to destroy all browsers.
|
||||||
|
void DestroyAllBrowsers();
|
||||||
|
|
||||||
|
// Retrieves the CefBrowserInfo matching the specified IDs or an empty
|
||||||
|
// pointer if no match is found. It is allowed to add new callers of this
|
||||||
|
// method but consider using CefBrowserHostImpl::GetBrowserFor[View|Frame]()
|
||||||
|
// or extensions::GetOwnerBrowserForView() instead.
|
||||||
|
// |is_guest_view| will be set to true if the IDs match a guest view
|
||||||
|
// associated with the returned browser info instead of the browser itself.
|
||||||
|
scoped_refptr<CefBrowserInfo> GetBrowserInfoForView(int render_process_id,
|
||||||
|
int render_routing_id,
|
||||||
|
bool* is_guest_view);
|
||||||
|
scoped_refptr<CefBrowserInfo> GetBrowserInfoForFrame(int render_process_id,
|
||||||
|
int render_routing_id,
|
||||||
|
bool* is_guest_view);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// RenderProcessHostObserver methods:
|
||||||
|
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;
|
||||||
|
|
||||||
|
// Store state information about pending popups. Call order is:
|
||||||
|
// - CefBrowserMessageFilter::OnCreateWindow (IOT)
|
||||||
|
// Intercepts the ViewHostMsg_CreateWindow message to gather information
|
||||||
|
// about the opener (parent browser) and target URL/frame.
|
||||||
|
// - CefContentBrowserClient::CanCreateWindow (IOT)
|
||||||
|
// Provides an opportunity to cancel the popup (calls OnBeforePopup) and
|
||||||
|
// creates the new platform delegate for the popup. If the popup owner is
|
||||||
|
// an extension guest view then the popup is canceled and
|
||||||
|
// CefBrowserHostImpl::OpenURLFromTab is called.
|
||||||
|
// And then the following calls may occur at the same time:
|
||||||
|
// - CefBrowserHostImpl::ShouldCreateWebContents (UIT)
|
||||||
|
// Creates the OSR views for windowless popups.
|
||||||
|
// - CefBrowserHostImpl::WebContentsCreated (UIT)
|
||||||
|
// Creates the CefBrowserHostImpl representation for the popup.
|
||||||
|
// - CefBrowserMessageFilter::OnGetNewBrowserInfo (IOT)
|
||||||
|
// Passes information about the popup to the renderer process.
|
||||||
|
struct PendingPopup {
|
||||||
|
// Track the last method that modified this PendingPopup instance. There may
|
||||||
|
// be multiple pending popups with the same identifiers and this allows us
|
||||||
|
// to differentiate between them at different processing steps.
|
||||||
|
enum Step {
|
||||||
|
ON_CREATE_WINDOW,
|
||||||
|
CAN_CREATE_WINDOW,
|
||||||
|
SHOULD_CREATE_WEB_CONTENTS
|
||||||
|
} step;
|
||||||
|
|
||||||
|
// Initial state from ViewHostMsg_CreateWindow.
|
||||||
|
int opener_process_id;
|
||||||
|
int opener_view_id;
|
||||||
|
int64 opener_frame_id;
|
||||||
|
GURL target_url;
|
||||||
|
std::string target_frame_name;
|
||||||
|
|
||||||
|
// Values specified by OnBeforePopup.
|
||||||
|
CefWindowInfo window_info;
|
||||||
|
CefBrowserSettings settings;
|
||||||
|
CefRefPtr<CefClient> client;
|
||||||
|
|
||||||
|
// Platform delegate specific to the new popup.
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegate> platform_delegate;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Between the calls to CanCreateWindow and ShouldCreateWebContents
|
||||||
|
// RenderViewHostImpl::CreateNewWindow() will call
|
||||||
|
// RenderProcessHostImpl::FilterURL() which, in the case of "javascript:"
|
||||||
|
// URIs, rewrites the URL to "about:blank". We need to apply the same filter
|
||||||
|
// otherwise ShouldCreateWebContents will fail to retrieve the PopupInfo.
|
||||||
|
static void FilterPendingPopupURL(
|
||||||
|
int render_process_id,
|
||||||
|
scoped_ptr<PendingPopup> pending_popup);
|
||||||
|
|
||||||
|
// Manage pending popups.
|
||||||
|
void PushPendingPopup(scoped_ptr<PendingPopup> popup);
|
||||||
|
scoped_ptr<PendingPopup> PopPendingPopup(
|
||||||
|
PendingPopup::Step step,
|
||||||
|
int opener_process_id,
|
||||||
|
int opener_view_id,
|
||||||
|
const GURL& target_url);
|
||||||
|
|
||||||
|
// Retrieves the BrowserInfo matching the specified IDs. If both sets are
|
||||||
|
// valid then this method makes sure both sets have been registered.
|
||||||
|
scoped_refptr<CefBrowserInfo> GetBrowserInfo(
|
||||||
|
int render_view_process_id,
|
||||||
|
int render_view_routing_id,
|
||||||
|
int render_frame_process_id,
|
||||||
|
int render_frame_routing_id,
|
||||||
|
bool* is_guest_view);
|
||||||
|
|
||||||
|
// Send the response for a pending OnGetNewBrowserInfo request.
|
||||||
|
static void SendNewBrowserInfoResponse(
|
||||||
|
content::RenderProcessHost* host,
|
||||||
|
CefBrowserInfo* browser_info,
|
||||||
|
bool is_guest_view,
|
||||||
|
IPC::Message* reply_msg);
|
||||||
|
|
||||||
|
// Pending request for OnGetNewBrowserInfo.
|
||||||
|
struct PendingNewBrowserInfo {
|
||||||
|
content::RenderProcessHost* host;
|
||||||
|
int render_view_routing_id;
|
||||||
|
int render_frame_routing_id;
|
||||||
|
IPC::Message* reply_msg;
|
||||||
|
};
|
||||||
|
|
||||||
|
mutable base::Lock browser_info_lock_;
|
||||||
|
|
||||||
|
// Access to the below members must be protected by |browser_info_lock_|.
|
||||||
|
|
||||||
|
typedef std::list<scoped_refptr<CefBrowserInfo> > BrowserInfoList;
|
||||||
|
BrowserInfoList browser_info_list_;
|
||||||
|
int next_browser_id_;
|
||||||
|
|
||||||
|
typedef ScopedVector<PendingNewBrowserInfo> PendingNewBrowserInfoList;
|
||||||
|
PendingNewBrowserInfoList pending_new_browser_info_list_;
|
||||||
|
|
||||||
|
base::Lock pending_popup_lock_;
|
||||||
|
|
||||||
|
// Access to the below members must be protected by |pending_popup_lock_|.
|
||||||
|
|
||||||
|
typedef ScopedVector<PendingPopup> PendingPopupList;
|
||||||
|
PendingPopupList pending_popup_list_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CefBrowserInfoManager);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_BROWSER_INFO_H_
|
@ -6,7 +6,6 @@
|
|||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
#include <Objbase.h>
|
#include <Objbase.h>
|
||||||
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
|
||||||
#include "libcef/browser/browser_main.h"
|
#include "libcef/browser/browser_main.h"
|
||||||
|
|
||||||
#include "chrome/common/chrome_utility_messages.h"
|
#include "chrome/common/chrome_utility_messages.h"
|
||||||
@ -45,9 +44,6 @@ void CefBrowserMainParts::PlatformInitialize() {
|
|||||||
// Start COM stuff.
|
// Start COM stuff.
|
||||||
res = OleInitialize(NULL);
|
res = OleInitialize(NULL);
|
||||||
DCHECK(SUCCEEDED(res));
|
DCHECK(SUCCEEDED(res));
|
||||||
|
|
||||||
// Register the browser window class.
|
|
||||||
CefBrowserHostImpl::RegisterWindowClass();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserMainParts::PlatformPreMainMessageLoopRun() {
|
void CefBrowserMainParts::PlatformPreMainMessageLoopRun() {
|
||||||
|
@ -6,8 +6,7 @@
|
|||||||
#include "libcef/browser/browser_message_filter.h"
|
#include "libcef/browser/browser_message_filter.h"
|
||||||
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
#include "libcef/browser/browser_info.h"
|
#include "libcef/browser/browser_info_manager.h"
|
||||||
#include "libcef/browser/content_browser_client.h"
|
|
||||||
#include "libcef/browser/context.h"
|
#include "libcef/browser/context.h"
|
||||||
#include "libcef/browser/origin_whitelist_impl.h"
|
#include "libcef/browser/origin_whitelist_impl.h"
|
||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
@ -55,7 +54,7 @@ bool CefBrowserMessageFilter::OnMessageReceived(const IPC::Message& message) {
|
|||||||
IPC_BEGIN_MESSAGE_MAP(CefBrowserMessageFilter, message)
|
IPC_BEGIN_MESSAGE_MAP(CefBrowserMessageFilter, message)
|
||||||
IPC_MESSAGE_HANDLER(CefProcessHostMsg_GetNewRenderThreadInfo,
|
IPC_MESSAGE_HANDLER(CefProcessHostMsg_GetNewRenderThreadInfo,
|
||||||
OnGetNewRenderThreadInfo)
|
OnGetNewRenderThreadInfo)
|
||||||
IPC_MESSAGE_HANDLER(CefProcessHostMsg_GetNewBrowserInfo,
|
IPC_MESSAGE_HANDLER_DELAY_REPLY(CefProcessHostMsg_GetNewBrowserInfo,
|
||||||
OnGetNewBrowserInfo)
|
OnGetNewBrowserInfo)
|
||||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_CreateWindow, OnCreateWindow)
|
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_CreateWindow, OnCreateWindow)
|
||||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||||
@ -87,33 +86,18 @@ void CefBrowserMessageFilter::OnGetNewRenderThreadInfo(
|
|||||||
void CefBrowserMessageFilter::OnGetNewBrowserInfo(
|
void CefBrowserMessageFilter::OnGetNewBrowserInfo(
|
||||||
int render_view_routing_id,
|
int render_view_routing_id,
|
||||||
int render_frame_routing_id,
|
int render_frame_routing_id,
|
||||||
CefProcessHostMsg_GetNewBrowserInfo_Params* params) {
|
IPC::Message* reply_msg) {
|
||||||
DCHECK_GT(render_view_routing_id, 0);
|
CefBrowserInfoManager::GetInstance()->OnGetNewBrowserInfo(
|
||||||
DCHECK_GT(render_frame_routing_id, 0);
|
host_,
|
||||||
|
|
||||||
// Popup windows may not have info yet.
|
|
||||||
scoped_refptr<CefBrowserInfo> info =
|
|
||||||
CefContentBrowserClient::Get()->GetOrCreateBrowserInfo(
|
|
||||||
host_->GetID(),
|
|
||||||
render_view_routing_id,
|
render_view_routing_id,
|
||||||
host_->GetID(),
|
|
||||||
render_frame_routing_id,
|
render_frame_routing_id,
|
||||||
¶ms->is_guest_view);
|
reply_msg);
|
||||||
params->browser_id = info->browser_id();
|
|
||||||
params->is_popup = info->is_popup();
|
|
||||||
params->is_windowless = info->is_windowless();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserMessageFilter::OnCreateWindow(
|
void CefBrowserMessageFilter::OnCreateWindow(
|
||||||
const ViewHostMsg_CreateWindow_Params& params,
|
const ViewHostMsg_CreateWindow_Params& params,
|
||||||
IPC::Message* reply_msg) {
|
IPC::Message* reply_msg) {
|
||||||
CefContentBrowserClient::LastCreateWindowParams lcwp;
|
CefBrowserInfoManager::GetInstance()->OnCreateWindow(host_, params);
|
||||||
lcwp.opener_process_id = host_->GetID();
|
|
||||||
lcwp.opener_view_id = params.opener_id;
|
|
||||||
lcwp.opener_frame_id = params.opener_render_frame_id;
|
|
||||||
lcwp.target_url = params.target_url;
|
|
||||||
lcwp.target_frame_name = params.frame_name;
|
|
||||||
CefContentBrowserClient::Get()->set_last_create_window_params(lcwp);
|
|
||||||
|
|
||||||
// Reply message is not used.
|
// Reply message is not used.
|
||||||
delete reply_msg;
|
delete reply_msg;
|
||||||
|
@ -38,7 +38,7 @@ class CefBrowserMessageFilter : public IPC::MessageFilter {
|
|||||||
void OnGetNewBrowserInfo(
|
void OnGetNewBrowserInfo(
|
||||||
int render_view_routing_id,
|
int render_view_routing_id,
|
||||||
int render_frame_routing_id,
|
int render_frame_routing_id,
|
||||||
CefProcessHostMsg_GetNewBrowserInfo_Params* params);
|
IPC::Message* reply_msg);
|
||||||
void OnCreateWindow(const ViewHostMsg_CreateWindow_Params& params,
|
void OnCreateWindow(const ViewHostMsg_CreateWindow_Params& params,
|
||||||
IPC::Message* reply_msg);
|
IPC::Message* reply_msg);
|
||||||
void OnFrameFocused(int32 render_frame_routing_id);
|
void OnFrameFocused(int32 render_frame_routing_id);
|
||||||
|
199
libcef/browser/browser_platform_delegate.cc
Normal file
199
libcef/browser/browser_platform_delegate.cc
Normal file
@ -0,0 +1,199 @@
|
|||||||
|
// Copyright 2015 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 "libcef/browser/browser_platform_delegate.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
#include "libcef/browser/osr/browser_platform_delegate_osr.h"
|
||||||
|
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||||
|
#include "content/public/browser/render_view_host.h"
|
||||||
|
#include "content/public/browser/render_widget_host.h"
|
||||||
|
|
||||||
|
CefBrowserPlatformDelegate::CefBrowserPlatformDelegate()
|
||||||
|
: browser_(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CefBrowserPlatformDelegate::~CefBrowserPlatformDelegate() {
|
||||||
|
DCHECK(!browser_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::CreateViewForWebContents(
|
||||||
|
content::WebContentsView** view,
|
||||||
|
content::RenderViewHostDelegateView** delegate_view) {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::WebContentsCreated(
|
||||||
|
content::WebContents* web_contents) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::RenderViewCreated(
|
||||||
|
content::RenderViewHost* render_view_host) {
|
||||||
|
// Indicate that the view has an external parent (namely us). This changes the
|
||||||
|
// default view behavior in some cases (e.g. focus handling on Linux).
|
||||||
|
if (render_view_host->GetWidget()->GetView())
|
||||||
|
render_view_host->GetWidget()->GetView()->SetHasExternalParent(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::BrowserCreated(CefBrowserHostImpl* browser) {
|
||||||
|
DCHECK(!browser_);
|
||||||
|
browser_ = browser;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::BrowserDestroyed(CefBrowserHostImpl* browser) {
|
||||||
|
DCHECK(browser_ && browser_ == browser);
|
||||||
|
browser_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefBrowserPlatformDelegate::CreateHostWindow() {
|
||||||
|
NOTREACHED();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::CloseHostWindow() {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(USE_AURA)
|
||||||
|
views::Widget* CefBrowserPlatformDelegate::GetWindowWidget() const {
|
||||||
|
NOTREACHED();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::SendCaptureLostEvent() {
|
||||||
|
content::RenderWidgetHostImpl* widget =
|
||||||
|
content::RenderWidgetHostImpl::From(
|
||||||
|
browser_->web_contents()->GetRenderViewHost()->GetWidget());
|
||||||
|
if (widget)
|
||||||
|
widget->LostCapture();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX))
|
||||||
|
void CefBrowserPlatformDelegate::NotifyMoveOrResizeStarted() {
|
||||||
|
// Dismiss any existing popups.
|
||||||
|
content::RenderViewHost* host = browser_->web_contents()->GetRenderViewHost();
|
||||||
|
if (host)
|
||||||
|
host->NotifyMoveOrResizeStarted();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::SizeTo(int width, int height) {
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(OS_MACOSX)
|
||||||
|
void CefBrowserPlatformDelegate::SetWindowVisibility(bool visible) {
|
||||||
|
content::RenderWidgetHostView* view =
|
||||||
|
browser_->web_contents()->GetRenderWidgetHostView();
|
||||||
|
if (view)
|
||||||
|
view->SetWindowVisibility(visible);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
scoped_ptr<CefFileDialogRunner>
|
||||||
|
CefBrowserPlatformDelegate::CreateFileDialogRunner() {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<CefJavaScriptDialogRunner>
|
||||||
|
CefBrowserPlatformDelegate::CreateJavaScriptDialogRunner() {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::WasHidden(bool hidden) {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::NotifyScreenInfoChanged() {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::Invalidate(cef_paint_element_type_t type) {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::SetWindowlessFrameRate(int frame_rate) {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(OS_MACOSX)
|
||||||
|
CefTextInputContext CefBrowserPlatformDelegate::GetNSTextInputContext() {
|
||||||
|
NOTREACHED();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::HandleKeyEventBeforeTextInputClient(
|
||||||
|
CefEventHandle keyEvent) {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::HandleKeyEventAfterTextInputClient(
|
||||||
|
CefEventHandle keyEvent) {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::DragTargetDragEnter(
|
||||||
|
CefRefPtr<CefDragData> drag_data,
|
||||||
|
const CefMouseEvent& event,
|
||||||
|
cef_drag_operations_mask_t allowed_ops) {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::DragTargetDragOver(
|
||||||
|
const CefMouseEvent& event,
|
||||||
|
cef_drag_operations_mask_t allowed_ops) {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::DragTargetDragLeave() {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::DragTargetDrop(const CefMouseEvent& event) {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::DragSourceEndedAt(
|
||||||
|
int x, int y,
|
||||||
|
cef_drag_operations_mask_t op) {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegate::DragSourceSystemDragEnded() {
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
int CefBrowserPlatformDelegate::TranslateModifiers(uint32 cef_modifiers) {
|
||||||
|
int webkit_modifiers = 0;
|
||||||
|
// Set modifiers based on key state.
|
||||||
|
if (cef_modifiers & EVENTFLAG_SHIFT_DOWN)
|
||||||
|
webkit_modifiers |= blink::WebInputEvent::ShiftKey;
|
||||||
|
if (cef_modifiers & EVENTFLAG_CONTROL_DOWN)
|
||||||
|
webkit_modifiers |= blink::WebInputEvent::ControlKey;
|
||||||
|
if (cef_modifiers & EVENTFLAG_ALT_DOWN)
|
||||||
|
webkit_modifiers |= blink::WebInputEvent::AltKey;
|
||||||
|
if (cef_modifiers & EVENTFLAG_COMMAND_DOWN)
|
||||||
|
webkit_modifiers |= blink::WebInputEvent::MetaKey;
|
||||||
|
if (cef_modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON)
|
||||||
|
webkit_modifiers |= blink::WebInputEvent::LeftButtonDown;
|
||||||
|
if (cef_modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON)
|
||||||
|
webkit_modifiers |= blink::WebInputEvent::MiddleButtonDown;
|
||||||
|
if (cef_modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON)
|
||||||
|
webkit_modifiers |= blink::WebInputEvent::RightButtonDown;
|
||||||
|
if (cef_modifiers & EVENTFLAG_CAPS_LOCK_ON)
|
||||||
|
webkit_modifiers |= blink::WebInputEvent::CapsLockOn;
|
||||||
|
if (cef_modifiers & EVENTFLAG_NUM_LOCK_ON)
|
||||||
|
webkit_modifiers |= blink::WebInputEvent::NumLockOn;
|
||||||
|
if (cef_modifiers & EVENTFLAG_IS_LEFT)
|
||||||
|
webkit_modifiers |= blink::WebInputEvent::IsLeft;
|
||||||
|
if (cef_modifiers & EVENTFLAG_IS_RIGHT)
|
||||||
|
webkit_modifiers |= blink::WebInputEvent::IsRight;
|
||||||
|
if (cef_modifiers & EVENTFLAG_IS_KEY_PAD)
|
||||||
|
webkit_modifiers |= blink::WebInputEvent::IsKeyPad;
|
||||||
|
return webkit_modifiers;
|
||||||
|
}
|
225
libcef/browser/browser_platform_delegate.h
Normal file
225
libcef/browser/browser_platform_delegate.h
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
// Copyright (c) 2015 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions 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 CEF_LIBCEF_BROWSER_BROWSER_PLATFORM_DELEGATE_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_BROWSER_PLATFORM_DELEGATE_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "include/cef_client.h"
|
||||||
|
#include "include/cef_drag_data.h"
|
||||||
|
#include "include/internal/cef_types.h"
|
||||||
|
|
||||||
|
#include "base/callback.h"
|
||||||
|
#include "content/public/browser/web_contents.h"
|
||||||
|
|
||||||
|
namespace blink {
|
||||||
|
class WebMouseEvent;
|
||||||
|
class WebMouseWheelEvent;
|
||||||
|
class WebInputEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace content {
|
||||||
|
struct NativeWebKeyboardEvent;
|
||||||
|
class RenderViewHost;
|
||||||
|
class RenderViewHostDelegateView;
|
||||||
|
class WebContentsView;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(USE_AURA)
|
||||||
|
namespace views {
|
||||||
|
class Widget;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CefBrowserHostImpl;
|
||||||
|
class CefBrowserInfo;
|
||||||
|
class CefFileDialogRunner;
|
||||||
|
class CefJavaScriptDialogRunner;
|
||||||
|
class CefMenuRunner;
|
||||||
|
|
||||||
|
// Provides platform-specific implementations of browser functionality. All
|
||||||
|
// methods are called on the browser process UI thread unless otherwise
|
||||||
|
// indicated.
|
||||||
|
class CefBrowserPlatformDelegate {
|
||||||
|
public:
|
||||||
|
// Create a new CefBrowserPlatformDelegate instance. May be called on multiple
|
||||||
|
// threads.
|
||||||
|
static scoped_ptr<CefBrowserPlatformDelegate> Create(
|
||||||
|
const CefWindowInfo& window_info,
|
||||||
|
const CefBrowserSettings& settings,
|
||||||
|
CefRefPtr<CefClient> client);
|
||||||
|
|
||||||
|
// Called to create the view objects for a new WebContents. Will only be
|
||||||
|
// called a single time per instance. May be called on multiple threads. Only
|
||||||
|
// used with windowless rendering.
|
||||||
|
virtual void CreateViewForWebContents(
|
||||||
|
content::WebContentsView** view,
|
||||||
|
content::RenderViewHostDelegateView** delegate_view);
|
||||||
|
|
||||||
|
// Called after the WebContents for the browser is created. Will only be
|
||||||
|
// called a single time per instance.
|
||||||
|
virtual void WebContentsCreated(content::WebContents* web_contents);
|
||||||
|
|
||||||
|
// Called after the RenderViewHost is created.
|
||||||
|
virtual void RenderViewCreated(
|
||||||
|
content::RenderViewHost* render_view_host);
|
||||||
|
|
||||||
|
// Called after the owning CefBrowserHostImpl is created. Will only be called
|
||||||
|
// a single time per instance.
|
||||||
|
virtual void BrowserCreated(CefBrowserHostImpl* browser);
|
||||||
|
|
||||||
|
// Called before the owning CefBrowserHostImpl is destroyed. Will only be
|
||||||
|
// called a single time per instance. All references to the CefBrowserHostImpl
|
||||||
|
// and WebContents should be cleared when this method is called.
|
||||||
|
virtual void BrowserDestroyed(CefBrowserHostImpl* browser);
|
||||||
|
|
||||||
|
// Create the window that hosts the browser. Will only be called a single time
|
||||||
|
// per instance. Only used with windowed rendering.
|
||||||
|
virtual bool CreateHostWindow();
|
||||||
|
|
||||||
|
// Sends a message to close the window that hosts the browser. On native
|
||||||
|
// platforms this will be done via the OS. DestroyBrowser will be called after
|
||||||
|
// the native window has closed. Only used with windowed rendering.
|
||||||
|
virtual void CloseHostWindow();
|
||||||
|
|
||||||
|
// Return the OS handle for the window that hosts the browser. For windowed
|
||||||
|
// rendering this will return the most immediate parent window handle. For
|
||||||
|
// windowless rendering this will return the parent window handle specified by
|
||||||
|
// the client, which may be NULL. May be called on multiple threads.
|
||||||
|
virtual CefWindowHandle GetHostWindowHandle() const = 0;
|
||||||
|
|
||||||
|
#if defined(USE_AURA)
|
||||||
|
// Returns the Widget owner for the browser window. Only used with windowed
|
||||||
|
// rendering.
|
||||||
|
virtual views::Widget* GetWindowWidget() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Notify the window that it was resized.
|
||||||
|
virtual void WasResized() = 0;
|
||||||
|
|
||||||
|
// Send input events.
|
||||||
|
virtual void SendKeyEvent(const content::NativeWebKeyboardEvent& event) = 0;
|
||||||
|
virtual void SendMouseEvent(const blink::WebMouseEvent& event) = 0;
|
||||||
|
virtual void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event) = 0;
|
||||||
|
|
||||||
|
// Send focus event. The browser's WebContents may be NULL when this method is
|
||||||
|
// called.
|
||||||
|
virtual void SendFocusEvent(bool setFocus) = 0;
|
||||||
|
|
||||||
|
// Send capture lost event.
|
||||||
|
virtual void SendCaptureLostEvent();
|
||||||
|
|
||||||
|
#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX))
|
||||||
|
// The window hosting the browser is about to be moved or resized. Only used
|
||||||
|
// on Windows and Linux.
|
||||||
|
virtual void NotifyMoveOrResizeStarted();
|
||||||
|
|
||||||
|
// Resize the host window to the given dimensions. Only used with windowed
|
||||||
|
// rendering on Windows and Linux.
|
||||||
|
virtual void SizeTo(int width, int height);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(OS_MACOSX)
|
||||||
|
// Set or remove host window visibility. Only used on OS X.
|
||||||
|
virtual void SetWindowVisibility(bool visible);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Convert from view coordinates to screen coordinates.
|
||||||
|
virtual gfx::Point GetScreenPoint(const gfx::Point& view) const = 0;
|
||||||
|
|
||||||
|
// Open the specified text in the default text editor.
|
||||||
|
virtual void ViewText(const std::string& text) = 0;
|
||||||
|
|
||||||
|
// Forward the keyboard event to the application or frame window to allow
|
||||||
|
// processing of shortcut keys.
|
||||||
|
virtual void HandleKeyboardEvent(
|
||||||
|
const content::NativeWebKeyboardEvent& event) = 0;
|
||||||
|
|
||||||
|
// Invoke platform specific handling for the external protocol.
|
||||||
|
virtual void HandleExternalProtocol(const GURL& url) = 0;
|
||||||
|
|
||||||
|
// Translate CEF events to Chromium/Blink events.
|
||||||
|
virtual void TranslateKeyEvent(content::NativeWebKeyboardEvent& result,
|
||||||
|
const CefKeyEvent& key_event) const = 0;
|
||||||
|
virtual void TranslateClickEvent(blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
CefBrowserHost::MouseButtonType type,
|
||||||
|
bool mouseUp, int clickCount) const = 0;
|
||||||
|
virtual void TranslateMoveEvent(blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
bool mouseLeave) const = 0;
|
||||||
|
virtual void TranslateWheelEvent(blink::WebMouseWheelEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
int deltaX, int deltaY) const = 0;
|
||||||
|
|
||||||
|
// Returns the OS event handle, if any, associated with |event|.
|
||||||
|
virtual CefEventHandle GetEventHandle(
|
||||||
|
const content::NativeWebKeyboardEvent& event) const = 0;
|
||||||
|
|
||||||
|
// Create the platform-specific file dialog runner.
|
||||||
|
virtual scoped_ptr<CefFileDialogRunner> CreateFileDialogRunner();
|
||||||
|
|
||||||
|
// Create the platform-specific JavaScript dialog runner.
|
||||||
|
virtual scoped_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner();
|
||||||
|
|
||||||
|
// Create the platform-specific menu runner.
|
||||||
|
virtual scoped_ptr<CefMenuRunner> CreateMenuRunner() = 0;
|
||||||
|
|
||||||
|
// Returns true if this delegate implements windowless rendering. May be
|
||||||
|
// called on multiple threads.
|
||||||
|
virtual bool IsWindowless() const = 0;
|
||||||
|
|
||||||
|
// Notify the browser that it was hidden. Only used with windowless rendering.
|
||||||
|
virtual void WasHidden(bool hidden);
|
||||||
|
|
||||||
|
// Notify the browser that screen information has changed. Only used with
|
||||||
|
// windowless rendering.
|
||||||
|
virtual void NotifyScreenInfoChanged();
|
||||||
|
|
||||||
|
// Invalidate the view. Only used with windowless rendering.
|
||||||
|
virtual void Invalidate(cef_paint_element_type_t type);
|
||||||
|
|
||||||
|
// Set the windowless frame rate. Only used with windowless rendering.
|
||||||
|
virtual void SetWindowlessFrameRate(int frame_rate);
|
||||||
|
|
||||||
|
#if defined(OS_MACOSX)
|
||||||
|
// IME-related callbacks. See documentation in CefRenderHandler. Only used
|
||||||
|
// with windowless rendering on OS X.
|
||||||
|
virtual CefTextInputContext GetNSTextInputContext();
|
||||||
|
virtual void HandleKeyEventBeforeTextInputClient(CefEventHandle keyEvent);
|
||||||
|
virtual void HandleKeyEventAfterTextInputClient(CefEventHandle keyEvent);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Drag/drop-related callbacks. See documentation in CefRenderHandler. Only
|
||||||
|
// used with windowless rendering.
|
||||||
|
virtual void DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,
|
||||||
|
const CefMouseEvent& event,
|
||||||
|
cef_drag_operations_mask_t allowed_ops);
|
||||||
|
virtual void DragTargetDragOver(const CefMouseEvent& event,
|
||||||
|
cef_drag_operations_mask_t allowed_ops);
|
||||||
|
virtual void DragTargetDragLeave();
|
||||||
|
virtual void DragTargetDrop(const CefMouseEvent& event);
|
||||||
|
virtual void DragSourceEndedAt(int x, int y,
|
||||||
|
cef_drag_operations_mask_t op);
|
||||||
|
virtual void DragSourceSystemDragEnded();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Allow deletion via scoped_ptr only.
|
||||||
|
friend struct base::DefaultDeleter<CefBrowserPlatformDelegate>;
|
||||||
|
|
||||||
|
CefBrowserPlatformDelegate();
|
||||||
|
virtual ~CefBrowserPlatformDelegate();
|
||||||
|
|
||||||
|
static int TranslateModifiers(uint32 cef_modifiers);
|
||||||
|
|
||||||
|
CefBrowserHostImpl *browser_; // Not owned by this object.
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CefBrowserPlatformDelegate);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_BROWSER_PLATFORM_DELEGATE_H_
|
62
libcef/browser/browser_platform_delegate_create.cc
Normal file
62
libcef/browser/browser_platform_delegate_create.cc
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
// Copyright 2015 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 "libcef/browser/browser_platform_delegate.h"
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
#include "libcef/browser/native/browser_platform_delegate_native_win.h"
|
||||||
|
#include "libcef/browser/osr/browser_platform_delegate_osr_win.h"
|
||||||
|
#elif defined(OS_MACOSX)
|
||||||
|
#include "libcef/browser/native/browser_platform_delegate_native_mac.h"
|
||||||
|
#include "libcef/browser/osr/browser_platform_delegate_osr_mac.h"
|
||||||
|
#elif defined(OS_LINUX)
|
||||||
|
#include "libcef/browser/native/browser_platform_delegate_native_linux.h"
|
||||||
|
#include "libcef/browser/osr/browser_platform_delegate_osr_linux.h"
|
||||||
|
#else
|
||||||
|
#error A delegate implementation is not available for your platform.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegateNative> CreateNativeDelegate(
|
||||||
|
const CefWindowInfo& window_info) {
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
return make_scoped_ptr(new CefBrowserPlatformDelegateNativeWin(window_info));
|
||||||
|
#elif defined(OS_MACOSX)
|
||||||
|
return make_scoped_ptr(new CefBrowserPlatformDelegateNativeMac(window_info));
|
||||||
|
#elif defined(OS_LINUX)
|
||||||
|
return make_scoped_ptr(
|
||||||
|
new CefBrowserPlatformDelegateNativeLinux(window_info));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegateOsr> CreateOSRDelegate(
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegateNative> native_delegate) {
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
return make_scoped_ptr(
|
||||||
|
new CefBrowserPlatformDelegateOsrWin(native_delegate.Pass()));
|
||||||
|
#elif defined(OS_MACOSX)
|
||||||
|
return make_scoped_ptr(
|
||||||
|
new CefBrowserPlatformDelegateOsrMac(native_delegate.Pass()));
|
||||||
|
#elif defined(OS_LINUX)
|
||||||
|
return make_scoped_ptr(
|
||||||
|
new CefBrowserPlatformDelegateOsrLinux(native_delegate.Pass()));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// static
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegate> CefBrowserPlatformDelegate::Create(
|
||||||
|
const CefWindowInfo& window_info,
|
||||||
|
const CefBrowserSettings& settings,
|
||||||
|
CefRefPtr<CefClient> client) {
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegateNative> native_delegate =
|
||||||
|
CreateNativeDelegate(window_info);
|
||||||
|
if (window_info.windowless_rendering_enabled &&
|
||||||
|
client->GetRenderHandler().get()) {
|
||||||
|
return CreateOSRDelegate(native_delegate.Pass());
|
||||||
|
}
|
||||||
|
return native_delegate.Pass();
|
||||||
|
}
|
@ -7,13 +7,14 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "libcef/browser/browser_info.h"
|
#include "libcef/browser/browser_info.h"
|
||||||
|
#include "libcef/browser/browser_info_manager.h"
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
#include "libcef/browser/browser_main.h"
|
#include "libcef/browser/browser_main.h"
|
||||||
#include "libcef/browser/browser_message_filter.h"
|
#include "libcef/browser/browser_message_filter.h"
|
||||||
|
#include "libcef/browser/browser_platform_delegate.h"
|
||||||
#include "libcef/browser/chrome_scheme_handler.h"
|
#include "libcef/browser/chrome_scheme_handler.h"
|
||||||
#include "libcef/browser/context.h"
|
#include "libcef/browser/context.h"
|
||||||
#include "libcef/browser/devtools_delegate.h"
|
#include "libcef/browser/devtools_delegate.h"
|
||||||
#include "libcef/browser/extensions/browser_extensions_util.h"
|
|
||||||
#include "libcef/browser/extensions/extension_system.h"
|
#include "libcef/browser/extensions/extension_system.h"
|
||||||
#include "libcef/browser/media_capture_devices_dispatcher.h"
|
#include "libcef/browser/media_capture_devices_dispatcher.h"
|
||||||
#include "libcef/browser/pepper/browser_pepper_host_factory.h"
|
#include "libcef/browser/pepper/browser_pepper_host_factory.h"
|
||||||
@ -277,37 +278,6 @@ class CefQuotaPermissionContext : public content::QuotaPermissionContext {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(CefQuotaPermissionContext);
|
DISALLOW_COPY_AND_ASSIGN(CefQuotaPermissionContext);
|
||||||
};
|
};
|
||||||
|
|
||||||
void TranslatePopupFeatures(const blink::WebWindowFeatures& webKitFeatures,
|
|
||||||
CefPopupFeatures& features) {
|
|
||||||
features.x = static_cast<int>(webKitFeatures.x);
|
|
||||||
features.xSet = webKitFeatures.xSet;
|
|
||||||
features.y = static_cast<int>(webKitFeatures.y);
|
|
||||||
features.ySet = webKitFeatures.ySet;
|
|
||||||
features.width = static_cast<int>(webKitFeatures.width);
|
|
||||||
features.widthSet = webKitFeatures.widthSet;
|
|
||||||
features.height = static_cast<int>(webKitFeatures.height);
|
|
||||||
features.heightSet = webKitFeatures.heightSet;
|
|
||||||
|
|
||||||
features.menuBarVisible = webKitFeatures.menuBarVisible;
|
|
||||||
features.statusBarVisible = webKitFeatures.statusBarVisible;
|
|
||||||
features.toolBarVisible = webKitFeatures.toolBarVisible;
|
|
||||||
features.locationBarVisible = webKitFeatures.locationBarVisible;
|
|
||||||
features.scrollbarsVisible = webKitFeatures.scrollbarsVisible;
|
|
||||||
features.resizable = webKitFeatures.resizable;
|
|
||||||
|
|
||||||
features.fullscreen = webKitFeatures.fullscreen;
|
|
||||||
features.dialog = webKitFeatures.dialog;
|
|
||||||
features.additionalFeatures = NULL;
|
|
||||||
if (webKitFeatures.additionalFeatures.size() > 0)
|
|
||||||
features.additionalFeatures = cef_string_list_alloc();
|
|
||||||
|
|
||||||
CefString str;
|
|
||||||
for (unsigned int i = 0; i < webKitFeatures.additionalFeatures.size(); ++i) {
|
|
||||||
str = base::string16(webKitFeatures.additionalFeatures[i]);
|
|
||||||
cef_string_list_append(features.additionalFeatures, str.GetStruct());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(OS_POSIX) && !defined(OS_MACOSX)
|
#if defined(OS_POSIX) && !defined(OS_MACOSX)
|
||||||
breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
|
breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
|
||||||
const std::string& process_type) {
|
const std::string& process_type) {
|
||||||
@ -436,13 +406,10 @@ void FindFrameHostForNavigationHandle(
|
|||||||
|
|
||||||
|
|
||||||
CefContentBrowserClient::CefContentBrowserClient()
|
CefContentBrowserClient::CefContentBrowserClient()
|
||||||
: browser_main_parts_(NULL),
|
: browser_main_parts_(NULL) {
|
||||||
next_browser_id_(0) {
|
|
||||||
plugin_service_filter_.reset(new CefPluginServiceFilter);
|
plugin_service_filter_.reset(new CefPluginServiceFilter);
|
||||||
content::PluginServiceImpl::GetInstance()->SetFilter(
|
content::PluginServiceImpl::GetInstance()->SetFilter(
|
||||||
plugin_service_filter_.get());
|
plugin_service_filter_.get());
|
||||||
|
|
||||||
last_create_window_params_.opener_process_id = MSG_ROUTING_NONE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CefContentBrowserClient::~CefContentBrowserClient() {
|
CefContentBrowserClient::~CefContentBrowserClient() {
|
||||||
@ -454,178 +421,6 @@ CefContentBrowserClient* CefContentBrowserClient::Get() {
|
|||||||
CefContentClient::Get()->browser());
|
CefContentClient::Get()->browser());
|
||||||
}
|
}
|
||||||
|
|
||||||
scoped_refptr<CefBrowserInfo> CefContentBrowserClient::CreateBrowserInfo(
|
|
||||||
bool is_popup) {
|
|
||||||
base::AutoLock lock_scope(browser_info_lock_);
|
|
||||||
|
|
||||||
scoped_refptr<CefBrowserInfo> browser_info =
|
|
||||||
new CefBrowserInfo(++next_browser_id_, is_popup);
|
|
||||||
browser_info_list_.push_back(browser_info);
|
|
||||||
return browser_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
scoped_refptr<CefBrowserInfo>
|
|
||||||
CefContentBrowserClient::GetOrCreateBrowserInfo(
|
|
||||||
int render_view_process_id,
|
|
||||||
int render_view_routing_id,
|
|
||||||
int render_frame_process_id,
|
|
||||||
int render_frame_routing_id,
|
|
||||||
bool* is_guest_view) {
|
|
||||||
base::AutoLock lock_scope(browser_info_lock_);
|
|
||||||
|
|
||||||
if (is_guest_view)
|
|
||||||
*is_guest_view = false;
|
|
||||||
|
|
||||||
BrowserInfoList::const_iterator it = browser_info_list_.begin();
|
|
||||||
for (; it != browser_info_list_.end(); ++it) {
|
|
||||||
const scoped_refptr<CefBrowserInfo>& browser_info = *it;
|
|
||||||
if (browser_info->render_id_manager()->is_render_view_id_match(
|
|
||||||
render_view_process_id, render_view_routing_id)) {
|
|
||||||
// Make sure the frame id is also registered.
|
|
||||||
browser_info->render_id_manager()->add_render_frame_id(
|
|
||||||
render_frame_process_id, render_frame_routing_id);
|
|
||||||
return browser_info;
|
|
||||||
}
|
|
||||||
if (browser_info->render_id_manager()->is_render_frame_id_match(
|
|
||||||
render_frame_process_id, render_frame_routing_id)) {
|
|
||||||
// Make sure the view id is also registered.
|
|
||||||
browser_info->render_id_manager()->add_render_view_id(
|
|
||||||
render_view_process_id, render_view_routing_id);
|
|
||||||
return browser_info;
|
|
||||||
}
|
|
||||||
if (extensions::ExtensionsEnabled() &&
|
|
||||||
(browser_info->guest_render_id_manager()->is_render_view_id_match(
|
|
||||||
render_view_process_id, render_view_routing_id) ||
|
|
||||||
browser_info->guest_render_id_manager()->is_render_frame_id_match(
|
|
||||||
render_frame_process_id, render_frame_routing_id))) {
|
|
||||||
if (is_guest_view)
|
|
||||||
*is_guest_view = true;
|
|
||||||
return browser_info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must be a popup if it hasn't already been created.
|
|
||||||
scoped_refptr<CefBrowserInfo> browser_info =
|
|
||||||
new CefBrowserInfo(++next_browser_id_, true);
|
|
||||||
browser_info->render_id_manager()->add_render_view_id(
|
|
||||||
render_view_process_id, render_view_routing_id);
|
|
||||||
browser_info->render_id_manager()->add_render_frame_id(
|
|
||||||
render_frame_process_id, render_frame_routing_id);
|
|
||||||
browser_info_list_.push_back(browser_info);
|
|
||||||
return browser_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefContentBrowserClient::RemoveBrowserInfo(
|
|
||||||
scoped_refptr<CefBrowserInfo> browser_info) {
|
|
||||||
base::AutoLock lock_scope(browser_info_lock_);
|
|
||||||
|
|
||||||
BrowserInfoList::iterator it = browser_info_list_.begin();
|
|
||||||
for (; it != browser_info_list_.end(); ++it) {
|
|
||||||
if (*it == browser_info) {
|
|
||||||
browser_info_list_.erase(it);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NOTREACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefContentBrowserClient::DestroyAllBrowsers() {
|
|
||||||
BrowserInfoList list;
|
|
||||||
|
|
||||||
{
|
|
||||||
base::AutoLock lock_scope(browser_info_lock_);
|
|
||||||
list = browser_info_list_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Destroy any remaining browser windows.
|
|
||||||
if (!list.empty()) {
|
|
||||||
BrowserInfoList::iterator it = list.begin();
|
|
||||||
for (; it != list.end(); ++it) {
|
|
||||||
CefRefPtr<CefBrowserHostImpl> browser = (*it)->browser();
|
|
||||||
if (browser.get()) {
|
|
||||||
// DestroyBrowser will call RemoveBrowserInfo.
|
|
||||||
browser->DestroyBrowser();
|
|
||||||
} else {
|
|
||||||
// Canceled popup windows may have browser info but no browser because
|
|
||||||
// CefBrowserMessageFilter::OnGetNewBrowserInfo is still called.
|
|
||||||
DCHECK((*it)->is_popup());
|
|
||||||
RemoveBrowserInfo(*it);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
{
|
|
||||||
// Verify that all browser windows have been destroyed.
|
|
||||||
base::AutoLock lock_scope(browser_info_lock_);
|
|
||||||
DCHECK(browser_info_list_.empty());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
scoped_refptr<CefBrowserInfo> CefContentBrowserClient::GetBrowserInfoForView(
|
|
||||||
int render_process_id,
|
|
||||||
int render_routing_id,
|
|
||||||
bool* is_guest_view) {
|
|
||||||
base::AutoLock lock_scope(browser_info_lock_);
|
|
||||||
|
|
||||||
if (is_guest_view)
|
|
||||||
*is_guest_view = false;
|
|
||||||
|
|
||||||
BrowserInfoList::const_iterator it = browser_info_list_.begin();
|
|
||||||
for (; it != browser_info_list_.end(); ++it) {
|
|
||||||
const scoped_refptr<CefBrowserInfo>& browser_info = *it;
|
|
||||||
if (browser_info->render_id_manager()->is_render_view_id_match(
|
|
||||||
render_process_id, render_routing_id)) {
|
|
||||||
return browser_info;
|
|
||||||
}
|
|
||||||
if (extensions::ExtensionsEnabled() &&
|
|
||||||
browser_info->guest_render_id_manager()->is_render_view_id_match(
|
|
||||||
render_process_id, render_routing_id)) {
|
|
||||||
if (is_guest_view)
|
|
||||||
*is_guest_view = true;
|
|
||||||
return browser_info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(WARNING) << "No browser info matching view process id " <<
|
|
||||||
render_process_id << " and routing id " << render_routing_id;
|
|
||||||
|
|
||||||
return scoped_refptr<CefBrowserInfo>();
|
|
||||||
}
|
|
||||||
|
|
||||||
scoped_refptr<CefBrowserInfo> CefContentBrowserClient::GetBrowserInfoForFrame(
|
|
||||||
int render_process_id,
|
|
||||||
int render_routing_id,
|
|
||||||
bool* is_guest_view) {
|
|
||||||
base::AutoLock lock_scope(browser_info_lock_);
|
|
||||||
|
|
||||||
if (is_guest_view)
|
|
||||||
*is_guest_view = false;
|
|
||||||
|
|
||||||
BrowserInfoList::const_iterator it = browser_info_list_.begin();
|
|
||||||
for (; it != browser_info_list_.end(); ++it) {
|
|
||||||
const scoped_refptr<CefBrowserInfo>& browser_info = *it;
|
|
||||||
if (browser_info->render_id_manager()->is_render_frame_id_match(
|
|
||||||
render_process_id, render_routing_id)) {
|
|
||||||
return browser_info;
|
|
||||||
}
|
|
||||||
if (extensions::ExtensionsEnabled() &&
|
|
||||||
browser_info->guest_render_id_manager()->is_render_frame_id_match(
|
|
||||||
render_process_id, render_routing_id)) {
|
|
||||||
if (is_guest_view)
|
|
||||||
*is_guest_view = true;
|
|
||||||
return browser_info;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(WARNING) << "No browser info matching frame process id " <<
|
|
||||||
render_process_id << " and routing id " << render_routing_id;
|
|
||||||
|
|
||||||
return scoped_refptr<CefBrowserInfo>();
|
|
||||||
}
|
|
||||||
|
|
||||||
content::BrowserMainParts* CefContentBrowserClient::CreateBrowserMainParts(
|
content::BrowserMainParts* CefContentBrowserClient::CreateBrowserMainParts(
|
||||||
const content::MainFunctionParams& parameters) {
|
const content::MainFunctionParams& parameters) {
|
||||||
browser_main_parts_ = new CefBrowserMainParts(parameters);
|
browser_main_parts_ = new CefBrowserMainParts(parameters);
|
||||||
@ -662,6 +457,8 @@ void CefContentBrowserClient::RenderProcessWillLaunch(
|
|||||||
new extensions::ExtensionsGuestViewMessageFilter(id, browser_context));
|
new extensions::ExtensionsGuestViewMessageFilter(id, browser_context));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
host->AddObserver(CefBrowserInfoManager::GetInstance());
|
||||||
|
|
||||||
host->Send(new CefProcessMsg_SetIsIncognitoProcess(
|
host->Send(new CefProcessMsg_SetIsIncognitoProcess(
|
||||||
browser_context->IsOffTheRecord()));
|
browser_context->IsOffTheRecord()));
|
||||||
}
|
}
|
||||||
@ -959,102 +756,10 @@ bool CefContentBrowserClient::CanCreateWindow(
|
|||||||
CEF_REQUIRE_IOT();
|
CEF_REQUIRE_IOT();
|
||||||
*no_javascript_access = false;
|
*no_javascript_access = false;
|
||||||
|
|
||||||
DCHECK_NE(last_create_window_params_.opener_process_id, MSG_ROUTING_NONE);
|
return CefBrowserInfoManager::GetInstance()->CanCreateWindow(
|
||||||
if (last_create_window_params_.opener_process_id == MSG_ROUTING_NONE)
|
target_url, referrer, disposition, features, user_gesture,
|
||||||
return false;
|
opener_suppressed, render_process_id, opener_render_view_id,
|
||||||
|
opener_render_frame_id, no_javascript_access);
|
||||||
bool is_guest_view = false;
|
|
||||||
CefRefPtr<CefBrowserHostImpl> browser =
|
|
||||||
extensions::GetOwnerBrowserForView(
|
|
||||||
last_create_window_params_.opener_process_id,
|
|
||||||
last_create_window_params_.opener_view_id,
|
|
||||||
&is_guest_view);
|
|
||||||
DCHECK(browser.get());
|
|
||||||
if (!browser.get()) {
|
|
||||||
// Cancel the popup.
|
|
||||||
last_create_window_params_.opener_process_id = MSG_ROUTING_NONE;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_guest_view) {
|
|
||||||
content::OpenURLParams params(target_url,
|
|
||||||
referrer,
|
|
||||||
disposition,
|
|
||||||
ui::PAGE_TRANSITION_LINK,
|
|
||||||
true);
|
|
||||||
params.user_gesture = user_gesture;
|
|
||||||
|
|
||||||
// Pass navigation to the owner browser.
|
|
||||||
CEF_POST_TASK(CEF_UIT,
|
|
||||||
base::Bind(base::IgnoreResult(&CefBrowserHostImpl::OpenURLFromTab),
|
|
||||||
browser.get(), nullptr, params));
|
|
||||||
|
|
||||||
// Cancel the popup.
|
|
||||||
last_create_window_params_.opener_process_id = MSG_ROUTING_NONE;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRefPtr<CefClient> client = browser->GetClient();
|
|
||||||
bool allow = true;
|
|
||||||
|
|
||||||
scoped_ptr<CefBrowserHostImpl::PendingPopupInfo> pending_info;
|
|
||||||
pending_info.reset(new CefBrowserHostImpl::PendingPopupInfo);
|
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
pending_info->window_info.SetAsPopup(NULL, CefString());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Start with the current browser's settings.
|
|
||||||
pending_info->client = client;
|
|
||||||
pending_info->settings = browser->settings();
|
|
||||||
|
|
||||||
if (client.get()) {
|
|
||||||
CefRefPtr<CefLifeSpanHandler> handler = client->GetLifeSpanHandler();
|
|
||||||
if (handler.get()) {
|
|
||||||
CefRefPtr<CefFrame> frame =
|
|
||||||
browser->GetFrame(last_create_window_params_.opener_frame_id);
|
|
||||||
|
|
||||||
CefPopupFeatures cef_features;
|
|
||||||
TranslatePopupFeatures(features, cef_features);
|
|
||||||
|
|
||||||
#if (defined(OS_WIN) || defined(OS_MACOSX))
|
|
||||||
// Default to the size from the popup features.
|
|
||||||
if (cef_features.xSet)
|
|
||||||
pending_info->window_info.x = cef_features.x;
|
|
||||||
if (cef_features.ySet)
|
|
||||||
pending_info->window_info.y = cef_features.y;
|
|
||||||
if (cef_features.widthSet)
|
|
||||||
pending_info->window_info.width = cef_features.width;
|
|
||||||
if (cef_features.heightSet)
|
|
||||||
pending_info->window_info.height = cef_features.height;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
allow = !handler->OnBeforePopup(browser.get(),
|
|
||||||
frame,
|
|
||||||
last_create_window_params_.target_url.spec(),
|
|
||||||
last_create_window_params_.target_frame_name,
|
|
||||||
static_cast<cef_window_open_disposition_t>(disposition),
|
|
||||||
user_gesture,
|
|
||||||
cef_features,
|
|
||||||
pending_info->window_info,
|
|
||||||
pending_info->client,
|
|
||||||
pending_info->settings,
|
|
||||||
no_javascript_access);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allow) {
|
|
||||||
CefRefPtr<CefClient> pending_client = pending_info->client;
|
|
||||||
allow = browser->SetPendingPopupInfo(pending_info.Pass());
|
|
||||||
if (!allow) {
|
|
||||||
LOG(WARNING) << "Creation of popup window denied because one is already "
|
|
||||||
"pending.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
last_create_window_params_.opener_process_id = MSG_ROUTING_NONE;
|
|
||||||
|
|
||||||
return allow;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefContentBrowserClient::ResourceDispatcherHostCreated() {
|
void CefContentBrowserClient::ResourceDispatcherHostCreated() {
|
||||||
@ -1198,12 +903,6 @@ void CefContentBrowserClient::RegisterCustomScheme(const std::string& scheme) {
|
|||||||
policy->RegisterWebSafeScheme(scheme);
|
policy->RegisterWebSafeScheme(scheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefContentBrowserClient::set_last_create_window_params(
|
|
||||||
const LastCreateWindowParams& params) {
|
|
||||||
CEF_REQUIRE_IOT();
|
|
||||||
last_create_window_params_ = params;
|
|
||||||
}
|
|
||||||
|
|
||||||
scoped_refptr<CefBrowserContextImpl>
|
scoped_refptr<CefBrowserContextImpl>
|
||||||
CefContentBrowserClient::browser_context() const {
|
CefContentBrowserClient::browser_context() const {
|
||||||
return browser_main_parts_->browser_context();
|
return browser_main_parts_->browser_context();
|
||||||
|
@ -6,9 +6,6 @@
|
|||||||
#define CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_
|
#define CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <list>
|
|
||||||
#include <map>
|
|
||||||
#include <set>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -19,13 +16,9 @@
|
|||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
#include "base/memory/ref_counted.h"
|
#include "base/memory/ref_counted.h"
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "base/memory/scoped_ptr.h"
|
||||||
#include "base/synchronization/lock.h"
|
|
||||||
#include "content/public/browser/content_browser_client.h"
|
#include "content/public/browser/content_browser_client.h"
|
||||||
#include "third_party/skia/include/core/SkColor.h"
|
#include "third_party/skia/include/core/SkColor.h"
|
||||||
#include "url/gurl.h"
|
|
||||||
|
|
||||||
class CefBrowserHostImpl;
|
|
||||||
class CefBrowserInfo;
|
|
||||||
class CefBrowserMainParts;
|
class CefBrowserMainParts;
|
||||||
class CefDevToolsDelegate;
|
class CefDevToolsDelegate;
|
||||||
class CefResourceDispatcherHostDelegate;
|
class CefResourceDispatcherHostDelegate;
|
||||||
@ -43,38 +36,6 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
|
|||||||
// Returns the singleton CefContentBrowserClient instance.
|
// Returns the singleton CefContentBrowserClient instance.
|
||||||
static CefContentBrowserClient* Get();
|
static CefContentBrowserClient* Get();
|
||||||
|
|
||||||
// Methods for managing CefBrowserInfo life span. Do not add new callers of
|
|
||||||
// these methods.
|
|
||||||
// During popup window creation there is a race between the call to
|
|
||||||
// CefBrowserMessageFilter::OnGetNewBrowserInfo on the IO thread and the call
|
|
||||||
// to CefBrowserHostImpl::ShouldCreateWebContents on the UI thread. To resolve
|
|
||||||
// this race CefBrowserInfo may be created when requested for the first time
|
|
||||||
// and before the associated CefBrowserHostImpl is created.
|
|
||||||
// |is_guest_view| will be set to true if the IDs match a guest view
|
|
||||||
// associated with the returned browser info instead of the browser itself.
|
|
||||||
scoped_refptr<CefBrowserInfo> CreateBrowserInfo(bool is_popup);
|
|
||||||
scoped_refptr<CefBrowserInfo> GetOrCreateBrowserInfo(
|
|
||||||
int render_view_process_id,
|
|
||||||
int render_view_routing_id,
|
|
||||||
int render_frame_process_id,
|
|
||||||
int render_frame_routing_id,
|
|
||||||
bool* is_guest_view);
|
|
||||||
void RemoveBrowserInfo(scoped_refptr<CefBrowserInfo> browser_info);
|
|
||||||
void DestroyAllBrowsers();
|
|
||||||
|
|
||||||
// Retrieves the CefBrowserInfo matching the specified IDs or an empty
|
|
||||||
// pointer if no match is found. It is allowed to add new callers of this
|
|
||||||
// method but consider using CefBrowserHostImpl::GetBrowserFor[View|Frame]()
|
|
||||||
// or extensions::GetOwnerBrowserForView() instead.
|
|
||||||
// |is_guest_view| will be set to true if the IDs match a guest view
|
|
||||||
// associated with the returned browser info instead of the browser itself.
|
|
||||||
scoped_refptr<CefBrowserInfo> GetBrowserInfoForView(int render_process_id,
|
|
||||||
int render_routing_id,
|
|
||||||
bool* is_guest_view);
|
|
||||||
scoped_refptr<CefBrowserInfo> GetBrowserInfoForFrame(int render_process_id,
|
|
||||||
int render_routing_id,
|
|
||||||
bool* is_guest_view);
|
|
||||||
|
|
||||||
// ContentBrowserClient implementation.
|
// ContentBrowserClient implementation.
|
||||||
content::BrowserMainParts* CreateBrowserMainParts(
|
content::BrowserMainParts* CreateBrowserMainParts(
|
||||||
const content::MainFunctionParams& parameters) override;
|
const content::MainFunctionParams& parameters) override;
|
||||||
@ -162,17 +123,6 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
|
|||||||
// Perform browser process registration for the custom scheme.
|
// Perform browser process registration for the custom scheme.
|
||||||
void RegisterCustomScheme(const std::string& scheme);
|
void RegisterCustomScheme(const std::string& scheme);
|
||||||
|
|
||||||
// Store additional state from the ViewHostMsg_CreateWindow message that will
|
|
||||||
// be used when CanCreateWindow() is called.
|
|
||||||
struct LastCreateWindowParams {
|
|
||||||
int opener_process_id;
|
|
||||||
int opener_view_id;
|
|
||||||
int64 opener_frame_id;
|
|
||||||
GURL target_url;
|
|
||||||
std::string target_frame_name;
|
|
||||||
};
|
|
||||||
void set_last_create_window_params(const LastCreateWindowParams& params);
|
|
||||||
|
|
||||||
scoped_refptr<CefBrowserContextImpl> browser_context() const;
|
scoped_refptr<CefBrowserContextImpl> browser_context() const;
|
||||||
CefDevToolsDelegate* devtools_delegate() const;
|
CefDevToolsDelegate* devtools_delegate() const;
|
||||||
|
|
||||||
@ -182,16 +132,6 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
|
|||||||
scoped_ptr<content::PluginServiceFilter> plugin_service_filter_;
|
scoped_ptr<content::PluginServiceFilter> plugin_service_filter_;
|
||||||
scoped_ptr<CefResourceDispatcherHostDelegate>
|
scoped_ptr<CefResourceDispatcherHostDelegate>
|
||||||
resource_dispatcher_host_delegate_;
|
resource_dispatcher_host_delegate_;
|
||||||
|
|
||||||
base::Lock browser_info_lock_;
|
|
||||||
|
|
||||||
// Access must be protected by |browser_info_lock_|.
|
|
||||||
typedef std::list<scoped_refptr<CefBrowserInfo> > BrowserInfoList;
|
|
||||||
BrowserInfoList browser_info_list_;
|
|
||||||
int next_browser_id_;
|
|
||||||
|
|
||||||
// Only accessed on the IO thread.
|
|
||||||
LastCreateWindowParams last_create_window_params_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_
|
#endif // CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "libcef/browser/browser_context.h"
|
#include "libcef/browser/browser_context.h"
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
#include "libcef/browser/browser_info.h"
|
#include "libcef/browser/browser_info.h"
|
||||||
|
#include "libcef/browser/browser_info_manager.h"
|
||||||
#include "libcef/browser/browser_main.h"
|
#include "libcef/browser/browser_main.h"
|
||||||
#include "libcef/browser/browser_message_loop.h"
|
#include "libcef/browser/browser_message_loop.h"
|
||||||
#include "libcef/browser/chrome_browser_process_stub.h"
|
#include "libcef/browser/chrome_browser_process_stub.h"
|
||||||
@ -246,6 +247,7 @@ bool CefContext::Initialize(const CefMainArgs& args,
|
|||||||
|
|
||||||
main_delegate_.reset(new CefMainDelegate(application));
|
main_delegate_.reset(new CefMainDelegate(application));
|
||||||
main_runner_.reset(content::ContentMainRunner::Create());
|
main_runner_.reset(content::ContentMainRunner::Create());
|
||||||
|
browser_info_manager_.reset(new CefBrowserInfoManager);
|
||||||
|
|
||||||
int exit_code;
|
int exit_code;
|
||||||
|
|
||||||
@ -415,7 +417,7 @@ void CefContext::FinishShutdownOnUIThread(
|
|||||||
print_job_manager_->Shutdown();
|
print_job_manager_->Shutdown();
|
||||||
print_job_manager_.reset(NULL);
|
print_job_manager_.reset(NULL);
|
||||||
|
|
||||||
CefContentBrowserClient::Get()->DestroyAllBrowsers();
|
browser_info_manager_->DestroyAllBrowsers();
|
||||||
|
|
||||||
if (trace_subscriber_.get())
|
if (trace_subscriber_.get())
|
||||||
trace_subscriber_.reset(NULL);
|
trace_subscriber_.reset(NULL);
|
||||||
@ -436,6 +438,7 @@ void CefContext::FinalizeShutdown() {
|
|||||||
// Shut down the content runner.
|
// Shut down the content runner.
|
||||||
main_runner_->Shutdown();
|
main_runner_->Shutdown();
|
||||||
|
|
||||||
|
browser_info_manager_.reset(NULL);
|
||||||
main_runner_.reset(NULL);
|
main_runner_.reset(NULL);
|
||||||
main_delegate_.reset(NULL);
|
main_delegate_.reset(NULL);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@ class PrintJobManager;
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CefBrowserHostImpl;
|
class CefBrowserHostImpl;
|
||||||
|
class CefBrowserInfoManager;
|
||||||
class CefMainDelegate;
|
class CefMainDelegate;
|
||||||
class CefTraceSubscriber;
|
class CefTraceSubscriber;
|
||||||
|
|
||||||
@ -97,6 +98,7 @@ class CefContext {
|
|||||||
scoped_ptr<CefMainDelegate> main_delegate_;
|
scoped_ptr<CefMainDelegate> main_delegate_;
|
||||||
scoped_ptr<content::ContentMainRunner> main_runner_;
|
scoped_ptr<content::ContentMainRunner> main_runner_;
|
||||||
scoped_ptr<CefTraceSubscriber> trace_subscriber_;
|
scoped_ptr<CefTraceSubscriber> trace_subscriber_;
|
||||||
|
scoped_ptr<CefBrowserInfoManager> browser_info_manager_;
|
||||||
|
|
||||||
// Only accessed on the UI Thread.
|
// Only accessed on the UI Thread.
|
||||||
scoped_ptr<printing::PrintJobManager> print_job_manager_;
|
scoped_ptr<printing::PrintJobManager> print_job_manager_;
|
||||||
|
@ -109,11 +109,10 @@ CefDevToolsFrontend* CefDevToolsFrontend::Show(
|
|||||||
CefRefPtr<CefBrowserHostImpl> frontend_browser =
|
CefRefPtr<CefBrowserHostImpl> frontend_browser =
|
||||||
CefBrowserHostImpl::Create(windowInfo, client, CefString(),
|
CefBrowserHostImpl::Create(windowInfo, client, CefString(),
|
||||||
new_settings,
|
new_settings,
|
||||||
inspected_browser->GetWindowHandle(), true,
|
inspected_browser, true,
|
||||||
inspected_browser->GetRequestContext());
|
inspected_browser->GetRequestContext());
|
||||||
|
|
||||||
content::WebContents* inspected_contents =
|
content::WebContents* inspected_contents = inspected_browser->web_contents();
|
||||||
inspected_browser->GetWebContents();
|
|
||||||
if (!inspect_element_at.IsEmpty()) {
|
if (!inspect_element_at.IsEmpty()) {
|
||||||
scoped_refptr<content::DevToolsAgentHost> agent_host =
|
scoped_refptr<content::DevToolsAgentHost> agent_host =
|
||||||
content::DevToolsAgentHost::GetOrCreateFor(inspected_contents);
|
content::DevToolsAgentHost::GetOrCreateFor(inspected_contents);
|
||||||
@ -166,7 +165,7 @@ void CefDevToolsFrontend::DisconnectFromTarget() {
|
|||||||
CefDevToolsFrontend::CefDevToolsFrontend(
|
CefDevToolsFrontend::CefDevToolsFrontend(
|
||||||
CefRefPtr<CefBrowserHostImpl> frontend_browser,
|
CefRefPtr<CefBrowserHostImpl> frontend_browser,
|
||||||
content::WebContents* inspected_contents)
|
content::WebContents* inspected_contents)
|
||||||
: WebContentsObserver(frontend_browser->GetWebContents()),
|
: WebContentsObserver(frontend_browser->web_contents()),
|
||||||
frontend_browser_(frontend_browser),
|
frontend_browser_(frontend_browser),
|
||||||
inspected_contents_(inspected_contents),
|
inspected_contents_(inspected_contents),
|
||||||
weak_factory_(this) {
|
weak_factory_(this) {
|
||||||
|
@ -142,7 +142,7 @@ class CefBeforeDownloadCallbackImpl : public CefBeforeDownloadCallback {
|
|||||||
if (browser.get()) {
|
if (browser.get()) {
|
||||||
handled = true;
|
handled = true;
|
||||||
|
|
||||||
CefBrowserHostImpl::FileChooserParams params;
|
CefFileDialogRunner::FileChooserParams params;
|
||||||
params.mode = content::FileChooserParams::Save;
|
params.mode = content::FileChooserParams::Save;
|
||||||
if (!suggested_path.empty()) {
|
if (!suggested_path.empty()) {
|
||||||
params.default_file_name = suggested_path;
|
params.default_file_name = suggested_path;
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "libcef/browser/extensions/browser_extensions_util.h"
|
#include "libcef/browser/extensions/browser_extensions_util.h"
|
||||||
|
|
||||||
#include "libcef/browser/content_browser_client.h"
|
#include "libcef/browser/browser_info_manager.h"
|
||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
#include "libcef/common/extensions/extensions_util.h"
|
#include "libcef/common/extensions/extensions_util.h"
|
||||||
|
|
||||||
@ -72,7 +72,7 @@ CefRefPtr<CefBrowserHostImpl> GetOwnerBrowserForView(int render_process_id,
|
|||||||
} else {
|
} else {
|
||||||
// Use the thread-safe approach.
|
// Use the thread-safe approach.
|
||||||
scoped_refptr<CefBrowserInfo> info =
|
scoped_refptr<CefBrowserInfo> info =
|
||||||
CefContentBrowserClient::Get()->GetBrowserInfoForView(
|
CefBrowserInfoManager::GetInstance()->GetBrowserInfoForView(
|
||||||
render_process_id, render_routing_id, is_guest_view);
|
render_process_id, render_routing_id, is_guest_view);
|
||||||
if (info.get()) {
|
if (info.get()) {
|
||||||
CefRefPtr<CefBrowserHostImpl> browser = info->browser();
|
CefRefPtr<CefBrowserHostImpl> browser = info->browser();
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
#include "libcef/browser/browser_info.h"
|
#include "libcef/browser/browser_info.h"
|
||||||
#include "libcef/browser/content_browser_client.h"
|
#include "libcef/browser/content_browser_client.h"
|
||||||
#include "libcef/browser/web_contents_view_osr.h"
|
#include "libcef/browser/osr/web_contents_view_osr.h"
|
||||||
|
|
||||||
#include "content/browser/browser_plugin/browser_plugin_guest.h"
|
#include "content/browser/browser_plugin/browser_plugin_guest.h"
|
||||||
#include "content/browser/web_contents/web_contents_impl.h"
|
#include "content/browser/web_contents/web_contents_impl.h"
|
||||||
@ -43,7 +43,7 @@ void CefMimeHandlerViewGuestDelegate::OverrideWebContentsCreateParams(
|
|||||||
|
|
||||||
CefRefPtr<CefBrowserHostImpl> owner_browser = GetOwnerBrowser(guest_);
|
CefRefPtr<CefBrowserHostImpl> owner_browser = GetOwnerBrowser(guest_);
|
||||||
if (owner_browser->IsWindowless()) {
|
if (owner_browser->IsWindowless()) {
|
||||||
CefWebContentsViewOSR* view_osr = new CefWebContentsViewOSR();
|
CefWebContentsViewOSR* view_osr = new CefWebContentsViewOSR(false);
|
||||||
params->view = view_osr;
|
params->view = view_osr;
|
||||||
params->delegate_view = view_osr;
|
params->delegate_view = view_osr;
|
||||||
}
|
}
|
||||||
|
396
libcef/browser/file_dialog_manager.cc
Normal file
396
libcef/browser/file_dialog_manager.cc
Normal file
@ -0,0 +1,396 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2012 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 "libcef/browser/file_dialog_manager.h"
|
||||||
|
|
||||||
|
#include "include/cef_dialog_handler.h"
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
#include "libcef/browser/thread_util.h"
|
||||||
|
|
||||||
|
#include "content/public/browser/render_view_host.h"
|
||||||
|
#include "content/public/common/file_chooser_file_info.h"
|
||||||
|
#include "net/base/directory_lister.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class CefFileDialogCallbackImpl : public CefFileDialogCallback {
|
||||||
|
public:
|
||||||
|
explicit CefFileDialogCallbackImpl(
|
||||||
|
const CefFileDialogRunner::RunFileChooserCallback& callback)
|
||||||
|
: callback_(callback) {
|
||||||
|
}
|
||||||
|
~CefFileDialogCallbackImpl() override {
|
||||||
|
if (!callback_.is_null()) {
|
||||||
|
// The callback is still pending. Cancel it now.
|
||||||
|
if (CEF_CURRENTLY_ON_UIT()) {
|
||||||
|
CancelNow(callback_);
|
||||||
|
} else {
|
||||||
|
CEF_POST_TASK(CEF_UIT,
|
||||||
|
base::Bind(&CefFileDialogCallbackImpl::CancelNow, callback_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Continue(int selected_accept_filter,
|
||||||
|
const std::vector<CefString>& file_paths) override {
|
||||||
|
if (CEF_CURRENTLY_ON_UIT()) {
|
||||||
|
if (!callback_.is_null()) {
|
||||||
|
std::vector<base::FilePath> vec;
|
||||||
|
if (!file_paths.empty()) {
|
||||||
|
std::vector<CefString>::const_iterator it = file_paths.begin();
|
||||||
|
for (; it != file_paths.end(); ++it)
|
||||||
|
vec.push_back(base::FilePath(*it));
|
||||||
|
}
|
||||||
|
callback_.Run(selected_accept_filter, vec);
|
||||||
|
callback_.Reset();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CEF_POST_TASK(CEF_UIT,
|
||||||
|
base::Bind(&CefFileDialogCallbackImpl::Continue, this,
|
||||||
|
selected_accept_filter, file_paths));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cancel() override {
|
||||||
|
if (CEF_CURRENTLY_ON_UIT()) {
|
||||||
|
if (!callback_.is_null()) {
|
||||||
|
CancelNow(callback_);
|
||||||
|
callback_.Reset();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CEF_POST_TASK(CEF_UIT,
|
||||||
|
base::Bind(&CefFileDialogCallbackImpl::Cancel, this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsConnected() {
|
||||||
|
return !callback_.is_null();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Disconnect() {
|
||||||
|
callback_.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void CancelNow(
|
||||||
|
const CefFileDialogRunner::RunFileChooserCallback& callback) {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
std::vector<base::FilePath> file_paths;
|
||||||
|
callback.Run(0, file_paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
CefFileDialogRunner::RunFileChooserCallback callback_;
|
||||||
|
|
||||||
|
IMPLEMENT_REFCOUNTING(CefFileDialogCallbackImpl);
|
||||||
|
};
|
||||||
|
|
||||||
|
void RunFileDialogDismissed(
|
||||||
|
CefRefPtr<CefRunFileDialogCallback> callback,
|
||||||
|
int selected_accept_filter,
|
||||||
|
const std::vector<base::FilePath>& file_paths) {
|
||||||
|
std::vector<CefString> paths;
|
||||||
|
if (file_paths.size() > 0) {
|
||||||
|
for (size_t i = 0; i < file_paths.size(); ++i)
|
||||||
|
paths.push_back(file_paths[i].value());
|
||||||
|
}
|
||||||
|
callback->OnFileDialogDismissed(selected_accept_filter, paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
class UploadFolderHelper :
|
||||||
|
public net::DirectoryLister::DirectoryListerDelegate {
|
||||||
|
public:
|
||||||
|
explicit UploadFolderHelper(
|
||||||
|
const CefFileDialogRunner::RunFileChooserCallback& callback)
|
||||||
|
: callback_(callback) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~UploadFolderHelper() override {
|
||||||
|
if (!callback_.is_null()) {
|
||||||
|
if (CEF_CURRENTLY_ON_UIT()) {
|
||||||
|
CancelNow(callback_);
|
||||||
|
} else {
|
||||||
|
CEF_POST_TASK(CEF_UIT,
|
||||||
|
base::Bind(&UploadFolderHelper::CancelNow, callback_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnListFile(
|
||||||
|
const net::DirectoryLister::DirectoryListerData& data) override {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
if (!data.info.IsDirectory())
|
||||||
|
select_files_.push_back(data.path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnListDone(int error) override {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
if (!callback_.is_null()) {
|
||||||
|
callback_.Run(0, select_files_);
|
||||||
|
callback_.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void CancelNow(
|
||||||
|
const CefFileDialogRunner::RunFileChooserCallback& callback) {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
std::vector<base::FilePath> file_paths;
|
||||||
|
callback.Run(0, file_paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
CefFileDialogRunner::RunFileChooserCallback callback_;
|
||||||
|
std::vector<base::FilePath> select_files_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(UploadFolderHelper);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
CefFileDialogManager::CefFileDialogManager(
|
||||||
|
CefBrowserHostImpl* browser,
|
||||||
|
scoped_ptr<CefFileDialogRunner> runner)
|
||||||
|
: content::WebContentsObserver(browser->web_contents()),
|
||||||
|
browser_(browser),
|
||||||
|
runner_(runner.Pass()),
|
||||||
|
file_chooser_pending_(false),
|
||||||
|
weak_ptr_factory_(this) {
|
||||||
|
DCHECK(web_contents());
|
||||||
|
}
|
||||||
|
|
||||||
|
CefFileDialogManager::~CefFileDialogManager() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefFileDialogManager::Destroy() {
|
||||||
|
DCHECK(!file_chooser_pending_);
|
||||||
|
runner_.reset(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefFileDialogManager::RunFileDialog(
|
||||||
|
cef_file_dialog_mode_t mode,
|
||||||
|
const CefString& title,
|
||||||
|
const CefString& default_file_path,
|
||||||
|
const std::vector<CefString>& accept_filters,
|
||||||
|
int selected_accept_filter,
|
||||||
|
CefRefPtr<CefRunFileDialogCallback> callback) {
|
||||||
|
DCHECK(callback.get());
|
||||||
|
if (!callback.get())
|
||||||
|
return;
|
||||||
|
|
||||||
|
CefFileDialogRunner::FileChooserParams params;
|
||||||
|
switch (mode & FILE_DIALOG_TYPE_MASK) {
|
||||||
|
case FILE_DIALOG_OPEN:
|
||||||
|
params.mode = content::FileChooserParams::Open;
|
||||||
|
break;
|
||||||
|
case FILE_DIALOG_OPEN_MULTIPLE:
|
||||||
|
params.mode = content::FileChooserParams::OpenMultiple;
|
||||||
|
break;
|
||||||
|
case FILE_DIALOG_OPEN_FOLDER:
|
||||||
|
params.mode = content::FileChooserParams::UploadFolder;
|
||||||
|
break;
|
||||||
|
case FILE_DIALOG_SAVE:
|
||||||
|
params.mode = content::FileChooserParams::Save;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
DCHECK_GE(selected_accept_filter, 0);
|
||||||
|
params.selected_accept_filter = selected_accept_filter;
|
||||||
|
|
||||||
|
params.overwriteprompt = !!(mode & FILE_DIALOG_OVERWRITEPROMPT_FLAG);
|
||||||
|
params.hidereadonly = !!(mode & FILE_DIALOG_HIDEREADONLY_FLAG);
|
||||||
|
|
||||||
|
params.title = title;
|
||||||
|
if (!default_file_path.empty())
|
||||||
|
params.default_file_name = base::FilePath(default_file_path);
|
||||||
|
|
||||||
|
if (!accept_filters.empty()) {
|
||||||
|
std::vector<CefString>::const_iterator it = accept_filters.begin();
|
||||||
|
for (; it != accept_filters.end(); ++it)
|
||||||
|
params.accept_types.push_back(*it);
|
||||||
|
}
|
||||||
|
|
||||||
|
RunFileChooser(params, base::Bind(RunFileDialogDismissed, callback));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefFileDialogManager::RunFileChooser(
|
||||||
|
content::WebContents* web_contents,
|
||||||
|
const content::FileChooserParams& params) {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
DCHECK_EQ(web_contents, this->web_contents());
|
||||||
|
|
||||||
|
content::RenderViewHost* render_view_host = web_contents->GetRenderViewHost();
|
||||||
|
if (!render_view_host)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CefFileDialogRunner::FileChooserParams cef_params;
|
||||||
|
static_cast<content::FileChooserParams&>(cef_params) = params;
|
||||||
|
|
||||||
|
if (lister_) {
|
||||||
|
// Cancel the previous upload folder run.
|
||||||
|
lister_->Cancel();
|
||||||
|
lister_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.mode == content::FileChooserParams::UploadFolder) {
|
||||||
|
RunFileChooser(cef_params,
|
||||||
|
base::Bind(
|
||||||
|
&CefFileDialogManager::OnRunFileChooserUploadFolderDelegateCallback,
|
||||||
|
weak_ptr_factory_.GetWeakPtr(), params.mode));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RunFileChooser(cef_params,
|
||||||
|
base::Bind(&CefFileDialogManager::OnRunFileChooserDelegateCallback,
|
||||||
|
weak_ptr_factory_.GetWeakPtr(), params.mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefFileDialogManager::RunFileChooser(
|
||||||
|
const CefFileDialogRunner::FileChooserParams& params,
|
||||||
|
const CefFileDialogRunner::RunFileChooserCallback& callback) {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
|
||||||
|
if (file_chooser_pending_) {
|
||||||
|
// Dismiss the new dialog immediately.
|
||||||
|
callback.Run(0, std::vector<base::FilePath>());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_chooser_pending_ = true;
|
||||||
|
|
||||||
|
// Ensure that the |file_chooser_pending_| flag is cleared.
|
||||||
|
const CefFileDialogRunner::RunFileChooserCallback& host_callback =
|
||||||
|
base::Bind(&CefFileDialogManager::OnRunFileChooserCallback,
|
||||||
|
weak_ptr_factory_.GetWeakPtr(), callback);
|
||||||
|
|
||||||
|
bool handled = false;
|
||||||
|
|
||||||
|
if (browser_->client().get()) {
|
||||||
|
CefRefPtr<CefDialogHandler> handler =
|
||||||
|
browser_->client()->GetDialogHandler();
|
||||||
|
if (handler.get()) {
|
||||||
|
int mode = FILE_DIALOG_OPEN;
|
||||||
|
switch (params.mode) {
|
||||||
|
case content::FileChooserParams::Open:
|
||||||
|
mode = FILE_DIALOG_OPEN;
|
||||||
|
break;
|
||||||
|
case content::FileChooserParams::OpenMultiple:
|
||||||
|
mode = FILE_DIALOG_OPEN_MULTIPLE;
|
||||||
|
break;
|
||||||
|
case content::FileChooserParams::UploadFolder:
|
||||||
|
mode = FILE_DIALOG_OPEN_FOLDER;
|
||||||
|
break;
|
||||||
|
case content::FileChooserParams::Save:
|
||||||
|
mode = FILE_DIALOG_SAVE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NOTREACHED();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.overwriteprompt)
|
||||||
|
mode |= FILE_DIALOG_OVERWRITEPROMPT_FLAG;
|
||||||
|
if (params.hidereadonly)
|
||||||
|
mode |= FILE_DIALOG_HIDEREADONLY_FLAG;
|
||||||
|
|
||||||
|
std::vector<base::string16>::const_iterator it;
|
||||||
|
|
||||||
|
std::vector<CefString> accept_filters;
|
||||||
|
it = params.accept_types.begin();
|
||||||
|
for (; it != params.accept_types.end(); ++it)
|
||||||
|
accept_filters.push_back(*it);
|
||||||
|
|
||||||
|
CefRefPtr<CefFileDialogCallbackImpl> callbackImpl(
|
||||||
|
new CefFileDialogCallbackImpl(host_callback));
|
||||||
|
handled = handler->OnFileDialog(
|
||||||
|
browser_,
|
||||||
|
static_cast<cef_file_dialog_mode_t>(mode),
|
||||||
|
params.title,
|
||||||
|
params.default_file_name.value(),
|
||||||
|
accept_filters,
|
||||||
|
params.selected_accept_filter,
|
||||||
|
callbackImpl.get());
|
||||||
|
if (!handled) {
|
||||||
|
if (callbackImpl->IsConnected()) {
|
||||||
|
callbackImpl->Disconnect();
|
||||||
|
} else {
|
||||||
|
// User executed the callback even though they returned false.
|
||||||
|
NOTREACHED();
|
||||||
|
handled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handled) {
|
||||||
|
if (runner_.get()) {
|
||||||
|
runner_->Run(browser_, params, host_callback);
|
||||||
|
} else {
|
||||||
|
LOG(WARNING) << "No file dialog runner available for this platform";
|
||||||
|
host_callback.Run(0, std::vector<base::FilePath>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefFileDialogManager::OnRunFileChooserCallback(
|
||||||
|
const CefFileDialogRunner::RunFileChooserCallback& callback,
|
||||||
|
int selected_accept_filter,
|
||||||
|
const std::vector<base::FilePath>& file_paths) {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
|
||||||
|
file_chooser_pending_ = false;
|
||||||
|
|
||||||
|
// Execute the callback asynchronously.
|
||||||
|
CEF_POST_TASK(CEF_UIT,
|
||||||
|
base::Bind(callback, selected_accept_filter, file_paths));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefFileDialogManager::OnRunFileChooserUploadFolderDelegateCallback(
|
||||||
|
const content::FileChooserParams::Mode mode,
|
||||||
|
int selected_accept_filter,
|
||||||
|
const std::vector<base::FilePath>& file_paths) {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
DCHECK_EQ(mode, content::FileChooserParams::UploadFolder);
|
||||||
|
|
||||||
|
if (file_paths.size() == 0) {
|
||||||
|
// Client canceled the file chooser.
|
||||||
|
OnRunFileChooserDelegateCallback(mode, selected_accept_filter, file_paths);
|
||||||
|
} else {
|
||||||
|
lister_.reset(new net::DirectoryLister(
|
||||||
|
file_paths[0],
|
||||||
|
net::DirectoryLister::NO_SORT,
|
||||||
|
new UploadFolderHelper(
|
||||||
|
base::Bind(&CefFileDialogManager::OnRunFileChooserDelegateCallback,
|
||||||
|
weak_ptr_factory_.GetWeakPtr(), mode))));
|
||||||
|
lister_->Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefFileDialogManager::OnRunFileChooserDelegateCallback(
|
||||||
|
content::FileChooserParams::Mode mode,
|
||||||
|
int selected_accept_filter,
|
||||||
|
const std::vector<base::FilePath>& file_paths) {
|
||||||
|
CEF_REQUIRE_UIT();
|
||||||
|
|
||||||
|
if (lister_.get())
|
||||||
|
lister_.reset();
|
||||||
|
|
||||||
|
if (!web_contents())
|
||||||
|
return;
|
||||||
|
|
||||||
|
content::RenderViewHost* render_view_host =
|
||||||
|
web_contents()->GetRenderViewHost();
|
||||||
|
if (!render_view_host)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Convert FilePath list to SelectedFileInfo list.
|
||||||
|
std::vector<content::FileChooserFileInfo> selected_files;
|
||||||
|
for (size_t i = 0; i < file_paths.size(); ++i) {
|
||||||
|
content::FileChooserFileInfo info;
|
||||||
|
info.file_path = file_paths[i];
|
||||||
|
selected_files.push_back(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify our RenderViewHost in all cases.
|
||||||
|
render_view_host->FilesSelectedInChooser(selected_files, mode);
|
||||||
|
}
|
99
libcef/browser/file_dialog_manager.h
Normal file
99
libcef/browser/file_dialog_manager.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2012 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 CEF_LIBCEF_BROWSER_FILE_DIALOG_MANAGER_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_FILE_DIALOG_MANAGER_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "include/cef_browser.h"
|
||||||
|
#include "libcef/browser/file_dialog_runner.h"
|
||||||
|
|
||||||
|
#include "base/compiler_specific.h"
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#include "base/memory/weak_ptr.h"
|
||||||
|
#include "content/public/browser/web_contents_observer.h"
|
||||||
|
|
||||||
|
namespace content {
|
||||||
|
class WebContents;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace net {
|
||||||
|
class DirectoryLister;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CefBrowserHostImpl;
|
||||||
|
|
||||||
|
class CefFileDialogManager : public content::WebContentsObserver {
|
||||||
|
public:
|
||||||
|
// |runner| may be NULL if the platform doesn't implement dialogs.
|
||||||
|
CefFileDialogManager(
|
||||||
|
CefBrowserHostImpl* browser,
|
||||||
|
scoped_ptr<CefFileDialogRunner> runner);
|
||||||
|
~CefFileDialogManager() override;
|
||||||
|
|
||||||
|
// Delete the runner to free any platform constructs.
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
// Called from CefBrowserHostImpl::RunFileChooser.
|
||||||
|
// See CefBrowserHost::RunFileDialog documentation.
|
||||||
|
void RunFileDialog(
|
||||||
|
cef_file_dialog_mode_t mode,
|
||||||
|
const CefString& title,
|
||||||
|
const CefString& default_file_path,
|
||||||
|
const std::vector<CefString>& accept_filters,
|
||||||
|
int selected_accept_filter,
|
||||||
|
CefRefPtr<CefRunFileDialogCallback> callback);
|
||||||
|
|
||||||
|
// Called from CefBrowserHostImpl::RunFileChooser.
|
||||||
|
// See WebContentsDelegate::RunFileChooser documentation.
|
||||||
|
void RunFileChooser(
|
||||||
|
content::WebContents* web_contents,
|
||||||
|
const content::FileChooserParams& params);
|
||||||
|
|
||||||
|
// Run the file chooser dialog specified by |params|. Only a single dialog may
|
||||||
|
// be pending at any given time. |callback| will be executed asynchronously
|
||||||
|
// after the dialog is dismissed or if another dialog is already pending.
|
||||||
|
void RunFileChooser(
|
||||||
|
const CefFileDialogRunner::FileChooserParams& params,
|
||||||
|
const CefFileDialogRunner::RunFileChooserCallback& callback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Used with RunFileChooser to clear the |file_chooser_pending_| flag.
|
||||||
|
void OnRunFileChooserCallback(
|
||||||
|
const CefFileDialogRunner::RunFileChooserCallback& callback,
|
||||||
|
int selected_accept_filter,
|
||||||
|
const std::vector<base::FilePath>& file_paths);
|
||||||
|
|
||||||
|
// Used with WebContentsDelegate::RunFileChooser when mode is
|
||||||
|
// content::FileChooserParams::UploadFolder.
|
||||||
|
void OnRunFileChooserUploadFolderDelegateCallback(
|
||||||
|
const content::FileChooserParams::Mode mode,
|
||||||
|
int selected_accept_filter,
|
||||||
|
const std::vector<base::FilePath>& file_paths);
|
||||||
|
|
||||||
|
// Used with WebContentsDelegate::RunFileChooser to notify the WebContents.
|
||||||
|
void OnRunFileChooserDelegateCallback(
|
||||||
|
content::FileChooserParams::Mode mode,
|
||||||
|
int selected_accept_filter,
|
||||||
|
const std::vector<base::FilePath>& file_paths);
|
||||||
|
|
||||||
|
// CefBrowserHostImpl pointer is guaranteed to outlive this object.
|
||||||
|
CefBrowserHostImpl* browser_;
|
||||||
|
|
||||||
|
scoped_ptr<CefFileDialogRunner> runner_;
|
||||||
|
|
||||||
|
// True if a file chooser is currently pending.
|
||||||
|
bool file_chooser_pending_;
|
||||||
|
|
||||||
|
// Used for asynchronously listing directory contents.
|
||||||
|
scoped_ptr<net::DirectoryLister> lister_;
|
||||||
|
|
||||||
|
// Must be the last member.
|
||||||
|
base::WeakPtrFactory<CefFileDialogManager> weak_ptr_factory_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CefFileDialogManager);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_MANAGER_H_
|
53
libcef/browser/file_dialog_runner.h
Normal file
53
libcef/browser/file_dialog_runner.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2012 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 CEF_LIBCEF_BROWSER_FILE_DIALOG_RUNNER_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_FILE_DIALOG_RUNNER_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/files/file_path.h"
|
||||||
|
#include "base/callback.h"
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#include "content/public/common/file_chooser_params.h"
|
||||||
|
|
||||||
|
class CefBrowserHostImpl;
|
||||||
|
|
||||||
|
class CefFileDialogRunner {
|
||||||
|
public:
|
||||||
|
// Extend content::FileChooserParams with some options unique to CEF.
|
||||||
|
struct FileChooserParams : public content::FileChooserParams {
|
||||||
|
// 0-based index of the selected value in |accept_types|.
|
||||||
|
int selected_accept_filter = 0;
|
||||||
|
|
||||||
|
// True if the Save dialog should prompt before overwriting files.
|
||||||
|
bool overwriteprompt = true;
|
||||||
|
|
||||||
|
// True if read-only files should be hidden.
|
||||||
|
bool hidereadonly = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// The argument vector will be empty if the dialog was canceled.
|
||||||
|
typedef base::Callback<void(int, const std::vector<base::FilePath>&)>
|
||||||
|
RunFileChooserCallback;
|
||||||
|
|
||||||
|
// Display the file chooser dialog. Execute |callback| on completion.
|
||||||
|
virtual void Run(CefBrowserHostImpl* browser,
|
||||||
|
const FileChooserParams& params,
|
||||||
|
RunFileChooserCallback callback) = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Allow deletion via scoped_ptr only.
|
||||||
|
friend struct base::DefaultDeleter<CefFileDialogRunner>;
|
||||||
|
|
||||||
|
CefFileDialogRunner() {}
|
||||||
|
virtual ~CefFileDialogRunner() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CefFileDialogRunner);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_FILE_DIALOG_RUNNER_H_
|
@ -1,28 +0,0 @@
|
|||||||
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
|
||||||
// Portions copyright (c) 2012 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 "libcef/browser/javascript_dialog.h"
|
|
||||||
#include "libcef/browser/javascript_dialog_manager.h"
|
|
||||||
|
|
||||||
CefJavaScriptDialog::CefJavaScriptDialog(
|
|
||||||
CefJavaScriptDialogManager* creator,
|
|
||||||
content::JavaScriptMessageType message_type,
|
|
||||||
const base::string16& display_url,
|
|
||||||
const base::string16& message_text,
|
|
||||||
const base::string16& default_prompt_text,
|
|
||||||
const content::JavaScriptDialogManager::DialogClosedCallback& callback)
|
|
||||||
: creator_(creator),
|
|
||||||
callback_(callback) {
|
|
||||||
NOTIMPLEMENTED();
|
|
||||||
callback_.Run(false, base::string16());
|
|
||||||
creator_->DialogClosed(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
CefJavaScriptDialog::~CefJavaScriptDialog() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefJavaScriptDialog::Cancel() {
|
|
||||||
}
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
#include "libcef/browser/javascript_dialog_manager.h"
|
#include "libcef/browser/javascript_dialog_manager.h"
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
#include "libcef/browser/javascript_dialog.h"
|
|
||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
|
|
||||||
#include "base/bind.h"
|
#include "base/bind.h"
|
||||||
@ -68,13 +67,24 @@ class CefJSDialogCallbackImpl : public CefJSDialogCallback {
|
|||||||
|
|
||||||
|
|
||||||
CefJavaScriptDialogManager::CefJavaScriptDialogManager(
|
CefJavaScriptDialogManager::CefJavaScriptDialogManager(
|
||||||
CefBrowserHostImpl* browser)
|
CefBrowserHostImpl* browser,
|
||||||
: browser_(browser) {
|
scoped_ptr<CefJavaScriptDialogRunner> runner)
|
||||||
|
: browser_(browser),
|
||||||
|
runner_(runner.Pass()),
|
||||||
|
dialog_running_(false),
|
||||||
|
weak_ptr_factory_(this) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CefJavaScriptDialogManager::~CefJavaScriptDialogManager() {
|
CefJavaScriptDialogManager::~CefJavaScriptDialogManager() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CefJavaScriptDialogManager::Destroy() {
|
||||||
|
if (runner_.get()) {
|
||||||
|
DCHECK(!dialog_running_);
|
||||||
|
runner_.reset(NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CefJavaScriptDialogManager::RunJavaScriptDialog(
|
void CefJavaScriptDialogManager::RunJavaScriptDialog(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
const GURL& origin_url,
|
const GURL& origin_url,
|
||||||
@ -111,29 +121,26 @@ void CefJavaScriptDialogManager::RunJavaScriptDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK)
|
|
||||||
*did_suppress_message = false;
|
*did_suppress_message = false;
|
||||||
|
|
||||||
if (dialog_.get()) {
|
if (!runner_.get() || dialog_running_) {
|
||||||
// One dialog at a time, please.
|
// Suppress the dialog if there is no platform runner or if the dialog is
|
||||||
|
// currently running.
|
||||||
|
if (!runner_.get())
|
||||||
|
LOG(WARNING) << "No javascript dialog runner available for this platform";
|
||||||
*did_suppress_message = true;
|
*did_suppress_message = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dialog_running_ = true;
|
||||||
|
|
||||||
base::string16 display_url =
|
base::string16 display_url =
|
||||||
url_formatter::FormatUrlForSecurityDisplay(origin_url, accept_lang);
|
url_formatter::FormatUrlForSecurityDisplay(origin_url, accept_lang);
|
||||||
|
|
||||||
dialog_.reset(new CefJavaScriptDialog(this,
|
runner_->Run(browser_, message_type, display_url, message_text,
|
||||||
message_type,
|
|
||||||
display_url,
|
|
||||||
message_text,
|
|
||||||
default_prompt_text,
|
default_prompt_text,
|
||||||
callback));
|
base::Bind(&CefJavaScriptDialogManager::DialogClosed,
|
||||||
#else
|
weak_ptr_factory_.GetWeakPtr(), callback));
|
||||||
// TODO(port): implement CefJavaScriptDialog for other platforms.
|
|
||||||
*did_suppress_message = true;
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefJavaScriptDialogManager::RunBeforeUnloadDialog(
|
void CefJavaScriptDialogManager::RunBeforeUnloadDialog(
|
||||||
@ -166,29 +173,28 @@ void CefJavaScriptDialogManager::RunBeforeUnloadDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK)
|
if (!runner_.get() || dialog_running_) {
|
||||||
if (dialog_.get()) {
|
if (!runner_.get())
|
||||||
// Seriously!?
|
LOG(WARNING) << "No javascript dialog runner available for this platform";
|
||||||
|
// Suppress the dialog if there is no platform runner or if the dialog is
|
||||||
|
// currently running.
|
||||||
callback.Run(true, base::string16());
|
callback.Run(true, base::string16());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dialog_running_ = true;
|
||||||
|
|
||||||
base::string16 new_message_text =
|
base::string16 new_message_text =
|
||||||
message_text +
|
message_text +
|
||||||
base::ASCIIToUTF16("\n\nIs it OK to leave/reload this page?");
|
base::ASCIIToUTF16("\n\nIs it OK to leave/reload this page?");
|
||||||
|
|
||||||
dialog_.reset(
|
runner_->Run(browser_,
|
||||||
new CefJavaScriptDialog(this,
|
|
||||||
content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM,
|
content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM,
|
||||||
base::string16(), // display_url
|
base::string16(), // display_url
|
||||||
new_message_text,
|
new_message_text,
|
||||||
base::string16(), // default_prompt_text
|
base::string16(), // default_prompt_text
|
||||||
callback));
|
base::Bind(&CefJavaScriptDialogManager::DialogClosed,
|
||||||
#else
|
weak_ptr_factory_.GetWeakPtr(), callback));
|
||||||
// TODO(port): implement CefJavaScriptDialog for other platforms.
|
|
||||||
callback.Run(true, base::string16());
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefJavaScriptDialogManager::CancelActiveAndPendingDialogs(
|
void CefJavaScriptDialogManager::CancelActiveAndPendingDialogs(
|
||||||
@ -202,27 +208,31 @@ void CefJavaScriptDialogManager::CancelActiveAndPendingDialogs(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK)
|
if (runner_.get() && dialog_running_) {
|
||||||
if (dialog_.get()) {
|
runner_->Cancel();
|
||||||
dialog_->Cancel();
|
dialog_running_ = false;
|
||||||
dialog_.reset();
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefJavaScriptDialogManager::ResetDialogState(
|
void CefJavaScriptDialogManager::ResetDialogState(
|
||||||
content::WebContents* web_contents) {
|
content::WebContents* web_contents) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefJavaScriptDialogManager::DialogClosed(CefJavaScriptDialog* dialog) {
|
void CefJavaScriptDialogManager::DialogClosed(
|
||||||
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK)
|
const DialogClosedCallback& callback,
|
||||||
DCHECK_EQ(dialog, dialog_.get());
|
bool success,
|
||||||
dialog_.reset();
|
const base::string16& user_input) {
|
||||||
CefRefPtr<CefClient> client = browser_->GetClient();
|
CefRefPtr<CefClient> client = browser_->GetClient();
|
||||||
if (client.get()) {
|
if (client.get()) {
|
||||||
CefRefPtr<CefJSDialogHandler> handler = client->GetJSDialogHandler();
|
CefRefPtr<CefJSDialogHandler> handler = client->GetJSDialogHandler();
|
||||||
if (handler.get())
|
if (handler.get())
|
||||||
handler->OnDialogClosed(browser_);
|
handler->OnDialogClosed(browser_);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
DCHECK(runner_.get());
|
||||||
|
DCHECK(dialog_running_);
|
||||||
|
|
||||||
|
dialog_running_ = false;
|
||||||
|
|
||||||
|
callback.Run(success, user_input);
|
||||||
}
|
}
|
||||||
|
@ -9,18 +9,26 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "libcef/browser/javascript_dialog_runner.h"
|
||||||
|
|
||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#include "base/memory/weak_ptr.h"
|
||||||
#include "content/public/browser/javascript_dialog_manager.h"
|
#include "content/public/browser/javascript_dialog_manager.h"
|
||||||
|
|
||||||
class CefBrowserHostImpl;
|
class CefBrowserHostImpl;
|
||||||
class CefJavaScriptDialog;
|
|
||||||
|
|
||||||
class CefJavaScriptDialogManager : public content::JavaScriptDialogManager {
|
class CefJavaScriptDialogManager : public content::JavaScriptDialogManager {
|
||||||
public:
|
public:
|
||||||
explicit CefJavaScriptDialogManager(CefBrowserHostImpl* browser);
|
// |runner| may be NULL if the platform doesn't implement dialogs.
|
||||||
|
CefJavaScriptDialogManager(
|
||||||
|
CefBrowserHostImpl* browser,
|
||||||
|
scoped_ptr<CefJavaScriptDialogRunner> runner);
|
||||||
~CefJavaScriptDialogManager() override;
|
~CefJavaScriptDialogManager() override;
|
||||||
|
|
||||||
|
// Delete the runner to free any platform constructs.
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
// JavaScriptDialogManager methods.
|
// JavaScriptDialogManager methods.
|
||||||
void RunJavaScriptDialog(
|
void RunJavaScriptDialog(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
@ -31,32 +39,32 @@ class CefJavaScriptDialogManager : public content::JavaScriptDialogManager {
|
|||||||
const base::string16& default_prompt_text,
|
const base::string16& default_prompt_text,
|
||||||
const DialogClosedCallback& callback,
|
const DialogClosedCallback& callback,
|
||||||
bool* did_suppress_message) override;
|
bool* did_suppress_message) override;
|
||||||
|
|
||||||
void RunBeforeUnloadDialog(
|
void RunBeforeUnloadDialog(
|
||||||
content::WebContents* web_contents,
|
content::WebContents* web_contents,
|
||||||
const base::string16& message_text,
|
const base::string16& message_text,
|
||||||
bool is_reload,
|
bool is_reload,
|
||||||
const DialogClosedCallback& callback) override;
|
const DialogClosedCallback& callback) override;
|
||||||
|
|
||||||
void CancelActiveAndPendingDialogs(
|
void CancelActiveAndPendingDialogs(
|
||||||
content::WebContents* web_contents) override;
|
content::WebContents* web_contents) override;
|
||||||
|
|
||||||
void ResetDialogState(
|
void ResetDialogState(
|
||||||
content::WebContents* web_contents) override;
|
content::WebContents* web_contents) override;
|
||||||
|
|
||||||
// Called by the CefJavaScriptDialog when it closes.
|
|
||||||
void DialogClosed(CefJavaScriptDialog* dialog);
|
|
||||||
|
|
||||||
CefBrowserHostImpl* browser() const { return browser_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This pointer is guaranteed to outlive the CefJavaScriptDialogManager.
|
// Method executed by the callback passed to CefJavaScriptDialogRunner::Run.
|
||||||
|
void DialogClosed(const DialogClosedCallback& callback,
|
||||||
|
bool success,
|
||||||
|
const base::string16& user_input);
|
||||||
|
|
||||||
|
// CefBrowserHostImpl pointer is guaranteed to outlive this object.
|
||||||
CefBrowserHostImpl* browser_;
|
CefBrowserHostImpl* browser_;
|
||||||
|
|
||||||
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK)
|
scoped_ptr<CefJavaScriptDialogRunner> runner_;
|
||||||
// The dialog being shown. No queueing.
|
|
||||||
scoped_ptr<CefJavaScriptDialog> dialog_;
|
// True if a dialog is currently running.
|
||||||
#endif
|
bool dialog_running_;
|
||||||
|
|
||||||
|
// Must be the last member.
|
||||||
|
base::WeakPtrFactory<CefJavaScriptDialogManager> weak_ptr_factory_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CefJavaScriptDialogManager);
|
DISALLOW_COPY_AND_ASSIGN(CefJavaScriptDialogManager);
|
||||||
};
|
};
|
||||||
|
46
libcef/browser/javascript_dialog_runner.h
Normal file
46
libcef/browser/javascript_dialog_runner.h
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2012 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 CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_RUNNER_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_RUNNER_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "base/callback.h"
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#include "base/strings/string16.h"
|
||||||
|
#include "content/public/common/javascript_message_type.h"
|
||||||
|
|
||||||
|
class CefBrowserHostImpl;
|
||||||
|
|
||||||
|
class CefJavaScriptDialogRunner {
|
||||||
|
public:
|
||||||
|
typedef base::Callback<void(bool /* success */,
|
||||||
|
const base::string16& /* user_input */)>
|
||||||
|
DialogClosedCallback;
|
||||||
|
|
||||||
|
// Run the dialog. Execute |callback| on completion.
|
||||||
|
virtual void Run(
|
||||||
|
CefBrowserHostImpl* browser,
|
||||||
|
content::JavaScriptMessageType message_type,
|
||||||
|
const base::string16& display_url,
|
||||||
|
const base::string16& message_text,
|
||||||
|
const base::string16& default_prompt_text,
|
||||||
|
const DialogClosedCallback& callback) = 0;
|
||||||
|
|
||||||
|
// Cancel a dialog mid-flight.
|
||||||
|
virtual void Cancel() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Allow deletion via scoped_ptr only.
|
||||||
|
friend struct base::DefaultDeleter<CefJavaScriptDialogRunner>;
|
||||||
|
|
||||||
|
CefJavaScriptDialogRunner() {}
|
||||||
|
virtual ~CefJavaScriptDialogRunner() {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CefJavaScriptDialogRunner);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_RUNNER_H_
|
@ -1,72 +0,0 @@
|
|||||||
// Copyright 2014 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 "libcef/browser/menu_creator_runner_linux.h"
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
|
||||||
#include "libcef/browser/window_x11.h"
|
|
||||||
|
|
||||||
#include "base/compiler_specific.h"
|
|
||||||
#include "base/strings/string_util.h"
|
|
||||||
#include "ui/aura/window.h"
|
|
||||||
#include "ui/gfx/geometry/point.h"
|
|
||||||
|
|
||||||
CefMenuCreatorRunnerLinux::CefMenuCreatorRunnerLinux() {
|
|
||||||
}
|
|
||||||
|
|
||||||
CefMenuCreatorRunnerLinux::~CefMenuCreatorRunnerLinux() {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CefMenuCreatorRunnerLinux::RunContextMenu(CefMenuCreator* manager) {
|
|
||||||
menu_.reset(
|
|
||||||
new views::MenuRunner(manager->model(), views::MenuRunner::CONTEXT_MENU));
|
|
||||||
|
|
||||||
gfx::Point screen_point;
|
|
||||||
|
|
||||||
if (manager->browser()->IsWindowless()) {
|
|
||||||
CefRefPtr<CefClient> client = manager->browser()->GetClient();
|
|
||||||
if (!client.get())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CefRefPtr<CefRenderHandler> handler = client->GetRenderHandler();
|
|
||||||
if (!handler.get())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int screenX = 0, screenY = 0;
|
|
||||||
if (!handler->GetScreenPoint(manager->browser(),
|
|
||||||
manager->params().x, manager->params().y,
|
|
||||||
screenX, screenY)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
screen_point = gfx::Point(screenX, screenY);
|
|
||||||
} else {
|
|
||||||
// We can't use aura::Window::GetBoundsInScreen on Linux because it will
|
|
||||||
// return bounds from DesktopWindowTreeHostX11 which in our case is relative
|
|
||||||
// to the parent window instead of the root window (screen).
|
|
||||||
const gfx::Rect& bounds_in_screen =
|
|
||||||
manager->browser()->window_x11()->GetBoundsInScreen();
|
|
||||||
screen_point = gfx::Point(bounds_in_screen.x() + manager->params().x,
|
|
||||||
bounds_in_screen.y() + manager->params().y);
|
|
||||||
}
|
|
||||||
|
|
||||||
views::MenuRunner::RunResult result =
|
|
||||||
menu_->RunMenuAt(manager->browser()->window_widget(),
|
|
||||||
NULL, gfx::Rect(screen_point, gfx::Size()),
|
|
||||||
views::MENU_ANCHOR_TOPRIGHT,
|
|
||||||
ui::MENU_SOURCE_NONE);
|
|
||||||
ALLOW_UNUSED_LOCAL(result);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefMenuCreatorRunnerLinux::CancelContextMenu() {
|
|
||||||
if (menu_)
|
|
||||||
menu_->Cancel();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CefMenuCreatorRunnerLinux::FormatLabel(base::string16& label) {
|
|
||||||
// Remove the accelerator indicator (&) from label strings.
|
|
||||||
const char16 replace[] = {L'&', 0};
|
|
||||||
return base::ReplaceChars(label, replace, base::string16(), &label);
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
// 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_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_LINUX_H_
|
|
||||||
#define CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_LINUX_H_
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "libcef/browser/menu_creator.h"
|
|
||||||
|
|
||||||
#include "base/memory/scoped_ptr.h"
|
|
||||||
#include "ui/views/controls/menu/menu_runner.h"
|
|
||||||
|
|
||||||
class CefMenuCreatorRunnerLinux: public CefMenuCreator::Runner {
|
|
||||||
public:
|
|
||||||
CefMenuCreatorRunnerLinux();
|
|
||||||
~CefMenuCreatorRunnerLinux() override;
|
|
||||||
|
|
||||||
// CefMemoryManager::Runner methods.
|
|
||||||
bool RunContextMenu(CefMenuCreator* manager) override;
|
|
||||||
void CancelContextMenu() override;
|
|
||||||
bool FormatLabel(base::string16& label) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
scoped_ptr<views::MenuRunner> menu_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_LINUX_H_
|
|
@ -1,29 +0,0 @@
|
|||||||
// 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_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_MAC_H_
|
|
||||||
#define CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_MAC_H_
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "libcef/browser/menu_creator.h"
|
|
||||||
|
|
||||||
#if __OBJC__
|
|
||||||
@class MenuController;
|
|
||||||
#else
|
|
||||||
class MenuController;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class CefMenuCreatorRunnerMac : public CefMenuCreator::Runner {
|
|
||||||
public:
|
|
||||||
CefMenuCreatorRunnerMac();
|
|
||||||
~CefMenuCreatorRunnerMac() override;
|
|
||||||
|
|
||||||
// CefMemoryManager::Runner methods.
|
|
||||||
bool RunContextMenu(CefMenuCreator* manager) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
MenuController* menu_controller_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_MAC_H_
|
|
@ -1,94 +0,0 @@
|
|||||||
// 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 "libcef/browser/menu_creator_runner_mac.h"
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
|
||||||
|
|
||||||
#include "base/message_loop/message_loop.h"
|
|
||||||
#include "base/compiler_specific.h"
|
|
||||||
#import "base/mac/scoped_sending_event.h"
|
|
||||||
#import "ui/base/cocoa/menu_controller.h"
|
|
||||||
|
|
||||||
CefMenuCreatorRunnerMac::CefMenuCreatorRunnerMac()
|
|
||||||
: menu_controller_(nil) {
|
|
||||||
}
|
|
||||||
|
|
||||||
CefMenuCreatorRunnerMac::~CefMenuCreatorRunnerMac() {
|
|
||||||
if (menu_controller_ != nil)
|
|
||||||
[menu_controller_ release];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CefMenuCreatorRunnerMac::RunContextMenu(CefMenuCreator* manager) {
|
|
||||||
// Create a menu controller based on the model.
|
|
||||||
if (menu_controller_ != nil)
|
|
||||||
[menu_controller_ release];
|
|
||||||
menu_controller_ =
|
|
||||||
[[MenuController alloc] initWithModel:manager->model()
|
|
||||||
useWithPopUpButtonCell:NO];
|
|
||||||
|
|
||||||
NSView* parent_view =
|
|
||||||
manager->browser()->GetWebContents()->GetContentNativeView();
|
|
||||||
|
|
||||||
// Synthesize an event for the click, as there is no certainty that
|
|
||||||
// [NSApp currentEvent] will return a valid event.
|
|
||||||
NSEvent* currentEvent = [NSApp currentEvent];
|
|
||||||
NSWindow* window = [parent_view window];
|
|
||||||
|
|
||||||
NSPoint position = [window mouseLocationOutsideOfEventStream];
|
|
||||||
|
|
||||||
NSTimeInterval eventTime = [currentEvent timestamp];
|
|
||||||
NSEvent* clickEvent = [NSEvent mouseEventWithType:NSRightMouseDown
|
|
||||||
location:position
|
|
||||||
modifierFlags:NSRightMouseDownMask
|
|
||||||
timestamp:eventTime
|
|
||||||
windowNumber:[window windowNumber]
|
|
||||||
context:nil
|
|
||||||
eventNumber:0
|
|
||||||
clickCount:1
|
|
||||||
pressure:1.0];
|
|
||||||
|
|
||||||
{
|
|
||||||
// Make sure events can be pumped while the menu is up.
|
|
||||||
base::MessageLoop::ScopedNestableTaskAllower allow(
|
|
||||||
base::MessageLoop::current());
|
|
||||||
|
|
||||||
// One of the events that could be pumped is |window.close()|.
|
|
||||||
// User-initiated event-tracking loops protect against this by
|
|
||||||
// setting flags in -[CrApplication sendEvent:], but since
|
|
||||||
// web-content menus are initiated by IPC message the setup has to
|
|
||||||
// be done manually.
|
|
||||||
base::mac::ScopedSendingEvent sendingEventScoper;
|
|
||||||
|
|
||||||
// Show the menu. Blocks until the menu is dismissed.
|
|
||||||
if (manager->browser()->IsWindowless()) {
|
|
||||||
// Showing the menu in OSR is pretty much self contained, only using
|
|
||||||
// the initialized menu_controller_ in this function, and the scoped
|
|
||||||
// variables in this block.
|
|
||||||
int screenX = 0, screenY = 0;
|
|
||||||
CefRefPtr<CefRenderHandler> handler =
|
|
||||||
manager->browser()->GetClient()->GetRenderHandler();
|
|
||||||
if (!handler->GetScreenPoint(manager->browser(),
|
|
||||||
manager->params().x, manager->params().y,
|
|
||||||
screenX, screenY)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't show the menu unless there is a parent native window to tie it to
|
|
||||||
if (!manager->browser()->GetWindowHandle())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
NSPoint screen_position =
|
|
||||||
NSPointFromCGPoint(gfx::Point(screenX, screenY).ToCGPoint());
|
|
||||||
[[menu_controller_ menu] popUpMenuPositioningItem:nil
|
|
||||||
atLocation:screen_position
|
|
||||||
inView:nil];
|
|
||||||
} else {
|
|
||||||
[NSMenu popUpContextMenu:[menu_controller_ menu]
|
|
||||||
withEvent:clickEvent
|
|
||||||
forView:parent_view];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
// 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 "libcef/browser/menu_creator_runner_win.h"
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
|
||||||
|
|
||||||
#include "base/message_loop/message_loop.h"
|
|
||||||
#include "ui/aura/window.h"
|
|
||||||
#include "ui/gfx/geometry/point.h"
|
|
||||||
#include "ui/gfx/geometry/point_conversions.h"
|
|
||||||
#include "ui/gfx/screen.h"
|
|
||||||
#include "ui/views/controls/menu/menu_2.h"
|
|
||||||
|
|
||||||
CefMenuCreatorRunnerWin::CefMenuCreatorRunnerWin() {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CefMenuCreatorRunnerWin::RunContextMenu(CefMenuCreator* manager) {
|
|
||||||
// Create a menu based on the model.
|
|
||||||
menu_.reset(new views::NativeMenuWin(manager->model(), NULL));
|
|
||||||
menu_->Rebuild(NULL);
|
|
||||||
|
|
||||||
// Make sure events can be pumped while the menu is up.
|
|
||||||
base::MessageLoop::ScopedNestableTaskAllower allow(
|
|
||||||
base::MessageLoop::current());
|
|
||||||
|
|
||||||
gfx::Point screen_point;
|
|
||||||
|
|
||||||
if (manager->browser()->IsWindowless()) {
|
|
||||||
CefRefPtr<CefClient> client = manager->browser()->GetClient();
|
|
||||||
if (!client.get())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CefRefPtr<CefRenderHandler> handler = client->GetRenderHandler();
|
|
||||||
if (!handler.get())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
int screenX = 0, screenY = 0;
|
|
||||||
if (!handler->GetScreenPoint(manager->browser(),
|
|
||||||
manager->params().x, manager->params().y,
|
|
||||||
screenX, screenY)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
screen_point = gfx::Point(screenX, screenY);
|
|
||||||
} else {
|
|
||||||
aura::Window* window = manager->browser()->GetContentView();
|
|
||||||
const gfx::Rect& bounds_in_screen = window->GetBoundsInScreen();
|
|
||||||
screen_point = gfx::Point(bounds_in_screen.x() + manager->params().x,
|
|
||||||
bounds_in_screen.y() + manager->params().y);
|
|
||||||
|
|
||||||
// Adjust for potential display scaling.
|
|
||||||
float scale = gfx::Screen::GetScreenFor(window)->
|
|
||||||
GetDisplayNearestWindow(window).device_scale_factor();
|
|
||||||
screen_point = gfx::ToFlooredPoint(
|
|
||||||
gfx::ScalePoint(gfx::PointF(screen_point), scale));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show the menu. Blocks until the menu is dismissed.
|
|
||||||
menu_->RunMenuAt(screen_point, views::Menu2::ALIGN_TOPLEFT);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
@ -1,25 +0,0 @@
|
|||||||
// 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_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_WIN_H_
|
|
||||||
#define CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_WIN_H_
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "libcef/browser/menu_creator.h"
|
|
||||||
|
|
||||||
#include "base/memory/scoped_ptr.h"
|
|
||||||
#include "ui/views/controls/menu/native_menu_win.h"
|
|
||||||
|
|
||||||
class CefMenuCreatorRunnerWin : public CefMenuCreator::Runner {
|
|
||||||
public:
|
|
||||||
CefMenuCreatorRunnerWin();
|
|
||||||
|
|
||||||
// CefMemoryManager::Runner methods.
|
|
||||||
bool RunContextMenu(CefMenuCreator* manager) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
scoped_ptr<views::NativeMenuWin> menu_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_MENU_MANAGER_RUNNER_WIN_H_
|
|
@ -2,9 +2,11 @@
|
|||||||
// reserved. Use of this source code is governed by a BSD-style license that can
|
// reserved. Use of this source code is governed by a BSD-style license that can
|
||||||
// be found in the LICENSE file.
|
// be found in the LICENSE file.
|
||||||
|
|
||||||
#include "libcef/browser/menu_creator.h"
|
#include "libcef/browser/menu_manager.h"
|
||||||
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
#include "libcef/browser/context_menu_params_impl.h"
|
#include "libcef/browser/context_menu_params_impl.h"
|
||||||
|
#include "libcef/browser/menu_runner.h"
|
||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
#include "libcef/common/content_client.h"
|
#include "libcef/common/content_client.h"
|
||||||
|
|
||||||
@ -15,14 +17,6 @@
|
|||||||
#include "content/public/browser/render_widget_host_view.h"
|
#include "content/public/browser/render_widget_host_view.h"
|
||||||
#include "grit/cef_strings.h"
|
#include "grit/cef_strings.h"
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
#include "libcef/browser/menu_creator_runner_win.h"
|
|
||||||
#elif defined(OS_MACOSX)
|
|
||||||
#include "libcef/browser/menu_creator_runner_mac.h"
|
|
||||||
#elif defined(OS_LINUX)
|
|
||||||
#include "libcef/browser/menu_creator_runner_linux.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
CefString GetLabel(int message_id) {
|
CefString GetLabel(int message_id) {
|
||||||
@ -93,24 +87,30 @@ class CefRunContextMenuCallbackImpl : public CefRunContextMenuCallback {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
CefMenuCreator::CefMenuCreator(content::WebContents* web_contents,
|
CefMenuManager::CefMenuManager(CefBrowserHostImpl* browser,
|
||||||
CefBrowserHostImpl* browser)
|
scoped_ptr<CefMenuRunner> runner)
|
||||||
: content::WebContentsObserver(web_contents),
|
: content::WebContentsObserver(browser->web_contents()),
|
||||||
browser_(browser),
|
browser_(browser),
|
||||||
|
runner_(runner.Pass()),
|
||||||
custom_menu_callback_(NULL),
|
custom_menu_callback_(NULL),
|
||||||
weak_ptr_factory_(this) {
|
weak_ptr_factory_(this) {
|
||||||
DCHECK(web_contents);
|
DCHECK(web_contents());
|
||||||
DCHECK(browser_);
|
DCHECK(runner_.get());
|
||||||
model_ = new CefMenuModelImpl(this);
|
model_ = new CefMenuModelImpl(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
CefMenuCreator::~CefMenuCreator() {
|
CefMenuManager::~CefMenuManager() {
|
||||||
// The model may outlive the delegate if the context menu is visible when the
|
// The model may outlive the delegate if the context menu is visible when the
|
||||||
// application is closed.
|
// application is closed.
|
||||||
model_->set_delegate(NULL);
|
model_->set_delegate(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefMenuCreator::IsShowingContextMenu() {
|
void CefMenuManager::Destroy() {
|
||||||
|
CancelContextMenu();
|
||||||
|
runner_.reset(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefMenuManager::IsShowingContextMenu() {
|
||||||
if (!web_contents())
|
if (!web_contents())
|
||||||
return false;
|
return false;
|
||||||
content::RenderWidgetHostView* view =
|
content::RenderWidgetHostView* view =
|
||||||
@ -118,11 +118,8 @@ bool CefMenuCreator::IsShowingContextMenu() {
|
|||||||
return (view && view->IsShowingContextMenu());
|
return (view && view->IsShowingContextMenu());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefMenuCreator::CreateContextMenu(
|
bool CefMenuManager::CreateContextMenu(
|
||||||
const content::ContextMenuParams& params) {
|
const content::ContextMenuParams& params) {
|
||||||
if (!CreateRunner())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// The renderer may send the "show context menu" message multiple times, one
|
// The renderer may send the "show context menu" message multiple times, one
|
||||||
// for each right click mouse event it receives. Normally, this doesn't happen
|
// for each right click mouse event it receives. Normally, this doesn't happen
|
||||||
// because mouse events are not forwarded once the context menu is showing.
|
// because mouse events are not forwarded once the context menu is showing.
|
||||||
@ -162,7 +159,7 @@ bool CefMenuCreator::CreateContextMenu(
|
|||||||
if (model_->GetCount() > 0) {
|
if (model_->GetCount() > 0) {
|
||||||
CefRefPtr<CefRunContextMenuCallbackImpl> callbackImpl(
|
CefRefPtr<CefRunContextMenuCallbackImpl> callbackImpl(
|
||||||
new CefRunContextMenuCallbackImpl(
|
new CefRunContextMenuCallbackImpl(
|
||||||
base::Bind(&CefMenuCreator::ExecuteCommandCallback,
|
base::Bind(&CefMenuManager::ExecuteCommandCallback,
|
||||||
weak_ptr_factory_.GetWeakPtr())));
|
weak_ptr_factory_.GetWeakPtr())));
|
||||||
|
|
||||||
// This reference will be cleared when the callback is executed or
|
// This reference will be cleared when the callback is executed or
|
||||||
@ -198,10 +195,10 @@ bool CefMenuCreator::CreateContextMenu(
|
|||||||
|
|
||||||
if (custom_menu)
|
if (custom_menu)
|
||||||
return true;
|
return true;
|
||||||
return runner_->RunContextMenu(this);
|
return runner_->RunContextMenu(browser_, model_->model(), params_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefMenuCreator::CancelContextMenu() {
|
void CefMenuManager::CancelContextMenu() {
|
||||||
if (IsShowingContextMenu()) {
|
if (IsShowingContextMenu()) {
|
||||||
if (custom_menu_callback_)
|
if (custom_menu_callback_)
|
||||||
custom_menu_callback_->Cancel();
|
custom_menu_callback_->Cancel();
|
||||||
@ -210,24 +207,7 @@ void CefMenuCreator::CancelContextMenu() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefMenuCreator::CreateRunner() {
|
void CefMenuManager::ExecuteCommand(CefRefPtr<CefMenuModelImpl> source,
|
||||||
if (!runner_.get()) {
|
|
||||||
// Create the menu runner.
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
runner_.reset(new CefMenuCreatorRunnerWin);
|
|
||||||
#elif defined(OS_MACOSX)
|
|
||||||
runner_.reset(new CefMenuCreatorRunnerMac);
|
|
||||||
#elif defined(OS_LINUX)
|
|
||||||
runner_.reset(new CefMenuCreatorRunnerLinux);
|
|
||||||
#else
|
|
||||||
// Need an implementation.
|
|
||||||
NOTREACHED();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
return (runner_.get() != NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefMenuCreator::ExecuteCommand(CefRefPtr<CefMenuModelImpl> source,
|
|
||||||
int command_id,
|
int command_id,
|
||||||
cef_event_flags_t event_flags) {
|
cef_event_flags_t event_flags) {
|
||||||
// Give the client a chance to handle the command.
|
// Give the client a chance to handle the command.
|
||||||
@ -259,7 +239,7 @@ void CefMenuCreator::ExecuteCommand(CefRefPtr<CefMenuModelImpl> source,
|
|||||||
ExecuteDefaultCommand(command_id);
|
ExecuteDefaultCommand(command_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefMenuCreator::MenuWillShow(CefRefPtr<CefMenuModelImpl> source) {
|
void CefMenuManager::MenuWillShow(CefRefPtr<CefMenuModelImpl> source) {
|
||||||
// May be called for sub-menus as well.
|
// May be called for sub-menus as well.
|
||||||
if (source.get() != model_.get())
|
if (source.get() != model_.get())
|
||||||
return;
|
return;
|
||||||
@ -278,7 +258,7 @@ void CefMenuCreator::MenuWillShow(CefRefPtr<CefMenuModelImpl> source) {
|
|||||||
view->SetShowingContextMenu(true);
|
view->SetShowingContextMenu(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefMenuCreator::MenuClosed(CefRefPtr<CefMenuModelImpl> source) {
|
void CefMenuManager::MenuClosed(CefRefPtr<CefMenuModelImpl> source) {
|
||||||
// May be called for sub-menus as well.
|
// May be called for sub-menus as well.
|
||||||
if (source.get() != model_.get())
|
if (source.get() != model_.get())
|
||||||
return;
|
return;
|
||||||
@ -306,11 +286,11 @@ void CefMenuCreator::MenuClosed(CefRefPtr<CefMenuModelImpl> source) {
|
|||||||
web_contents()->NotifyContextMenuClosed(params_.custom_context);
|
web_contents()->NotifyContextMenuClosed(params_.custom_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefMenuCreator::FormatLabel(base::string16& label) {
|
bool CefMenuManager::FormatLabel(base::string16& label) {
|
||||||
return runner_->FormatLabel(label);
|
return runner_->FormatLabel(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefMenuCreator::ExecuteCommandCallback(int command_id,
|
void CefMenuManager::ExecuteCommandCallback(int command_id,
|
||||||
cef_event_flags_t event_flags) {
|
cef_event_flags_t event_flags) {
|
||||||
DCHECK(IsShowingContextMenu());
|
DCHECK(IsShowingContextMenu());
|
||||||
DCHECK(custom_menu_callback_);
|
DCHECK(custom_menu_callback_);
|
||||||
@ -320,7 +300,7 @@ void CefMenuCreator::ExecuteCommandCallback(int command_id,
|
|||||||
custom_menu_callback_ = NULL;
|
custom_menu_callback_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefMenuCreator::CreateDefaultModel() {
|
void CefMenuManager::CreateDefaultModel() {
|
||||||
if (!params_.custom_items.empty()) {
|
if (!params_.custom_items.empty()) {
|
||||||
// Custom menu items originating from the renderer process. For example,
|
// Custom menu items originating from the renderer process. For example,
|
||||||
// plugin placeholder menu items or Flash menu items.
|
// plugin placeholder menu items or Flash menu items.
|
||||||
@ -410,7 +390,7 @@ void CefMenuCreator::CreateDefaultModel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefMenuCreator::ExecuteDefaultCommand(int command_id) {
|
void CefMenuManager::ExecuteDefaultCommand(int command_id) {
|
||||||
if (IsCustomContextMenuCommand(command_id)) {
|
if (IsCustomContextMenuCommand(command_id)) {
|
||||||
if (web_contents()) {
|
if (web_contents()) {
|
||||||
web_contents()->ExecuteCustomContextMenuCommand(
|
web_contents()->ExecuteCustomContextMenuCommand(
|
||||||
@ -494,7 +474,7 @@ void CefMenuCreator::ExecuteDefaultCommand(int command_id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefMenuCreator::IsCustomContextMenuCommand(int command_id) {
|
bool CefMenuManager::IsCustomContextMenuCommand(int command_id) {
|
||||||
// Verify that the command ID is in the correct range.
|
// Verify that the command ID is in the correct range.
|
||||||
if (command_id < MENU_ID_CUSTOM_FIRST || command_id > MENU_ID_CUSTOM_LAST)
|
if (command_id < MENU_ID_CUSTOM_FIRST || command_id > MENU_ID_CUSTOM_LAST)
|
||||||
return false;
|
return false;
|
@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
#include "libcef/browser/menu_model_impl.h"
|
#include "libcef/browser/menu_model_impl.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/menu_runner.h"
|
||||||
|
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "base/memory/scoped_ptr.h"
|
||||||
#include "base/memory/weak_ptr.h"
|
#include "base/memory/weak_ptr.h"
|
||||||
#include "content/public/browser/web_contents_observer.h"
|
#include "content/public/browser/web_contents_observer.h"
|
||||||
@ -18,24 +20,18 @@ class RenderFrameHost;
|
|||||||
class WebContents;
|
class WebContents;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CefRunContextMenuCallback;
|
|
||||||
class CefBrowserHostImpl;
|
class CefBrowserHostImpl;
|
||||||
|
class CefRunContextMenuCallback;
|
||||||
|
|
||||||
class CefMenuCreator : public CefMenuModelImpl::Delegate,
|
class CefMenuManager : public CefMenuModelImpl::Delegate,
|
||||||
public content::WebContentsObserver {
|
public content::WebContentsObserver {
|
||||||
public:
|
public:
|
||||||
// Used for OS-specific menu implementations.
|
CefMenuManager(CefBrowserHostImpl* browser,
|
||||||
class Runner {
|
scoped_ptr<CefMenuRunner> runner);
|
||||||
public:
|
~CefMenuManager() override;
|
||||||
virtual ~Runner() {}
|
|
||||||
virtual bool RunContextMenu(CefMenuCreator* manager) =0;
|
|
||||||
virtual void CancelContextMenu() {}
|
|
||||||
virtual bool FormatLabel(base::string16& label) { return false; }
|
|
||||||
};
|
|
||||||
|
|
||||||
CefMenuCreator(content::WebContents* web_contents,
|
// Delete the runner to free any platform constructs.
|
||||||
CefBrowserHostImpl* browser);
|
void Destroy();
|
||||||
~CefMenuCreator() override;
|
|
||||||
|
|
||||||
// Returns true if the context menu is currently showing.
|
// Returns true if the context menu is currently showing.
|
||||||
bool IsShowingContextMenu();
|
bool IsShowingContextMenu();
|
||||||
@ -44,14 +40,7 @@ class CefMenuCreator : public CefMenuModelImpl::Delegate,
|
|||||||
bool CreateContextMenu(const content::ContextMenuParams& params);
|
bool CreateContextMenu(const content::ContextMenuParams& params);
|
||||||
void CancelContextMenu();
|
void CancelContextMenu();
|
||||||
|
|
||||||
CefBrowserHostImpl* browser() { return browser_; }
|
|
||||||
ui::MenuModel* model() { return model_->model(); }
|
|
||||||
const content::ContextMenuParams& params() const { return params_; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Create the menu runner if it doesn't already exist.
|
|
||||||
bool CreateRunner();
|
|
||||||
|
|
||||||
// CefMenuModelImpl::Delegate methods.
|
// CefMenuModelImpl::Delegate methods.
|
||||||
void ExecuteCommand(CefRefPtr<CefMenuModelImpl> source,
|
void ExecuteCommand(CefRefPtr<CefMenuModelImpl> source,
|
||||||
int command_id,
|
int command_id,
|
||||||
@ -74,17 +63,18 @@ class CefMenuCreator : public CefMenuModelImpl::Delegate,
|
|||||||
// CefBrowserHostImpl pointer is guaranteed to outlive this object.
|
// CefBrowserHostImpl pointer is guaranteed to outlive this object.
|
||||||
CefBrowserHostImpl* browser_;
|
CefBrowserHostImpl* browser_;
|
||||||
|
|
||||||
|
scoped_ptr<CefMenuRunner> runner_;
|
||||||
|
|
||||||
CefRefPtr<CefMenuModelImpl> model_;
|
CefRefPtr<CefMenuModelImpl> model_;
|
||||||
content::ContextMenuParams params_;
|
content::ContextMenuParams params_;
|
||||||
scoped_ptr<Runner> runner_;
|
|
||||||
|
|
||||||
// Not owned by this class.
|
// Not owned by this class.
|
||||||
CefRunContextMenuCallback* custom_menu_callback_;
|
CefRunContextMenuCallback* custom_menu_callback_;
|
||||||
|
|
||||||
// Must be the last member.
|
// Must be the last member.
|
||||||
base::WeakPtrFactory<CefMenuCreator> weak_ptr_factory_;
|
base::WeakPtrFactory<CefMenuManager> weak_ptr_factory_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CefMenuCreator);
|
DISALLOW_COPY_AND_ASSIGN(CefMenuManager);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_MENU_MANAGER_H_
|
#endif // CEF_LIBCEF_BROWSER_MENU_MANAGER_H_
|
40
libcef/browser/menu_runner.h
Normal file
40
libcef/browser/menu_runner.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
// 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_LIBCEF_BROWSER_MENU_RUNNER_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_MENU_RUNNER_H_
|
||||||
|
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#include "base/strings/string16.h"
|
||||||
|
|
||||||
|
namespace content {
|
||||||
|
struct ContextMenuParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ui {
|
||||||
|
class MenuModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
class CefBrowserHostImpl;
|
||||||
|
|
||||||
|
// Provides platform-specific menu implementations for CefMenuCreator.
|
||||||
|
class CefMenuRunner {
|
||||||
|
public:
|
||||||
|
virtual bool RunContextMenu(CefBrowserHostImpl* browser,
|
||||||
|
ui::MenuModel* model,
|
||||||
|
const content::ContextMenuParams& params) = 0;
|
||||||
|
virtual void CancelContextMenu() {}
|
||||||
|
virtual bool FormatLabel(base::string16& label) { return false; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Allow deletion via scoped_ptr only.
|
||||||
|
friend struct base::DefaultDeleter<CefMenuRunner>;
|
||||||
|
|
||||||
|
CefMenuRunner() {}
|
||||||
|
virtual ~CefMenuRunner() {}
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CefMenuRunner);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_MENU_RUNNER_H_
|
47
libcef/browser/native/browser_platform_delegate_native.cc
Normal file
47
libcef/browser/native/browser_platform_delegate_native.cc
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright 2015 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 "libcef/browser/native/browser_platform_delegate_native.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
|
||||||
|
#include "content/public/browser/render_view_host.h"
|
||||||
|
#include "content/public/browser/render_widget_host.h"
|
||||||
|
|
||||||
|
CefBrowserPlatformDelegateNative::CefBrowserPlatformDelegateNative(
|
||||||
|
const CefWindowInfo& window_info)
|
||||||
|
: window_info_(window_info),
|
||||||
|
windowless_handler_(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNative::WasResized() {
|
||||||
|
content::RenderViewHost* host = browser_->web_contents()->GetRenderViewHost();
|
||||||
|
if (host)
|
||||||
|
host->GetWidget()->WasResized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNative::SendKeyEvent(
|
||||||
|
const content::NativeWebKeyboardEvent& event) {
|
||||||
|
content::RenderViewHost* host = browser_->web_contents()->GetRenderViewHost();
|
||||||
|
if (host)
|
||||||
|
host->GetWidget()->ForwardKeyboardEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNative::SendMouseEvent(
|
||||||
|
const blink::WebMouseEvent& event) {
|
||||||
|
content::RenderViewHost* host = browser_->web_contents()->GetRenderViewHost();
|
||||||
|
if (host)
|
||||||
|
host->GetWidget()->ForwardMouseEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNative::SendMouseWheelEvent(
|
||||||
|
const blink::WebMouseWheelEvent& event) {
|
||||||
|
content::RenderViewHost* host = browser_->web_contents()->GetRenderViewHost();
|
||||||
|
if (host)
|
||||||
|
host->GetWidget()->ForwardWheelEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefBrowserPlatformDelegateNative::IsWindowless() const {
|
||||||
|
return false;
|
||||||
|
}
|
48
libcef/browser/native/browser_platform_delegate_native.h
Normal file
48
libcef/browser/native/browser_platform_delegate_native.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Copyright 2015 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_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_H_
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_platform_delegate.h"
|
||||||
|
|
||||||
|
// Base implementation of native browser functionality.
|
||||||
|
class CefBrowserPlatformDelegateNative : public CefBrowserPlatformDelegate {
|
||||||
|
public:
|
||||||
|
// Used by the windowless implementation to override specific functionality
|
||||||
|
// when delegating to the native implementation.
|
||||||
|
class WindowlessHandler {
|
||||||
|
public:
|
||||||
|
// Returns the parent window handle.
|
||||||
|
virtual CefWindowHandle GetParentWindowHandle() const = 0;
|
||||||
|
|
||||||
|
// Convert from view coordinates to screen coordinates.
|
||||||
|
virtual gfx::Point GetParentScreenPoint(const gfx::Point& view) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~WindowlessHandler() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// CefBrowserPlatformDelegate methods:
|
||||||
|
void WasResized() override;
|
||||||
|
void SendKeyEvent(const content::NativeWebKeyboardEvent& event) override;
|
||||||
|
void SendMouseEvent(const blink::WebMouseEvent& event) override;
|
||||||
|
void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;
|
||||||
|
bool IsWindowless() const override;
|
||||||
|
|
||||||
|
const CefWindowInfo& window_info() const { return window_info_; }
|
||||||
|
|
||||||
|
void set_windowless_handler(WindowlessHandler* handler) {
|
||||||
|
windowless_handler_ = handler;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
explicit CefBrowserPlatformDelegateNative(const CefWindowInfo& window_info);
|
||||||
|
|
||||||
|
CefWindowInfo window_info_;
|
||||||
|
|
||||||
|
WindowlessHandler* windowless_handler_; // Not owned by this object.
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_H_
|
@ -1,29 +1,27 @@
|
|||||||
// Copyright (c) 2014 The Chromium Embedded Framework Authors.
|
// Copyright 2015 The Chromium Embedded Framework Authors. All rights reserved.
|
||||||
// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/native/browser_platform_delegate_native_linux.h"
|
||||||
|
|
||||||
// Include this first to avoid type conflict errors.
|
// Include this first to avoid type conflict errors.
|
||||||
#include "base/tracked_objects.h"
|
#include "base/tracked_objects.h"
|
||||||
#undef Status
|
#undef Status
|
||||||
|
|
||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
#include <X11/cursorfont.h>
|
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
#include "libcef/browser/context.h"
|
#include "libcef/browser/context.h"
|
||||||
#include "libcef/browser/window_delegate_view.h"
|
#include "libcef/browser/native/menu_runner_linux.h"
|
||||||
#include "libcef/browser/window_x11.h"
|
#include "libcef/browser/native/window_delegate_view.h"
|
||||||
|
#include "libcef/browser/native/window_x11.h"
|
||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
|
|
||||||
#include "base/bind.h"
|
|
||||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||||
#include "content/public/browser/native_web_keyboard_event.h"
|
#include "content/public/browser/native_web_keyboard_event.h"
|
||||||
#include "content/public/browser/render_view_host.h"
|
#include "content/public/browser/render_view_host.h"
|
||||||
#include "content/public/common/file_chooser_params.h"
|
|
||||||
#include "content/public/common/renderer_preferences.h"
|
#include "content/public/common/renderer_preferences.h"
|
||||||
#include "third_party/WebKit/public/web/WebInputEvent.h"
|
#include "ui/gfx/font_render_params.h"
|
||||||
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
|
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
|
||||||
#include "ui/views/widget/widget.h"
|
#include "ui/views/widget/widget.h"
|
||||||
|
|
||||||
@ -37,121 +35,27 @@ long GetSystemUptime() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Based on ui/base/cursor/cursor_loader_x11.cc.
|
|
||||||
|
|
||||||
using blink::WebCursorInfo;
|
|
||||||
|
|
||||||
int ToCursorID(WebCursorInfo::Type type) {
|
|
||||||
switch (type) {
|
|
||||||
case WebCursorInfo::TypePointer:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeCross:
|
|
||||||
return XC_crosshair;
|
|
||||||
case WebCursorInfo::TypeHand:
|
|
||||||
return XC_hand2;
|
|
||||||
case WebCursorInfo::TypeIBeam:
|
|
||||||
return XC_xterm;
|
|
||||||
case WebCursorInfo::TypeWait:
|
|
||||||
return XC_watch;
|
|
||||||
case WebCursorInfo::TypeHelp:
|
|
||||||
return XC_question_arrow;
|
|
||||||
case WebCursorInfo::TypeEastResize:
|
|
||||||
return XC_right_side;
|
|
||||||
case WebCursorInfo::TypeNorthResize:
|
|
||||||
return XC_top_side;
|
|
||||||
case WebCursorInfo::TypeNorthEastResize:
|
|
||||||
return XC_top_right_corner;
|
|
||||||
case WebCursorInfo::TypeNorthWestResize:
|
|
||||||
return XC_top_left_corner;
|
|
||||||
case WebCursorInfo::TypeSouthResize:
|
|
||||||
return XC_bottom_side;
|
|
||||||
case WebCursorInfo::TypeSouthEastResize:
|
|
||||||
return XC_bottom_right_corner;
|
|
||||||
case WebCursorInfo::TypeSouthWestResize:
|
|
||||||
return XC_bottom_left_corner;
|
|
||||||
case WebCursorInfo::TypeWestResize:
|
|
||||||
return XC_left_side;
|
|
||||||
case WebCursorInfo::TypeNorthSouthResize:
|
|
||||||
return XC_sb_v_double_arrow;
|
|
||||||
case WebCursorInfo::TypeEastWestResize:
|
|
||||||
return XC_sb_h_double_arrow;
|
|
||||||
case WebCursorInfo::TypeNorthEastSouthWestResize:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeNorthWestSouthEastResize:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeColumnResize:
|
|
||||||
return XC_sb_h_double_arrow;
|
|
||||||
case WebCursorInfo::TypeRowResize:
|
|
||||||
return XC_sb_v_double_arrow;
|
|
||||||
case WebCursorInfo::TypeMiddlePanning:
|
|
||||||
return XC_fleur;
|
|
||||||
case WebCursorInfo::TypeEastPanning:
|
|
||||||
return XC_sb_right_arrow;
|
|
||||||
case WebCursorInfo::TypeNorthPanning:
|
|
||||||
return XC_sb_up_arrow;
|
|
||||||
case WebCursorInfo::TypeNorthEastPanning:
|
|
||||||
return XC_top_right_corner;
|
|
||||||
case WebCursorInfo::TypeNorthWestPanning:
|
|
||||||
return XC_top_left_corner;
|
|
||||||
case WebCursorInfo::TypeSouthPanning:
|
|
||||||
return XC_sb_down_arrow;
|
|
||||||
case WebCursorInfo::TypeSouthEastPanning:
|
|
||||||
return XC_bottom_right_corner;
|
|
||||||
case WebCursorInfo::TypeSouthWestPanning:
|
|
||||||
return XC_bottom_left_corner;
|
|
||||||
case WebCursorInfo::TypeWestPanning:
|
|
||||||
return XC_sb_left_arrow;
|
|
||||||
case WebCursorInfo::TypeMove:
|
|
||||||
return XC_fleur;
|
|
||||||
case WebCursorInfo::TypeVerticalText:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeCell:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeContextMenu:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeAlias:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeProgress:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeNoDrop:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeCopy:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeNotAllowed:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeZoomIn:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeZoomOut:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeGrab:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeGrabbing:
|
|
||||||
return XC_left_ptr;
|
|
||||||
case WebCursorInfo::TypeCustom:
|
|
||||||
case WebCursorInfo::TypeNone:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
NOTREACHED();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
ui::PlatformCursor CefBrowserHostImpl::GetPlatformCursor(
|
CefBrowserPlatformDelegateNativeLinux::CefBrowserPlatformDelegateNativeLinux(
|
||||||
blink::WebCursorInfo::Type type) {
|
const CefWindowInfo& window_info)
|
||||||
if (type == WebCursorInfo::TypeNone) {
|
: CefBrowserPlatformDelegateNative(window_info),
|
||||||
if (!invisible_cursor_) {
|
host_window_created_(false),
|
||||||
invisible_cursor_.reset(
|
window_widget_(nullptr),
|
||||||
new ui::XScopedCursor(ui::CreateInvisibleCursor(),
|
window_x11_(nullptr) {
|
||||||
gfx::GetXDisplay()));
|
}
|
||||||
}
|
|
||||||
return invisible_cursor_->get();
|
void CefBrowserPlatformDelegateNativeLinux::BrowserDestroyed(
|
||||||
} else {
|
CefBrowserHostImpl* browser) {
|
||||||
return ui::GetXCursor(ToCursorID(type));
|
CefBrowserPlatformDelegate::BrowserDestroyed(browser);
|
||||||
|
|
||||||
|
if (host_window_created_) {
|
||||||
|
// Release the reference added in CreateHostWindow().
|
||||||
|
browser->Release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefBrowserHostImpl::PlatformCreateWindow() {
|
bool CefBrowserPlatformDelegateNativeLinux::CreateHostWindow() {
|
||||||
DCHECK(!window_x11_);
|
DCHECK(!window_x11_);
|
||||||
DCHECK(!window_widget_);
|
DCHECK(!window_widget_);
|
||||||
|
|
||||||
@ -165,11 +69,13 @@ bool CefBrowserHostImpl::PlatformCreateWindow() {
|
|||||||
|
|
||||||
// Create a new window object. It will delete itself when the associated X11
|
// Create a new window object. It will delete itself when the associated X11
|
||||||
// window is destroyed.
|
// window is destroyed.
|
||||||
window_x11_ = new CefWindowX11(this, window_info_.parent_window, rect);
|
window_x11_ = new CefWindowX11(browser_, window_info_.parent_window, rect);
|
||||||
window_info_.window = window_x11_->xwindow();
|
window_info_.window = window_x11_->xwindow();
|
||||||
|
|
||||||
// Add a reference that will be released in the destroy handler.
|
host_window_created_ = true;
|
||||||
AddRef();
|
|
||||||
|
// Add a reference that will be released in BrowserDestroyed().
|
||||||
|
browser_->AddRef();
|
||||||
|
|
||||||
SkColor background_color = SK_ColorWHITE;
|
SkColor background_color = SK_ColorWHITE;
|
||||||
const CefSettings& settings = CefContext::Get()->settings();
|
const CefSettings& settings = CefContext::Get()->settings();
|
||||||
@ -183,7 +89,7 @@ bool CefBrowserHostImpl::PlatformCreateWindow() {
|
|||||||
CefWindowDelegateView* delegate_view =
|
CefWindowDelegateView* delegate_view =
|
||||||
new CefWindowDelegateView(background_color);
|
new CefWindowDelegateView(background_color);
|
||||||
delegate_view->Init(window_info_.window,
|
delegate_view->Init(window_info_.window,
|
||||||
web_contents(),
|
browser_->web_contents(),
|
||||||
gfx::Rect(gfx::Point(), rect.size()));
|
gfx::Rect(gfx::Point(), rect.size()));
|
||||||
|
|
||||||
window_widget_ = delegate_view->GetWidget();
|
window_widget_ = delegate_view->GetWidget();
|
||||||
@ -194,7 +100,7 @@ bool CefBrowserHostImpl::PlatformCreateWindow() {
|
|||||||
// As an additional requirement on Linux, we must set the colors for the
|
// As an additional requirement on Linux, we must set the colors for the
|
||||||
// render widgets in webkit.
|
// render widgets in webkit.
|
||||||
content::RendererPreferences* prefs =
|
content::RendererPreferences* prefs =
|
||||||
web_contents_->GetMutableRendererPrefs();
|
browser_->web_contents()->GetMutableRendererPrefs();
|
||||||
prefs->focus_ring_color = SkColorSetARGB(255, 229, 151, 0);
|
prefs->focus_ring_color = SkColorSetARGB(255, 229, 151, 0);
|
||||||
prefs->thumb_active_color = SkColorSetRGB(244, 244, 244);
|
prefs->thumb_active_color = SkColorSetRGB(244, 244, 244);
|
||||||
prefs->thumb_inactive_color = SkColorSetRGB(234, 234, 234);
|
prefs->thumb_inactive_color = SkColorSetRGB(234, 234, 234);
|
||||||
@ -205,29 +111,45 @@ bool CefBrowserHostImpl::PlatformCreateWindow() {
|
|||||||
prefs->inactive_selection_bg_color = SkColorSetRGB(200, 200, 200);
|
prefs->inactive_selection_bg_color = SkColorSetRGB(200, 200, 200);
|
||||||
prefs->inactive_selection_fg_color = SkColorSetRGB(50, 50, 50);
|
prefs->inactive_selection_fg_color = SkColorSetRGB(50, 50, 50);
|
||||||
|
|
||||||
|
// Set font-related attributes.
|
||||||
|
CR_DEFINE_STATIC_LOCAL(const gfx::FontRenderParams, params,
|
||||||
|
(gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), NULL)));
|
||||||
|
prefs->should_antialias_text = params.antialiasing;
|
||||||
|
prefs->use_subpixel_positioning = params.subpixel_positioning;
|
||||||
|
prefs->hinting = params.hinting;
|
||||||
|
prefs->use_autohinter = params.autohinter;
|
||||||
|
prefs->use_bitmaps = params.use_bitmaps;
|
||||||
|
prefs->subpixel_rendering = params.subpixel_rendering;
|
||||||
|
|
||||||
|
browser_->web_contents()->GetRenderViewHost()->SyncRendererPrefs();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformCloseWindow() {
|
void CefBrowserPlatformDelegateNativeLinux::CloseHostWindow() {
|
||||||
if (window_x11_)
|
if (window_x11_)
|
||||||
window_x11_->Close();
|
window_x11_->Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformSizeTo(int width, int height) {
|
CefWindowHandle
|
||||||
if (window_x11_) {
|
CefBrowserPlatformDelegateNativeLinux::GetHostWindowHandle() const {
|
||||||
window_x11_->SetBounds(
|
if (windowless_handler_)
|
||||||
gfx::Rect(window_x11_->bounds().origin(), gfx::Size(width, height)));
|
return windowless_handler_->GetParentWindowHandle();
|
||||||
}
|
return window_info_.window;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformSetFocus(bool focus) {
|
views::Widget* CefBrowserPlatformDelegateNativeLinux::GetWindowWidget() const {
|
||||||
if (!focus)
|
return window_widget_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeLinux::SendFocusEvent(bool setFocus) {
|
||||||
|
if (!setFocus)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (web_contents_) {
|
if (browser_->web_contents()) {
|
||||||
// Give logical focus to the RenderWidgetHostViewAura in the views
|
// Give logical focus to the RenderWidgetHostViewAura in the views
|
||||||
// hierarchy. This does not change the native keyboard focus.
|
// hierarchy. This does not change the native keyboard focus.
|
||||||
web_contents_->Focus();
|
browser_->web_contents()->Focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window_x11_) {
|
if (window_x11_) {
|
||||||
@ -238,26 +160,66 @@ void CefBrowserHostImpl::PlatformSetFocus(bool focus) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CefWindowHandle CefBrowserHostImpl::PlatformGetWindowHandle() {
|
void CefBrowserPlatformDelegateNativeLinux::NotifyMoveOrResizeStarted() {
|
||||||
return IsWindowless() ? window_info_.parent_window : window_info_.window;
|
// Call the parent method to dismiss any existing popups.
|
||||||
|
CefBrowserPlatformDelegate::NotifyMoveOrResizeStarted();
|
||||||
|
|
||||||
|
if (!window_x11_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
views::DesktopWindowTreeHostX11* tree_host = window_x11_->GetHost();
|
||||||
|
if (!tree_host)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Explicitly set the screen bounds so that WindowTreeHost::*Screen()
|
||||||
|
// methods return the correct results.
|
||||||
|
const gfx::Rect& bounds = window_x11_->GetBoundsInScreen();
|
||||||
|
tree_host->set_screen_bounds(bounds);
|
||||||
|
|
||||||
|
// Send updated screen rectangle information to the renderer process so that
|
||||||
|
// popups are displayed in the correct location.
|
||||||
|
content::RenderWidgetHostImpl::From(
|
||||||
|
browser_->web_contents()->GetRenderViewHost()->GetWidget())->
|
||||||
|
SendScreenRects();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CefBrowserHostImpl::PlatformViewText(const std::string& text) {
|
void CefBrowserPlatformDelegateNativeLinux::SizeTo(int width, int height) {
|
||||||
CEF_REQUIRE_UIT();
|
if (window_x11_) {
|
||||||
|
window_x11_->SetBounds(
|
||||||
|
gfx::Rect(window_x11_->bounds().origin(), gfx::Size(width, height)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::Point CefBrowserPlatformDelegateNativeLinux::GetScreenPoint(
|
||||||
|
const gfx::Point& view) const {
|
||||||
|
if (windowless_handler_)
|
||||||
|
return windowless_handler_->GetParentScreenPoint(view);
|
||||||
|
|
||||||
|
if (!window_x11_)
|
||||||
|
return view;
|
||||||
|
|
||||||
|
// We can't use aura::Window::GetBoundsInScreen on Linux because it will
|
||||||
|
// return bounds from DesktopWindowTreeHostX11 which in our case is relative
|
||||||
|
// to the parent window instead of the root window (screen).
|
||||||
|
const gfx::Rect& bounds_in_screen = window_x11_->GetBoundsInScreen();
|
||||||
|
return gfx::Point(bounds_in_screen.x() + view.x(),
|
||||||
|
bounds_in_screen.y() + view.y());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeLinux::ViewText(const std::string& text) {
|
||||||
char buff[] = "/tmp/CEFSourceXXXXXX";
|
char buff[] = "/tmp/CEFSourceXXXXXX";
|
||||||
int fd = mkstemp(buff);
|
int fd = mkstemp(buff);
|
||||||
|
|
||||||
if (fd == -1)
|
if (fd == -1)
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
FILE* srcOutput = fdopen(fd, "w+");
|
FILE* srcOutput = fdopen(fd, "w+");
|
||||||
if (!srcOutput)
|
if (!srcOutput)
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
if (fputs(text.c_str(), srcOutput) < 0) {
|
if (fputs(text.c_str(), srcOutput) < 0) {
|
||||||
fclose(srcOutput);
|
fclose(srcOutput);
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(srcOutput);
|
fclose(srcOutput);
|
||||||
@ -265,35 +227,26 @@ bool CefBrowserHostImpl::PlatformViewText(const std::string& text) {
|
|||||||
std::string newName(buff);
|
std::string newName(buff);
|
||||||
newName.append(".txt");
|
newName.append(".txt");
|
||||||
if (rename(buff, newName.c_str()) != 0)
|
if (rename(buff, newName.c_str()) != 0)
|
||||||
return false;
|
return;
|
||||||
|
|
||||||
std::string openCommand("xdg-open ");
|
std::string openCommand("xdg-open ");
|
||||||
openCommand += newName;
|
openCommand += newName;
|
||||||
|
|
||||||
if (system(openCommand.c_str()) != 0)
|
system(openCommand.c_str());
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformHandleKeyboardEvent(
|
void CefBrowserPlatformDelegateNativeLinux::HandleKeyboardEvent(
|
||||||
const content::NativeWebKeyboardEvent& event) {
|
const content::NativeWebKeyboardEvent& event) {
|
||||||
// TODO(cef): Is something required here to handle shortcut keys?
|
// TODO(cef): Is something required here to handle shortcut keys?
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformRunFileChooser(
|
void CefBrowserPlatformDelegateNativeLinux::HandleExternalProtocol(
|
||||||
const FileChooserParams& params,
|
const GURL& url) {
|
||||||
RunFileChooserCallback callback) {
|
|
||||||
NOTIMPLEMENTED();
|
|
||||||
callback.Run(0, std::vector<base::FilePath>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {
|
void CefBrowserPlatformDelegateNativeLinux::TranslateKeyEvent(
|
||||||
}
|
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformTranslateKeyEvent(
|
|
||||||
content::NativeWebKeyboardEvent& result,
|
content::NativeWebKeyboardEvent& result,
|
||||||
const CefKeyEvent& key_event) {
|
const CefKeyEvent& key_event) const {
|
||||||
result.timeStampSeconds = GetSystemUptime();
|
result.timeStampSeconds = GetSystemUptime();
|
||||||
|
|
||||||
result.windowsKeyCode = key_event.windows_key_code;
|
result.windowsKeyCode = key_event.windows_key_code;
|
||||||
@ -322,12 +275,12 @@ void CefBrowserHostImpl::PlatformTranslateKeyEvent(
|
|||||||
result.modifiers |= TranslateModifiers(key_event.modifiers);
|
result.modifiers |= TranslateModifiers(key_event.modifiers);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformTranslateClickEvent(
|
void CefBrowserPlatformDelegateNativeLinux::TranslateClickEvent(
|
||||||
blink::WebMouseEvent& result,
|
blink::WebMouseEvent& result,
|
||||||
const CefMouseEvent& mouse_event,
|
const CefMouseEvent& mouse_event,
|
||||||
MouseButtonType type,
|
CefBrowserHost::MouseButtonType type,
|
||||||
bool mouseUp, int clickCount) {
|
bool mouseUp, int clickCount) const {
|
||||||
PlatformTranslateMouseEvent(result, mouse_event);
|
TranslateMouseEvent(result, mouse_event);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case MBT_LEFT:
|
case MBT_LEFT:
|
||||||
@ -352,11 +305,11 @@ void CefBrowserHostImpl::PlatformTranslateClickEvent(
|
|||||||
result.clickCount = clickCount;
|
result.clickCount = clickCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformTranslateMoveEvent(
|
void CefBrowserPlatformDelegateNativeLinux::TranslateMoveEvent(
|
||||||
blink::WebMouseEvent& result,
|
blink::WebMouseEvent& result,
|
||||||
const CefMouseEvent& mouse_event,
|
const CefMouseEvent& mouse_event,
|
||||||
bool mouseLeave) {
|
bool mouseLeave) const {
|
||||||
PlatformTranslateMouseEvent(result, mouse_event);
|
TranslateMouseEvent(result, mouse_event);
|
||||||
|
|
||||||
if (!mouseLeave) {
|
if (!mouseLeave) {
|
||||||
result.type = blink::WebInputEvent::MouseMove;
|
result.type = blink::WebInputEvent::MouseMove;
|
||||||
@ -376,12 +329,12 @@ void CefBrowserHostImpl::PlatformTranslateMoveEvent(
|
|||||||
result.clickCount = 0;
|
result.clickCount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformTranslateWheelEvent(
|
void CefBrowserPlatformDelegateNativeLinux::TranslateWheelEvent(
|
||||||
blink::WebMouseWheelEvent& result,
|
blink::WebMouseWheelEvent& result,
|
||||||
const CefMouseEvent& mouse_event,
|
const CefMouseEvent& mouse_event,
|
||||||
int deltaX, int deltaY) {
|
int deltaX, int deltaY) const {
|
||||||
result = blink::WebMouseWheelEvent();
|
result = blink::WebMouseWheelEvent();
|
||||||
PlatformTranslateMouseEvent(result, mouse_event);
|
TranslateMouseEvent(result, mouse_event);
|
||||||
|
|
||||||
result.type = blink::WebInputEvent::MouseWheel;
|
result.type = blink::WebInputEvent::MouseWheel;
|
||||||
|
|
||||||
@ -407,28 +360,30 @@ void CefBrowserHostImpl::PlatformTranslateWheelEvent(
|
|||||||
result.button = blink::WebMouseEvent::ButtonNone;
|
result.button = blink::WebMouseEvent::ButtonNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformTranslateMouseEvent(
|
CefEventHandle CefBrowserPlatformDelegateNativeLinux::GetEventHandle(
|
||||||
|
const content::NativeWebKeyboardEvent& event) const {
|
||||||
|
if (!event.os_event)
|
||||||
|
return NULL;
|
||||||
|
return const_cast<CefEventHandle>(event.os_event->native_event());
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<CefMenuRunner>
|
||||||
|
CefBrowserPlatformDelegateNativeLinux::CreateMenuRunner() {
|
||||||
|
return make_scoped_ptr(new CefMenuRunnerLinux);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeLinux::TranslateMouseEvent(
|
||||||
blink::WebMouseEvent& result,
|
blink::WebMouseEvent& result,
|
||||||
const CefMouseEvent& mouse_event) {
|
const CefMouseEvent& mouse_event) const {
|
||||||
// position
|
// position
|
||||||
result.x = mouse_event.x;
|
result.x = mouse_event.x;
|
||||||
result.y = mouse_event.y;
|
result.y = mouse_event.y;
|
||||||
result.windowX = result.x;
|
result.windowX = result.x;
|
||||||
result.windowY = result.y;
|
result.windowY = result.y;
|
||||||
result.globalX = result.x;
|
|
||||||
result.globalY = result.y;
|
|
||||||
|
|
||||||
if (IsWindowless()) {
|
const gfx::Point& screen_pt = GetScreenPoint(gfx::Point(result.x, result.y));
|
||||||
CefRefPtr<CefRenderHandler> handler = client_->GetRenderHandler();
|
result.globalX = screen_pt.x();
|
||||||
if (handler.get()) {
|
result.globalY = screen_pt.y();
|
||||||
handler->GetScreenPoint(this, result.x, result.y, result.globalX,
|
|
||||||
result.globalY);
|
|
||||||
}
|
|
||||||
} else if (window_x11_) {
|
|
||||||
const gfx::Point& origin = window_x11_->bounds().origin();
|
|
||||||
result.globalX += origin.x();
|
|
||||||
result.globalY += origin.y();
|
|
||||||
}
|
|
||||||
|
|
||||||
// modifiers
|
// modifiers
|
||||||
result.modifiers |= TranslateModifiers(mouse_event.modifiers);
|
result.modifiers |= TranslateModifiers(mouse_event.modifiers);
|
||||||
@ -437,25 +392,3 @@ void CefBrowserHostImpl::PlatformTranslateMouseEvent(
|
|||||||
result.timeStampSeconds = GetSystemUptime();
|
result.timeStampSeconds = GetSystemUptime();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefBrowserHostImpl::PlatformNotifyMoveOrResizeStarted() {
|
|
||||||
if (IsWindowless())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!window_x11_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
views::DesktopWindowTreeHostX11* tree_host = window_x11_->GetHost();
|
|
||||||
if (!tree_host)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Explicitly set the screen bounds so that WindowTreeHost::*Screen()
|
|
||||||
// methods return the correct results.
|
|
||||||
const gfx::Rect& bounds = window_x11_->GetBoundsInScreen();
|
|
||||||
tree_host->set_screen_bounds(bounds);
|
|
||||||
|
|
||||||
// Send updated screen rectangle information to the renderer process so that
|
|
||||||
// popups are displayed in the correct location.
|
|
||||||
content::RenderWidgetHostImpl::From(
|
|
||||||
web_contents()->GetRenderViewHost()->GetWidget())->SendScreenRects();
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
|||||||
|
// Copyright 2015 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_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_LINUX_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_LINUX_H_
|
||||||
|
|
||||||
|
#include "libcef/browser/native/browser_platform_delegate_native.h"
|
||||||
|
|
||||||
|
class CefWindowX11;
|
||||||
|
|
||||||
|
// Windowed browser implementation for Linux.
|
||||||
|
class CefBrowserPlatformDelegateNativeLinux :
|
||||||
|
public CefBrowserPlatformDelegateNative {
|
||||||
|
public:
|
||||||
|
explicit CefBrowserPlatformDelegateNativeLinux(
|
||||||
|
const CefWindowInfo& window_info);
|
||||||
|
|
||||||
|
// CefBrowserPlatformDelegate methods:
|
||||||
|
void BrowserDestroyed(CefBrowserHostImpl* browser) override;
|
||||||
|
bool CreateHostWindow() override;
|
||||||
|
void CloseHostWindow() override;
|
||||||
|
CefWindowHandle GetHostWindowHandle() const override;
|
||||||
|
views::Widget* GetWindowWidget() const override;
|
||||||
|
void SendFocusEvent(bool setFocus) override;
|
||||||
|
void NotifyMoveOrResizeStarted() override;
|
||||||
|
void SizeTo(int width, int height) override;
|
||||||
|
gfx::Point GetScreenPoint(const gfx::Point& view) const override;
|
||||||
|
void ViewText(const std::string& text) override;
|
||||||
|
void HandleKeyboardEvent(
|
||||||
|
const content::NativeWebKeyboardEvent& event) override;
|
||||||
|
void HandleExternalProtocol(const GURL& url) override;
|
||||||
|
void TranslateKeyEvent(content::NativeWebKeyboardEvent& result,
|
||||||
|
const CefKeyEvent& key_event) const override;
|
||||||
|
void TranslateClickEvent(blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
CefBrowserHost::MouseButtonType type,
|
||||||
|
bool mouseUp, int clickCount) const override;
|
||||||
|
void TranslateMoveEvent(blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
bool mouseLeave) const override;
|
||||||
|
void TranslateWheelEvent(blink::WebMouseWheelEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
int deltaX, int deltaY) const override;
|
||||||
|
CefEventHandle GetEventHandle(
|
||||||
|
const content::NativeWebKeyboardEvent& event) const override;
|
||||||
|
scoped_ptr<CefMenuRunner> CreateMenuRunner() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void TranslateMouseEvent(blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event) const;
|
||||||
|
|
||||||
|
// True if the host window has been created.
|
||||||
|
bool host_window_created_;
|
||||||
|
|
||||||
|
// Widget hosting the web contents. It will be deleted automatically when the
|
||||||
|
// associated root window is destroyed.
|
||||||
|
views::Widget* window_widget_;
|
||||||
|
|
||||||
|
CefWindowX11* window_x11_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_LINUX_H_
|
54
libcef/browser/native/browser_platform_delegate_native_mac.h
Normal file
54
libcef/browser/native/browser_platform_delegate_native_mac.h
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// Copyright 2015 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_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_MAC_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_MAC_H_
|
||||||
|
|
||||||
|
#include "libcef/browser/native/browser_platform_delegate_native.h"
|
||||||
|
|
||||||
|
// Windowed browser implementation for Mac OS X.
|
||||||
|
class CefBrowserPlatformDelegateNativeMac :
|
||||||
|
public CefBrowserPlatformDelegateNative {
|
||||||
|
public:
|
||||||
|
explicit CefBrowserPlatformDelegateNativeMac(
|
||||||
|
const CefWindowInfo& window_info);
|
||||||
|
|
||||||
|
// CefBrowserPlatformDelegate methods:
|
||||||
|
void BrowserDestroyed(CefBrowserHostImpl* browser) override;
|
||||||
|
bool CreateHostWindow() override;
|
||||||
|
void CloseHostWindow() override;
|
||||||
|
CefWindowHandle GetHostWindowHandle() const override;
|
||||||
|
void SendFocusEvent(bool setFocus) override;
|
||||||
|
gfx::Point GetScreenPoint(const gfx::Point& view) const override;
|
||||||
|
void ViewText(const std::string& text) override;
|
||||||
|
void HandleKeyboardEvent(
|
||||||
|
const content::NativeWebKeyboardEvent& event) override;
|
||||||
|
void HandleExternalProtocol(const GURL& url) override;
|
||||||
|
void TranslateKeyEvent(content::NativeWebKeyboardEvent& result,
|
||||||
|
const CefKeyEvent& key_event) const override;
|
||||||
|
void TranslateClickEvent(blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
CefBrowserHost::MouseButtonType type,
|
||||||
|
bool mouseUp, int clickCount) const override;
|
||||||
|
void TranslateMoveEvent(blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
bool mouseLeave) const override;
|
||||||
|
void TranslateWheelEvent(blink::WebMouseWheelEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
int deltaX, int deltaY) const override;
|
||||||
|
CefEventHandle GetEventHandle(
|
||||||
|
const content::NativeWebKeyboardEvent& event) const override;
|
||||||
|
scoped_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
|
||||||
|
scoped_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner() override;
|
||||||
|
scoped_ptr<CefMenuRunner> CreateMenuRunner() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void TranslateMouseEvent(blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event) const;
|
||||||
|
|
||||||
|
// True if the host window has been created.
|
||||||
|
bool host_window_created_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_MAC_H_
|
536
libcef/browser/native/browser_platform_delegate_native_mac.mm
Normal file
536
libcef/browser/native/browser_platform_delegate_native_mac.mm
Normal file
@ -0,0 +1,536 @@
|
|||||||
|
// Copyright 2015 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 "libcef/browser/native/browser_platform_delegate_native_mac.h"
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import <CoreServices/CoreServices.h>
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
#include "libcef/browser/context.h"
|
||||||
|
#include "libcef/browser/native/file_dialog_runner_mac.h"
|
||||||
|
#include "libcef/browser/native/javascript_dialog_runner_mac.h"
|
||||||
|
#include "libcef/browser/native/menu_runner_mac.h"
|
||||||
|
#include "libcef/browser/thread_util.h"
|
||||||
|
|
||||||
|
#include "base/mac/scoped_nsautorelease_pool.h"
|
||||||
|
#include "base/threading/thread_restrictions.h"
|
||||||
|
#include "content/public/browser/native_web_keyboard_event.h"
|
||||||
|
#include "content/public/browser/render_widget_host_view.h"
|
||||||
|
#include "content/public/browser/web_contents.h"
|
||||||
|
#include "third_party/WebKit/public/web/WebInputEvent.h"
|
||||||
|
#import "ui/base/cocoa/underlay_opengl_hosting_window.h"
|
||||||
|
#include "ui/events/keycodes/keyboard_codes_posix.h"
|
||||||
|
#include "ui/gfx/geometry/rect.h"
|
||||||
|
|
||||||
|
// Wrapper NSView for the native view. Necessary to destroy the browser when
|
||||||
|
// the view is deleted.
|
||||||
|
@interface CefBrowserHostView : NSView {
|
||||||
|
@private
|
||||||
|
CefBrowserHostImpl* browser_; // weak
|
||||||
|
}
|
||||||
|
|
||||||
|
@property (nonatomic, assign) CefBrowserHostImpl* browser;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation CefBrowserHostView
|
||||||
|
|
||||||
|
@synthesize browser = browser_;
|
||||||
|
|
||||||
|
- (void) dealloc {
|
||||||
|
if (browser_) {
|
||||||
|
// Force the browser to be destroyed and release the reference added in
|
||||||
|
// PlatformCreateWindow().
|
||||||
|
browser_->WindowDestroyed();
|
||||||
|
}
|
||||||
|
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
// Receives notifications from the browser window. Will delete itself when done.
|
||||||
|
@interface CefWindowDelegate : NSObject <NSWindowDelegate> {
|
||||||
|
@private
|
||||||
|
CefBrowserHostImpl* browser_; // weak
|
||||||
|
NSWindow* window_;
|
||||||
|
}
|
||||||
|
- (id)initWithWindow:(NSWindow*)window andBrowser:(CefBrowserHostImpl*)browser;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation CefWindowDelegate
|
||||||
|
|
||||||
|
- (id)initWithWindow:(NSWindow*)window andBrowser:(CefBrowserHostImpl*)browser {
|
||||||
|
if (self = [super init]) {
|
||||||
|
window_ = window;
|
||||||
|
browser_ = browser;
|
||||||
|
|
||||||
|
[window_ setDelegate:self];
|
||||||
|
|
||||||
|
// Register for application hide/unhide notifications.
|
||||||
|
[[NSNotificationCenter defaultCenter]
|
||||||
|
addObserver:self
|
||||||
|
selector:@selector(applicationDidHide:)
|
||||||
|
name:NSApplicationDidHideNotification
|
||||||
|
object:nil];
|
||||||
|
[[NSNotificationCenter defaultCenter]
|
||||||
|
addObserver:self
|
||||||
|
selector:@selector(applicationDidUnhide:)
|
||||||
|
name:NSApplicationDidUnhideNotification
|
||||||
|
object:nil];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)dealloc {
|
||||||
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||||
|
|
||||||
|
[super dealloc];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when we are activated (when we gain focus).
|
||||||
|
- (void)windowDidBecomeKey:(NSNotification*)notification {
|
||||||
|
if (browser_)
|
||||||
|
browser_->SetFocus(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when we are deactivated (when we lose focus).
|
||||||
|
- (void)windowDidResignKey:(NSNotification*)notification {
|
||||||
|
if (browser_)
|
||||||
|
browser_->SetFocus(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when we have been minimized.
|
||||||
|
- (void)windowDidMiniaturize:(NSNotification *)notification {
|
||||||
|
if (browser_)
|
||||||
|
browser_->SetWindowVisibility(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when we have been unminimized.
|
||||||
|
- (void)windowDidDeminiaturize:(NSNotification *)notification {
|
||||||
|
if (browser_)
|
||||||
|
browser_->SetWindowVisibility(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when the application has been hidden.
|
||||||
|
- (void)applicationDidHide:(NSNotification *)notification {
|
||||||
|
// If the window is miniaturized then nothing has really changed.
|
||||||
|
if (![window_ isMiniaturized]) {
|
||||||
|
if (browser_)
|
||||||
|
browser_->SetWindowVisibility(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when the application has been unhidden.
|
||||||
|
- (void)applicationDidUnhide:(NSNotification *)notification {
|
||||||
|
// If the window is miniaturized then nothing has really changed.
|
||||||
|
if (![window_ isMiniaturized]) {
|
||||||
|
if (browser_)
|
||||||
|
browser_->SetWindowVisibility(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)windowShouldClose:(id)window {
|
||||||
|
// Protect against multiple requests to close while the close is pending.
|
||||||
|
if (browser_ && browser_->destruction_state() <=
|
||||||
|
CefBrowserHostImpl::DESTRUCTION_STATE_PENDING) {
|
||||||
|
if (browser_->destruction_state() ==
|
||||||
|
CefBrowserHostImpl::DESTRUCTION_STATE_NONE) {
|
||||||
|
// Request that the browser close.
|
||||||
|
browser_->CloseBrowser(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel the close.
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean ourselves up after clearing the stack of anything that might have the
|
||||||
|
// window on it.
|
||||||
|
[self performSelectorOnMainThread:@selector(cleanup:)
|
||||||
|
withObject:window
|
||||||
|
waitUntilDone:NO];
|
||||||
|
|
||||||
|
// Allow the close.
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)cleanup:(id)window {
|
||||||
|
[self release];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
NSTimeInterval currentEventTimestamp() {
|
||||||
|
NSEvent* currentEvent = [NSApp currentEvent];
|
||||||
|
if (currentEvent)
|
||||||
|
return [currentEvent timestamp];
|
||||||
|
else {
|
||||||
|
// FIXME(API): In case there is no current event, the timestamp could be
|
||||||
|
// obtained by getting the time since the application started. This involves
|
||||||
|
// taking some more static functions from Chromium code.
|
||||||
|
// Another option is to have the timestamp as a field in CefEvent structures
|
||||||
|
// and let the client provide it.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSUInteger NativeModifiers(int cef_modifiers) {
|
||||||
|
NSUInteger native_modifiers = 0;
|
||||||
|
if (cef_modifiers & EVENTFLAG_SHIFT_DOWN)
|
||||||
|
native_modifiers |= NSShiftKeyMask;
|
||||||
|
if (cef_modifiers & EVENTFLAG_CONTROL_DOWN)
|
||||||
|
native_modifiers |= NSControlKeyMask;
|
||||||
|
if (cef_modifiers & EVENTFLAG_ALT_DOWN)
|
||||||
|
native_modifiers |= NSAlternateKeyMask;
|
||||||
|
if (cef_modifiers & EVENTFLAG_COMMAND_DOWN)
|
||||||
|
native_modifiers |= NSCommandKeyMask;
|
||||||
|
if (cef_modifiers & EVENTFLAG_CAPS_LOCK_ON)
|
||||||
|
native_modifiers |= NSAlphaShiftKeyMask;
|
||||||
|
if (cef_modifiers & EVENTFLAG_NUM_LOCK_ON)
|
||||||
|
native_modifiers |= NSNumericPadKeyMask;
|
||||||
|
|
||||||
|
return native_modifiers;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
CefBrowserPlatformDelegateNativeMac::CefBrowserPlatformDelegateNativeMac(
|
||||||
|
const CefWindowInfo& window_info)
|
||||||
|
: CefBrowserPlatformDelegateNative(window_info),
|
||||||
|
host_window_created_(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeMac::BrowserDestroyed(
|
||||||
|
CefBrowserHostImpl* browser) {
|
||||||
|
CefBrowserPlatformDelegate::BrowserDestroyed(browser);
|
||||||
|
|
||||||
|
if (host_window_created_) {
|
||||||
|
// Release the reference added in CreateHostWindow().
|
||||||
|
browser->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefBrowserPlatformDelegateNativeMac::CreateHostWindow() {
|
||||||
|
base::mac::ScopedNSAutoreleasePool autorelease_pool;
|
||||||
|
|
||||||
|
NSWindow* newWnd = nil;
|
||||||
|
|
||||||
|
NSView* parentView = window_info_.parent_view;
|
||||||
|
NSRect contentRect = {{window_info_.x, window_info_.y},
|
||||||
|
{window_info_.width, window_info_.height}};
|
||||||
|
if (parentView == nil) {
|
||||||
|
// Create a new window.
|
||||||
|
NSRect screen_rect = [[NSScreen mainScreen] visibleFrame];
|
||||||
|
NSRect window_rect = {{window_info_.x,
|
||||||
|
screen_rect.size.height - window_info_.y},
|
||||||
|
{window_info_.width, window_info_.height}};
|
||||||
|
if (window_rect.size.width == 0)
|
||||||
|
window_rect.size.width = 750;
|
||||||
|
if (window_rect.size.height == 0)
|
||||||
|
window_rect.size.height = 750;
|
||||||
|
|
||||||
|
contentRect.origin.x = 0;
|
||||||
|
contentRect.origin.y = 0;
|
||||||
|
contentRect.size.width = window_rect.size.width;
|
||||||
|
contentRect.size.height = window_rect.size.height;
|
||||||
|
|
||||||
|
newWnd = [[UnderlayOpenGLHostingWindow alloc]
|
||||||
|
initWithContentRect:window_rect
|
||||||
|
styleMask:(NSTitledWindowMask |
|
||||||
|
NSClosableWindowMask |
|
||||||
|
NSMiniaturizableWindowMask |
|
||||||
|
NSResizableWindowMask |
|
||||||
|
NSUnifiedTitleAndToolbarWindowMask )
|
||||||
|
backing:NSBackingStoreBuffered
|
||||||
|
defer:NO];
|
||||||
|
|
||||||
|
// Create the delegate for control and browser window events.
|
||||||
|
[[CefWindowDelegate alloc] initWithWindow:newWnd andBrowser:browser_];
|
||||||
|
|
||||||
|
parentView = [newWnd contentView];
|
||||||
|
window_info_.parent_view = parentView;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make the content view for the window have a layer. This will make all
|
||||||
|
// sub-views have layers. This is necessary to ensure correct layer
|
||||||
|
// ordering of all child views and their layers.
|
||||||
|
[[[parentView window] contentView] setWantsLayer:YES];
|
||||||
|
|
||||||
|
host_window_created_ = true;
|
||||||
|
|
||||||
|
// Add a reference that will be released in BrowserDestroyed().
|
||||||
|
browser_->AddRef();
|
||||||
|
|
||||||
|
// Create the browser view.
|
||||||
|
CefBrowserHostView* browser_view =
|
||||||
|
[[CefBrowserHostView alloc] initWithFrame:contentRect];
|
||||||
|
browser_view.browser = browser_;
|
||||||
|
[parentView addSubview:browser_view];
|
||||||
|
[browser_view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
|
||||||
|
[browser_view setNeedsDisplay:YES];
|
||||||
|
[browser_view release];
|
||||||
|
|
||||||
|
// Parent the TabContents to the browser view.
|
||||||
|
const NSRect bounds = [browser_view bounds];
|
||||||
|
NSView* native_view = browser_->web_contents()->GetNativeView();
|
||||||
|
[browser_view addSubview:native_view];
|
||||||
|
[native_view setFrame:bounds];
|
||||||
|
[native_view setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
|
||||||
|
[native_view setNeedsDisplay:YES];
|
||||||
|
|
||||||
|
window_info_.view = browser_view;
|
||||||
|
|
||||||
|
if (newWnd != nil && !window_info_.hidden) {
|
||||||
|
// Show the window.
|
||||||
|
[newWnd makeKeyAndOrderFront: nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeMac::CloseHostWindow() {
|
||||||
|
if (window_info_.view != nil) {
|
||||||
|
[[window_info_.view window]
|
||||||
|
performSelectorOnMainThread:@selector(performClose:)
|
||||||
|
withObject:nil
|
||||||
|
waitUntilDone:NO];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CefWindowHandle
|
||||||
|
CefBrowserPlatformDelegateNativeMac::GetHostWindowHandle() const {
|
||||||
|
if (windowless_handler_)
|
||||||
|
return windowless_handler_->GetParentWindowHandle();
|
||||||
|
return window_info_.view;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeMac::SendFocusEvent(bool setFocus) {
|
||||||
|
content::RenderWidgetHostView* view =
|
||||||
|
browser_->web_contents()->GetRenderWidgetHostView();
|
||||||
|
if (view) {
|
||||||
|
view->SetActive(setFocus);
|
||||||
|
|
||||||
|
if (setFocus) {
|
||||||
|
// Give keyboard focus to the native view.
|
||||||
|
NSView* view = browser_->web_contents()->GetContentNativeView();
|
||||||
|
DCHECK([view canBecomeKeyView]);
|
||||||
|
[[view window] makeFirstResponder:view];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::Point CefBrowserPlatformDelegateNativeMac::GetScreenPoint(
|
||||||
|
const gfx::Point& view) const {
|
||||||
|
if (windowless_handler_)
|
||||||
|
return windowless_handler_->GetParentScreenPoint(view);
|
||||||
|
|
||||||
|
NSView* nsview = window_info_.parent_view;
|
||||||
|
if (nsview) {
|
||||||
|
NSRect bounds = [nsview bounds];
|
||||||
|
NSPoint view_pt = {view.x(), bounds.size.height - view.y()};
|
||||||
|
NSPoint window_pt = [nsview convertPoint:view_pt toView:nil];
|
||||||
|
NSPoint screen_pt = [[nsview window] convertBaseToScreen:window_pt];
|
||||||
|
return gfx::Point(screen_pt.x, screen_pt.y);
|
||||||
|
}
|
||||||
|
return gfx::Point();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeMac::ViewText(const std::string& text) {
|
||||||
|
// TODO(cef): Implement this functionality.
|
||||||
|
NOTIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeMac::HandleKeyboardEvent(
|
||||||
|
const content::NativeWebKeyboardEvent& event) {
|
||||||
|
// Give the top level menu equivalents a chance to handle the event.
|
||||||
|
if ([event.os_event type] == NSKeyDown)
|
||||||
|
[[NSApp mainMenu] performKeyEquivalent:event.os_event];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeMac::HandleExternalProtocol(
|
||||||
|
const GURL& url) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeMac::TranslateKeyEvent(
|
||||||
|
content::NativeWebKeyboardEvent& result,
|
||||||
|
const CefKeyEvent& key_event) const {
|
||||||
|
// Use a synthetic NSEvent in order to obtain the windowsKeyCode member from
|
||||||
|
// the NativeWebKeyboardEvent constructor. This is the only member which can
|
||||||
|
// not be easily translated (without hardcoding keyCodes)
|
||||||
|
// Determining whether a modifier key is left or right seems to be done
|
||||||
|
// through the key code as well.
|
||||||
|
|
||||||
|
NSEventType event_type;
|
||||||
|
if (key_event.character == 0 && key_event.unmodified_character == 0) {
|
||||||
|
// Check if both character and unmodified_characther are empty to determine
|
||||||
|
// if this was a NSFlagsChanged event.
|
||||||
|
// A dead key will have an empty character, but a non-empty unmodified
|
||||||
|
// character
|
||||||
|
event_type = NSFlagsChanged;
|
||||||
|
} else {
|
||||||
|
switch (key_event.type) {
|
||||||
|
case KEYEVENT_RAWKEYDOWN:
|
||||||
|
case KEYEVENT_KEYDOWN:
|
||||||
|
case KEYEVENT_CHAR:
|
||||||
|
event_type = NSKeyDown;
|
||||||
|
break;
|
||||||
|
case KEYEVENT_KEYUP:
|
||||||
|
event_type = NSKeyUp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NSString* charactersIgnoringModifiers = [[[NSString alloc]
|
||||||
|
initWithCharacters:&key_event.unmodified_character length:1]
|
||||||
|
autorelease];
|
||||||
|
NSString* characters = [[[NSString alloc]
|
||||||
|
initWithCharacters:&key_event.character length:1] autorelease];
|
||||||
|
|
||||||
|
NSEvent* synthetic_event =
|
||||||
|
[NSEvent keyEventWithType:event_type
|
||||||
|
location:NSMakePoint(0, 0)
|
||||||
|
modifierFlags:NativeModifiers(key_event.modifiers)
|
||||||
|
timestamp:currentEventTimestamp()
|
||||||
|
windowNumber:0
|
||||||
|
context:nil
|
||||||
|
characters:characters
|
||||||
|
charactersIgnoringModifiers:charactersIgnoringModifiers
|
||||||
|
isARepeat:NO
|
||||||
|
keyCode:key_event.native_key_code];
|
||||||
|
|
||||||
|
result = content::NativeWebKeyboardEvent(synthetic_event);
|
||||||
|
if (key_event.type == KEYEVENT_CHAR)
|
||||||
|
result.type = blink::WebInputEvent::Char;
|
||||||
|
|
||||||
|
result.isSystemKey = key_event.is_system_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeMac::TranslateClickEvent(
|
||||||
|
blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
CefBrowserHost::MouseButtonType type,
|
||||||
|
bool mouseUp, int clickCount) const {
|
||||||
|
TranslateMouseEvent(result, mouse_event);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case MBT_LEFT:
|
||||||
|
result.type = mouseUp ? blink::WebInputEvent::MouseUp :
|
||||||
|
blink::WebInputEvent::MouseDown;
|
||||||
|
result.button = blink::WebMouseEvent::ButtonLeft;
|
||||||
|
break;
|
||||||
|
case MBT_MIDDLE:
|
||||||
|
result.type = mouseUp ? blink::WebInputEvent::MouseUp :
|
||||||
|
blink::WebInputEvent::MouseDown;
|
||||||
|
result.button = blink::WebMouseEvent::ButtonMiddle;
|
||||||
|
break;
|
||||||
|
case MBT_RIGHT:
|
||||||
|
result.type = mouseUp ? blink::WebInputEvent::MouseUp :
|
||||||
|
blink::WebInputEvent::MouseDown;
|
||||||
|
result.button = blink::WebMouseEvent::ButtonRight;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.clickCount = clickCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeMac::TranslateMoveEvent(
|
||||||
|
blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
bool mouseLeave) const {
|
||||||
|
TranslateMouseEvent(result, mouse_event);
|
||||||
|
|
||||||
|
if (!mouseLeave) {
|
||||||
|
result.type = blink::WebInputEvent::MouseMove;
|
||||||
|
if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON)
|
||||||
|
result.button = blink::WebMouseEvent::ButtonLeft;
|
||||||
|
else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON)
|
||||||
|
result.button = blink::WebMouseEvent::ButtonMiddle;
|
||||||
|
else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON)
|
||||||
|
result.button = blink::WebMouseEvent::ButtonRight;
|
||||||
|
else
|
||||||
|
result.button = blink::WebMouseEvent::ButtonNone;
|
||||||
|
} else {
|
||||||
|
result.type = blink::WebInputEvent::MouseLeave;
|
||||||
|
result.button = blink::WebMouseEvent::ButtonNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.clickCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeMac::TranslateWheelEvent(
|
||||||
|
blink::WebMouseWheelEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
int deltaX, int deltaY) const {
|
||||||
|
result = blink::WebMouseWheelEvent();
|
||||||
|
TranslateMouseEvent(result, mouse_event);
|
||||||
|
|
||||||
|
result.type = blink::WebInputEvent::MouseWheel;
|
||||||
|
|
||||||
|
static const double scrollbarPixelsPerCocoaTick = 40.0;
|
||||||
|
result.deltaX = deltaX;
|
||||||
|
result.deltaY = deltaY;
|
||||||
|
result.wheelTicksX = result.deltaX / scrollbarPixelsPerCocoaTick;
|
||||||
|
result.wheelTicksY = result.deltaY / scrollbarPixelsPerCocoaTick;
|
||||||
|
result.hasPreciseScrollingDeltas = true;
|
||||||
|
|
||||||
|
// Unless the phase and momentumPhase are passed in as parameters to this
|
||||||
|
// function, there is no way to know them
|
||||||
|
result.phase = blink::WebMouseWheelEvent::PhaseNone;
|
||||||
|
result.momentumPhase = blink::WebMouseWheelEvent::PhaseNone;
|
||||||
|
|
||||||
|
if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON)
|
||||||
|
result.button = blink::WebMouseEvent::ButtonLeft;
|
||||||
|
else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON)
|
||||||
|
result.button = blink::WebMouseEvent::ButtonMiddle;
|
||||||
|
else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON)
|
||||||
|
result.button = blink::WebMouseEvent::ButtonRight;
|
||||||
|
else
|
||||||
|
result.button = blink::WebMouseEvent::ButtonNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
CefEventHandle CefBrowserPlatformDelegateNativeMac::GetEventHandle(
|
||||||
|
const content::NativeWebKeyboardEvent& event) const {
|
||||||
|
return event.os_event;
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<CefFileDialogRunner>
|
||||||
|
CefBrowserPlatformDelegateNativeMac::CreateFileDialogRunner() {
|
||||||
|
return make_scoped_ptr(new CefFileDialogRunnerMac);
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<CefJavaScriptDialogRunner>
|
||||||
|
CefBrowserPlatformDelegateNativeMac::CreateJavaScriptDialogRunner() {
|
||||||
|
return make_scoped_ptr(new CefJavaScriptDialogRunnerMac);
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<CefMenuRunner>
|
||||||
|
CefBrowserPlatformDelegateNativeMac::CreateMenuRunner() {
|
||||||
|
return make_scoped_ptr(new CefMenuRunnerMac);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeMac::TranslateMouseEvent(
|
||||||
|
blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event) const {
|
||||||
|
// position
|
||||||
|
result.x = mouse_event.x;
|
||||||
|
result.y = mouse_event.y;
|
||||||
|
result.windowX = result.x;
|
||||||
|
result.windowY = result.y;
|
||||||
|
|
||||||
|
const gfx::Point& screen_pt = GetScreenPoint(gfx::Point(result.x, result.y));
|
||||||
|
result.globalX = screen_pt.x();
|
||||||
|
result.globalY = screen_pt.y();
|
||||||
|
|
||||||
|
// modifiers
|
||||||
|
result.modifiers |= TranslateModifiers(mouse_event.modifiers);
|
||||||
|
|
||||||
|
// timestamp - Mac OSX specific
|
||||||
|
result.timeStampSeconds = currentEventTimestamp();
|
||||||
|
}
|
||||||
|
|
637
libcef/browser/native/browser_platform_delegate_native_win.cc
Normal file
637
libcef/browser/native/browser_platform_delegate_native_win.cc
Normal file
@ -0,0 +1,637 @@
|
|||||||
|
// Copyright 2015 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 "libcef/browser/native/browser_platform_delegate_native_win.h"
|
||||||
|
|
||||||
|
#include <shellapi.h>
|
||||||
|
#include <wininet.h>
|
||||||
|
#include <winspool.h>
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
#include "libcef/browser/context.h"
|
||||||
|
#include "libcef/browser/native/file_dialog_runner_win.h"
|
||||||
|
#include "libcef/browser/native/javascript_dialog_runner_win.h"
|
||||||
|
#include "libcef/browser/native/menu_runner_win.h"
|
||||||
|
#include "libcef/browser/native/window_delegate_view.h"
|
||||||
|
#include "libcef/browser/thread_util.h"
|
||||||
|
|
||||||
|
#include "base/files/file_util.h"
|
||||||
|
#include "base/strings/utf_string_conversions.h"
|
||||||
|
#include "base/win/registry.h"
|
||||||
|
#include "content/public/browser/native_web_keyboard_event.h"
|
||||||
|
#include "ui/aura/window.h"
|
||||||
|
#include "ui/base/win/shell.h"
|
||||||
|
#include "ui/gfx/screen.h"
|
||||||
|
#include "ui/gfx/win/hwnd_util.h"
|
||||||
|
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
|
||||||
|
#include "ui/views/widget/widget.h"
|
||||||
|
#include "ui/views/win/hwnd_util.h"
|
||||||
|
|
||||||
|
#pragma comment(lib, "dwmapi.lib")
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void WriteTempFileAndView(scoped_refptr<base::RefCountedString> str) {
|
||||||
|
CEF_REQUIRE_FILET();
|
||||||
|
|
||||||
|
base::FilePath tmp_file;
|
||||||
|
if (!base::CreateTemporaryFile(&tmp_file))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// The shell command will look at the file extension to identify the correct
|
||||||
|
// program to open.
|
||||||
|
tmp_file = tmp_file.AddExtension(L"txt");
|
||||||
|
|
||||||
|
const std::string& data = str->data();
|
||||||
|
int write_ct = base::WriteFile(tmp_file, data.c_str(), data.size());
|
||||||
|
DCHECK_EQ(static_cast<int>(data.size()), write_ct);
|
||||||
|
|
||||||
|
ui::win::OpenFileViaShell(tmp_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// According to Mozilla in uriloader/exthandler/win/nsOSHelperAppService.cpp:
|
||||||
|
// "Some versions of windows (Win2k before SP3, Win XP before SP1) crash in
|
||||||
|
// ShellExecute on long URLs (bug 161357 on bugzilla.mozilla.org). IE 5 and 6
|
||||||
|
// support URLS of 2083 chars in length, 2K is safe."
|
||||||
|
const int kMaxAddressLengthChars = 2048;
|
||||||
|
|
||||||
|
bool HasExternalHandler(const std::string& scheme) {
|
||||||
|
base::win::RegKey key;
|
||||||
|
const std::wstring registry_path =
|
||||||
|
base::ASCIIToUTF16(scheme + "\\shell\\open\\command");
|
||||||
|
key.Open(HKEY_CLASSES_ROOT, registry_path.c_str(), KEY_READ);
|
||||||
|
if (key.Valid()) {
|
||||||
|
DWORD size = 0;
|
||||||
|
key.ReadValue(NULL, NULL, &size, NULL);
|
||||||
|
if (size > 2) {
|
||||||
|
// ShellExecute crashes the process when the command is empty.
|
||||||
|
// We check for "2" because it always returns the trailing NULL.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExecuteExternalProtocol(const GURL& url) {
|
||||||
|
CEF_REQUIRE_FILET();
|
||||||
|
|
||||||
|
if (!HasExternalHandler(url.scheme()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const std::string& address = url.spec();
|
||||||
|
if (address.length() > kMaxAddressLengthChars)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ShellExecuteA(NULL, "open", address.c_str(), NULL, NULL, SW_SHOWNORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
WORD KeyStatesToWord() {
|
||||||
|
static const USHORT kHighBitMaskShort = 0x8000;
|
||||||
|
WORD result = 0;
|
||||||
|
|
||||||
|
if (GetKeyState(VK_CONTROL) & kHighBitMaskShort)
|
||||||
|
result |= MK_CONTROL;
|
||||||
|
if (GetKeyState(VK_SHIFT) & kHighBitMaskShort)
|
||||||
|
result |= MK_SHIFT;
|
||||||
|
if (GetKeyState(VK_LBUTTON) & kHighBitMaskShort)
|
||||||
|
result |= MK_LBUTTON;
|
||||||
|
if (GetKeyState(VK_MBUTTON) & kHighBitMaskShort)
|
||||||
|
result |= MK_MBUTTON;
|
||||||
|
if (GetKeyState(VK_RBUTTON) & kHighBitMaskShort)
|
||||||
|
result |= MK_RBUTTON;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
CefBrowserPlatformDelegateNativeWin::CefBrowserPlatformDelegateNativeWin(
|
||||||
|
const CefWindowInfo& window_info)
|
||||||
|
: CefBrowserPlatformDelegateNative(window_info),
|
||||||
|
host_window_created_(false),
|
||||||
|
window_widget_(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::BrowserDestroyed(
|
||||||
|
CefBrowserHostImpl* browser) {
|
||||||
|
CefBrowserPlatformDelegate::BrowserDestroyed(browser);
|
||||||
|
|
||||||
|
if (host_window_created_) {
|
||||||
|
// Release the reference added in CreateHostWindow().
|
||||||
|
browser->Release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefBrowserPlatformDelegateNativeWin::CreateHostWindow() {
|
||||||
|
RegisterWindowClass();
|
||||||
|
|
||||||
|
std::wstring windowName(CefString(&window_info_.window_name));
|
||||||
|
|
||||||
|
// Create the new browser window.
|
||||||
|
window_info_.window = CreateWindowEx(window_info_.ex_style,
|
||||||
|
GetWndClass(), windowName.c_str(), window_info_.style,
|
||||||
|
window_info_.x, window_info_.y, window_info_.width,
|
||||||
|
window_info_.height, window_info_.parent_window, window_info_.menu,
|
||||||
|
::GetModuleHandle(NULL), NULL);
|
||||||
|
|
||||||
|
// It's possible for CreateWindowEx to fail if the parent window was
|
||||||
|
// destroyed between the call to CreateBrowser and the above one.
|
||||||
|
DCHECK(window_info_.window != NULL);
|
||||||
|
if (!window_info_.window)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
host_window_created_ = true;
|
||||||
|
|
||||||
|
// Set window user data to this object for future reference from the window
|
||||||
|
// procedure.
|
||||||
|
gfx::SetWindowUserData(window_info_.window, this);
|
||||||
|
|
||||||
|
// Add a reference that will later be released in DestroyBrowser().
|
||||||
|
browser_->AddRef();
|
||||||
|
|
||||||
|
RECT cr;
|
||||||
|
GetClientRect(window_info_.window, &cr);
|
||||||
|
|
||||||
|
DCHECK(!window_widget_);
|
||||||
|
|
||||||
|
SkColor background_color = SK_ColorWHITE;
|
||||||
|
const CefSettings& settings = CefContext::Get()->settings();
|
||||||
|
if (CefColorGetA(settings.background_color) > 0) {
|
||||||
|
background_color = SkColorSetRGB(
|
||||||
|
CefColorGetR(settings.background_color),
|
||||||
|
CefColorGetG(settings.background_color),
|
||||||
|
CefColorGetB(settings.background_color));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adjust for potential display scaling.
|
||||||
|
gfx::Point point = gfx::Point(cr.right, cr.bottom);
|
||||||
|
float scale = gfx::Screen::GetNativeScreen()->
|
||||||
|
GetDisplayNearestPoint(point).device_scale_factor();
|
||||||
|
point = gfx::ToFlooredPoint(
|
||||||
|
gfx::ScalePoint(gfx::PointF(point), 1.0f / scale));
|
||||||
|
|
||||||
|
CefWindowDelegateView* delegate_view =
|
||||||
|
new CefWindowDelegateView(background_color);
|
||||||
|
delegate_view->Init(window_info_.window,
|
||||||
|
browser_->web_contents(),
|
||||||
|
gfx::Rect(0, 0, point.x(), point.y()));
|
||||||
|
|
||||||
|
window_widget_ = delegate_view->GetWidget();
|
||||||
|
window_widget_->Show();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::CloseHostWindow() {
|
||||||
|
if (window_info_.window != NULL) {
|
||||||
|
HWND frameWnd = GetAncestor(window_info_.window, GA_ROOT);
|
||||||
|
PostMessage(frameWnd, WM_CLOSE, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CefWindowHandle
|
||||||
|
CefBrowserPlatformDelegateNativeWin::GetHostWindowHandle() const {
|
||||||
|
if (windowless_handler_)
|
||||||
|
return windowless_handler_->GetParentWindowHandle();
|
||||||
|
return window_info_.window;
|
||||||
|
}
|
||||||
|
|
||||||
|
views::Widget* CefBrowserPlatformDelegateNativeWin::GetWindowWidget() const {
|
||||||
|
return window_widget_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::SendFocusEvent(bool setFocus) {
|
||||||
|
if (!setFocus)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (browser_->web_contents()) {
|
||||||
|
// Give logical focus to the RenderWidgetHostViewAura in the views
|
||||||
|
// hierarchy. This does not change the native keyboard focus.
|
||||||
|
browser_->web_contents()->Focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window_widget_) {
|
||||||
|
// Give native focus to the DesktopWindowTreeHostWin associated with the
|
||||||
|
// root window.
|
||||||
|
//
|
||||||
|
// The DesktopWindowTreeHostWin HandleNativeFocus/HandleNativeBlur methods
|
||||||
|
// are called in response to WM_SETFOCUS/WM_KILLFOCUS respectively. The
|
||||||
|
// implementation has been patched to call HandleActivationChanged which
|
||||||
|
// results in the following behaviors:
|
||||||
|
// 1. Update focus/activation state of the aura::Window indirectly via
|
||||||
|
// wm::FocusController. This allows focus-related behaviors (e.g. focus
|
||||||
|
// rings, flashing caret, onFocus/onBlur JS events, etc.) to work as
|
||||||
|
// expected (see issue #1677).
|
||||||
|
// 2. Update focus state of the ui::InputMethod. If this does not occur
|
||||||
|
// then InputMethodBase::GetTextInputClient will return NULL and
|
||||||
|
// InputMethodWin::OnChar will fail to sent character events to the
|
||||||
|
// renderer (see issue #1700).
|
||||||
|
//
|
||||||
|
// This differs from activation in Chrome which is handled via
|
||||||
|
// HWNDMessageHandler::PostProcessActivateMessage (Widget::Show indirectly
|
||||||
|
// calls HWNDMessageHandler::Activate which calls ::SetForegroundWindow
|
||||||
|
// resulting in a WM_ACTIVATE message being sent to the window). The Chrome
|
||||||
|
// code path doesn't work for CEF because IsTopLevelWindow in
|
||||||
|
// hwnd_message_handler.cc will return false and consequently
|
||||||
|
// HWNDMessageHandler::PostProcessActivateMessage will not be called.
|
||||||
|
//
|
||||||
|
// Activation events are usually reserved for the top-level window so
|
||||||
|
// triggering activation based on focus events may be incorrect in some
|
||||||
|
// circumstances. Revisit this implementation if additional problems are
|
||||||
|
// discovered.
|
||||||
|
::SetFocus(HWNDForWidget(window_widget_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::NotifyMoveOrResizeStarted() {
|
||||||
|
// Call the parent method to dismiss any existing popups.
|
||||||
|
CefBrowserPlatformDelegate::NotifyMoveOrResizeStarted();
|
||||||
|
|
||||||
|
if (!window_widget_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Notify DesktopWindowTreeHostWin of move events so that screen rectangle
|
||||||
|
// information is communicated to the renderer process and popups are
|
||||||
|
// displayed in the correct location.
|
||||||
|
views::DesktopWindowTreeHostWin* tree_host =
|
||||||
|
static_cast<views::DesktopWindowTreeHostWin*>(
|
||||||
|
aura::WindowTreeHost::GetForAcceleratedWidget(
|
||||||
|
HWNDForWidget(window_widget_)));
|
||||||
|
DCHECK(tree_host);
|
||||||
|
if (tree_host) {
|
||||||
|
// Cast to HWNDMessageHandlerDelegate so we can access HandleMove().
|
||||||
|
static_cast<views::HWNDMessageHandlerDelegate*>(tree_host)->HandleMove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::SizeTo(int width, int height) {
|
||||||
|
HWND window = window_info_.window;
|
||||||
|
|
||||||
|
RECT rect = {0, 0, width, height};
|
||||||
|
DWORD style = GetWindowLong(window, GWL_STYLE);
|
||||||
|
DWORD ex_style = GetWindowLong(window, GWL_EXSTYLE);
|
||||||
|
bool has_menu = !(style & WS_CHILD) && (GetMenu(window) != NULL);
|
||||||
|
|
||||||
|
// The size value is for the client area. Calculate the whole window size
|
||||||
|
// based on the current style.
|
||||||
|
AdjustWindowRectEx(&rect, style, has_menu, ex_style);
|
||||||
|
|
||||||
|
// Size the window.
|
||||||
|
SetWindowPos(window, NULL, 0, 0, rect.right,
|
||||||
|
rect.bottom, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::Point CefBrowserPlatformDelegateNativeWin::GetScreenPoint(
|
||||||
|
const gfx::Point& view) const {
|
||||||
|
if (windowless_handler_)
|
||||||
|
return windowless_handler_->GetParentScreenPoint(view);
|
||||||
|
|
||||||
|
if (!window_widget_)
|
||||||
|
return view;
|
||||||
|
|
||||||
|
aura::Window* window = window_widget_->GetNativeView();
|
||||||
|
const gfx::Rect& bounds_in_screen = window->GetBoundsInScreen();
|
||||||
|
const gfx::Point& screen_point = gfx::Point(bounds_in_screen.x() + view.x(),
|
||||||
|
bounds_in_screen.y() + view.y());
|
||||||
|
|
||||||
|
// Adjust for potential display scaling.
|
||||||
|
float scale = gfx::Screen::GetScreenFor(window)->
|
||||||
|
GetDisplayNearestWindow(window).device_scale_factor();
|
||||||
|
return gfx::ToFlooredPoint(
|
||||||
|
gfx::ScalePoint(gfx::PointF(screen_point), scale));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::ViewText(const std::string& text) {
|
||||||
|
std::string str = text;
|
||||||
|
scoped_refptr<base::RefCountedString> str_ref =
|
||||||
|
base::RefCountedString::TakeString(&str);
|
||||||
|
CEF_POST_TASK(CEF_FILET, base::Bind(WriteTempFileAndView, str_ref));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::HandleKeyboardEvent(
|
||||||
|
const content::NativeWebKeyboardEvent& event) {
|
||||||
|
// Any unhandled keyboard/character messages are sent to DefWindowProc so that
|
||||||
|
// shortcut keys work correctly.
|
||||||
|
if (event.os_event) {
|
||||||
|
const MSG& msg = event.os_event->native_event();
|
||||||
|
DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
|
||||||
|
} else {
|
||||||
|
MSG msg = {};
|
||||||
|
|
||||||
|
msg.hwnd = GetHostWindowHandle();
|
||||||
|
if (!msg.hwnd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (event.type) {
|
||||||
|
case blink::WebInputEvent::RawKeyDown:
|
||||||
|
msg.message = event.isSystemKey ? WM_SYSKEYDOWN : WM_KEYDOWN;
|
||||||
|
break;
|
||||||
|
case blink::WebInputEvent::KeyUp:
|
||||||
|
msg.message = event.isSystemKey ? WM_SYSKEYUP : WM_KEYUP;
|
||||||
|
break;
|
||||||
|
case blink::WebInputEvent::Char:
|
||||||
|
msg.message = event.isSystemKey ? WM_SYSCHAR: WM_CHAR;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NOTREACHED();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg.wParam = event.windowsKeyCode;
|
||||||
|
|
||||||
|
UINT scan_code = ::MapVirtualKeyW(event.windowsKeyCode, MAPVK_VK_TO_VSC);
|
||||||
|
msg.lParam = (scan_code << 16) | // key scan code
|
||||||
|
1; // key repeat count
|
||||||
|
if (event.modifiers & content::NativeWebKeyboardEvent::AltKey)
|
||||||
|
msg.lParam |= (1 << 29);
|
||||||
|
|
||||||
|
DefWindowProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::HandleExternalProtocol(
|
||||||
|
const GURL& url) {
|
||||||
|
// Execute on the FILE thread.
|
||||||
|
CEF_POST_TASK(CEF_FILET,
|
||||||
|
base::Bind(ExecuteExternalProtocol, url));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::TranslateKeyEvent(
|
||||||
|
content::NativeWebKeyboardEvent& result,
|
||||||
|
const CefKeyEvent& key_event) const {
|
||||||
|
result.timeStampSeconds = GetMessageTime() / 1000.0;
|
||||||
|
|
||||||
|
result.windowsKeyCode = key_event.windows_key_code;
|
||||||
|
result.nativeKeyCode = key_event.native_key_code;
|
||||||
|
result.isSystemKey = key_event.is_system_key ? 1 : 0;
|
||||||
|
switch (key_event.type) {
|
||||||
|
case KEYEVENT_RAWKEYDOWN:
|
||||||
|
case KEYEVENT_KEYDOWN:
|
||||||
|
result.type = blink::WebInputEvent::RawKeyDown;
|
||||||
|
break;
|
||||||
|
case KEYEVENT_KEYUP:
|
||||||
|
result.type = blink::WebInputEvent::KeyUp;
|
||||||
|
break;
|
||||||
|
case KEYEVENT_CHAR:
|
||||||
|
result.type = blink::WebInputEvent::Char;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result.type == blink::WebInputEvent::Char ||
|
||||||
|
result.type == blink::WebInputEvent::RawKeyDown) {
|
||||||
|
result.text[0] = result.windowsKeyCode;
|
||||||
|
result.unmodifiedText[0] = result.windowsKeyCode;
|
||||||
|
}
|
||||||
|
if (result.type != blink::WebInputEvent::Char)
|
||||||
|
result.setKeyIdentifierFromWindowsKeyCode();
|
||||||
|
|
||||||
|
result.modifiers |= TranslateModifiers(key_event.modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::TranslateClickEvent(
|
||||||
|
blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
CefBrowserHost::MouseButtonType type,
|
||||||
|
bool mouseUp, int clickCount) const {
|
||||||
|
TranslateMouseEvent(result, mouse_event);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case MBT_LEFT:
|
||||||
|
result.type = mouseUp ? blink::WebInputEvent::MouseUp :
|
||||||
|
blink::WebInputEvent::MouseDown;
|
||||||
|
result.button = blink::WebMouseEvent::ButtonLeft;
|
||||||
|
break;
|
||||||
|
case MBT_MIDDLE:
|
||||||
|
result.type = mouseUp ? blink::WebInputEvent::MouseUp :
|
||||||
|
blink::WebInputEvent::MouseDown;
|
||||||
|
result.button = blink::WebMouseEvent::ButtonMiddle;
|
||||||
|
break;
|
||||||
|
case MBT_RIGHT:
|
||||||
|
result.type = mouseUp ? blink::WebInputEvent::MouseUp :
|
||||||
|
blink::WebInputEvent::MouseDown;
|
||||||
|
result.button = blink::WebMouseEvent::ButtonRight;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
result.clickCount = clickCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::TranslateMoveEvent(
|
||||||
|
blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
bool mouseLeave) const {
|
||||||
|
TranslateMouseEvent(result, mouse_event);
|
||||||
|
|
||||||
|
if (!mouseLeave) {
|
||||||
|
result.type = blink::WebInputEvent::MouseMove;
|
||||||
|
if (mouse_event.modifiers & EVENTFLAG_LEFT_MOUSE_BUTTON)
|
||||||
|
result.button = blink::WebMouseEvent::ButtonLeft;
|
||||||
|
else if (mouse_event.modifiers & EVENTFLAG_MIDDLE_MOUSE_BUTTON)
|
||||||
|
result.button = blink::WebMouseEvent::ButtonMiddle;
|
||||||
|
else if (mouse_event.modifiers & EVENTFLAG_RIGHT_MOUSE_BUTTON)
|
||||||
|
result.button = blink::WebMouseEvent::ButtonRight;
|
||||||
|
else
|
||||||
|
result.button = blink::WebMouseEvent::ButtonNone;
|
||||||
|
} else {
|
||||||
|
result.type = blink::WebInputEvent::MouseLeave;
|
||||||
|
result.button = blink::WebMouseEvent::ButtonNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.clickCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::TranslateWheelEvent(
|
||||||
|
blink::WebMouseWheelEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
int deltaX, int deltaY) const {
|
||||||
|
TranslateMouseEvent(result, mouse_event);
|
||||||
|
|
||||||
|
result.type = blink::WebInputEvent::MouseWheel;
|
||||||
|
result.button = blink::WebMouseEvent::ButtonNone;
|
||||||
|
|
||||||
|
float wheelDelta;
|
||||||
|
bool horizontalScroll = false;
|
||||||
|
|
||||||
|
wheelDelta = static_cast<float>(deltaY ? deltaY : deltaX);
|
||||||
|
|
||||||
|
horizontalScroll = (deltaY == 0);
|
||||||
|
|
||||||
|
static const ULONG defaultScrollCharsPerWheelDelta = 1;
|
||||||
|
static const FLOAT scrollbarPixelsPerLine = 100.0f / 3.0f;
|
||||||
|
static const ULONG defaultScrollLinesPerWheelDelta = 3;
|
||||||
|
wheelDelta /= WHEEL_DELTA;
|
||||||
|
float scrollDelta = wheelDelta;
|
||||||
|
if (horizontalScroll) {
|
||||||
|
ULONG scrollChars = defaultScrollCharsPerWheelDelta;
|
||||||
|
SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &scrollChars, 0);
|
||||||
|
scrollDelta *= static_cast<FLOAT>(scrollChars) * scrollbarPixelsPerLine;
|
||||||
|
} else {
|
||||||
|
ULONG scrollLines = defaultScrollLinesPerWheelDelta;
|
||||||
|
SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &scrollLines, 0);
|
||||||
|
if (scrollLines == WHEEL_PAGESCROLL)
|
||||||
|
result.scrollByPage = true;
|
||||||
|
if (!result.scrollByPage)
|
||||||
|
scrollDelta *= static_cast<FLOAT>(scrollLines) * scrollbarPixelsPerLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set scroll amount based on above calculations. WebKit expects positive
|
||||||
|
// deltaY to mean "scroll up" and positive deltaX to mean "scroll left".
|
||||||
|
if (horizontalScroll) {
|
||||||
|
result.deltaX = scrollDelta;
|
||||||
|
result.wheelTicksX = wheelDelta;
|
||||||
|
} else {
|
||||||
|
result.deltaY = scrollDelta;
|
||||||
|
result.wheelTicksY = wheelDelta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CefEventHandle CefBrowserPlatformDelegateNativeWin::GetEventHandle(
|
||||||
|
const content::NativeWebKeyboardEvent& event) const {
|
||||||
|
if (!event.os_event)
|
||||||
|
return NULL;
|
||||||
|
return const_cast<CefEventHandle>(&event.os_event->native_event());
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<CefFileDialogRunner>
|
||||||
|
CefBrowserPlatformDelegateNativeWin::CreateFileDialogRunner() {
|
||||||
|
return make_scoped_ptr(new CefFileDialogRunnerWin);
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<CefJavaScriptDialogRunner>
|
||||||
|
CefBrowserPlatformDelegateNativeWin::CreateJavaScriptDialogRunner() {
|
||||||
|
return make_scoped_ptr(new CefJavaScriptDialogRunnerWin);
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<CefMenuRunner>
|
||||||
|
CefBrowserPlatformDelegateNativeWin::CreateMenuRunner() {
|
||||||
|
return make_scoped_ptr(new CefMenuRunnerWin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::TranslateMouseEvent(
|
||||||
|
blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event) const {
|
||||||
|
// position
|
||||||
|
result.x = mouse_event.x;
|
||||||
|
result.y = mouse_event.y;
|
||||||
|
result.windowX = result.x;
|
||||||
|
result.windowY = result.y;
|
||||||
|
|
||||||
|
const gfx::Point& screen_pt = GetScreenPoint(gfx::Point(result.x, result.y));
|
||||||
|
result.globalX = screen_pt.x();
|
||||||
|
result.globalY = screen_pt.y();
|
||||||
|
|
||||||
|
// modifiers
|
||||||
|
result.modifiers |= TranslateModifiers(mouse_event.modifiers);
|
||||||
|
|
||||||
|
// timestamp
|
||||||
|
result.timeStampSeconds = GetMessageTime() / 1000.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void CefBrowserPlatformDelegateNativeWin::RegisterWindowClass() {
|
||||||
|
static bool registered = false;
|
||||||
|
if (registered)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Register the window class
|
||||||
|
WNDCLASSEX wcex = {
|
||||||
|
/* cbSize = */ sizeof(WNDCLASSEX),
|
||||||
|
/* style = */ CS_HREDRAW | CS_VREDRAW,
|
||||||
|
/* lpfnWndProc = */ CefBrowserPlatformDelegateNativeWin::WndProc,
|
||||||
|
/* cbClsExtra = */ 0,
|
||||||
|
/* cbWndExtra = */ 0,
|
||||||
|
/* hInstance = */ ::GetModuleHandle(NULL),
|
||||||
|
/* hIcon = */ NULL,
|
||||||
|
/* hCursor = */ LoadCursor(NULL, IDC_ARROW),
|
||||||
|
/* hbrBackground = */ 0,
|
||||||
|
/* lpszMenuName = */ NULL,
|
||||||
|
/* lpszClassName = */ CefBrowserPlatformDelegateNativeWin::GetWndClass(),
|
||||||
|
/* hIconSm = */ NULL,
|
||||||
|
};
|
||||||
|
RegisterClassEx(&wcex);
|
||||||
|
|
||||||
|
registered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
LPCTSTR CefBrowserPlatformDelegateNativeWin::GetWndClass() {
|
||||||
|
return L"CefBrowserWindow";
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
LRESULT CALLBACK CefBrowserPlatformDelegateNativeWin::WndProc(
|
||||||
|
HWND hwnd, UINT message,
|
||||||
|
WPARAM wParam, LPARAM lParam) {
|
||||||
|
CefBrowserPlatformDelegateNativeWin* platform_delegate =
|
||||||
|
static_cast<CefBrowserPlatformDelegateNativeWin*>(
|
||||||
|
gfx::GetWindowUserData(hwnd));
|
||||||
|
CefBrowserHostImpl* browser = nullptr;
|
||||||
|
if (platform_delegate)
|
||||||
|
browser = platform_delegate->browser_;
|
||||||
|
|
||||||
|
switch (message) {
|
||||||
|
case WM_CLOSE:
|
||||||
|
// Protect against multiple requests to close while the close is pending.
|
||||||
|
if (browser &&
|
||||||
|
browser->destruction_state() <=
|
||||||
|
CefBrowserHostImpl::DESTRUCTION_STATE_PENDING) {
|
||||||
|
if (browser->destruction_state() ==
|
||||||
|
CefBrowserHostImpl::DESTRUCTION_STATE_NONE) {
|
||||||
|
// Request that the browser close.
|
||||||
|
browser->CloseBrowser(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel the close.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow the close.
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_DESTROY:
|
||||||
|
if (platform_delegate) {
|
||||||
|
// Clear the user data pointer.
|
||||||
|
gfx::SetWindowUserData(hwnd, NULL);
|
||||||
|
|
||||||
|
// Force the browser to be destroyed. This will result in a call to
|
||||||
|
// BrowserDestroyed() that will release the reference added in
|
||||||
|
// CreateHostWindow().
|
||||||
|
browser->WindowDestroyed();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_SIZE:
|
||||||
|
if (platform_delegate && platform_delegate->window_widget_) {
|
||||||
|
// Pass window resize events to the HWND for the DesktopNativeWidgetAura
|
||||||
|
// root window. Passing size 0x0 (wParam == SIZE_MINIMIZED, for example)
|
||||||
|
// will cause the widget to be hidden which reduces resource usage.
|
||||||
|
RECT rc;
|
||||||
|
GetClientRect(hwnd, &rc);
|
||||||
|
SetWindowPos(HWNDForWidget(platform_delegate->window_widget_), NULL,
|
||||||
|
rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
|
||||||
|
SWP_NOZORDER);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_MOVING:
|
||||||
|
case WM_MOVE:
|
||||||
|
if (browser)
|
||||||
|
browser->NotifyMoveOrResizeStarted();
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_SETFOCUS:
|
||||||
|
if (browser)
|
||||||
|
browser->SetFocus(true);
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case WM_ERASEBKGND:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return DefWindowProc(hwnd, message, wParam, lParam);
|
||||||
|
}
|
68
libcef/browser/native/browser_platform_delegate_native_win.h
Normal file
68
libcef/browser/native/browser_platform_delegate_native_win.h
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Copyright 2015 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_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_WIN_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_WIN_H_
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "libcef/browser/native/browser_platform_delegate_native.h"
|
||||||
|
|
||||||
|
// Windowed browser implementation for Windows.
|
||||||
|
class CefBrowserPlatformDelegateNativeWin :
|
||||||
|
public CefBrowserPlatformDelegateNative {
|
||||||
|
public:
|
||||||
|
explicit CefBrowserPlatformDelegateNativeWin(
|
||||||
|
const CefWindowInfo& window_info);
|
||||||
|
|
||||||
|
// CefBrowserPlatformDelegate methods:
|
||||||
|
void BrowserDestroyed(CefBrowserHostImpl* browser) override;
|
||||||
|
bool CreateHostWindow() override;
|
||||||
|
void CloseHostWindow() override;
|
||||||
|
CefWindowHandle GetHostWindowHandle() const override;
|
||||||
|
views::Widget* GetWindowWidget() const override;
|
||||||
|
void SendFocusEvent(bool setFocus) override;
|
||||||
|
void NotifyMoveOrResizeStarted() override;
|
||||||
|
void SizeTo(int width, int height) override;
|
||||||
|
gfx::Point GetScreenPoint(const gfx::Point& view) const override;
|
||||||
|
void ViewText(const std::string& text) override;
|
||||||
|
void HandleKeyboardEvent(
|
||||||
|
const content::NativeWebKeyboardEvent& event) override;
|
||||||
|
void HandleExternalProtocol(const GURL& url) override;
|
||||||
|
void TranslateKeyEvent(content::NativeWebKeyboardEvent& result,
|
||||||
|
const CefKeyEvent& key_event) const override;
|
||||||
|
void TranslateClickEvent(blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
CefBrowserHost::MouseButtonType type,
|
||||||
|
bool mouseUp, int clickCount) const override;
|
||||||
|
void TranslateMoveEvent(blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
bool mouseLeave) const override;
|
||||||
|
void TranslateWheelEvent(blink::WebMouseWheelEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
int deltaX, int deltaY) const override;
|
||||||
|
CefEventHandle GetEventHandle(
|
||||||
|
const content::NativeWebKeyboardEvent& event) const override;
|
||||||
|
scoped_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
|
||||||
|
scoped_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner() override;
|
||||||
|
scoped_ptr<CefMenuRunner> CreateMenuRunner() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void TranslateMouseEvent(blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event) const;
|
||||||
|
|
||||||
|
static void RegisterWindowClass();
|
||||||
|
static LPCTSTR GetWndClass();
|
||||||
|
static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||||
|
WPARAM wParam, LPARAM lParam);
|
||||||
|
|
||||||
|
// True if the host window has been created.
|
||||||
|
bool host_window_created_;
|
||||||
|
|
||||||
|
// Widget hosting the web contents. It will be deleted automatically when the
|
||||||
|
// associated root window is destroyed.
|
||||||
|
views::Widget* window_widget_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_NATIVE_WIN_H_
|
22
libcef/browser/native/file_dialog_runner_mac.h
Normal file
22
libcef/browser/native/file_dialog_runner_mac.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2012 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 CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_MAC_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_MAC_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "libcef/browser/file_dialog_runner.h"
|
||||||
|
|
||||||
|
class CefFileDialogRunnerMac : public CefFileDialogRunner {
|
||||||
|
public:
|
||||||
|
CefFileDialogRunnerMac();
|
||||||
|
|
||||||
|
// CefFileDialogRunner methods:
|
||||||
|
void Run(CefBrowserHostImpl* browser,
|
||||||
|
const FileChooserParams& params,
|
||||||
|
RunFileChooserCallback callback) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_MAC_H_
|
406
libcef/browser/native/file_dialog_runner_mac.mm
Normal file
406
libcef/browser/native/file_dialog_runner_mac.mm
Normal file
@ -0,0 +1,406 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2012 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 "libcef/browser/native/file_dialog_runner_mac.h"
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#import <CoreServices/CoreServices.h>
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
|
||||||
|
#include "base/mac/mac_util.h"
|
||||||
|
#include "base/strings/string_split.h"
|
||||||
|
#include "base/strings/string_util.h"
|
||||||
|
#include "base/strings/sys_string_conversions.h"
|
||||||
|
#include "base/strings/utf_string_conversions.h"
|
||||||
|
#include "base/threading/thread_restrictions.h"
|
||||||
|
#include "content/public/common/file_chooser_params.h"
|
||||||
|
#include "grit/cef_strings.h"
|
||||||
|
#include "grit/ui_strings.h"
|
||||||
|
#include "net/base/mime_util.h"
|
||||||
|
#include "ui/base/l10n/l10n_util.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
base::string16 GetDescriptionFromMimeType(const std::string& mime_type) {
|
||||||
|
// Check for wild card mime types and return an appropriate description.
|
||||||
|
static const struct {
|
||||||
|
const char* mime_type;
|
||||||
|
int string_id;
|
||||||
|
} kWildCardMimeTypes[] = {
|
||||||
|
{ "audio", IDS_APP_AUDIO_FILES },
|
||||||
|
{ "image", IDS_APP_IMAGE_FILES },
|
||||||
|
{ "text", IDS_APP_TEXT_FILES },
|
||||||
|
{ "video", IDS_APP_VIDEO_FILES },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < arraysize(kWildCardMimeTypes); ++i) {
|
||||||
|
if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*")
|
||||||
|
return l10n_util::GetStringUTF16(kWildCardMimeTypes[i].string_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return base::string16();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddFilters(NSPopUpButton *button,
|
||||||
|
const std::vector<base::string16>& accept_filters,
|
||||||
|
bool include_all_files,
|
||||||
|
std::vector<std::vector<base::string16> >* all_extensions) {
|
||||||
|
for (size_t i = 0; i < accept_filters.size(); ++i) {
|
||||||
|
const base::string16& filter = accept_filters[i];
|
||||||
|
if (filter.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::vector<base::string16> extensions;
|
||||||
|
base::string16 description;
|
||||||
|
|
||||||
|
size_t sep_index = filter.find('|');
|
||||||
|
if (sep_index != std::string::npos) {
|
||||||
|
// Treat as a filter of the form "Filter Name|.ext1;.ext2;.ext3".
|
||||||
|
description = filter.substr(0, sep_index);
|
||||||
|
|
||||||
|
const std::vector<base::string16>& ext =
|
||||||
|
base::SplitString(filter.substr(sep_index + 1),
|
||||||
|
base::ASCIIToUTF16(";"),
|
||||||
|
base::TRIM_WHITESPACE,
|
||||||
|
base::SPLIT_WANT_NONEMPTY);
|
||||||
|
for (size_t x = 0; x < ext.size(); ++x) {
|
||||||
|
const base::string16& file_ext = ext[x];
|
||||||
|
if (!file_ext.empty() && file_ext[0] == '.')
|
||||||
|
extensions.push_back(file_ext);
|
||||||
|
}
|
||||||
|
} else if (filter[0] == '.') {
|
||||||
|
// Treat as an extension beginning with the '.' character.
|
||||||
|
extensions.push_back(filter);
|
||||||
|
} else {
|
||||||
|
// Otherwise convert mime type to one or more extensions.
|
||||||
|
const std::string& ascii = base::UTF16ToASCII(filter);
|
||||||
|
std::vector<base::FilePath::StringType> ext;
|
||||||
|
net::GetExtensionsForMimeType(ascii, &ext);
|
||||||
|
if (!ext.empty()) {
|
||||||
|
for (size_t x = 0; x < ext.size(); ++x)
|
||||||
|
extensions.push_back(base::ASCIIToUTF16("." + ext[x]));
|
||||||
|
description = GetDescriptionFromMimeType(ascii);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extensions.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Don't display a crazy number of extensions since the NSPopUpButton width
|
||||||
|
// will keep growing.
|
||||||
|
const size_t kMaxExtensions = 10;
|
||||||
|
|
||||||
|
base::string16 ext_str;
|
||||||
|
for (size_t x = 0; x < std::min(kMaxExtensions, extensions.size()); ++x) {
|
||||||
|
const base::string16& pattern = base::ASCIIToUTF16("*") + extensions[x];
|
||||||
|
if (x != 0)
|
||||||
|
ext_str += base::ASCIIToUTF16(";");
|
||||||
|
ext_str += pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (extensions.size() > kMaxExtensions)
|
||||||
|
ext_str += base::ASCIIToUTF16(";...");
|
||||||
|
|
||||||
|
if (description.empty()) {
|
||||||
|
description = ext_str;
|
||||||
|
} else {
|
||||||
|
description +=
|
||||||
|
base::ASCIIToUTF16(" (") + ext_str + base::ASCIIToUTF16(")");
|
||||||
|
}
|
||||||
|
|
||||||
|
[button addItemWithTitle:base::SysUTF16ToNSString(description)];
|
||||||
|
|
||||||
|
all_extensions->push_back(extensions);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the *.* filter, but only if we have added other filters (otherwise it
|
||||||
|
// is implied).
|
||||||
|
if (include_all_files && !all_extensions->empty()) {
|
||||||
|
[button addItemWithTitle:base::SysUTF8ToNSString("All Files (*)")];
|
||||||
|
all_extensions->push_back(std::vector<base::string16>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Used to manage the file type filter in the NSSavePanel/NSOpenPanel.
|
||||||
|
@interface CefFilterDelegate : NSObject {
|
||||||
|
@private
|
||||||
|
NSSavePanel* panel_;
|
||||||
|
std::vector<std::vector<base::string16> > extensions_;
|
||||||
|
int selected_index_;
|
||||||
|
}
|
||||||
|
- (id)initWithPanel:(NSSavePanel*)panel
|
||||||
|
andAcceptFilters:(const std::vector<base::string16>&)accept_filters
|
||||||
|
andFilterIndex:(int)index;
|
||||||
|
- (void)setFilter:(int)index;
|
||||||
|
- (int)filter;
|
||||||
|
- (void)filterSelectionChanged:(id)sender;
|
||||||
|
- (void)setFileExtension;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation CefFilterDelegate
|
||||||
|
|
||||||
|
- (id)initWithPanel:(NSSavePanel*)panel
|
||||||
|
andAcceptFilters:(const std::vector<base::string16>&)accept_filters
|
||||||
|
andFilterIndex:(int)index {
|
||||||
|
if (self = [super init]) {
|
||||||
|
DCHECK(panel);
|
||||||
|
panel_ = panel;
|
||||||
|
selected_index_ = 0;
|
||||||
|
|
||||||
|
NSPopUpButton *button = [[NSPopUpButton alloc] init];
|
||||||
|
AddFilters(button, accept_filters, true, &extensions_);
|
||||||
|
[button sizeToFit];
|
||||||
|
[button setTarget:self];
|
||||||
|
[button setAction:@selector(filterSelectionChanged:)];
|
||||||
|
|
||||||
|
if (index < static_cast<int>(extensions_.size())) {
|
||||||
|
[button selectItemAtIndex:index];
|
||||||
|
[self setFilter:index];
|
||||||
|
}
|
||||||
|
|
||||||
|
[panel_ setAccessoryView:button];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the current filter index.
|
||||||
|
- (void)setFilter:(int)index {
|
||||||
|
DCHECK(index >= 0 && index < static_cast<int>(extensions_.size()));
|
||||||
|
selected_index_ = index;
|
||||||
|
|
||||||
|
// Set the selectable file types. For open panels this limits the files that
|
||||||
|
// can be selected. For save panels this applies a default file extenion when
|
||||||
|
// the dialog is dismissed if none is already provided.
|
||||||
|
NSMutableArray* acceptArray = nil;
|
||||||
|
if (!extensions_[index].empty()) {
|
||||||
|
acceptArray = [[NSMutableArray alloc] init];
|
||||||
|
for (size_t i = 0; i < extensions_[index].size(); ++i) {
|
||||||
|
[acceptArray addObject:
|
||||||
|
base::SysUTF16ToNSString(extensions_[index][i].substr(1))];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[panel_ setAllowedFileTypes:acceptArray];
|
||||||
|
|
||||||
|
if (![panel_ isKindOfClass:[NSOpenPanel class]]) {
|
||||||
|
// For save panels set the file extension.
|
||||||
|
[self setFileExtension];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the current filter index.
|
||||||
|
- (int)filter {
|
||||||
|
return selected_index_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when the selected filter is changed via the NSPopUpButton.
|
||||||
|
- (void)filterSelectionChanged:(id)sender {
|
||||||
|
NSPopUpButton *button = (NSPopUpButton*)sender;
|
||||||
|
[self setFilter:[button indexOfSelectedItem]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the extension on the currently selected file name.
|
||||||
|
- (void)setFileExtension {
|
||||||
|
const std::vector<base::string16>& filter = extensions_[selected_index_];
|
||||||
|
if (filter.empty()) {
|
||||||
|
// All extensions are allowed so don't change anything.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
base::FilePath path(base::SysNSStringToUTF8([panel_ nameFieldStringValue]));
|
||||||
|
|
||||||
|
// If the file name currently includes an extension from |filter| then don't
|
||||||
|
// change anything.
|
||||||
|
base::string16 extension = base::UTF8ToUTF16(path.Extension());
|
||||||
|
if (!extension.empty()) {
|
||||||
|
for (size_t i = 0; i < filter.size(); ++i) {
|
||||||
|
if (filter[i] == extension)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change the extension to the first value in |filter|.
|
||||||
|
path = path.ReplaceExtension(base::UTF16ToUTF8(filter[0]));
|
||||||
|
[panel_ setNameFieldStringValue:base::SysUTF8ToNSString(path.value())];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void RunOpenFileDialog(
|
||||||
|
const CefFileDialogRunner::FileChooserParams& params,
|
||||||
|
NSView* view,
|
||||||
|
int* filter_index,
|
||||||
|
std::vector<base::FilePath>* files) {
|
||||||
|
NSOpenPanel* openPanel = [NSOpenPanel openPanel];
|
||||||
|
|
||||||
|
base::string16 title;
|
||||||
|
if (!params.title.empty()) {
|
||||||
|
title = params.title;
|
||||||
|
} else {
|
||||||
|
title = l10n_util::GetStringUTF16(
|
||||||
|
params.mode == content::FileChooserParams::Open ?
|
||||||
|
IDS_OPEN_FILE_DIALOG_TITLE :
|
||||||
|
(params.mode == content::FileChooserParams::OpenMultiple ?
|
||||||
|
IDS_OPEN_FILES_DIALOG_TITLE : IDS_SELECT_FOLDER_DIALOG_TITLE));
|
||||||
|
}
|
||||||
|
[openPanel setTitle:base::SysUTF16ToNSString(title)];
|
||||||
|
|
||||||
|
std::string filename, directory;
|
||||||
|
if (!params.default_file_name.empty()) {
|
||||||
|
if (params.mode == content::FileChooserParams::UploadFolder ||
|
||||||
|
params.default_file_name.EndsWithSeparator()) {
|
||||||
|
// The value is only a directory.
|
||||||
|
directory = params.default_file_name.value();
|
||||||
|
} else {
|
||||||
|
// The value is a file name and possibly a directory.
|
||||||
|
filename = params.default_file_name.BaseName().value();
|
||||||
|
directory = params.default_file_name.DirName().value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!filename.empty()) {
|
||||||
|
[openPanel setNameFieldStringValue:base::SysUTF8ToNSString(filename)];
|
||||||
|
}
|
||||||
|
if (!directory.empty()) {
|
||||||
|
[openPanel setDirectoryURL:
|
||||||
|
[NSURL fileURLWithPath:base::SysUTF8ToNSString(directory)]];
|
||||||
|
}
|
||||||
|
|
||||||
|
CefFilterDelegate* filter_delegate = nil;
|
||||||
|
if (params.mode != content::FileChooserParams::UploadFolder &&
|
||||||
|
!params.accept_types.empty()) {
|
||||||
|
// Add the file filter control.
|
||||||
|
filter_delegate =
|
||||||
|
[[CefFilterDelegate alloc] initWithPanel:openPanel
|
||||||
|
andAcceptFilters:params.accept_types
|
||||||
|
andFilterIndex:*filter_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Further panel configuration.
|
||||||
|
[openPanel setAllowsOtherFileTypes:YES];
|
||||||
|
[openPanel setAllowsMultipleSelection:
|
||||||
|
(params.mode == content::FileChooserParams::OpenMultiple)];
|
||||||
|
[openPanel setCanChooseFiles:
|
||||||
|
(params.mode != content::FileChooserParams::UploadFolder)];
|
||||||
|
[openPanel setCanChooseDirectories:
|
||||||
|
(params.mode == content::FileChooserParams::UploadFolder)];
|
||||||
|
[openPanel setShowsHiddenFiles:!params.hidereadonly];
|
||||||
|
|
||||||
|
// Show panel.
|
||||||
|
[openPanel beginSheetModalForWindow:[view window]
|
||||||
|
completionHandler:^(NSInteger returnCode) {
|
||||||
|
[NSApp stopModalWithCode:returnCode];
|
||||||
|
}];
|
||||||
|
NSInteger result = [NSApp runModalForWindow:[view window]];
|
||||||
|
if (result == NSFileHandlingPanelOKButton) {
|
||||||
|
NSArray *urls = [openPanel URLs];
|
||||||
|
int i, count = [urls count];
|
||||||
|
for (i=0; i<count; i++) {
|
||||||
|
NSURL* url = [urls objectAtIndex:i];
|
||||||
|
if ([url isFileURL])
|
||||||
|
files->push_back(base::FilePath(base::SysNSStringToUTF8([url path])));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter_delegate != nil)
|
||||||
|
*filter_index = [filter_delegate filter];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RunSaveFileDialog(
|
||||||
|
const CefFileDialogRunner::FileChooserParams& params,
|
||||||
|
NSView* view,
|
||||||
|
int* filter_index,
|
||||||
|
base::FilePath* file) {
|
||||||
|
NSSavePanel* savePanel = [NSSavePanel savePanel];
|
||||||
|
|
||||||
|
base::string16 title;
|
||||||
|
if (!params.title.empty())
|
||||||
|
title = params.title;
|
||||||
|
else
|
||||||
|
title = l10n_util::GetStringUTF16(IDS_SAVE_AS_DIALOG_TITLE);
|
||||||
|
[savePanel setTitle:base::SysUTF16ToNSString(title)];
|
||||||
|
|
||||||
|
std::string filename, directory;
|
||||||
|
if (!params.default_file_name.empty()) {
|
||||||
|
if (params.default_file_name.EndsWithSeparator()) {
|
||||||
|
// The value is only a directory.
|
||||||
|
directory = params.default_file_name.value();
|
||||||
|
} else {
|
||||||
|
// The value is a file name and possibly a directory.
|
||||||
|
filename = params.default_file_name.BaseName().value();
|
||||||
|
directory = params.default_file_name.DirName().value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!filename.empty()) {
|
||||||
|
[savePanel setNameFieldStringValue:base::SysUTF8ToNSString(filename)];
|
||||||
|
}
|
||||||
|
if (!directory.empty()) {
|
||||||
|
[savePanel setDirectoryURL:
|
||||||
|
[NSURL fileURLWithPath:base::SysUTF8ToNSString(directory)]];
|
||||||
|
}
|
||||||
|
|
||||||
|
CefFilterDelegate* filter_delegate = nil;
|
||||||
|
if (!params.accept_types.empty()) {
|
||||||
|
// Add the file filter control.
|
||||||
|
filter_delegate =
|
||||||
|
[[CefFilterDelegate alloc] initWithPanel:savePanel
|
||||||
|
andAcceptFilters:params.accept_types
|
||||||
|
andFilterIndex:*filter_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
[savePanel setAllowsOtherFileTypes:YES];
|
||||||
|
[savePanel setShowsHiddenFiles:!params.hidereadonly];
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
// Show panel.
|
||||||
|
[savePanel beginSheetModalForWindow:[view window]
|
||||||
|
completionHandler:^(NSInteger resultCode) {
|
||||||
|
[NSApp stopModalWithCode:resultCode];
|
||||||
|
}];
|
||||||
|
NSInteger result = [NSApp runModalForWindow:[view window]];
|
||||||
|
if (result == NSFileHandlingPanelOKButton) {
|
||||||
|
NSURL* url = [savePanel URL];
|
||||||
|
NSString* path = [url path];
|
||||||
|
*file = base::FilePath([path UTF8String]);
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filter_delegate != nil)
|
||||||
|
*filter_index = [filter_delegate filter];
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
CefFileDialogRunnerMac::CefFileDialogRunnerMac() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefFileDialogRunnerMac::Run(CefBrowserHostImpl* browser,
|
||||||
|
const FileChooserParams& params,
|
||||||
|
RunFileChooserCallback callback) {
|
||||||
|
std::vector<base::FilePath> files;
|
||||||
|
int filter_index = params.selected_accept_filter;
|
||||||
|
NSView* owner = browser->GetWindowHandle();
|
||||||
|
|
||||||
|
if (params.mode == content::FileChooserParams::Open ||
|
||||||
|
params.mode == content::FileChooserParams::OpenMultiple ||
|
||||||
|
params.mode == content::FileChooserParams::UploadFolder) {
|
||||||
|
RunOpenFileDialog(params, owner, &filter_index, &files);
|
||||||
|
} else if (params.mode == content::FileChooserParams::Save) {
|
||||||
|
base::FilePath file;
|
||||||
|
if (RunSaveFileDialog(params, owner, &filter_index, &file)) {
|
||||||
|
files.push_back(file);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NOTIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.Run(filter_index, files);
|
||||||
|
}
|
525
libcef/browser/native/file_dialog_runner_win.cc
Normal file
525
libcef/browser/native/file_dialog_runner_win.cc
Normal file
@ -0,0 +1,525 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2012 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 "libcef/browser/native/file_dialog_runner_win.h"
|
||||||
|
|
||||||
|
#include <commdlg.h>
|
||||||
|
#include <shlobj.h>
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
|
||||||
|
#include "base/files/file_util.h"
|
||||||
|
#include "base/strings/string_split.h"
|
||||||
|
#include "base/strings/string_util.h"
|
||||||
|
#include "base/strings/utf_string_conversions.h"
|
||||||
|
#include "base/win/registry.h"
|
||||||
|
#include "base/win/scoped_comptr.h"
|
||||||
|
#include "grit/cef_strings.h"
|
||||||
|
#include "grit/ui_strings.h"
|
||||||
|
#include "net/base/mime_util.h"
|
||||||
|
#include "ui/base/l10n/l10n_util.h"
|
||||||
|
#include "ui/base/win/shell.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// From ui/base/dialogs/select_file_dialog_win.cc.
|
||||||
|
|
||||||
|
// Get the file type description from the registry. This will be "Text Document"
|
||||||
|
// for .txt files, "JPEG Image" for .jpg files, etc. If the registry doesn't
|
||||||
|
// have an entry for the file type, we return false, true if the description was
|
||||||
|
// found. 'file_ext' must be in form ".txt".
|
||||||
|
static bool GetRegistryDescriptionFromExtension(const std::wstring& file_ext,
|
||||||
|
std::wstring* reg_description) {
|
||||||
|
DCHECK(reg_description);
|
||||||
|
base::win::RegKey reg_ext(HKEY_CLASSES_ROOT, file_ext.c_str(), KEY_READ);
|
||||||
|
std::wstring reg_app;
|
||||||
|
if (reg_ext.ReadValue(NULL, ®_app) == ERROR_SUCCESS && !reg_app.empty()) {
|
||||||
|
base::win::RegKey reg_link(HKEY_CLASSES_ROOT, reg_app.c_str(), KEY_READ);
|
||||||
|
if (reg_link.ReadValue(NULL, reg_description) == ERROR_SUCCESS)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up a filter for a Save/Open dialog, which will consist of |file_ext| file
|
||||||
|
// extensions (internally separated by semicolons), |ext_desc| as the text
|
||||||
|
// descriptions of the |file_ext| types (optional), and (optionally) the default
|
||||||
|
// 'All Files' view. The purpose of the filter is to show only files of a
|
||||||
|
// particular type in a Windows Save/Open dialog box. The resulting filter is
|
||||||
|
// returned. The filters created here are:
|
||||||
|
// 1. only files that have 'file_ext' as their extension
|
||||||
|
// 2. all files (only added if 'include_all_files' is true)
|
||||||
|
// Example:
|
||||||
|
// file_ext: { "*.txt", "*.htm;*.html" }
|
||||||
|
// ext_desc: { "Text Document" }
|
||||||
|
// returned: "Text Document\0*.txt\0HTML Document\0*.htm;*.html\0"
|
||||||
|
// "All Files\0*.*\0\0" (in one big string)
|
||||||
|
// If a description is not provided for a file extension, it will be retrieved
|
||||||
|
// from the registry. If the file extension does not exist in the registry, it
|
||||||
|
// will be omitted from the filter, as it is likely a bogus extension.
|
||||||
|
std::wstring FormatFilterForExtensions(
|
||||||
|
const std::vector<std::wstring>& file_ext,
|
||||||
|
const std::vector<std::wstring>& ext_desc,
|
||||||
|
bool include_all_files) {
|
||||||
|
const std::wstring all_ext = L"*.*";
|
||||||
|
const std::wstring all_desc =
|
||||||
|
l10n_util::GetStringUTF16(IDS_APP_SAVEAS_ALL_FILES) +
|
||||||
|
L" (" + all_ext + L")";
|
||||||
|
|
||||||
|
DCHECK(file_ext.size() >= ext_desc.size());
|
||||||
|
|
||||||
|
if (file_ext.empty())
|
||||||
|
include_all_files = true;
|
||||||
|
|
||||||
|
std::wstring result;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < file_ext.size(); ++i) {
|
||||||
|
std::wstring ext = file_ext[i];
|
||||||
|
std::wstring desc;
|
||||||
|
if (i < ext_desc.size())
|
||||||
|
desc = ext_desc[i];
|
||||||
|
|
||||||
|
if (ext.empty()) {
|
||||||
|
// Force something reasonable to appear in the dialog box if there is no
|
||||||
|
// extension provided.
|
||||||
|
include_all_files = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (desc.empty()) {
|
||||||
|
DCHECK(ext.find(L'.') != std::wstring::npos);
|
||||||
|
std::wstring first_extension = ext.substr(ext.find(L'.'));
|
||||||
|
size_t first_separator_index = first_extension.find(L';');
|
||||||
|
if (first_separator_index != std::wstring::npos)
|
||||||
|
first_extension = first_extension.substr(0, first_separator_index);
|
||||||
|
|
||||||
|
// Find the extension name without the preceeding '.' character.
|
||||||
|
std::wstring ext_name = first_extension;
|
||||||
|
size_t ext_index = ext_name.find_first_not_of(L'.');
|
||||||
|
if (ext_index != std::wstring::npos)
|
||||||
|
ext_name = ext_name.substr(ext_index);
|
||||||
|
|
||||||
|
if (!GetRegistryDescriptionFromExtension(first_extension, &desc)) {
|
||||||
|
// The extension doesn't exist in the registry.
|
||||||
|
include_all_files = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!desc.empty())
|
||||||
|
desc += L" (" + ext + L")";
|
||||||
|
else
|
||||||
|
desc = ext;
|
||||||
|
|
||||||
|
result.append(desc.c_str(), desc.size() + 1); // Append NULL too.
|
||||||
|
result.append(ext.c_str(), ext.size() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (include_all_files) {
|
||||||
|
result.append(all_desc.c_str(), all_desc.size() + 1);
|
||||||
|
result.append(all_ext.c_str(), all_ext.size() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result.append(1, '\0'); // Double NULL required.
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring GetDescriptionFromMimeType(const std::string& mime_type) {
|
||||||
|
// Check for wild card mime types and return an appropriate description.
|
||||||
|
static const struct {
|
||||||
|
const char* mime_type;
|
||||||
|
int string_id;
|
||||||
|
} kWildCardMimeTypes[] = {
|
||||||
|
{ "audio", IDS_APP_AUDIO_FILES },
|
||||||
|
{ "image", IDS_APP_IMAGE_FILES },
|
||||||
|
{ "text", IDS_APP_TEXT_FILES },
|
||||||
|
{ "video", IDS_APP_VIDEO_FILES },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (size_t i = 0; i < arraysize(kWildCardMimeTypes); ++i) {
|
||||||
|
if (mime_type == std::string(kWildCardMimeTypes[i].mime_type) + "/*")
|
||||||
|
return l10n_util::GetStringUTF16(kWildCardMimeTypes[i].string_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::wstring();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring GetFilterString(
|
||||||
|
const std::vector<base::string16>& accept_filters) {
|
||||||
|
std::vector<std::wstring> extensions;
|
||||||
|
std::vector<std::wstring> descriptions;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < accept_filters.size(); ++i) {
|
||||||
|
const base::string16& filter = accept_filters[i];
|
||||||
|
if (filter.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
size_t sep_index = filter.find('|');
|
||||||
|
if (sep_index != base::string16::npos) {
|
||||||
|
// Treat as a filter of the form "Filter Name|.ext1;.ext2;.ext3".
|
||||||
|
const base::string16& desc = filter.substr(0, sep_index);
|
||||||
|
const std::vector<base::string16>& ext =
|
||||||
|
base::SplitString(filter.substr(sep_index + 1),
|
||||||
|
base::ASCIIToUTF16(";"),
|
||||||
|
base::TRIM_WHITESPACE,
|
||||||
|
base::SPLIT_WANT_NONEMPTY);
|
||||||
|
std::wstring ext_str;
|
||||||
|
for (size_t x = 0; x < ext.size(); ++x) {
|
||||||
|
const base::string16& file_ext = ext[x];
|
||||||
|
if (!file_ext.empty() && file_ext[0] == '.') {
|
||||||
|
if (!ext_str.empty())
|
||||||
|
ext_str += L";";
|
||||||
|
ext_str += L"*" + file_ext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ext_str.empty()) {
|
||||||
|
extensions.push_back(ext_str);
|
||||||
|
descriptions.push_back(desc);
|
||||||
|
}
|
||||||
|
} else if (filter[0] == L'.') {
|
||||||
|
// Treat as an extension beginning with the '.' character.
|
||||||
|
extensions.push_back(L"*" + filter);
|
||||||
|
descriptions.push_back(std::wstring());
|
||||||
|
} else {
|
||||||
|
// Otherwise convert mime type to one or more extensions.
|
||||||
|
const std::string& ascii = base::UTF16ToASCII(filter);
|
||||||
|
std::vector<base::FilePath::StringType> ext;
|
||||||
|
std::wstring ext_str;
|
||||||
|
net::GetExtensionsForMimeType(ascii, &ext);
|
||||||
|
if (!ext.empty()) {
|
||||||
|
for (size_t x = 0; x < ext.size(); ++x) {
|
||||||
|
if (x != 0)
|
||||||
|
ext_str += L";";
|
||||||
|
ext_str += L"*." + ext[x];
|
||||||
|
}
|
||||||
|
extensions.push_back(ext_str);
|
||||||
|
descriptions.push_back(GetDescriptionFromMimeType(ascii));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FormatFilterForExtensions(extensions, descriptions, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// From chrome/browser/views/shell_dialogs_win.cc
|
||||||
|
|
||||||
|
bool RunOpenFileDialog(
|
||||||
|
const CefFileDialogRunner::FileChooserParams& params,
|
||||||
|
HWND owner,
|
||||||
|
int* filter_index,
|
||||||
|
base::FilePath* path) {
|
||||||
|
OPENFILENAME ofn;
|
||||||
|
|
||||||
|
// We must do this otherwise the ofn's FlagsEx may be initialized to random
|
||||||
|
// junk in release builds which can cause the Places Bar not to show up!
|
||||||
|
ZeroMemory(&ofn, sizeof(ofn));
|
||||||
|
ofn.lStructSize = sizeof(ofn);
|
||||||
|
ofn.hwndOwner = owner;
|
||||||
|
|
||||||
|
wchar_t filename[MAX_PATH] = {0};
|
||||||
|
|
||||||
|
ofn.lpstrFile = filename;
|
||||||
|
ofn.nMaxFile = MAX_PATH;
|
||||||
|
|
||||||
|
std::wstring directory;
|
||||||
|
if (!params.default_file_name.empty()) {
|
||||||
|
if (params.default_file_name.EndsWithSeparator()) {
|
||||||
|
// The value is only a directory.
|
||||||
|
directory = params.default_file_name.value();
|
||||||
|
} else {
|
||||||
|
// The value is a file name and possibly a directory.
|
||||||
|
base::wcslcpy(filename, params.default_file_name.value().c_str(),
|
||||||
|
arraysize(filename));
|
||||||
|
directory = params.default_file_name.DirName().value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!directory.empty())
|
||||||
|
ofn.lpstrInitialDir = directory.c_str();
|
||||||
|
|
||||||
|
std::wstring title;
|
||||||
|
if (!params.title.empty())
|
||||||
|
title = params.title;
|
||||||
|
else
|
||||||
|
title = l10n_util::GetStringUTF16(IDS_OPEN_FILE_DIALOG_TITLE);
|
||||||
|
if (!title.empty())
|
||||||
|
ofn.lpstrTitle = title.c_str();
|
||||||
|
|
||||||
|
// We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
|
||||||
|
// without having to close Chrome first.
|
||||||
|
ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_EXPLORER |
|
||||||
|
OFN_ENABLESIZING;
|
||||||
|
if (params.hidereadonly)
|
||||||
|
ofn.Flags |= OFN_HIDEREADONLY;
|
||||||
|
|
||||||
|
const std::wstring& filter = GetFilterString(params.accept_types);
|
||||||
|
if (!filter.empty()) {
|
||||||
|
ofn.lpstrFilter = filter.c_str();
|
||||||
|
// Indices into |lpstrFilter| start at 1.
|
||||||
|
ofn.nFilterIndex = *filter_index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = !!GetOpenFileName(&ofn);
|
||||||
|
if (success) {
|
||||||
|
*filter_index = ofn.nFilterIndex == 0 ? 0 : ofn.nFilterIndex - 1;
|
||||||
|
*path = base::FilePath(filename);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RunOpenMultiFileDialog(
|
||||||
|
const CefFileDialogRunner::FileChooserParams& params,
|
||||||
|
HWND owner,
|
||||||
|
int* filter_index,
|
||||||
|
std::vector<base::FilePath>* paths) {
|
||||||
|
OPENFILENAME ofn;
|
||||||
|
|
||||||
|
// We must do this otherwise the ofn's FlagsEx may be initialized to random
|
||||||
|
// junk in release builds which can cause the Places Bar not to show up!
|
||||||
|
ZeroMemory(&ofn, sizeof(ofn));
|
||||||
|
ofn.lStructSize = sizeof(ofn);
|
||||||
|
ofn.hwndOwner = owner;
|
||||||
|
|
||||||
|
scoped_ptr<wchar_t[]> filename(new wchar_t[UNICODE_STRING_MAX_CHARS]);
|
||||||
|
filename[0] = 0;
|
||||||
|
|
||||||
|
ofn.lpstrFile = filename.get();
|
||||||
|
ofn.nMaxFile = UNICODE_STRING_MAX_CHARS;
|
||||||
|
|
||||||
|
std::wstring directory;
|
||||||
|
if (!params.default_file_name.empty()) {
|
||||||
|
if (params.default_file_name.EndsWithSeparator()) {
|
||||||
|
// The value is only a directory.
|
||||||
|
directory = params.default_file_name.value();
|
||||||
|
} else {
|
||||||
|
// The value is a file name and possibly a directory.
|
||||||
|
directory = params.default_file_name.DirName().value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!directory.empty())
|
||||||
|
ofn.lpstrInitialDir = directory.c_str();
|
||||||
|
|
||||||
|
std::wstring title;
|
||||||
|
if (!params.title.empty())
|
||||||
|
title = params.title;
|
||||||
|
else
|
||||||
|
title = l10n_util::GetStringUTF16(IDS_OPEN_FILES_DIALOG_TITLE);
|
||||||
|
if (!title.empty())
|
||||||
|
ofn.lpstrTitle = title.c_str();
|
||||||
|
|
||||||
|
// We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
|
||||||
|
// without having to close Chrome first.
|
||||||
|
ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER |
|
||||||
|
OFN_ALLOWMULTISELECT | OFN_ENABLESIZING;
|
||||||
|
if (params.hidereadonly)
|
||||||
|
ofn.Flags |= OFN_HIDEREADONLY;
|
||||||
|
|
||||||
|
const std::wstring& filter = GetFilterString(params.accept_types);
|
||||||
|
if (!filter.empty()) {
|
||||||
|
ofn.lpstrFilter = filter.c_str();
|
||||||
|
// Indices into |lpstrFilter| start at 1.
|
||||||
|
ofn.nFilterIndex = *filter_index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = !!GetOpenFileName(&ofn);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
std::vector<base::FilePath> files;
|
||||||
|
const wchar_t* selection = ofn.lpstrFile;
|
||||||
|
while (*selection) { // Empty string indicates end of list.
|
||||||
|
files.push_back(base::FilePath(selection));
|
||||||
|
// Skip over filename and null-terminator.
|
||||||
|
selection += files.back().value().length() + 1;
|
||||||
|
}
|
||||||
|
if (files.empty()) {
|
||||||
|
success = false;
|
||||||
|
} else if (files.size() == 1) {
|
||||||
|
// When there is one file, it contains the path and filename.
|
||||||
|
paths->swap(files);
|
||||||
|
} else {
|
||||||
|
// Otherwise, the first string is the path, and the remainder are
|
||||||
|
// filenames.
|
||||||
|
std::vector<base::FilePath>::iterator path = files.begin();
|
||||||
|
for (std::vector<base::FilePath>::iterator file = path + 1;
|
||||||
|
file != files.end(); ++file) {
|
||||||
|
paths->push_back(path->Append(*file));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
*filter_index = ofn.nFilterIndex == 0 ? 0 : ofn.nFilterIndex - 1;
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The callback function for when the select folder dialog is opened.
|
||||||
|
int CALLBACK BrowseCallbackProc(HWND window,
|
||||||
|
UINT message,
|
||||||
|
LPARAM parameter,
|
||||||
|
LPARAM data)
|
||||||
|
{
|
||||||
|
if (message == BFFM_INITIALIZED) {
|
||||||
|
// WParam is TRUE since passing a path.
|
||||||
|
// data lParam member of the BROWSEINFO structure.
|
||||||
|
SendMessage(window, BFFM_SETSELECTION, TRUE, (LPARAM)data);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RunOpenFolderDialog(
|
||||||
|
const CefFileDialogRunner::FileChooserParams& params,
|
||||||
|
HWND owner,
|
||||||
|
base::FilePath* path) {
|
||||||
|
wchar_t dir_buffer[MAX_PATH + 1] = {0};
|
||||||
|
|
||||||
|
bool result = false;
|
||||||
|
BROWSEINFO browse_info = {0};
|
||||||
|
browse_info.hwndOwner = owner;
|
||||||
|
browse_info.pszDisplayName = dir_buffer;
|
||||||
|
browse_info.ulFlags = BIF_USENEWUI | BIF_RETURNONLYFSDIRS;
|
||||||
|
|
||||||
|
std::wstring title;
|
||||||
|
if (!params.title.empty())
|
||||||
|
title = params.title;
|
||||||
|
else
|
||||||
|
title = l10n_util::GetStringUTF16(IDS_SELECT_FOLDER_DIALOG_TITLE);
|
||||||
|
if (!title.empty())
|
||||||
|
browse_info.lpszTitle = title.c_str();
|
||||||
|
|
||||||
|
const std::wstring& file_path = params.default_file_name.value();
|
||||||
|
if (!file_path.empty()) {
|
||||||
|
// Highlight the current value.
|
||||||
|
browse_info.lParam = (LPARAM)file_path.c_str();
|
||||||
|
browse_info.lpfn = &BrowseCallbackProc;
|
||||||
|
}
|
||||||
|
|
||||||
|
LPITEMIDLIST list = SHBrowseForFolder(&browse_info);
|
||||||
|
if (list) {
|
||||||
|
STRRET out_dir_buffer;
|
||||||
|
ZeroMemory(&out_dir_buffer, sizeof(out_dir_buffer));
|
||||||
|
out_dir_buffer.uType = STRRET_WSTR;
|
||||||
|
base::win::ScopedComPtr<IShellFolder> shell_folder;
|
||||||
|
if (SHGetDesktopFolder(shell_folder.Receive()) == NOERROR) {
|
||||||
|
HRESULT hr = shell_folder->GetDisplayNameOf(list, SHGDN_FORPARSING,
|
||||||
|
&out_dir_buffer);
|
||||||
|
if (SUCCEEDED(hr) && out_dir_buffer.uType == STRRET_WSTR) {
|
||||||
|
*path = base::FilePath(out_dir_buffer.pOleStr);
|
||||||
|
CoTaskMemFree(out_dir_buffer.pOleStr);
|
||||||
|
result = true;
|
||||||
|
} else {
|
||||||
|
// Use old way if we don't get what we want.
|
||||||
|
wchar_t old_out_dir_buffer[MAX_PATH + 1];
|
||||||
|
if (SHGetPathFromIDList(list, old_out_dir_buffer)) {
|
||||||
|
*path = base::FilePath(old_out_dir_buffer);
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CoTaskMemFree(list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RunSaveFileDialog(
|
||||||
|
const CefFileDialogRunner::FileChooserParams& params,
|
||||||
|
HWND owner,
|
||||||
|
int* filter_index,
|
||||||
|
base::FilePath* path) {
|
||||||
|
OPENFILENAME ofn;
|
||||||
|
|
||||||
|
// We must do this otherwise the ofn's FlagsEx may be initialized to random
|
||||||
|
// junk in release builds which can cause the Places Bar not to show up!
|
||||||
|
ZeroMemory(&ofn, sizeof(ofn));
|
||||||
|
ofn.lStructSize = sizeof(ofn);
|
||||||
|
ofn.hwndOwner = owner;
|
||||||
|
|
||||||
|
wchar_t filename[MAX_PATH] = {0};
|
||||||
|
|
||||||
|
ofn.lpstrFile = filename;
|
||||||
|
ofn.nMaxFile = MAX_PATH;
|
||||||
|
|
||||||
|
std::wstring directory;
|
||||||
|
if (!params.default_file_name.empty()) {
|
||||||
|
if (params.default_file_name.EndsWithSeparator()) {
|
||||||
|
// The value is only a directory.
|
||||||
|
directory = params.default_file_name.value();
|
||||||
|
} else {
|
||||||
|
// The value is a file name and possibly a directory.
|
||||||
|
base::wcslcpy(filename, params.default_file_name.value().c_str(),
|
||||||
|
arraysize(filename));
|
||||||
|
directory = params.default_file_name.DirName().value();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!directory.empty())
|
||||||
|
ofn.lpstrInitialDir = directory.c_str();
|
||||||
|
|
||||||
|
std::wstring title;
|
||||||
|
if (!params.title.empty())
|
||||||
|
title = params.title;
|
||||||
|
else
|
||||||
|
title = l10n_util::GetStringUTF16(IDS_SAVE_AS_DIALOG_TITLE);
|
||||||
|
if (!title.empty())
|
||||||
|
ofn.lpstrTitle = title.c_str();
|
||||||
|
|
||||||
|
// We use OFN_NOCHANGEDIR so that the user can rename or delete the directory
|
||||||
|
// without having to close Chrome first.
|
||||||
|
ofn.Flags = OFN_EXPLORER | OFN_ENABLESIZING | OFN_NOCHANGEDIR |
|
||||||
|
OFN_PATHMUSTEXIST;
|
||||||
|
if (params.hidereadonly)
|
||||||
|
ofn.Flags |= OFN_HIDEREADONLY;
|
||||||
|
if (params.overwriteprompt)
|
||||||
|
ofn.Flags |= OFN_OVERWRITEPROMPT;
|
||||||
|
|
||||||
|
const std::wstring& filter = GetFilterString(params.accept_types);
|
||||||
|
if (!filter.empty()) {
|
||||||
|
ofn.lpstrFilter = filter.c_str();
|
||||||
|
// Indices into |lpstrFilter| start at 1.
|
||||||
|
ofn.nFilterIndex = *filter_index + 1;
|
||||||
|
// If a filter is specified and the default file name is changed then append
|
||||||
|
// a file extension to the new name.
|
||||||
|
ofn.lpstrDefExt = L"";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = !!GetSaveFileName(&ofn);
|
||||||
|
if (success) {
|
||||||
|
*filter_index = ofn.nFilterIndex == 0 ? 0 : ofn.nFilterIndex - 1;
|
||||||
|
*path = base::FilePath(filename);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
CefFileDialogRunnerWin::CefFileDialogRunnerWin() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefFileDialogRunnerWin::Run(CefBrowserHostImpl* browser,
|
||||||
|
const FileChooserParams& params,
|
||||||
|
RunFileChooserCallback callback) {
|
||||||
|
int filter_index = params.selected_accept_filter;
|
||||||
|
std::vector<base::FilePath> files;
|
||||||
|
|
||||||
|
HWND owner = browser->GetWindowHandle();
|
||||||
|
|
||||||
|
if (params.mode == content::FileChooserParams::Open) {
|
||||||
|
base::FilePath file;
|
||||||
|
if (RunOpenFileDialog(params, owner, &filter_index, &file))
|
||||||
|
files.push_back(file);
|
||||||
|
} else if (params.mode == content::FileChooserParams::OpenMultiple) {
|
||||||
|
RunOpenMultiFileDialog(params, owner, &filter_index, &files);
|
||||||
|
} else if (params.mode == content::FileChooserParams::UploadFolder) {
|
||||||
|
base::FilePath file;
|
||||||
|
if (RunOpenFolderDialog(params, owner, &file))
|
||||||
|
files.push_back(file);
|
||||||
|
} else if (params.mode == content::FileChooserParams::Save) {
|
||||||
|
base::FilePath file;
|
||||||
|
if (RunSaveFileDialog(params, owner, &filter_index, &file))
|
||||||
|
files.push_back(file);
|
||||||
|
} else {
|
||||||
|
NOTIMPLEMENTED();
|
||||||
|
}
|
||||||
|
|
||||||
|
callback.Run(filter_index, files);
|
||||||
|
}
|
22
libcef/browser/native/file_dialog_runner_win.h
Normal file
22
libcef/browser/native/file_dialog_runner_win.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2012 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 CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_WIN_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_WIN_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "libcef/browser/file_dialog_runner.h"
|
||||||
|
|
||||||
|
class CefFileDialogRunnerWin : public CefFileDialogRunner {
|
||||||
|
public:
|
||||||
|
CefFileDialogRunnerWin();
|
||||||
|
|
||||||
|
// CefFileDialogRunner methods:
|
||||||
|
void Run(CefBrowserHostImpl* browser,
|
||||||
|
const FileChooserParams& params,
|
||||||
|
RunFileChooserCallback callback) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_FILE_DIALOG_RUNNER_WIN_H_
|
49
libcef/browser/native/javascript_dialog_runner_mac.h
Normal file
49
libcef/browser/native/javascript_dialog_runner_mac.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright (c) 2012 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2012 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 CEF_LIBCEF_BROWSER_NATIVE_JAVASCRIPT_DIALOG_RUNNER_MAC_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_NATIVE_JAVASCRIPT_DIALOG_RUNNER_MAC_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "libcef/browser/javascript_dialog_runner.h"
|
||||||
|
|
||||||
|
#include "base/mac/scoped_nsobject.h"
|
||||||
|
#include "base/memory/weak_ptr.h"
|
||||||
|
|
||||||
|
#if __OBJC__
|
||||||
|
@class CefJavaScriptDialogHelper;
|
||||||
|
#else
|
||||||
|
class CefJavaScriptDialogHelper;
|
||||||
|
#endif // __OBJC__
|
||||||
|
|
||||||
|
class CefJavaScriptDialogRunnerMac : public CefJavaScriptDialogRunner {
|
||||||
|
public:
|
||||||
|
CefJavaScriptDialogRunnerMac();
|
||||||
|
~CefJavaScriptDialogRunnerMac() override;
|
||||||
|
|
||||||
|
// CefJavaScriptDialogRunner methods:
|
||||||
|
void Run(
|
||||||
|
CefBrowserHostImpl* browser,
|
||||||
|
content::JavaScriptMessageType message_type,
|
||||||
|
const base::string16& display_url,
|
||||||
|
const base::string16& message_text,
|
||||||
|
const base::string16& default_prompt_text,
|
||||||
|
const DialogClosedCallback& callback) override;
|
||||||
|
void Cancel() override;
|
||||||
|
|
||||||
|
// Callback from CefJavaScriptDialogHelper when the dialog is closed.
|
||||||
|
void DialogClosed(bool success,
|
||||||
|
const base::string16& user_input);
|
||||||
|
|
||||||
|
private:
|
||||||
|
DialogClosedCallback callback_;
|
||||||
|
|
||||||
|
base::scoped_nsobject<CefJavaScriptDialogHelper> helper_;
|
||||||
|
|
||||||
|
// Must be the last member.
|
||||||
|
base::WeakPtrFactory<CefJavaScriptDialogRunnerMac> weak_ptr_factory_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_JAVASCRIPT_DIALOG_RUNNER_MAC_H_
|
@ -3,12 +3,11 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "libcef/browser/javascript_dialog.h"
|
#include "libcef/browser/native/javascript_dialog_runner_mac.h"
|
||||||
#include "libcef/browser/javascript_dialog_manager.h"
|
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
#import "base/mac/scoped_nsobject.h"
|
#include "base/bind.h"
|
||||||
#include "base/strings/sys_string_conversions.h"
|
#include "base/strings/sys_string_conversions.h"
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
||||||
|
|
||||||
@ -20,12 +19,11 @@
|
|||||||
NSTextField* textField_; // WEAK; owned by alert_
|
NSTextField* textField_; // WEAK; owned by alert_
|
||||||
|
|
||||||
// Copies of the fields in CefJavaScriptDialog because they're private.
|
// Copies of the fields in CefJavaScriptDialog because they're private.
|
||||||
CefJavaScriptDialogManager* creator_;
|
CefJavaScriptDialogRunner::DialogClosedCallback callback_;
|
||||||
content::JavaScriptDialogManager::DialogClosedCallback callback_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)initHelperWithCreator:(CefJavaScriptDialogManager*)creator
|
- (id)initHelperWithCallback:
|
||||||
andCallback:(content::JavaScriptDialogManager::DialogClosedCallback)callback;
|
(CefJavaScriptDialogRunner::DialogClosedCallback)callback;
|
||||||
- (NSAlert*)alert;
|
- (NSAlert*)alert;
|
||||||
- (NSTextField*)textField;
|
- (NSTextField*)textField;
|
||||||
- (void)alertDidEnd:(NSAlert*)alert
|
- (void)alertDidEnd:(NSAlert*)alert
|
||||||
@ -37,12 +35,10 @@
|
|||||||
|
|
||||||
@implementation CefJavaScriptDialogHelper
|
@implementation CefJavaScriptDialogHelper
|
||||||
|
|
||||||
- (id)initHelperWithCreator:(CefJavaScriptDialogManager*)creator
|
- (id)initHelperWithCallback:
|
||||||
andCallback:(content::JavaScriptDialogManager::DialogClosedCallback)callback {
|
(CefJavaScriptDialogRunner::DialogClosedCallback)callback {
|
||||||
if (self = [super init]) {
|
if (self = [super init])
|
||||||
creator_ = creator;
|
|
||||||
callback_ = callback;
|
callback_ = callback;
|
||||||
}
|
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -73,10 +69,7 @@
|
|||||||
if (textField_)
|
if (textField_)
|
||||||
input = base::SysNSStringToUTF16([textField_ stringValue]);
|
input = base::SysNSStringToUTF16([textField_ stringValue]);
|
||||||
|
|
||||||
CefJavaScriptDialog* native_dialog =
|
|
||||||
reinterpret_cast<CefJavaScriptDialog*>(contextInfo);
|
|
||||||
callback_.Run(success, input);
|
callback_.Run(success, input);
|
||||||
creator_->DialogClosed(native_dialog);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)cancel {
|
- (void)cancel {
|
||||||
@ -86,23 +79,33 @@
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
CefJavaScriptDialog::CefJavaScriptDialog(
|
CefJavaScriptDialogRunnerMac::CefJavaScriptDialogRunnerMac()
|
||||||
CefJavaScriptDialogManager* creator,
|
: weak_ptr_factory_(this) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CefJavaScriptDialogRunnerMac::~CefJavaScriptDialogRunnerMac() {
|
||||||
|
Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefJavaScriptDialogRunnerMac::Run(
|
||||||
|
CefBrowserHostImpl* browser,
|
||||||
content::JavaScriptMessageType message_type,
|
content::JavaScriptMessageType message_type,
|
||||||
const base::string16& display_url,
|
const base::string16& display_url,
|
||||||
const base::string16& message_text,
|
const base::string16& message_text,
|
||||||
const base::string16& default_prompt_text,
|
const base::string16& default_prompt_text,
|
||||||
const content::JavaScriptDialogManager::DialogClosedCallback& callback)
|
const DialogClosedCallback& callback) {
|
||||||
: creator_(creator),
|
DCHECK(!helper_.get());
|
||||||
callback_(callback) {
|
callback_ = callback;
|
||||||
|
|
||||||
bool text_field =
|
bool text_field =
|
||||||
message_type == content::JAVASCRIPT_MESSAGE_TYPE_PROMPT;
|
message_type == content::JAVASCRIPT_MESSAGE_TYPE_PROMPT;
|
||||||
bool one_button =
|
bool one_button =
|
||||||
message_type == content::JAVASCRIPT_MESSAGE_TYPE_ALERT;
|
message_type == content::JAVASCRIPT_MESSAGE_TYPE_ALERT;
|
||||||
|
|
||||||
helper_ =
|
helper_.reset(
|
||||||
[[CefJavaScriptDialogHelper alloc] initHelperWithCreator:creator
|
[[CefJavaScriptDialogHelper alloc] initHelperWithCallback:
|
||||||
andCallback:callback];
|
base::Bind(&CefJavaScriptDialogRunnerMac::DialogClosed,
|
||||||
|
weak_ptr_factory_.GetWeakPtr())]);
|
||||||
|
|
||||||
// Show the modal dialog.
|
// Show the modal dialog.
|
||||||
NSAlert* alert = [helper_ alert];
|
NSAlert* alert = [helper_ alert];
|
||||||
@ -147,10 +150,17 @@ CefJavaScriptDialog::CefJavaScriptDialog(
|
|||||||
[[alert window] makeFirstResponder:[alert accessoryView]];
|
[[alert window] makeFirstResponder:[alert accessoryView]];
|
||||||
}
|
}
|
||||||
|
|
||||||
CefJavaScriptDialog::~CefJavaScriptDialog() {
|
void CefJavaScriptDialogRunnerMac::Cancel() {
|
||||||
[helper_ release];
|
if (helper_.get()) {
|
||||||
|
[helper_ cancel];
|
||||||
|
helper_.reset(nil);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefJavaScriptDialog::Cancel() {
|
void CefJavaScriptDialogRunnerMac::DialogClosed(
|
||||||
[helper_ cancel];
|
bool success,
|
||||||
|
const base::string16& user_input) {
|
||||||
|
helper_.reset(nil);
|
||||||
|
callback_.Run(success, user_input);
|
||||||
}
|
}
|
||||||
|
|
@ -3,8 +3,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "libcef/browser/javascript_dialog.h"
|
#include "libcef/browser/native/javascript_dialog_runner_win.h"
|
||||||
#include "libcef/browser/javascript_dialog_manager.h"
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
#include "libcef_dll/resource.h"
|
#include "libcef_dll/resource.h"
|
||||||
|
|
||||||
@ -13,20 +13,18 @@
|
|||||||
#include "base/strings/string_util.h"
|
#include "base/strings/string_util.h"
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
||||||
|
|
||||||
class CefJavaScriptDialog;
|
class CefJavaScriptDialogRunnerWin;
|
||||||
|
|
||||||
HHOOK CefJavaScriptDialog::msg_hook_ = NULL;
|
HHOOK CefJavaScriptDialogRunnerWin::msg_hook_ = NULL;
|
||||||
int CefJavaScriptDialog::msg_hook_user_count_ = 0;
|
int CefJavaScriptDialogRunnerWin::msg_hook_user_count_ = 0;
|
||||||
|
|
||||||
INT_PTR CALLBACK CefJavaScriptDialog::DialogProc(HWND dialog,
|
INT_PTR CALLBACK CefJavaScriptDialogRunnerWin::DialogProc(
|
||||||
UINT message,
|
HWND dialog, UINT message, WPARAM wparam, LPARAM lparam) {
|
||||||
WPARAM wparam,
|
|
||||||
LPARAM lparam) {
|
|
||||||
switch (message) {
|
switch (message) {
|
||||||
case WM_INITDIALOG: {
|
case WM_INITDIALOG: {
|
||||||
SetWindowLongPtr(dialog, DWLP_USER, static_cast<LONG_PTR>(lparam));
|
SetWindowLongPtr(dialog, DWLP_USER, static_cast<LONG_PTR>(lparam));
|
||||||
CefJavaScriptDialog* owner =
|
CefJavaScriptDialogRunnerWin* owner =
|
||||||
reinterpret_cast<CefJavaScriptDialog*>(lparam);
|
reinterpret_cast<CefJavaScriptDialogRunnerWin*>(lparam);
|
||||||
owner->dialog_win_ = dialog;
|
owner->dialog_win_ = dialog;
|
||||||
SetDlgItemText(dialog, IDC_DIALOGTEXT, owner->message_text_.c_str());
|
SetDlgItemText(dialog, IDC_DIALOGTEXT, owner->message_text_.c_str());
|
||||||
if (owner->message_type_ == content::JAVASCRIPT_MESSAGE_TYPE_PROMPT)
|
if (owner->message_type_ == content::JAVASCRIPT_MESSAGE_TYPE_PROMPT)
|
||||||
@ -35,12 +33,12 @@ INT_PTR CALLBACK CefJavaScriptDialog::DialogProc(HWND dialog,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_CLOSE: {
|
case WM_CLOSE: {
|
||||||
CefJavaScriptDialog* owner = reinterpret_cast<CefJavaScriptDialog*>(
|
CefJavaScriptDialogRunnerWin* owner =
|
||||||
|
reinterpret_cast<CefJavaScriptDialogRunnerWin*>(
|
||||||
GetWindowLongPtr(dialog, DWLP_USER));
|
GetWindowLongPtr(dialog, DWLP_USER));
|
||||||
if (owner) {
|
if (owner) {
|
||||||
owner->Cancel();
|
owner->Cancel();
|
||||||
owner->callback_.Run(false, base::string16());
|
owner->callback_.Run(false, base::string16());
|
||||||
owner->creator_->DialogClosed(owner);
|
|
||||||
|
|
||||||
// No need for the system to call DestroyWindow() because it will be
|
// No need for the system to call DestroyWindow() because it will be
|
||||||
// called by the Cancel() method.
|
// called by the Cancel() method.
|
||||||
@ -49,7 +47,8 @@ INT_PTR CALLBACK CefJavaScriptDialog::DialogProc(HWND dialog,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case WM_COMMAND: {
|
case WM_COMMAND: {
|
||||||
CefJavaScriptDialog* owner = reinterpret_cast<CefJavaScriptDialog*>(
|
CefJavaScriptDialogRunnerWin* owner =
|
||||||
|
reinterpret_cast<CefJavaScriptDialogRunnerWin*>(
|
||||||
GetWindowLongPtr(dialog, DWLP_USER));
|
GetWindowLongPtr(dialog, DWLP_USER));
|
||||||
base::string16 user_input;
|
base::string16 user_input;
|
||||||
bool finish = false;
|
bool finish = false;
|
||||||
@ -75,7 +74,6 @@ INT_PTR CALLBACK CefJavaScriptDialog::DialogProc(HWND dialog,
|
|||||||
if (finish) {
|
if (finish) {
|
||||||
owner->Cancel();
|
owner->Cancel();
|
||||||
owner->callback_.Run(result, user_input);
|
owner->callback_.Run(result, user_input);
|
||||||
owner->creator_->DialogClosed(owner);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -85,19 +83,32 @@ INT_PTR CALLBACK CefJavaScriptDialog::DialogProc(HWND dialog,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CefJavaScriptDialog::CefJavaScriptDialog(
|
CefJavaScriptDialogRunnerWin::CefJavaScriptDialogRunnerWin()
|
||||||
CefJavaScriptDialogManager* creator,
|
: dialog_win_(NULL),
|
||||||
|
parent_win_(NULL),
|
||||||
|
hook_installed_(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CefJavaScriptDialogRunnerWin::~CefJavaScriptDialogRunnerWin() {
|
||||||
|
Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefJavaScriptDialogRunnerWin::Run(
|
||||||
|
CefBrowserHostImpl* browser,
|
||||||
content::JavaScriptMessageType message_type,
|
content::JavaScriptMessageType message_type,
|
||||||
const base::string16& display_url,
|
const base::string16& display_url,
|
||||||
const base::string16& message_text,
|
const base::string16& message_text,
|
||||||
const base::string16& default_prompt_text,
|
const base::string16& default_prompt_text,
|
||||||
const content::JavaScriptDialogManager::DialogClosedCallback& callback)
|
const DialogClosedCallback& callback) {
|
||||||
: creator_(creator),
|
DCHECK(!dialog_win_);
|
||||||
callback_(callback),
|
|
||||||
message_type_(message_type),
|
message_type_ = message_type;
|
||||||
message_text_(message_text),
|
message_text_ = message_text;
|
||||||
default_prompt_text_(default_prompt_text) {
|
default_prompt_text_ = default_prompt_text;
|
||||||
|
callback_ = callback;
|
||||||
|
|
||||||
InstallMessageHook();
|
InstallMessageHook();
|
||||||
|
hook_installed_ = true;
|
||||||
|
|
||||||
int dialog_type;
|
int dialog_type;
|
||||||
if (message_type == content::JAVASCRIPT_MESSAGE_TYPE_ALERT)
|
if (message_type == content::JAVASCRIPT_MESSAGE_TYPE_ALERT)
|
||||||
@ -117,7 +128,7 @@ CefJavaScriptDialog::CefJavaScriptDialog(
|
|||||||
hModule = ::GetModuleHandle(NULL);
|
hModule = ::GetModuleHandle(NULL);
|
||||||
DCHECK(hModule);
|
DCHECK(hModule);
|
||||||
|
|
||||||
parent_win_ = GetAncestor(creator->browser()->GetWindowHandle(), GA_ROOT);
|
parent_win_ = GetAncestor(browser->GetWindowHandle(), GA_ROOT);
|
||||||
dialog_win_ = CreateDialogParam(hModule,
|
dialog_win_ = CreateDialogParam(hModule,
|
||||||
MAKEINTRESOURCE(dialog_type),
|
MAKEINTRESOURCE(dialog_type),
|
||||||
parent_win_,
|
parent_win_,
|
||||||
@ -142,12 +153,7 @@ CefJavaScriptDialog::CefJavaScriptDialog(
|
|||||||
ShowWindow(dialog_win_, SW_SHOWNORMAL);
|
ShowWindow(dialog_win_, SW_SHOWNORMAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
CefJavaScriptDialog::~CefJavaScriptDialog() {
|
void CefJavaScriptDialogRunnerWin::Cancel() {
|
||||||
Cancel();
|
|
||||||
UninstallMessageHook();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefJavaScriptDialog::Cancel() {
|
|
||||||
HWND parent = NULL;
|
HWND parent = NULL;
|
||||||
|
|
||||||
// Re-enable the parent before closing the popup to avoid focus/activation/
|
// Re-enable the parent before closing the popup to avoid focus/activation/
|
||||||
@ -167,11 +173,16 @@ void CefJavaScriptDialog::Cancel() {
|
|||||||
// Return focus to the parent window.
|
// Return focus to the parent window.
|
||||||
if (parent)
|
if (parent)
|
||||||
SetFocus(parent);
|
SetFocus(parent);
|
||||||
|
|
||||||
|
if (hook_installed_) {
|
||||||
|
UninstallMessageHook();
|
||||||
|
hook_installed_ = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
LRESULT CALLBACK CefJavaScriptDialog::GetMsgProc(int code, WPARAM wparam,
|
LRESULT CALLBACK CefJavaScriptDialogRunnerWin::GetMsgProc(
|
||||||
LPARAM lparam) {
|
int code, WPARAM wparam, LPARAM lparam) {
|
||||||
// Mostly borrowed from http://support.microsoft.com/kb/q187988/
|
// Mostly borrowed from http://support.microsoft.com/kb/q187988/
|
||||||
// and http://www.codeproject.com/KB/atl/cdialogmessagehook.aspx.
|
// and http://www.codeproject.com/KB/atl/cdialogmessagehook.aspx.
|
||||||
LPMSG msg = reinterpret_cast<LPMSG>(lparam);
|
LPMSG msg = reinterpret_cast<LPMSG>(lparam);
|
||||||
@ -196,7 +207,7 @@ LRESULT CALLBACK CefJavaScriptDialog::GetMsgProc(int code, WPARAM wparam,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool CefJavaScriptDialog::InstallMessageHook() {
|
bool CefJavaScriptDialogRunnerWin::InstallMessageHook() {
|
||||||
msg_hook_user_count_++;
|
msg_hook_user_count_++;
|
||||||
|
|
||||||
// Make sure we only call this once.
|
// Make sure we only call this once.
|
||||||
@ -204,7 +215,7 @@ bool CefJavaScriptDialog::InstallMessageHook() {
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
msg_hook_ = ::SetWindowsHookEx(WH_GETMESSAGE,
|
msg_hook_ = ::SetWindowsHookEx(WH_GETMESSAGE,
|
||||||
&CefJavaScriptDialog::GetMsgProc,
|
&CefJavaScriptDialogRunnerWin::GetMsgProc,
|
||||||
NULL,
|
NULL,
|
||||||
GetCurrentThreadId());
|
GetCurrentThreadId());
|
||||||
DCHECK(msg_hook_ != NULL);
|
DCHECK(msg_hook_ != NULL);
|
||||||
@ -212,7 +223,7 @@ bool CefJavaScriptDialog::InstallMessageHook() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool CefJavaScriptDialog::UninstallMessageHook() {
|
bool CefJavaScriptDialogRunnerWin::UninstallMessageHook() {
|
||||||
msg_hook_user_count_--;
|
msg_hook_user_count_--;
|
||||||
DCHECK_GE(msg_hook_user_count_, 0);
|
DCHECK_GE(msg_hook_user_count_, 0);
|
||||||
|
|
@ -3,51 +3,38 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_H_
|
#ifndef CEF_LIBCEF_BROWSER_NATIVE_JAVASCRIPT_DIALOG_RUNNER_WIN_H_
|
||||||
#define CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_H_
|
#define CEF_LIBCEF_BROWSER_NATIVE_JAVASCRIPT_DIALOG_RUNNER_WIN_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "content/public/browser/javascript_dialog_manager.h"
|
#include "libcef/browser/javascript_dialog_runner.h"
|
||||||
|
|
||||||
#if defined(OS_MACOSX)
|
class CefJavaScriptDialogRunnerWin : public CefJavaScriptDialogRunner {
|
||||||
#if __OBJC__
|
|
||||||
@class CefJavaScriptDialogHelper;
|
|
||||||
#else
|
|
||||||
class CefJavaScriptDialogHelper;
|
|
||||||
#endif // __OBJC__
|
|
||||||
#endif // defined(OS_MACOSX)
|
|
||||||
|
|
||||||
class CefJavaScriptDialogManager;
|
|
||||||
|
|
||||||
class CefJavaScriptDialog {
|
|
||||||
public:
|
public:
|
||||||
CefJavaScriptDialog(
|
CefJavaScriptDialogRunnerWin();
|
||||||
CefJavaScriptDialogManager* creator,
|
~CefJavaScriptDialogRunnerWin() override;
|
||||||
|
|
||||||
|
// CefJavaScriptDialogRunner methods:
|
||||||
|
void Run(
|
||||||
|
CefBrowserHostImpl* browser,
|
||||||
content::JavaScriptMessageType message_type,
|
content::JavaScriptMessageType message_type,
|
||||||
const base::string16& display_url,
|
const base::string16& display_url,
|
||||||
const base::string16& message_text,
|
const base::string16& message_text,
|
||||||
const base::string16& default_prompt_text,
|
const base::string16& default_prompt_text,
|
||||||
const content::JavaScriptDialogManager::DialogClosedCallback& callback);
|
const DialogClosedCallback& callback) override;
|
||||||
~CefJavaScriptDialog();
|
void Cancel() override;
|
||||||
|
|
||||||
// Called to cancel a dialog mid-flight.
|
|
||||||
void Cancel();
|
|
||||||
|
|
||||||
// Activate the dialog.
|
|
||||||
void Activate();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CefJavaScriptDialogManager* creator_;
|
|
||||||
content::JavaScriptDialogManager::DialogClosedCallback callback_;
|
|
||||||
|
|
||||||
#if defined(OS_MACOSX)
|
|
||||||
CefJavaScriptDialogHelper* helper_; // owned
|
|
||||||
#elif defined(OS_WIN)
|
|
||||||
content::JavaScriptMessageType message_type_;
|
|
||||||
HWND dialog_win_;
|
HWND dialog_win_;
|
||||||
HWND parent_win_;
|
HWND parent_win_;
|
||||||
|
|
||||||
|
content::JavaScriptMessageType message_type_;
|
||||||
base::string16 message_text_;
|
base::string16 message_text_;
|
||||||
base::string16 default_prompt_text_;
|
base::string16 default_prompt_text_;
|
||||||
|
DialogClosedCallback callback_;
|
||||||
|
|
||||||
|
bool hook_installed_;
|
||||||
|
|
||||||
static INT_PTR CALLBACK DialogProc(HWND dialog, UINT message, WPARAM wparam,
|
static INT_PTR CALLBACK DialogProc(HWND dialog, UINT message, WPARAM wparam,
|
||||||
LPARAM lparam);
|
LPARAM lparam);
|
||||||
|
|
||||||
@ -59,9 +46,6 @@ class CefJavaScriptDialog {
|
|||||||
static LRESULT CALLBACK GetMsgProc(int code, WPARAM wparam, LPARAM lparam);
|
static LRESULT CALLBACK GetMsgProc(int code, WPARAM wparam, LPARAM lparam);
|
||||||
static HHOOK msg_hook_;
|
static HHOOK msg_hook_;
|
||||||
static int msg_hook_user_count_;
|
static int msg_hook_user_count_;
|
||||||
#endif
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CefJavaScriptDialog);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_H_
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_JAVASCRIPT_DIALOG_RUNNER_WIN_H_
|
49
libcef/browser/native/menu_runner_linux.cc
Normal file
49
libcef/browser/native/menu_runner_linux.cc
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
// Copyright 2014 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 "libcef/browser/native/menu_runner_linux.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
|
||||||
|
#include "base/compiler_specific.h"
|
||||||
|
#include "base/strings/string_util.h"
|
||||||
|
#include "ui/gfx/geometry/point.h"
|
||||||
|
|
||||||
|
CefMenuRunnerLinux::CefMenuRunnerLinux() {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefMenuRunnerLinux::RunContextMenu(
|
||||||
|
CefBrowserHostImpl* browser,
|
||||||
|
ui::MenuModel* model,
|
||||||
|
const content::ContextMenuParams& params) {
|
||||||
|
menu_.reset(
|
||||||
|
new views::MenuRunner(model, views::MenuRunner::CONTEXT_MENU));
|
||||||
|
|
||||||
|
const gfx::Point& screen_point =
|
||||||
|
browser->GetScreenPoint(gfx::Point(params.x, params.y));
|
||||||
|
|
||||||
|
views::Widget* parent_widget = nullptr;
|
||||||
|
if (!browser->IsWindowless())
|
||||||
|
parent_widget = browser->GetWindowWidget();
|
||||||
|
|
||||||
|
views::MenuRunner::RunResult result =
|
||||||
|
menu_->RunMenuAt(parent_widget,
|
||||||
|
NULL, gfx::Rect(screen_point, gfx::Size()),
|
||||||
|
views::MENU_ANCHOR_TOPRIGHT,
|
||||||
|
ui::MENU_SOURCE_NONE);
|
||||||
|
ALLOW_UNUSED_LOCAL(result);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefMenuRunnerLinux::CancelContextMenu() {
|
||||||
|
if (menu_)
|
||||||
|
menu_->Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefMenuRunnerLinux::FormatLabel(base::string16& label) {
|
||||||
|
// Remove the accelerator indicator (&) from label strings.
|
||||||
|
const char16 replace[] = {L'&', 0};
|
||||||
|
return base::ReplaceChars(label, replace, base::string16(), &label);
|
||||||
|
}
|
29
libcef/browser/native/menu_runner_linux.h
Normal file
29
libcef/browser/native/menu_runner_linux.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// 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_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_LINUX_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_LINUX_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "libcef/browser/menu_runner.h"
|
||||||
|
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#include "ui/views/controls/menu/menu_runner.h"
|
||||||
|
|
||||||
|
class CefMenuRunnerLinux: public CefMenuRunner {
|
||||||
|
public:
|
||||||
|
CefMenuRunnerLinux();
|
||||||
|
|
||||||
|
// CefMenuRunner methods.
|
||||||
|
bool RunContextMenu(CefBrowserHostImpl* browser,
|
||||||
|
ui::MenuModel* model,
|
||||||
|
const content::ContextMenuParams& params) override;
|
||||||
|
void CancelContextMenu() override;
|
||||||
|
bool FormatLabel(base::string16& label) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
scoped_ptr<views::MenuRunner> menu_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_LINUX_H_
|
34
libcef/browser/native/menu_runner_mac.h
Normal file
34
libcef/browser/native/menu_runner_mac.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// 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_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_MAC_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_MAC_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "libcef/browser/menu_runner.h"
|
||||||
|
|
||||||
|
#include "base/mac/scoped_nsobject.h"
|
||||||
|
|
||||||
|
#if __OBJC__
|
||||||
|
@class MenuController;
|
||||||
|
#else
|
||||||
|
class MenuController;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class CefMenuRunnerMac : public CefMenuRunner {
|
||||||
|
public:
|
||||||
|
CefMenuRunnerMac();
|
||||||
|
~CefMenuRunnerMac() override;
|
||||||
|
|
||||||
|
// CefMenuRunner methods.
|
||||||
|
bool RunContextMenu(CefBrowserHostImpl* browser,
|
||||||
|
ui::MenuModel* model,
|
||||||
|
const content::ContextMenuParams& params) override;
|
||||||
|
void CancelContextMenu() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
base::scoped_nsobject<MenuController> menu_controller_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_MAC_H_
|
91
libcef/browser/native/menu_runner_mac.mm
Normal file
91
libcef/browser/native/menu_runner_mac.mm
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
// 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 "libcef/browser/native/menu_runner_mac.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
|
||||||
|
#include "base/message_loop/message_loop.h"
|
||||||
|
#include "base/compiler_specific.h"
|
||||||
|
#import "base/mac/scoped_sending_event.h"
|
||||||
|
#import "ui/base/cocoa/menu_controller.h"
|
||||||
|
#include "ui/gfx/geometry/point.h"
|
||||||
|
|
||||||
|
CefMenuRunnerMac::CefMenuRunnerMac() {
|
||||||
|
}
|
||||||
|
|
||||||
|
CefMenuRunnerMac::~CefMenuRunnerMac() {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefMenuRunnerMac::RunContextMenu(
|
||||||
|
CefBrowserHostImpl* browser,
|
||||||
|
ui::MenuModel* model,
|
||||||
|
const content::ContextMenuParams& params) {
|
||||||
|
// Create a menu controller based on the model.
|
||||||
|
menu_controller_.reset([[MenuController alloc] initWithModel:model
|
||||||
|
useWithPopUpButtonCell:NO]);
|
||||||
|
|
||||||
|
// Keep the menu controller alive (by adding an additional retain) until after
|
||||||
|
// the menu has been dismissed. Otherwise it will crash if the browser is
|
||||||
|
// destroyed (and consequently the menu controller is destroyed) while the
|
||||||
|
// menu is still pending.
|
||||||
|
base::scoped_nsobject<MenuController> menu_controller_ref(menu_controller_);
|
||||||
|
|
||||||
|
// Make sure events can be pumped while the menu is up.
|
||||||
|
base::MessageLoop::ScopedNestableTaskAllower allow(
|
||||||
|
base::MessageLoop::current());
|
||||||
|
|
||||||
|
// One of the events that could be pumped is |window.close()|.
|
||||||
|
// User-initiated event-tracking loops protect against this by
|
||||||
|
// setting flags in -[CrApplication sendEvent:], but since
|
||||||
|
// web-content menus are initiated by IPC message the setup has to
|
||||||
|
// be done manually.
|
||||||
|
base::mac::ScopedSendingEvent sendingEventScoper;
|
||||||
|
|
||||||
|
// Show the menu. Blocks until the menu is dismissed.
|
||||||
|
if (browser->IsWindowless()) {
|
||||||
|
// Don't show the menu unless a native window handle exists.
|
||||||
|
if (!browser->GetWindowHandle())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const gfx::Point& screen_point =
|
||||||
|
browser->GetScreenPoint(gfx::Point(params.x, params.y));
|
||||||
|
NSPoint screen_position = NSPointFromCGPoint(screen_point.ToCGPoint());
|
||||||
|
[[menu_controller_ menu] popUpMenuPositioningItem:nil
|
||||||
|
atLocation:screen_position
|
||||||
|
inView:nil];
|
||||||
|
} else {
|
||||||
|
NSView* parent_view = browser->web_contents()->GetContentNativeView();
|
||||||
|
|
||||||
|
// Synthesize an event for the click, as there is no certainty that
|
||||||
|
// [NSApp currentEvent] will return a valid event.
|
||||||
|
NSEvent* currentEvent = [NSApp currentEvent];
|
||||||
|
NSWindow* window = [parent_view window];
|
||||||
|
|
||||||
|
NSPoint position = [window mouseLocationOutsideOfEventStream];
|
||||||
|
|
||||||
|
NSTimeInterval eventTime = [currentEvent timestamp];
|
||||||
|
NSEvent* clickEvent = [NSEvent mouseEventWithType:NSRightMouseDown
|
||||||
|
location:position
|
||||||
|
modifierFlags:NSRightMouseDownMask
|
||||||
|
timestamp:eventTime
|
||||||
|
windowNumber:[window windowNumber]
|
||||||
|
context:nil
|
||||||
|
eventNumber:0
|
||||||
|
clickCount:1
|
||||||
|
pressure:1.0];
|
||||||
|
|
||||||
|
[NSMenu popUpContextMenu:[menu_controller_ menu]
|
||||||
|
withEvent:clickEvent
|
||||||
|
forView:parent_view];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefMenuRunnerMac::CancelContextMenu() {
|
||||||
|
if (menu_controller_.get())
|
||||||
|
[menu_controller_ cancel];
|
||||||
|
}
|
||||||
|
|
35
libcef/browser/native/menu_runner_win.cc
Normal file
35
libcef/browser/native/menu_runner_win.cc
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// 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 "libcef/browser/native/menu_runner_win.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
|
||||||
|
#include "base/message_loop/message_loop.h"
|
||||||
|
#include "ui/gfx/geometry/point.h"
|
||||||
|
#include "ui/views/controls/menu/menu_2.h"
|
||||||
|
|
||||||
|
CefMenuRunnerWin::CefMenuRunnerWin() {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefMenuRunnerWin::RunContextMenu(
|
||||||
|
CefBrowserHostImpl* browser,
|
||||||
|
ui::MenuModel* model,
|
||||||
|
const content::ContextMenuParams& params) {
|
||||||
|
// Create a menu based on the model.
|
||||||
|
menu_.reset(new views::NativeMenuWin(model, NULL));
|
||||||
|
menu_->Rebuild(NULL);
|
||||||
|
|
||||||
|
// Make sure events can be pumped while the menu is up.
|
||||||
|
base::MessageLoop::ScopedNestableTaskAllower allow(
|
||||||
|
base::MessageLoop::current());
|
||||||
|
|
||||||
|
const gfx::Point& screen_point =
|
||||||
|
browser->GetScreenPoint(gfx::Point(params.x, params.y));
|
||||||
|
|
||||||
|
// Show the menu. Blocks until the menu is dismissed.
|
||||||
|
menu_->RunMenuAt(screen_point, views::Menu2::ALIGN_TOPLEFT);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
27
libcef/browser/native/menu_runner_win.h
Normal file
27
libcef/browser/native/menu_runner_win.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
// 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_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_WIN_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_WIN_H_
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "libcef/browser/menu_runner.h"
|
||||||
|
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#include "ui/views/controls/menu/native_menu_win.h"
|
||||||
|
|
||||||
|
class CefMenuRunnerWin : public CefMenuRunner {
|
||||||
|
public:
|
||||||
|
CefMenuRunnerWin();
|
||||||
|
|
||||||
|
// CefMenuRunner methods.
|
||||||
|
bool RunContextMenu(CefBrowserHostImpl* browser,
|
||||||
|
ui::MenuModel* model,
|
||||||
|
const content::ContextMenuParams& params) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
scoped_ptr<views::NativeMenuWin> menu_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_MENU_RUNNER_WIN_H_
|
@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be found
|
// Use of this source code is governed by a BSD-style license that can be found
|
||||||
// in the LICENSE file.
|
// in the LICENSE file.
|
||||||
|
|
||||||
#include "libcef/browser/window_delegate_view.h"
|
#include "libcef/browser/native/window_delegate_view.h"
|
||||||
|
|
||||||
#include "content/public/browser/web_contents.h"
|
#include "content/public/browser/web_contents.h"
|
||||||
#include "ui/views/background.h"
|
#include "ui/views/background.h"
|
@ -2,8 +2,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be found
|
// Use of this source code is governed by a BSD-style license that can be found
|
||||||
// in the LICENSE file.
|
// in the LICENSE file.
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_BROWSER_WINDOW_DELEGATE_VIEW_H_
|
#ifndef CEF_LIBCEF_BROWSER_NATIVE_WINDOW_DELEGATE_VIEW_H_
|
||||||
#define CEF_LIBCEF_BROWSER_WINDOW_DELEGATE_VIEW_H_
|
#define CEF_LIBCEF_BROWSER_NATIVE_WINDOW_DELEGATE_VIEW_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "ui/views/widget/widget_delegate.h"
|
#include "ui/views/widget/widget_delegate.h"
|
||||||
@ -47,4 +47,4 @@ class CefWindowDelegateView : public views::WidgetDelegateView {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(CefWindowDelegateView);
|
DISALLOW_COPY_AND_ASSIGN(CefWindowDelegateView);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_WINDOW_DELEGATE_VIEW_H_
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_WINDOW_DELEGATE_VIEW_H_
|
@ -3,7 +3,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "libcef/browser/window_x11.h"
|
#include "libcef/browser/native/window_x11.h"
|
||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
|
|
||||||
#include <X11/extensions/XInput2.h>
|
#include <X11/extensions/XInput2.h>
|
@ -3,8 +3,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_BROWSER_WINDOW_X11_H_
|
#ifndef CEF_LIBCEF_BROWSER_NATIVE_WINDOW_X11_H_
|
||||||
#define CEF_LIBCEF_BROWSER_WINDOW_X11_H_
|
#define CEF_LIBCEF_BROWSER_NATIVE_WINDOW_X11_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
@ -75,4 +75,4 @@ class CefWindowX11 : public ui::PlatformEventDispatcher {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(CefWindowX11);
|
DISALLOW_COPY_AND_ASSIGN(CefWindowX11);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_WINDOW_X11_H_
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_WINDOW_X11_H_
|
309
libcef/browser/osr/browser_platform_delegate_osr.cc
Normal file
309
libcef/browser/osr/browser_platform_delegate_osr.cc
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
// Copyright 2015 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 "libcef/browser/osr/browser_platform_delegate_osr.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
#include "libcef/browser/osr/render_widget_host_view_osr.h"
|
||||||
|
#include "libcef/browser/osr/web_contents_view_osr.h"
|
||||||
|
#include "libcef/common/drag_data_impl.h"
|
||||||
|
|
||||||
|
#include "content/public/browser/render_view_host.h"
|
||||||
|
|
||||||
|
CefBrowserPlatformDelegateOsr::CefBrowserPlatformDelegateOsr(
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegateNative> native_delegate)
|
||||||
|
: native_delegate_(native_delegate.Pass()),
|
||||||
|
view_osr_(nullptr) {
|
||||||
|
native_delegate_->set_windowless_handler(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::CreateViewForWebContents(
|
||||||
|
content::WebContentsView** view,
|
||||||
|
content::RenderViewHostDelegateView** delegate_view) {
|
||||||
|
DCHECK(!view_osr_);
|
||||||
|
|
||||||
|
// Use the OSR view instead of the default platform view.
|
||||||
|
view_osr_ = new CefWebContentsViewOSR(
|
||||||
|
!!native_delegate_->window_info().transparent_painting_enabled);
|
||||||
|
*view = view_osr_;
|
||||||
|
*delegate_view = view_osr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::WebContentsCreated(
|
||||||
|
content::WebContents* web_contents) {
|
||||||
|
DCHECK(view_osr_);
|
||||||
|
DCHECK(!view_osr_->web_contents());
|
||||||
|
|
||||||
|
// Associate the WebContents with the OSR view.
|
||||||
|
view_osr_->set_web_contents(web_contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::BrowserCreated(
|
||||||
|
CefBrowserHostImpl* browser) {
|
||||||
|
CefBrowserPlatformDelegate::BrowserCreated(browser);
|
||||||
|
|
||||||
|
if (browser->IsPopup()) {
|
||||||
|
// Associate the RenderWidget host view with the browser now because the
|
||||||
|
// browser wasn't known at the time that the host view was created.
|
||||||
|
content::RenderViewHost* host =
|
||||||
|
browser->web_contents()->GetRenderViewHost();
|
||||||
|
DCHECK(host);
|
||||||
|
CefRenderWidgetHostViewOSR* view =
|
||||||
|
static_cast<CefRenderWidgetHostViewOSR*>(host->GetWidget()->GetView());
|
||||||
|
// |view| will be null if the popup is a DevTools window.
|
||||||
|
if (view)
|
||||||
|
view->set_browser_impl(browser);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::BrowserDestroyed(
|
||||||
|
CefBrowserHostImpl* browser) {
|
||||||
|
CefBrowserPlatformDelegate::BrowserDestroyed(browser);
|
||||||
|
|
||||||
|
view_osr_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::WasResized() {
|
||||||
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
|
||||||
|
if (view)
|
||||||
|
view->WasResized();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::SendKeyEvent(
|
||||||
|
const content::NativeWebKeyboardEvent& event) {
|
||||||
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
|
||||||
|
if (view)
|
||||||
|
view->SendKeyEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::SendMouseEvent(
|
||||||
|
const blink::WebMouseEvent& event) {
|
||||||
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
|
||||||
|
if (view)
|
||||||
|
view->SendMouseEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::SendMouseWheelEvent(
|
||||||
|
const blink::WebMouseWheelEvent& event) {
|
||||||
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
|
||||||
|
if (view)
|
||||||
|
view->SendMouseWheelEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::SendFocusEvent(bool setFocus) {
|
||||||
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
|
||||||
|
if (view)
|
||||||
|
view->SendFocusEvent(setFocus);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gfx::Point CefBrowserPlatformDelegateOsr::GetScreenPoint(
|
||||||
|
const gfx::Point& view) const {
|
||||||
|
CefRefPtr<CefRenderHandler> handler = browser_->client()->GetRenderHandler();
|
||||||
|
if (handler.get()) {
|
||||||
|
int screenX = 0, screenY = 0;
|
||||||
|
if (handler->GetScreenPoint(browser_, view.x(), view.y(),
|
||||||
|
screenX, screenY)) {
|
||||||
|
return gfx::Point(screenX, screenY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::ViewText(const std::string& text) {
|
||||||
|
native_delegate_->ViewText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::HandleKeyboardEvent(
|
||||||
|
const content::NativeWebKeyboardEvent& event) {
|
||||||
|
native_delegate_->HandleKeyboardEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::HandleExternalProtocol(const GURL& url) {
|
||||||
|
native_delegate_->HandleExternalProtocol(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::TranslateKeyEvent(
|
||||||
|
content::NativeWebKeyboardEvent& result,
|
||||||
|
const CefKeyEvent& key_event) const {
|
||||||
|
native_delegate_->TranslateKeyEvent(result, key_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::TranslateClickEvent(
|
||||||
|
blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
CefBrowserHost::MouseButtonType type,
|
||||||
|
bool mouseUp, int clickCount) const {
|
||||||
|
native_delegate_->TranslateClickEvent(result, mouse_event, type, mouseUp,
|
||||||
|
clickCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::TranslateMoveEvent(
|
||||||
|
blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
bool mouseLeave) const {
|
||||||
|
native_delegate_->TranslateMoveEvent(result, mouse_event, mouseLeave);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::TranslateWheelEvent(
|
||||||
|
blink::WebMouseWheelEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
int deltaX, int deltaY) const {
|
||||||
|
native_delegate_->TranslateWheelEvent(result, mouse_event, deltaX, deltaY);
|
||||||
|
}
|
||||||
|
|
||||||
|
CefEventHandle CefBrowserPlatformDelegateOsr::GetEventHandle(
|
||||||
|
const content::NativeWebKeyboardEvent& event) const {
|
||||||
|
return native_delegate_->GetEventHandle(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<CefFileDialogRunner>
|
||||||
|
CefBrowserPlatformDelegateOsr::CreateFileDialogRunner() {
|
||||||
|
return native_delegate_->CreateFileDialogRunner();
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<CefJavaScriptDialogRunner>
|
||||||
|
CefBrowserPlatformDelegateOsr::CreateJavaScriptDialogRunner() {
|
||||||
|
return native_delegate_->CreateJavaScriptDialogRunner();
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<CefMenuRunner> CefBrowserPlatformDelegateOsr::CreateMenuRunner() {
|
||||||
|
return native_delegate_->CreateMenuRunner();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CefBrowserPlatformDelegateOsr::IsWindowless() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::WasHidden(bool hidden) {
|
||||||
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
|
||||||
|
if (view) {
|
||||||
|
if (hidden)
|
||||||
|
view->Hide();
|
||||||
|
else
|
||||||
|
view->Show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::NotifyScreenInfoChanged() {
|
||||||
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
|
||||||
|
if (view)
|
||||||
|
view->OnScreenInfoChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::Invalidate(cef_paint_element_type_t type) {
|
||||||
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
|
||||||
|
if (view)
|
||||||
|
view->Invalidate(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::SetWindowlessFrameRate(int frame_rate) {
|
||||||
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
|
||||||
|
if (view)
|
||||||
|
view->UpdateFrameRate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::DragTargetDragEnter(
|
||||||
|
CefRefPtr<CefDragData> drag_data,
|
||||||
|
const CefMouseEvent& event,
|
||||||
|
cef_drag_operations_mask_t allowed_ops) {
|
||||||
|
content::RenderViewHost* rvh = browser_->web_contents()->GetRenderViewHost();
|
||||||
|
if (!rvh)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CefDragDataImpl* data_impl = static_cast<CefDragDataImpl*>(drag_data.get());
|
||||||
|
base::AutoLock lock_scope(data_impl->lock());
|
||||||
|
const content::DropData& drop_data = data_impl->drop_data();
|
||||||
|
const gfx::Point client_pt(event.x, event.y);
|
||||||
|
const gfx::Point& screen_pt = GetScreenPoint(client_pt);
|
||||||
|
blink::WebDragOperationsMask ops =
|
||||||
|
static_cast<blink::WebDragOperationsMask>(allowed_ops);
|
||||||
|
int modifiers = TranslateModifiers(event.modifiers);
|
||||||
|
|
||||||
|
rvh->DragTargetDragEnter(drop_data, client_pt, screen_pt, ops, modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::DragTargetDragOver(
|
||||||
|
const CefMouseEvent& event,
|
||||||
|
cef_drag_operations_mask_t allowed_ops) {
|
||||||
|
content::RenderViewHost* rvh = browser_->web_contents()->GetRenderViewHost();
|
||||||
|
if (!rvh)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const gfx::Point client_pt(event.x, event.y);
|
||||||
|
const gfx::Point& screen_pt = GetScreenPoint(client_pt);
|
||||||
|
blink::WebDragOperationsMask ops =
|
||||||
|
static_cast<blink::WebDragOperationsMask>(allowed_ops);
|
||||||
|
int modifiers = TranslateModifiers(event.modifiers);
|
||||||
|
|
||||||
|
rvh->DragTargetDragOver(client_pt, screen_pt, ops, modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::DragTargetDragLeave() {
|
||||||
|
content::RenderViewHost* rvh = browser_->web_contents()->GetRenderViewHost();
|
||||||
|
if (!rvh)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rvh->DragTargetDragLeave();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::DragTargetDrop(const CefMouseEvent& event) {
|
||||||
|
content::RenderViewHost* rvh = browser_->web_contents()->GetRenderViewHost();
|
||||||
|
if (!rvh)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const gfx::Point client_pt(event.x, event.y);
|
||||||
|
const gfx::Point& screen_pt = GetScreenPoint(client_pt);
|
||||||
|
int modifiers = TranslateModifiers(event.modifiers);
|
||||||
|
|
||||||
|
rvh->DragTargetDrop(client_pt, screen_pt, modifiers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::DragSourceEndedAt(
|
||||||
|
int x, int y,
|
||||||
|
cef_drag_operations_mask_t op) {
|
||||||
|
content::RenderViewHost* rvh = browser_->web_contents()->GetRenderViewHost();
|
||||||
|
if (!rvh)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const gfx::Point& screen_pt = GetScreenPoint(gfx::Point(x, y));
|
||||||
|
blink::WebDragOperation drag_op = static_cast<blink::WebDragOperation>(op);
|
||||||
|
|
||||||
|
rvh->DragSourceEndedAt(x, y, screen_pt.x(), screen_pt.y(), drag_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsr::DragSourceSystemDragEnded() {
|
||||||
|
content::RenderViewHost* rvh = browser_->web_contents()->GetRenderViewHost();
|
||||||
|
if (!rvh)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rvh->DragSourceSystemDragEnded();
|
||||||
|
}
|
||||||
|
|
||||||
|
CefWindowHandle CefBrowserPlatformDelegateOsr::GetParentWindowHandle() const {
|
||||||
|
return GetHostWindowHandle();
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::Point CefBrowserPlatformDelegateOsr::GetParentScreenPoint(
|
||||||
|
const gfx::Point& view) const {
|
||||||
|
return GetScreenPoint(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
CefRenderWidgetHostViewOSR*
|
||||||
|
CefBrowserPlatformDelegateOsr::GetOSRHostView() const {
|
||||||
|
content::WebContents* web_contents = browser_->web_contents();
|
||||||
|
CefRenderWidgetHostViewOSR* fs_view =
|
||||||
|
static_cast<CefRenderWidgetHostViewOSR*>(
|
||||||
|
web_contents->GetFullscreenRenderWidgetHostView());
|
||||||
|
if (fs_view)
|
||||||
|
return fs_view;
|
||||||
|
|
||||||
|
content::RenderViewHost* host = web_contents->GetRenderViewHost();
|
||||||
|
if (host) {
|
||||||
|
return static_cast<CefRenderWidgetHostViewOSR*>(
|
||||||
|
host->GetWidget()->GetView());
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
87
libcef/browser/osr/browser_platform_delegate_osr.h
Normal file
87
libcef/browser/osr/browser_platform_delegate_osr.h
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
// Copyright 2015 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_LIBCEF_BROWSER_OSR_BROWSER_PLATFORM_DELEGATE_OSR_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_OSR_BROWSER_PLATFORM_DELEGATE_OSR_H_
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_platform_delegate.h"
|
||||||
|
#include "libcef/browser/native/browser_platform_delegate_native.h"
|
||||||
|
|
||||||
|
class CefRenderWidgetHostViewOSR;
|
||||||
|
class CefWebContentsViewOSR;
|
||||||
|
|
||||||
|
// Base implementation of windowless browser functionality.
|
||||||
|
class CefBrowserPlatformDelegateOsr :
|
||||||
|
public CefBrowserPlatformDelegate,
|
||||||
|
public CefBrowserPlatformDelegateNative::WindowlessHandler {
|
||||||
|
public:
|
||||||
|
// CefBrowserPlatformDelegate methods:
|
||||||
|
void CreateViewForWebContents(
|
||||||
|
content::WebContentsView** view,
|
||||||
|
content::RenderViewHostDelegateView** delegate_view) override;
|
||||||
|
void WebContentsCreated(content::WebContents* web_contents) override;
|
||||||
|
void BrowserCreated(CefBrowserHostImpl* browser) override;
|
||||||
|
void BrowserDestroyed(CefBrowserHostImpl* browser) override;
|
||||||
|
void WasResized() override;
|
||||||
|
void SendKeyEvent(const content::NativeWebKeyboardEvent& event) override;
|
||||||
|
void SendMouseEvent(const blink::WebMouseEvent& event) override;
|
||||||
|
void SendMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;
|
||||||
|
void SendFocusEvent(bool setFocus) override;
|
||||||
|
gfx::Point GetScreenPoint(const gfx::Point& view) const override;
|
||||||
|
void ViewText(const std::string& text) override;
|
||||||
|
void HandleKeyboardEvent(
|
||||||
|
const content::NativeWebKeyboardEvent& event) override;
|
||||||
|
void HandleExternalProtocol(const GURL& url) override;
|
||||||
|
void TranslateKeyEvent(content::NativeWebKeyboardEvent& result,
|
||||||
|
const CefKeyEvent& key_event) const override;
|
||||||
|
void TranslateClickEvent(blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
CefBrowserHost::MouseButtonType type,
|
||||||
|
bool mouseUp, int clickCount) const override;
|
||||||
|
void TranslateMoveEvent(blink::WebMouseEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
bool mouseLeave) const override;
|
||||||
|
void TranslateWheelEvent(blink::WebMouseWheelEvent& result,
|
||||||
|
const CefMouseEvent& mouse_event,
|
||||||
|
int deltaX, int deltaY) const override;
|
||||||
|
CefEventHandle GetEventHandle(
|
||||||
|
const content::NativeWebKeyboardEvent& event) const override;
|
||||||
|
scoped_ptr<CefFileDialogRunner> CreateFileDialogRunner() override;
|
||||||
|
scoped_ptr<CefJavaScriptDialogRunner> CreateJavaScriptDialogRunner() override;
|
||||||
|
scoped_ptr<CefMenuRunner> CreateMenuRunner() override;
|
||||||
|
bool IsWindowless() const override;
|
||||||
|
void WasHidden(bool hidden) override;
|
||||||
|
void NotifyScreenInfoChanged() override;
|
||||||
|
void Invalidate(cef_paint_element_type_t type) override;
|
||||||
|
void SetWindowlessFrameRate(int frame_rate) override;
|
||||||
|
void DragTargetDragEnter(CefRefPtr<CefDragData> drag_data,
|
||||||
|
const CefMouseEvent& event,
|
||||||
|
cef_drag_operations_mask_t allowed_ops) override;
|
||||||
|
void DragTargetDragOver(const CefMouseEvent& event,
|
||||||
|
cef_drag_operations_mask_t allowed_ops) override;
|
||||||
|
void DragTargetDragLeave() override;
|
||||||
|
void DragTargetDrop(const CefMouseEvent& event) override;
|
||||||
|
void DragSourceEndedAt(int x, int y,
|
||||||
|
cef_drag_operations_mask_t op) override;
|
||||||
|
void DragSourceSystemDragEnded() override;
|
||||||
|
|
||||||
|
// CefBrowserPlatformDelegateNative::WindowlessHandler methods:
|
||||||
|
CefWindowHandle GetParentWindowHandle() const override;
|
||||||
|
gfx::Point GetParentScreenPoint(const gfx::Point& view) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Platform-specific behaviors will be delegated to |native_delegate|.
|
||||||
|
explicit CefBrowserPlatformDelegateOsr(
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegateNative> native_delegate);
|
||||||
|
|
||||||
|
// Returns the primary OSR host view for the underlying browser. If a
|
||||||
|
// full-screen host view currently exists then it will be returned. Otherwise,
|
||||||
|
// the main host view will be returned.
|
||||||
|
CefRenderWidgetHostViewOSR* GetOSRHostView() const;
|
||||||
|
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegateNative> native_delegate_;
|
||||||
|
CefWebContentsViewOSR* view_osr_; // Not owned by this class.
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_OSR_BROWSER_PLATFORM_DELEGATE_OSR_H_
|
18
libcef/browser/osr/browser_platform_delegate_osr_linux.cc
Normal file
18
libcef/browser/osr/browser_platform_delegate_osr_linux.cc
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// Copyright 2015 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 "libcef/browser/osr/browser_platform_delegate_osr_linux.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
|
||||||
|
CefBrowserPlatformDelegateOsrLinux::CefBrowserPlatformDelegateOsrLinux(
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegateNative> native_delegate)
|
||||||
|
: CefBrowserPlatformDelegateOsr(native_delegate.Pass()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CefWindowHandle
|
||||||
|
CefBrowserPlatformDelegateOsrLinux::GetHostWindowHandle() const {
|
||||||
|
return native_delegate_->window_info().parent_window;
|
||||||
|
}
|
||||||
|
|
21
libcef/browser/osr/browser_platform_delegate_osr_linux.h
Normal file
21
libcef/browser/osr/browser_platform_delegate_osr_linux.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Copyright 2015 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_LIBCEF_BROWSER_OSR_BROWSER_PLATFORM_DELEGATE_OSR_LINUX_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_OSR_BROWSER_PLATFORM_DELEGATE_OSR_LINUX_H_
|
||||||
|
|
||||||
|
#include "libcef/browser/osr/browser_platform_delegate_osr.h"
|
||||||
|
|
||||||
|
// Windowless browser implementation for Linux.
|
||||||
|
class CefBrowserPlatformDelegateOsrLinux :
|
||||||
|
public CefBrowserPlatformDelegateOsr {
|
||||||
|
public:
|
||||||
|
explicit CefBrowserPlatformDelegateOsrLinux(
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegateNative> native_delegate);
|
||||||
|
|
||||||
|
// CefBrowserPlatformDelegate methods:
|
||||||
|
CefWindowHandle GetHostWindowHandle() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_OSR_LINUX_H_
|
23
libcef/browser/osr/browser_platform_delegate_osr_mac.h
Normal file
23
libcef/browser/osr/browser_platform_delegate_osr_mac.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// Copyright 2015 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_LIBCEF_BROWSER_OSR_BROWSER_PLATFORM_DELEGATE_OSR_MAC_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_OSR_BROWSER_PLATFORM_DELEGATE_OSR_MAC_H_
|
||||||
|
|
||||||
|
#include "libcef/browser/osr/browser_platform_delegate_osr.h"
|
||||||
|
|
||||||
|
// Windowless browser implementation for Mac OS X.
|
||||||
|
class CefBrowserPlatformDelegateOsrMac : public CefBrowserPlatformDelegateOsr {
|
||||||
|
public:
|
||||||
|
explicit CefBrowserPlatformDelegateOsrMac(
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegateNative> native_delegate);
|
||||||
|
|
||||||
|
// CefBrowserPlatformDelegate methods:
|
||||||
|
CefWindowHandle GetHostWindowHandle() const override;
|
||||||
|
CefTextInputContext GetNSTextInputContext() override;
|
||||||
|
void HandleKeyEventBeforeTextInputClient(CefEventHandle keyEvent) override;
|
||||||
|
void HandleKeyEventAfterTextInputClient(CefEventHandle keyEvent) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_OSR_MAC_H_
|
38
libcef/browser/osr/browser_platform_delegate_osr_mac.mm
Normal file
38
libcef/browser/osr/browser_platform_delegate_osr_mac.mm
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
// Copyright 2015 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 "libcef/browser/osr/browser_platform_delegate_osr_mac.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
#include "libcef/browser/osr/render_widget_host_view_osr.h"
|
||||||
|
|
||||||
|
CefBrowserPlatformDelegateOsrMac::CefBrowserPlatformDelegateOsrMac(
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegateNative> native_delegate)
|
||||||
|
: CefBrowserPlatformDelegateOsr(native_delegate.Pass()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CefWindowHandle CefBrowserPlatformDelegateOsrMac::GetHostWindowHandle() const {
|
||||||
|
return native_delegate_->window_info().parent_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
CefTextInputContext CefBrowserPlatformDelegateOsrMac::GetNSTextInputContext() {
|
||||||
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
|
||||||
|
if (view)
|
||||||
|
return view->GetNSTextInputContext();
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsrMac::HandleKeyEventBeforeTextInputClient(
|
||||||
|
CefEventHandle keyEvent) {
|
||||||
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
|
||||||
|
if (view)
|
||||||
|
view->HandleKeyEventBeforeTextInputClient(keyEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefBrowserPlatformDelegateOsrMac::HandleKeyEventAfterTextInputClient(
|
||||||
|
CefEventHandle keyEvent) {
|
||||||
|
CefRenderWidgetHostViewOSR* view = GetOSRHostView();
|
||||||
|
if (view)
|
||||||
|
view->HandleKeyEventAfterTextInputClient(keyEvent);
|
||||||
|
}
|
16
libcef/browser/osr/browser_platform_delegate_osr_win.cc
Normal file
16
libcef/browser/osr/browser_platform_delegate_osr_win.cc
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright 2015 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 "libcef/browser/osr/browser_platform_delegate_osr_win.h"
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
|
||||||
|
CefBrowserPlatformDelegateOsrWin::CefBrowserPlatformDelegateOsrWin(
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegateNative> native_delegate)
|
||||||
|
: CefBrowserPlatformDelegateOsr(native_delegate.Pass()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
CefWindowHandle CefBrowserPlatformDelegateOsrWin::GetHostWindowHandle() const {
|
||||||
|
return native_delegate_->window_info().parent_window;
|
||||||
|
}
|
20
libcef/browser/osr/browser_platform_delegate_osr_win.h
Normal file
20
libcef/browser/osr/browser_platform_delegate_osr_win.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
// Copyright 2015 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_LIBCEF_BROWSER_OSR_BROWSER_PLATFORM_DELEGATE_OSR_WIN_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_OSR_BROWSER_PLATFORM_DELEGATE_OSR_WIN_H_
|
||||||
|
|
||||||
|
#include "libcef/browser/osr/browser_platform_delegate_osr.h"
|
||||||
|
|
||||||
|
// Windowless browser implementation for Windows.
|
||||||
|
class CefBrowserPlatformDelegateOsrWin : public CefBrowserPlatformDelegateOsr {
|
||||||
|
public:
|
||||||
|
explicit CefBrowserPlatformDelegateOsrWin(
|
||||||
|
scoped_ptr<CefBrowserPlatformDelegateNative> native_delegate);
|
||||||
|
|
||||||
|
// CefBrowserPlatformDelegate methods:
|
||||||
|
CefWindowHandle GetHostWindowHandle() const override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_NATIVE_BROWSER_PLATFORM_DELEGATE_OSR_WIN_H_
|
25
libcef/browser/osr/osr_util.cc
Normal file
25
libcef/browser/osr/osr_util.cc
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// Copyright 2015 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 "libcef/browser/osr/osr_util.h"
|
||||||
|
|
||||||
|
namespace osr_util {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// The rate at which new calls to OnPaint will be generated.
|
||||||
|
const int kDefaultFrameRate = 30;
|
||||||
|
const int kMaximumFrameRate = 60;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
int ClampFrameRate(int frame_rate) {
|
||||||
|
if (frame_rate < 1)
|
||||||
|
return kDefaultFrameRate;
|
||||||
|
else if (frame_rate > kMaximumFrameRate)
|
||||||
|
return kMaximumFrameRate;
|
||||||
|
return frame_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace osr_util
|
14
libcef/browser/osr/osr_util.h
Normal file
14
libcef/browser/osr/osr_util.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
// Copyright 2015 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_LIBCEF_BROWSER_OSR_OSR_UTIL_H_
|
||||||
|
#define CEF_LIBCEF_BROWSER_OSR_OSR_UTIL_H_
|
||||||
|
|
||||||
|
namespace osr_util {
|
||||||
|
|
||||||
|
int ClampFrameRate(int frame_rate);
|
||||||
|
|
||||||
|
} // namespace osr_util
|
||||||
|
|
||||||
|
#endif // CEF_LIBCEF_BROWSER_OSR_OSR_UTIL_H_
|
@ -3,9 +3,11 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "libcef/browser/render_widget_host_view_osr.h"
|
#include "libcef/browser/osr/render_widget_host_view_osr.h"
|
||||||
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
#include "libcef/browser/software_output_device_osr.h"
|
#include "libcef/browser/osr/osr_util.h"
|
||||||
|
#include "libcef/browser/osr/software_output_device_osr.h"
|
||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
|
|
||||||
#include "base/callback_helpers.h"
|
#include "base/callback_helpers.h"
|
||||||
@ -34,10 +36,6 @@ namespace {
|
|||||||
|
|
||||||
const float kDefaultScaleFactor = 1.0;
|
const float kDefaultScaleFactor = 1.0;
|
||||||
|
|
||||||
// The rate at which new calls to OnPaint will be generated.
|
|
||||||
const int kDefaultFrameRate = 30;
|
|
||||||
const int kMaximumFrameRate = 60;
|
|
||||||
|
|
||||||
// The maximum number of retry counts if frame capture fails.
|
// The maximum number of retry counts if frame capture fails.
|
||||||
const int kFrameRetryLimit = 2;
|
const int kFrameRetryLimit = 2;
|
||||||
|
|
||||||
@ -437,9 +435,11 @@ class CefBeginFrameTimer : public cc::DelayBasedTimeSourceClient {
|
|||||||
|
|
||||||
|
|
||||||
CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
|
CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
|
||||||
|
bool transparent,
|
||||||
content::RenderWidgetHost* widget,
|
content::RenderWidgetHost* widget,
|
||||||
CefRenderWidgetHostViewOSR* parent_host_view)
|
CefRenderWidgetHostViewOSR* parent_host_view)
|
||||||
: scale_factor_(kDefaultScaleFactor),
|
: transparent_(transparent),
|
||||||
|
scale_factor_(kDefaultScaleFactor),
|
||||||
frame_rate_threshold_ms_(0),
|
frame_rate_threshold_ms_(0),
|
||||||
delegated_frame_host_(new content::DelegatedFrameHost(this)),
|
delegated_frame_host_(new content::DelegatedFrameHost(this)),
|
||||||
compositor_widget_(gfx::kNullAcceleratedWidget),
|
compositor_widget_(gfx::kNullAcceleratedWidget),
|
||||||
@ -767,7 +767,7 @@ void CefRenderWidgetHostViewOSR::UpdateCursor(
|
|||||||
// |web_cursor| owns the resulting |platform_cursor|.
|
// |web_cursor| owns the resulting |platform_cursor|.
|
||||||
platform_cursor = web_cursor.GetPlatformCursor();
|
platform_cursor = web_cursor.GetPlatformCursor();
|
||||||
} else {
|
} else {
|
||||||
platform_cursor = browser_impl_->GetPlatformCursor(cursor_info.type);
|
platform_cursor = GetPlatformCursor(cursor_info.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
handler->OnCursorChange(browser_impl_.get(), platform_cursor, cursor_type,
|
handler->OnCursorChange(browser_impl_.get(), platform_cursor, cursor_type,
|
||||||
@ -1003,8 +1003,7 @@ CefRenderWidgetHostViewOSR::CreateSoftwareOutputDevice(
|
|||||||
DCHECK(!copy_frame_generator_);
|
DCHECK(!copy_frame_generator_);
|
||||||
DCHECK(!software_output_device_);
|
DCHECK(!software_output_device_);
|
||||||
software_output_device_ = new CefSoftwareOutputDeviceOSR(
|
software_output_device_ = new CefSoftwareOutputDeviceOSR(
|
||||||
compositor,
|
compositor, transparent_,
|
||||||
browser_impl_.get() ? browser_impl_->IsTransparent() : false,
|
|
||||||
base::Bind(&CefRenderWidgetHostViewOSR::OnPaint,
|
base::Bind(&CefRenderWidgetHostViewOSR::OnPaint,
|
||||||
weak_ptr_factory_.GetWeakPtr()));
|
weak_ptr_factory_.GetWeakPtr()));
|
||||||
return make_scoped_ptr<cc::SoftwareOutputDevice>(software_output_device_);
|
return make_scoped_ptr<cc::SoftwareOutputDevice>(software_output_device_);
|
||||||
@ -1070,7 +1069,7 @@ void CefRenderWidgetHostViewOSR::DelegatedFrameHostUpdateVSyncParameters(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CefRenderWidgetHostViewOSR::InstallTransparency() {
|
bool CefRenderWidgetHostViewOSR::InstallTransparency() {
|
||||||
if (browser_impl_.get() && browser_impl_->IsTransparent()) {
|
if (transparent_) {
|
||||||
SetBackgroundColor(SkColorSetARGB(SK_AlphaTRANSPARENT, 0, 0, 0));
|
SetBackgroundColor(SkColorSetARGB(SK_AlphaTRANSPARENT, 0, 0, 0));
|
||||||
compositor_->SetHostHasTransparentBackground(true);
|
compositor_->SetHostHasTransparentBackground(true);
|
||||||
return true;
|
return true;
|
||||||
@ -1284,15 +1283,6 @@ void CefRenderWidgetHostViewOSR::RemoveGuestHostView(
|
|||||||
guest_host_views_.erase(guest_host);
|
guest_host_views_.erase(guest_host);
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
|
||||||
int CefRenderWidgetHostViewOSR::ClampFrameRate(int frame_rate) {
|
|
||||||
if (frame_rate < 1)
|
|
||||||
return kDefaultFrameRate;
|
|
||||||
else if (frame_rate > kMaximumFrameRate)
|
|
||||||
return kMaximumFrameRate;
|
|
||||||
return frame_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::SetFrameRate() {
|
void CefRenderWidgetHostViewOSR::SetFrameRate() {
|
||||||
CefRefPtr<CefBrowserHostImpl> browser;
|
CefRefPtr<CefBrowserHostImpl> browser;
|
||||||
if (parent_host_view_) {
|
if (parent_host_view_) {
|
||||||
@ -1308,7 +1298,7 @@ void CefRenderWidgetHostViewOSR::SetFrameRate() {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
const int frame_rate =
|
const int frame_rate =
|
||||||
ClampFrameRate(browser->settings().windowless_frame_rate);
|
osr_util::ClampFrameRate(browser->settings().windowless_frame_rate);
|
||||||
frame_rate_threshold_ms_ = 1000 / frame_rate;
|
frame_rate_threshold_ms_ = 1000 / frame_rate;
|
||||||
|
|
||||||
// Configure the VSync interval for the browser process.
|
// Configure the VSync interval for the browser process.
|
@ -3,8 +3,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_BROWSER_RENDER_WIDGET_HOST_VIEW_OSR_H_
|
#ifndef CEF_LIBCEF_BROWSER_OSR_RENDER_WIDGET_HOST_VIEW_OSR_H_
|
||||||
#define CEF_LIBCEF_BROWSER_RENDER_WIDGET_HOST_VIEW_OSR_H_
|
#define CEF_LIBCEF_BROWSER_OSR_RENDER_WIDGET_HOST_VIEW_OSR_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
@ -18,6 +18,10 @@
|
|||||||
#include "content/browser/renderer_host/render_widget_host_view_base.h"
|
#include "content/browser/renderer_host/render_widget_host_view_base.h"
|
||||||
#include "ui/compositor/compositor.h"
|
#include "ui/compositor/compositor.h"
|
||||||
|
|
||||||
|
#if defined(OS_LINUX)
|
||||||
|
#include "ui/base/x/x11_util.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(OS_MACOSX)
|
#if defined(OS_MACOSX)
|
||||||
#include "content/browser/compositor/browser_compositor_view_mac.h"
|
#include "content/browser/compositor/browser_compositor_view_mac.h"
|
||||||
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
|
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
|
||||||
@ -79,7 +83,8 @@ class CefRenderWidgetHostViewOSR
|
|||||||
public ui::CompositorDelegate,
|
public ui::CompositorDelegate,
|
||||||
public content::DelegatedFrameHostClient {
|
public content::DelegatedFrameHostClient {
|
||||||
public:
|
public:
|
||||||
CefRenderWidgetHostViewOSR(content::RenderWidgetHost* widget,
|
CefRenderWidgetHostViewOSR(const bool transparent,
|
||||||
|
content::RenderWidgetHost* widget,
|
||||||
CefRenderWidgetHostViewOSR* parent_host_view);
|
CefRenderWidgetHostViewOSR* parent_host_view);
|
||||||
~CefRenderWidgetHostViewOSR() override;
|
~CefRenderWidgetHostViewOSR() override;
|
||||||
|
|
||||||
@ -284,8 +289,6 @@ class CefRenderWidgetHostViewOSR
|
|||||||
content::RenderWidgetHostImpl* render_widget_host() const
|
content::RenderWidgetHostImpl* render_widget_host() const
|
||||||
{ return render_widget_host_; }
|
{ return render_widget_host_; }
|
||||||
|
|
||||||
static int ClampFrameRate(int frame_rate);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetFrameRate();
|
void SetFrameRate();
|
||||||
void SetDeviceScaleFactor();
|
void SetDeviceScaleFactor();
|
||||||
@ -328,6 +331,12 @@ class CefRenderWidgetHostViewOSR
|
|||||||
void PlatformCreateCompositorWidget();
|
void PlatformCreateCompositorWidget();
|
||||||
void PlatformDestroyCompositorWidget();
|
void PlatformDestroyCompositorWidget();
|
||||||
|
|
||||||
|
#if defined(USE_AURA)
|
||||||
|
ui::PlatformCursor GetPlatformCursor(blink::WebCursorInfo::Type type);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const bool transparent_;
|
||||||
|
|
||||||
float scale_factor_;
|
float scale_factor_;
|
||||||
int frame_rate_threshold_ms_;
|
int frame_rate_threshold_ms_;
|
||||||
|
|
||||||
@ -344,6 +353,7 @@ class CefRenderWidgetHostViewOSR
|
|||||||
scoped_ptr<content::BrowserCompositorMac> browser_compositor_;
|
scoped_ptr<content::BrowserCompositorMac> browser_compositor_;
|
||||||
#elif defined(USE_X11)
|
#elif defined(USE_X11)
|
||||||
CefWindowX11* window_;
|
CefWindowX11* window_;
|
||||||
|
scoped_ptr<ui::XScopedCursor> invisible_cursor_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Used to control the VSync rate in subprocesses when BeginFrame scheduling
|
// Used to control the VSync rate in subprocesses when BeginFrame scheduling
|
||||||
@ -403,5 +413,5 @@ class CefRenderWidgetHostViewOSR
|
|||||||
DISALLOW_COPY_AND_ASSIGN(CefRenderWidgetHostViewOSR);
|
DISALLOW_COPY_AND_ASSIGN(CefRenderWidgetHostViewOSR);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_RENDER_WIDGET_HOST_VIEW_OSR_H_
|
#endif // CEF_LIBCEF_BROWSER_OSR_RENDER_WIDGET_HOST_VIEW_OSR_H_
|
||||||
|
|
144
libcef/browser/osr/render_widget_host_view_osr_linux.cc
Normal file
144
libcef/browser/osr/render_widget_host_view_osr_linux.cc
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
// Copyright (c) 2014 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2012 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 "libcef/browser/osr/render_widget_host_view_osr.h"
|
||||||
|
|
||||||
|
#include <X11/cursorfont.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
#include "libcef/browser/native/window_x11.h"
|
||||||
|
|
||||||
|
#include "third_party/WebKit/public/platform/WebCursorInfo.h"
|
||||||
|
#include "ui/base/x/x11_util.h"
|
||||||
|
#include "ui/gfx/x/x11_types.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// Based on ui/base/cursor/cursor_loader_x11.cc.
|
||||||
|
|
||||||
|
using blink::WebCursorInfo;
|
||||||
|
|
||||||
|
int ToCursorID(WebCursorInfo::Type type) {
|
||||||
|
switch (type) {
|
||||||
|
case WebCursorInfo::TypePointer:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeCross:
|
||||||
|
return XC_crosshair;
|
||||||
|
case WebCursorInfo::TypeHand:
|
||||||
|
return XC_hand2;
|
||||||
|
case WebCursorInfo::TypeIBeam:
|
||||||
|
return XC_xterm;
|
||||||
|
case WebCursorInfo::TypeWait:
|
||||||
|
return XC_watch;
|
||||||
|
case WebCursorInfo::TypeHelp:
|
||||||
|
return XC_question_arrow;
|
||||||
|
case WebCursorInfo::TypeEastResize:
|
||||||
|
return XC_right_side;
|
||||||
|
case WebCursorInfo::TypeNorthResize:
|
||||||
|
return XC_top_side;
|
||||||
|
case WebCursorInfo::TypeNorthEastResize:
|
||||||
|
return XC_top_right_corner;
|
||||||
|
case WebCursorInfo::TypeNorthWestResize:
|
||||||
|
return XC_top_left_corner;
|
||||||
|
case WebCursorInfo::TypeSouthResize:
|
||||||
|
return XC_bottom_side;
|
||||||
|
case WebCursorInfo::TypeSouthEastResize:
|
||||||
|
return XC_bottom_right_corner;
|
||||||
|
case WebCursorInfo::TypeSouthWestResize:
|
||||||
|
return XC_bottom_left_corner;
|
||||||
|
case WebCursorInfo::TypeWestResize:
|
||||||
|
return XC_left_side;
|
||||||
|
case WebCursorInfo::TypeNorthSouthResize:
|
||||||
|
return XC_sb_v_double_arrow;
|
||||||
|
case WebCursorInfo::TypeEastWestResize:
|
||||||
|
return XC_sb_h_double_arrow;
|
||||||
|
case WebCursorInfo::TypeNorthEastSouthWestResize:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeNorthWestSouthEastResize:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeColumnResize:
|
||||||
|
return XC_sb_h_double_arrow;
|
||||||
|
case WebCursorInfo::TypeRowResize:
|
||||||
|
return XC_sb_v_double_arrow;
|
||||||
|
case WebCursorInfo::TypeMiddlePanning:
|
||||||
|
return XC_fleur;
|
||||||
|
case WebCursorInfo::TypeEastPanning:
|
||||||
|
return XC_sb_right_arrow;
|
||||||
|
case WebCursorInfo::TypeNorthPanning:
|
||||||
|
return XC_sb_up_arrow;
|
||||||
|
case WebCursorInfo::TypeNorthEastPanning:
|
||||||
|
return XC_top_right_corner;
|
||||||
|
case WebCursorInfo::TypeNorthWestPanning:
|
||||||
|
return XC_top_left_corner;
|
||||||
|
case WebCursorInfo::TypeSouthPanning:
|
||||||
|
return XC_sb_down_arrow;
|
||||||
|
case WebCursorInfo::TypeSouthEastPanning:
|
||||||
|
return XC_bottom_right_corner;
|
||||||
|
case WebCursorInfo::TypeSouthWestPanning:
|
||||||
|
return XC_bottom_left_corner;
|
||||||
|
case WebCursorInfo::TypeWestPanning:
|
||||||
|
return XC_sb_left_arrow;
|
||||||
|
case WebCursorInfo::TypeMove:
|
||||||
|
return XC_fleur;
|
||||||
|
case WebCursorInfo::TypeVerticalText:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeCell:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeContextMenu:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeAlias:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeProgress:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeNoDrop:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeCopy:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeNotAllowed:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeZoomIn:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeZoomOut:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeGrab:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeGrabbing:
|
||||||
|
return XC_left_ptr;
|
||||||
|
case WebCursorInfo::TypeCustom:
|
||||||
|
case WebCursorInfo::TypeNone:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
NOTREACHED();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void CefRenderWidgetHostViewOSR::PlatformCreateCompositorWidget() {
|
||||||
|
// Create a hidden 1x1 window. It will delete itself on close.
|
||||||
|
window_ = new CefWindowX11(NULL, None, gfx::Rect(0, 0, 1, 1));
|
||||||
|
compositor_widget_ = window_->xwindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefRenderWidgetHostViewOSR::PlatformDestroyCompositorWidget() {
|
||||||
|
DCHECK(window_);
|
||||||
|
window_->Close();
|
||||||
|
compositor_widget_ = gfx::kNullAcceleratedWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui::PlatformCursor CefRenderWidgetHostViewOSR::GetPlatformCursor(
|
||||||
|
blink::WebCursorInfo::Type type) {
|
||||||
|
if (type == WebCursorInfo::TypeNone) {
|
||||||
|
if (!invisible_cursor_) {
|
||||||
|
invisible_cursor_.reset(
|
||||||
|
new ui::XScopedCursor(ui::CreateInvisibleCursor(),
|
||||||
|
gfx::GetXDisplay()));
|
||||||
|
}
|
||||||
|
return invisible_cursor_->get();
|
||||||
|
} else {
|
||||||
|
return ui::GetXCursor(ToCursorID(type));
|
||||||
|
}
|
||||||
|
}
|
@ -3,12 +3,12 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "libcef/browser/render_widget_host_view_osr.h"
|
#include "libcef/browser/osr/render_widget_host_view_osr.h"
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
#include "libcef/browser/text_input_client_osr_mac.h"
|
#include "libcef/browser/osr/text_input_client_osr_mac.h"
|
||||||
|
|
||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
182
libcef/browser/osr/render_widget_host_view_osr_win.cc
Normal file
182
libcef/browser/osr/render_widget_host_view_osr_win.cc
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
// Copyright (c) 2014 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2012 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 "libcef/browser/osr/render_widget_host_view_osr.h"
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
#include "libcef/browser/content_browser_client.h"
|
||||||
|
|
||||||
|
#include "grit/ui_unscaled_resources.h"
|
||||||
|
#include "third_party/WebKit/public/platform/WebCursorInfo.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class CefCompositorHostWin : public gfx::WindowImpl {
|
||||||
|
public:
|
||||||
|
CefCompositorHostWin() {
|
||||||
|
// Create a hidden 1x1 borderless window.
|
||||||
|
set_window_style(WS_POPUP | WS_SYSMENU);
|
||||||
|
Init(NULL, gfx::Rect(0, 0, 1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
~CefCompositorHostWin() override {
|
||||||
|
DestroyWindow(hwnd());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CR_BEGIN_MSG_MAP_EX(CompositorHostWin)
|
||||||
|
CR_MSG_WM_PAINT(OnPaint)
|
||||||
|
CR_END_MSG_MAP()
|
||||||
|
|
||||||
|
void OnPaint(HDC dc) {
|
||||||
|
ValidateRect(hwnd(), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CefCompositorHostWin);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// From content/common/cursors/webcursor_win.cc.
|
||||||
|
|
||||||
|
using blink::WebCursorInfo;
|
||||||
|
|
||||||
|
LPCWSTR ToCursorID(WebCursorInfo::Type type) {
|
||||||
|
switch (type) {
|
||||||
|
case WebCursorInfo::TypePointer:
|
||||||
|
return IDC_ARROW;
|
||||||
|
case WebCursorInfo::TypeCross:
|
||||||
|
return IDC_CROSS;
|
||||||
|
case WebCursorInfo::TypeHand:
|
||||||
|
return IDC_HAND;
|
||||||
|
case WebCursorInfo::TypeIBeam:
|
||||||
|
return IDC_IBEAM;
|
||||||
|
case WebCursorInfo::TypeWait:
|
||||||
|
return IDC_WAIT;
|
||||||
|
case WebCursorInfo::TypeHelp:
|
||||||
|
return IDC_HELP;
|
||||||
|
case WebCursorInfo::TypeEastResize:
|
||||||
|
return IDC_SIZEWE;
|
||||||
|
case WebCursorInfo::TypeNorthResize:
|
||||||
|
return IDC_SIZENS;
|
||||||
|
case WebCursorInfo::TypeNorthEastResize:
|
||||||
|
return IDC_SIZENESW;
|
||||||
|
case WebCursorInfo::TypeNorthWestResize:
|
||||||
|
return IDC_SIZENWSE;
|
||||||
|
case WebCursorInfo::TypeSouthResize:
|
||||||
|
return IDC_SIZENS;
|
||||||
|
case WebCursorInfo::TypeSouthEastResize:
|
||||||
|
return IDC_SIZENWSE;
|
||||||
|
case WebCursorInfo::TypeSouthWestResize:
|
||||||
|
return IDC_SIZENESW;
|
||||||
|
case WebCursorInfo::TypeWestResize:
|
||||||
|
return IDC_SIZEWE;
|
||||||
|
case WebCursorInfo::TypeNorthSouthResize:
|
||||||
|
return IDC_SIZENS;
|
||||||
|
case WebCursorInfo::TypeEastWestResize:
|
||||||
|
return IDC_SIZEWE;
|
||||||
|
case WebCursorInfo::TypeNorthEastSouthWestResize:
|
||||||
|
return IDC_SIZENESW;
|
||||||
|
case WebCursorInfo::TypeNorthWestSouthEastResize:
|
||||||
|
return IDC_SIZENWSE;
|
||||||
|
case WebCursorInfo::TypeColumnResize:
|
||||||
|
return MAKEINTRESOURCE(IDC_COLRESIZE);
|
||||||
|
case WebCursorInfo::TypeRowResize:
|
||||||
|
return MAKEINTRESOURCE(IDC_ROWRESIZE);
|
||||||
|
case WebCursorInfo::TypeMiddlePanning:
|
||||||
|
return MAKEINTRESOURCE(IDC_PAN_MIDDLE);
|
||||||
|
case WebCursorInfo::TypeEastPanning:
|
||||||
|
return MAKEINTRESOURCE(IDC_PAN_EAST);
|
||||||
|
case WebCursorInfo::TypeNorthPanning:
|
||||||
|
return MAKEINTRESOURCE(IDC_PAN_NORTH);
|
||||||
|
case WebCursorInfo::TypeNorthEastPanning:
|
||||||
|
return MAKEINTRESOURCE(IDC_PAN_NORTH_EAST);
|
||||||
|
case WebCursorInfo::TypeNorthWestPanning:
|
||||||
|
return MAKEINTRESOURCE(IDC_PAN_NORTH_WEST);
|
||||||
|
case WebCursorInfo::TypeSouthPanning:
|
||||||
|
return MAKEINTRESOURCE(IDC_PAN_SOUTH);
|
||||||
|
case WebCursorInfo::TypeSouthEastPanning:
|
||||||
|
return MAKEINTRESOURCE(IDC_PAN_SOUTH_EAST);
|
||||||
|
case WebCursorInfo::TypeSouthWestPanning:
|
||||||
|
return MAKEINTRESOURCE(IDC_PAN_SOUTH_WEST);
|
||||||
|
case WebCursorInfo::TypeWestPanning:
|
||||||
|
return MAKEINTRESOURCE(IDC_PAN_WEST);
|
||||||
|
case WebCursorInfo::TypeMove:
|
||||||
|
return IDC_SIZEALL;
|
||||||
|
case WebCursorInfo::TypeVerticalText:
|
||||||
|
return MAKEINTRESOURCE(IDC_VERTICALTEXT);
|
||||||
|
case WebCursorInfo::TypeCell:
|
||||||
|
return MAKEINTRESOURCE(IDC_CELL);
|
||||||
|
case WebCursorInfo::TypeContextMenu:
|
||||||
|
return IDC_ARROW;
|
||||||
|
case WebCursorInfo::TypeAlias:
|
||||||
|
return MAKEINTRESOURCE(IDC_ALIAS);
|
||||||
|
case WebCursorInfo::TypeProgress:
|
||||||
|
return IDC_APPSTARTING;
|
||||||
|
case WebCursorInfo::TypeNoDrop:
|
||||||
|
return IDC_NO;
|
||||||
|
case WebCursorInfo::TypeCopy:
|
||||||
|
return MAKEINTRESOURCE(IDC_COPYCUR);
|
||||||
|
case WebCursorInfo::TypeNone:
|
||||||
|
return MAKEINTRESOURCE(IDC_CURSOR_NONE);
|
||||||
|
case WebCursorInfo::TypeNotAllowed:
|
||||||
|
return IDC_NO;
|
||||||
|
case WebCursorInfo::TypeZoomIn:
|
||||||
|
return MAKEINTRESOURCE(IDC_ZOOMIN);
|
||||||
|
case WebCursorInfo::TypeZoomOut:
|
||||||
|
return MAKEINTRESOURCE(IDC_ZOOMOUT);
|
||||||
|
case WebCursorInfo::TypeGrab:
|
||||||
|
return MAKEINTRESOURCE(IDC_HAND_GRAB);
|
||||||
|
case WebCursorInfo::TypeGrabbing:
|
||||||
|
return MAKEINTRESOURCE(IDC_HAND_GRABBING);
|
||||||
|
}
|
||||||
|
NOTREACHED();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsSystemCursorID(LPCWSTR cursor_id) {
|
||||||
|
return cursor_id >= IDC_ARROW; // See WinUser.h
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void CefRenderWidgetHostViewOSR::SetParentNativeViewAccessible(
|
||||||
|
gfx::NativeViewAccessible accessible_parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
gfx::NativeViewId
|
||||||
|
CefRenderWidgetHostViewOSR::GetParentForWindowlessPlugin() const {
|
||||||
|
if (browser_impl_.get()) {
|
||||||
|
return reinterpret_cast<gfx::NativeViewId>(
|
||||||
|
browser_impl_->GetWindowHandle());
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefRenderWidgetHostViewOSR::PlatformCreateCompositorWidget() {
|
||||||
|
DCHECK(!window_);
|
||||||
|
window_.reset(new CefCompositorHostWin());
|
||||||
|
compositor_widget_ = window_->hwnd();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefRenderWidgetHostViewOSR::PlatformDestroyCompositorWidget() {
|
||||||
|
window_.reset(NULL);
|
||||||
|
compositor_widget_ = gfx::kNullAcceleratedWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui::PlatformCursor CefRenderWidgetHostViewOSR::GetPlatformCursor(
|
||||||
|
blink::WebCursorInfo::Type type) {
|
||||||
|
HMODULE module_handle = NULL;
|
||||||
|
const wchar_t* cursor_id = ToCursorID(type);
|
||||||
|
if (!IsSystemCursorID(cursor_id)) {
|
||||||
|
module_handle = ::GetModuleHandle(
|
||||||
|
CefContentBrowserClient::Get()->GetResourceDllName());
|
||||||
|
if (!module_handle)
|
||||||
|
module_handle = ::GetModuleHandle(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return LoadCursor(module_handle, cursor_id);
|
||||||
|
}
|
@ -3,10 +3,10 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "libcef/browser/software_output_device_osr.h"
|
#include "libcef/browser/osr/software_output_device_osr.h"
|
||||||
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
#include "libcef/browser/render_widget_host_view_osr.h"
|
#include "libcef/browser/osr/render_widget_host_view_osr.h"
|
||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
|
|
||||||
#include "third_party/skia/include/core/SkDevice.h"
|
#include "third_party/skia/include/core/SkDevice.h"
|
@ -3,8 +3,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_BROWSER_SOFTWARE_OUTPUT_DEVICE_OSR_H_
|
#ifndef CEF_LIBCEF_BROWSER_OSR_SOFTWARE_OUTPUT_DEVICE_OSR_H_
|
||||||
#define CEF_LIBCEF_BROWSER_SOFTWARE_OUTPUT_DEVICE_OSR_H_
|
#define CEF_LIBCEF_BROWSER_OSR_SOFTWARE_OUTPUT_DEVICE_OSR_H_
|
||||||
|
|
||||||
#include "base/callback.h"
|
#include "base/callback.h"
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "base/memory/scoped_ptr.h"
|
||||||
@ -52,4 +52,4 @@ class CefSoftwareOutputDeviceOSR : public cc::SoftwareOutputDevice {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(CefSoftwareOutputDeviceOSR);
|
DISALLOW_COPY_AND_ASSIGN(CefSoftwareOutputDeviceOSR);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_SOFTWARE_OUTPUT_DEVICE_OSR_H_
|
#endif // CEF_LIBCEF_BROWSER_OSR_SOFTWARE_OUTPUT_DEVICE_OSR_H_
|
@ -2,14 +2,14 @@
|
|||||||
// reserved. Use of this source code is governed by a BSD-style license that
|
// reserved. Use of this source code is governed by a BSD-style license that
|
||||||
// can be found in the LICENSE file.
|
// can be found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_BROWSER_TEXT_INPUT_CLIENT_OSR_MAC_H_
|
#ifndef CEF_LIBCEF_BROWSER_OSR_TEXT_INPUT_CLIENT_OSR_MAC_H_
|
||||||
#define CEF_LIBCEF_BROWSER_TEXT_INPUT_CLIENT_OSR_MAC_H_
|
#define CEF_LIBCEF_BROWSER_OSR_TEXT_INPUT_CLIENT_OSR_MAC_H_
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "libcef/browser/render_widget_host_view_osr.h"
|
#include "libcef/browser/osr/render_widget_host_view_osr.h"
|
||||||
|
|
||||||
#include "base/mac/scoped_nsobject.h"
|
#include "base/mac/scoped_nsobject.h"
|
||||||
#include "base/strings/string16.h"
|
#include "base/strings/string16.h"
|
||||||
@ -73,4 +73,4 @@
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_TEXT_INPUT_CLIENT_OSR_MAC_H_
|
#endif // CEF_LIBCEF_BROWSER_OSR_TEXT_INPUT_CLIENT_OSR_MAC_H_
|
@ -2,7 +2,8 @@
|
|||||||
// reserved. Use of this source code is governed by a BSD-style license that
|
// reserved. Use of this source code is governed by a BSD-style license that
|
||||||
// can be found in the LICENSE file.
|
// can be found in the LICENSE file.
|
||||||
|
|
||||||
#include "libcef/browser/text_input_client_osr_mac.h"
|
#include "libcef/browser/osr/text_input_client_osr_mac.h"
|
||||||
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
|
|
||||||
#include "base/numerics/safe_conversions.h"
|
#include "base/numerics/safe_conversions.h"
|
@ -3,9 +3,10 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "libcef/browser/web_contents_view_osr.h"
|
#include "libcef/browser/osr/web_contents_view_osr.h"
|
||||||
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
#include "libcef/browser/browser_host_impl.h"
|
||||||
#include "libcef/browser/render_widget_host_view_osr.h"
|
#include "libcef/browser/osr/render_widget_host_view_osr.h"
|
||||||
#include "libcef/common/drag_data_impl.h"
|
#include "libcef/common/drag_data_impl.h"
|
||||||
|
|
||||||
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
|
#include "content/browser/browser_plugin/browser_plugin_embedder.h"
|
||||||
@ -15,8 +16,9 @@
|
|||||||
#include "content/public/browser/render_widget_host.h"
|
#include "content/public/browser/render_widget_host.h"
|
||||||
#include "content/public/browser/user_metrics.h"
|
#include "content/public/browser/user_metrics.h"
|
||||||
|
|
||||||
CefWebContentsViewOSR::CefWebContentsViewOSR()
|
CefWebContentsViewOSR::CefWebContentsViewOSR(bool transparent)
|
||||||
: web_contents_(NULL),
|
: transparent_(transparent),
|
||||||
|
web_contents_(NULL),
|
||||||
view_(NULL),
|
view_(NULL),
|
||||||
guest_(NULL) {
|
guest_(NULL) {
|
||||||
}
|
}
|
||||||
@ -126,7 +128,8 @@ content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget(
|
|||||||
embedder_web_contents->GetRenderViewHost()->GetWidget()->GetView());
|
embedder_web_contents->GetRenderViewHost()->GetWidget()->GetView());
|
||||||
|
|
||||||
CefRenderWidgetHostViewOSR* platform_widget =
|
CefRenderWidgetHostViewOSR* platform_widget =
|
||||||
new CefRenderWidgetHostViewOSR(render_widget_host, embedder_host_view);
|
new CefRenderWidgetHostViewOSR(transparent_, render_widget_host,
|
||||||
|
embedder_host_view);
|
||||||
embedder_host_view->AddGuestHostView(platform_widget);
|
embedder_host_view->AddGuestHostView(platform_widget);
|
||||||
|
|
||||||
return new content::RenderWidgetHostViewGuest(
|
return new content::RenderWidgetHostViewGuest(
|
||||||
@ -135,7 +138,8 @@ content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget(
|
|||||||
platform_widget->GetWeakPtr());
|
platform_widget->GetWeakPtr());
|
||||||
}
|
}
|
||||||
|
|
||||||
view_ = new CefRenderWidgetHostViewOSR(render_widget_host, NULL);
|
view_ = new CefRenderWidgetHostViewOSR(transparent_, render_widget_host,
|
||||||
|
NULL);
|
||||||
return view_;
|
return view_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +147,8 @@ content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget(
|
|||||||
content::RenderWidgetHostViewBase*
|
content::RenderWidgetHostViewBase*
|
||||||
CefWebContentsViewOSR::CreateViewForPopupWidget(
|
CefWebContentsViewOSR::CreateViewForPopupWidget(
|
||||||
content::RenderWidgetHost* render_widget_host) {
|
content::RenderWidgetHost* render_widget_host) {
|
||||||
return new CefRenderWidgetHostViewOSR(render_widget_host, view_);
|
return new CefRenderWidgetHostViewOSR(transparent_, render_widget_host,
|
||||||
|
view_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CefWebContentsViewOSR::SetPageTitle(const base::string16& title) {
|
void CefWebContentsViewOSR::SetPageTitle(const base::string16& title) {
|
@ -3,8 +3,8 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#ifndef CEF_LIBCEF_BROWSER_WEB_CONTENTS_VIEW_OSR_H_
|
#ifndef CEF_LIBCEF_BROWSER_OSR_WEB_CONTENTS_VIEW_OSR_H_
|
||||||
#define CEF_LIBCEF_BROWSER_WEB_CONTENTS_VIEW_OSR_H_
|
#define CEF_LIBCEF_BROWSER_OSR_WEB_CONTENTS_VIEW_OSR_H_
|
||||||
|
|
||||||
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
|
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
|
||||||
#include "content/browser/web_contents/web_contents_view.h"
|
#include "content/browser/web_contents/web_contents_view.h"
|
||||||
@ -21,10 +21,11 @@ class CefRenderWidgetHostViewOSR;
|
|||||||
class CefWebContentsViewOSR : public content::WebContentsView,
|
class CefWebContentsViewOSR : public content::WebContentsView,
|
||||||
public content::RenderViewHostDelegateView {
|
public content::RenderViewHostDelegateView {
|
||||||
public:
|
public:
|
||||||
CefWebContentsViewOSR();
|
explicit CefWebContentsViewOSR(bool transparent);
|
||||||
~CefWebContentsViewOSR() override;
|
~CefWebContentsViewOSR() override;
|
||||||
|
|
||||||
void set_web_contents(content::WebContents* web_contents);
|
void set_web_contents(content::WebContents* web_contents);
|
||||||
|
content::WebContents* web_contents() const { return web_contents_; }
|
||||||
void set_guest(content::BrowserPluginGuest* guest);
|
void set_guest(content::BrowserPluginGuest* guest);
|
||||||
|
|
||||||
// WebContentsView methods.
|
// WebContentsView methods.
|
||||||
@ -68,6 +69,8 @@ class CefWebContentsViewOSR : public content::WebContentsView,
|
|||||||
void UpdateDragCursor(blink::WebDragOperation operation) override;
|
void UpdateDragCursor(blink::WebDragOperation operation) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const bool transparent_;
|
||||||
|
|
||||||
content::WebContents* web_contents_;
|
content::WebContents* web_contents_;
|
||||||
CefRenderWidgetHostViewOSR* view_;
|
CefRenderWidgetHostViewOSR* view_;
|
||||||
|
|
||||||
@ -77,4 +80,4 @@ class CefWebContentsViewOSR : public content::WebContentsView,
|
|||||||
DISALLOW_COPY_AND_ASSIGN(CefWebContentsViewOSR);
|
DISALLOW_COPY_AND_ASSIGN(CefWebContentsViewOSR);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_WEB_CONTENTS_VIEW_OSR_H_
|
#endif // CEF_LIBCEF_BROWSER_OSR_WEB_CONTENTS_VIEW_OSR_H_
|
@ -1,25 +0,0 @@
|
|||||||
// Copyright (c) 2014 The Chromium Embedded Framework Authors.
|
|
||||||
// Portions copyright (c) 2012 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 "libcef/browser/render_widget_host_view_osr.h"
|
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
|
||||||
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
|
||||||
#include "libcef/browser/window_x11.h"
|
|
||||||
|
|
||||||
#include "ui/gfx/x/x11_types.h"
|
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::PlatformCreateCompositorWidget() {
|
|
||||||
// Create a hidden 1x1 window. It will delete itself on close.
|
|
||||||
window_ = new CefWindowX11(NULL, None, gfx::Rect(0, 0, 1, 1));
|
|
||||||
compositor_widget_ = window_->xwindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::PlatformDestroyCompositorWidget() {
|
|
||||||
DCHECK(window_);
|
|
||||||
window_->Close();
|
|
||||||
compositor_widget_ = gfx::kNullAcceleratedWidget;
|
|
||||||
}
|
|
@ -1,59 +0,0 @@
|
|||||||
// Copyright (c) 2014 The Chromium Embedded Framework Authors.
|
|
||||||
// Portions copyright (c) 2012 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 "libcef/browser/render_widget_host_view_osr.h"
|
|
||||||
#include "libcef/browser/browser_host_impl.h"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class CefCompositorHostWin : public gfx::WindowImpl {
|
|
||||||
public:
|
|
||||||
CefCompositorHostWin() {
|
|
||||||
// Create a hidden 1x1 borderless window.
|
|
||||||
set_window_style(WS_POPUP | WS_SYSMENU);
|
|
||||||
Init(NULL, gfx::Rect(0, 0, 1, 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
~CefCompositorHostWin() override {
|
|
||||||
DestroyWindow(hwnd());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
CR_BEGIN_MSG_MAP_EX(CompositorHostWin)
|
|
||||||
CR_MSG_WM_PAINT(OnPaint)
|
|
||||||
CR_END_MSG_MAP()
|
|
||||||
|
|
||||||
void OnPaint(HDC dc) {
|
|
||||||
ValidateRect(hwnd(), NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(CefCompositorHostWin);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::SetParentNativeViewAccessible(
|
|
||||||
gfx::NativeViewAccessible accessible_parent) {
|
|
||||||
}
|
|
||||||
|
|
||||||
gfx::NativeViewId
|
|
||||||
CefRenderWidgetHostViewOSR::GetParentForWindowlessPlugin() const {
|
|
||||||
if (browser_impl_.get()) {
|
|
||||||
return reinterpret_cast<gfx::NativeViewId>(
|
|
||||||
browser_impl_->GetWindowHandle());
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::PlatformCreateCompositorWidget() {
|
|
||||||
DCHECK(!window_);
|
|
||||||
window_.reset(new CefCompositorHostWin());
|
|
||||||
compositor_widget_ = window_->hwnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CefRenderWidgetHostViewOSR::PlatformDestroyCompositorWidget() {
|
|
||||||
window_.reset(NULL);
|
|
||||||
compositor_widget_ = gfx::kNullAcceleratedWidget;
|
|
||||||
}
|
|
@ -30,6 +30,7 @@
|
|||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
#include "base/metrics/user_metrics_action.h"
|
#include "base/metrics/user_metrics_action.h"
|
||||||
#include "base/path_service.h"
|
#include "base/path_service.h"
|
||||||
|
#include "base/stl_util.h"
|
||||||
#include "base/strings/string_number_conversions.h"
|
#include "base/strings/string_number_conversions.h"
|
||||||
#include "base/strings/utf_string_conversions.h"
|
#include "base/strings/utf_string_conversions.h"
|
||||||
#include "chrome/common/chrome_switches.h"
|
#include "chrome/common/chrome_switches.h"
|
||||||
@ -58,6 +59,7 @@
|
|||||||
#include "content/public/renderer/render_view.h"
|
#include "content/public/renderer/render_view.h"
|
||||||
#include "content/public/renderer/render_view_visitor.h"
|
#include "content/public/renderer/render_view_visitor.h"
|
||||||
#include "content/renderer/render_frame_impl.h"
|
#include "content/renderer/render_frame_impl.h"
|
||||||
|
#include "content/renderer/render_widget.h"
|
||||||
#include "extensions/renderer/renderer_extension_registry.h"
|
#include "extensions/renderer/renderer_extension_registry.h"
|
||||||
#include "ipc/ipc_sync_channel.h"
|
#include "ipc/ipc_sync_channel.h"
|
||||||
#include "media/base/media.h"
|
#include "media/base/media.h"
|
||||||
@ -147,6 +149,20 @@ std::string GetPluginInstancePosterAttribute(
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
// Placeholder object for guest views.
|
||||||
|
class CefGuestView : public content::RenderViewObserver {
|
||||||
|
public:
|
||||||
|
explicit CefGuestView(content::RenderView* render_view)
|
||||||
|
: content::RenderViewObserver(render_view) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// RenderViewObserver methods.
|
||||||
|
void OnDestruct() override {
|
||||||
|
CefContentRendererClient::Get()->OnGuestViewDestroyed(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
CefContentRendererClient::CefContentRendererClient()
|
CefContentRendererClient::CefContentRendererClient()
|
||||||
: devtools_agent_count_(0),
|
: devtools_agent_count_(0),
|
||||||
uncaught_exception_stack_size_(0),
|
uncaught_exception_stack_size_(0),
|
||||||
@ -162,6 +178,10 @@ CefContentRendererClient::CefContentRendererClient()
|
|||||||
}
|
}
|
||||||
|
|
||||||
CefContentRendererClient::~CefContentRendererClient() {
|
CefContentRendererClient::~CefContentRendererClient() {
|
||||||
|
if (!guest_views_.empty()) {
|
||||||
|
STLDeleteContainerPairSecondPointers(guest_views_.begin(),
|
||||||
|
guest_views_.end());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
@ -209,6 +229,28 @@ void CefContentRendererClient::OnBrowserDestroyed(CefBrowserImpl* browser) {
|
|||||||
NOTREACHED();
|
NOTREACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CefContentRendererClient::HasGuestViewForView(
|
||||||
|
content::RenderView* view) {
|
||||||
|
CEF_REQUIRE_RT_RETURN(false);
|
||||||
|
|
||||||
|
GuestViewMap::const_iterator it = guest_views_.find(view);
|
||||||
|
return it != guest_views_.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CefContentRendererClient::OnGuestViewDestroyed(CefGuestView* guest_view) {
|
||||||
|
GuestViewMap::iterator it = guest_views_.begin();
|
||||||
|
for (; it != guest_views_.end(); ++it) {
|
||||||
|
if (it->second == guest_view) {
|
||||||
|
delete it->second;
|
||||||
|
guest_views_.erase(it);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No guest view was found in the map.
|
||||||
|
NOTREACHED();
|
||||||
|
}
|
||||||
|
|
||||||
void CefContentRendererClient::WebKitInitialized() {
|
void CefContentRendererClient::WebKitInitialized() {
|
||||||
const base::CommandLine* command_line =
|
const base::CommandLine* command_line =
|
||||||
base::CommandLine::ForCurrentProcess();
|
base::CommandLine::ForCurrentProcess();
|
||||||
@ -769,24 +811,42 @@ blink::WebPlugin* CefContentRendererClient::CreatePlugin(
|
|||||||
void CefContentRendererClient::BrowserCreated(
|
void CefContentRendererClient::BrowserCreated(
|
||||||
content::RenderView* render_view,
|
content::RenderView* render_view,
|
||||||
content::RenderFrame* render_frame) {
|
content::RenderFrame* render_frame) {
|
||||||
|
// Swapped out RenderWidgets will be created in the parent/owner process for
|
||||||
|
// frames that are hosted in a separate process (e.g. guest views or OOP
|
||||||
|
// frames). Don't create any CEF objects for swapped out RenderWidgets.
|
||||||
|
content::RenderFrameImpl* render_frame_impl =
|
||||||
|
static_cast<content::RenderFrameImpl*>(render_frame);
|
||||||
|
if (render_frame_impl->GetRenderWidget()->is_swapped_out())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Don't create another browser or guest view object if one already exists for
|
||||||
|
// the view.
|
||||||
|
if (GetBrowserForView(render_view).get() || HasGuestViewForView(render_view))
|
||||||
|
return;
|
||||||
|
|
||||||
|
const int render_view_routing_id = render_view->GetRoutingID();
|
||||||
|
const int render_frame_routing_id = render_frame->GetRoutingID();
|
||||||
|
|
||||||
// Retrieve the browser information synchronously. This will also register
|
// Retrieve the browser information synchronously. This will also register
|
||||||
// the routing ids with the browser info object in the browser process.
|
// the routing ids with the browser info object in the browser process.
|
||||||
CefProcessHostMsg_GetNewBrowserInfo_Params params;
|
CefProcessHostMsg_GetNewBrowserInfo_Params params;
|
||||||
content::RenderThread::Get()->Send(
|
content::RenderThread::Get()->Send(
|
||||||
new CefProcessHostMsg_GetNewBrowserInfo(
|
new CefProcessHostMsg_GetNewBrowserInfo(
|
||||||
render_view->GetRoutingID(),
|
render_view_routing_id,
|
||||||
render_frame->GetRoutingID(),
|
render_frame_routing_id,
|
||||||
¶ms));
|
¶ms));
|
||||||
DCHECK_GT(params.browser_id, 0);
|
DCHECK_GT(params.browser_id, 0);
|
||||||
|
if (params.browser_id == 0) {
|
||||||
if (params.is_guest_view) {
|
// The request failed for some reason.
|
||||||
// Don't create a CefBrowser for guest views.
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't create another browser object if one already exists for the view.
|
if (params.is_guest_view) {
|
||||||
if (GetBrowserForView(render_view).get())
|
// Don't create a CefBrowser for guest views.
|
||||||
|
guest_views_.insert(
|
||||||
|
std::make_pair(render_view, new CefGuestView(render_view)));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(OS_MACOSX)
|
#if defined(OS_MACOSX)
|
||||||
// FIXME: It would be better if this API would be a callback from the
|
// FIXME: It would be better if this API would be a callback from the
|
||||||
|
@ -34,6 +34,7 @@ namespace web_cache {
|
|||||||
class WebCacheRenderProcessObserver;
|
class WebCacheRenderProcessObserver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CefGuestView;
|
||||||
class CefRenderProcessObserver;
|
class CefRenderProcessObserver;
|
||||||
struct Cef_CrossOriginWhiteListEntry_Params;
|
struct Cef_CrossOriginWhiteListEntry_Params;
|
||||||
struct CefViewHostMsg_GetPluginInfo_Output;
|
struct CefViewHostMsg_GetPluginInfo_Output;
|
||||||
@ -58,6 +59,12 @@ class CefContentRendererClient : public content::ContentRendererClient,
|
|||||||
// Called from CefBrowserImpl::OnDestruct().
|
// Called from CefBrowserImpl::OnDestruct().
|
||||||
void OnBrowserDestroyed(CefBrowserImpl* browser);
|
void OnBrowserDestroyed(CefBrowserImpl* browser);
|
||||||
|
|
||||||
|
// Returns true if a guest view associated with the specified RenderView.
|
||||||
|
bool HasGuestViewForView(content::RenderView* view);
|
||||||
|
|
||||||
|
// Called from CefGuestView::OnDestruct().
|
||||||
|
void OnGuestViewDestroyed(CefGuestView* guest_view);
|
||||||
|
|
||||||
// Render thread task runner.
|
// Render thread task runner.
|
||||||
base::SequencedTaskRunner* render_task_runner() const {
|
base::SequencedTaskRunner* render_task_runner() const {
|
||||||
return render_task_runner_.get();
|
return render_task_runner_.get();
|
||||||
@ -143,6 +150,10 @@ class CefContentRendererClient : public content::ContentRendererClient,
|
|||||||
typedef std::map<content::RenderView*, CefRefPtr<CefBrowserImpl> > BrowserMap;
|
typedef std::map<content::RenderView*, CefRefPtr<CefBrowserImpl> > BrowserMap;
|
||||||
BrowserMap browsers_;
|
BrowserMap browsers_;
|
||||||
|
|
||||||
|
// Map of RenderView poiners to CefGuestView implementations.
|
||||||
|
typedef std::map<content::RenderView*, CefGuestView* > GuestViewMap;
|
||||||
|
GuestViewMap guest_views_;
|
||||||
|
|
||||||
// Cross-origin white list entries that need to be registered with WebKit.
|
// Cross-origin white list entries that need to be registered with WebKit.
|
||||||
typedef std::vector<Cef_CrossOriginWhiteListEntry_Params> CrossOriginList;
|
typedef std::vector<Cef_CrossOriginWhiteListEntry_Params> CrossOriginList;
|
||||||
CrossOriginList cross_origin_whitelist_entries_;
|
CrossOriginList cross_origin_whitelist_entries_;
|
||||||
|
@ -220,11 +220,10 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
|||||||
gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dialog),
|
gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dialog),
|
||||||
!(mode & FILE_DIALOG_HIDEREADONLY_FLAG));
|
!(mode & FILE_DIALOG_HIDEREADONLY_FLAG));
|
||||||
|
|
||||||
if (!default_file_path.empty()) {
|
if (!default_file_path.empty() && mode_type == FILE_DIALOG_SAVE) {
|
||||||
const std::string& file_path = default_file_path;
|
const std::string& file_path = default_file_path;
|
||||||
bool exists = false;
|
bool exists = false;
|
||||||
|
|
||||||
if (mode_type == FILE_DIALOG_SAVE) {
|
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
if (stat(file_path.c_str(), &sb) == 0 && S_ISREG(sb.st_mode)) {
|
if (stat(file_path.c_str(), &sb) == 0 && S_ISREG(sb.st_mode)) {
|
||||||
// Use the directory and name of the existing file.
|
// Use the directory and name of the existing file.
|
||||||
@ -232,7 +231,6 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
|||||||
file_path.data());
|
file_path.data());
|
||||||
exists = true;
|
exists = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
// Set the current file name but let the user choose the directory.
|
// Set the current file name but let the user choose the directory.
|
||||||
|
@ -2152,6 +2152,275 @@ TEST(NavigationTest, PopupNavigateAfterCreation) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const char kSimultPopupMainUrl[] = "http://www.tests-sp.com/main.html";
|
||||||
|
const char kSimultPopupPopupUrl[] = "http://www.tests-sp.com/popup";
|
||||||
|
const size_t kSimultPopupCount = 5U;
|
||||||
|
|
||||||
|
// Test multiple popups simultaniously.
|
||||||
|
class PopupSimultaneousTestHandler : public TestHandler {
|
||||||
|
public:
|
||||||
|
explicit PopupSimultaneousTestHandler(bool same_url)
|
||||||
|
: same_url_(same_url),
|
||||||
|
before_popup_ct_(0U),
|
||||||
|
after_created_ct_(0U),
|
||||||
|
before_close_ct_(0U) {}
|
||||||
|
|
||||||
|
void RunTest() override {
|
||||||
|
std::string main_html = "<html><script>\n";
|
||||||
|
for (size_t i = 0; i < kSimultPopupCount; ++i) {
|
||||||
|
if (same_url_) {
|
||||||
|
popup_url_[i] = std::string(kSimultPopupPopupUrl) + ".html";
|
||||||
|
} else {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << kSimultPopupPopupUrl << i << ".html";
|
||||||
|
popup_url_[i] = ss.str();
|
||||||
|
}
|
||||||
|
main_html += "window.open('" + popup_url_[i] + "');\n";
|
||||||
|
AddResource(popup_url_[i], "<html>Popup " + popup_url_[i] + "</html>",
|
||||||
|
"text/html");
|
||||||
|
}
|
||||||
|
main_html += "</script></html>";
|
||||||
|
|
||||||
|
AddResource(kSimultPopupMainUrl, main_html, "text/html");
|
||||||
|
|
||||||
|
// Create the browser.
|
||||||
|
CreateBrowser(kSimultPopupMainUrl);
|
||||||
|
|
||||||
|
// Time out the test after a reasonable period of time.
|
||||||
|
SetTestTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
|
||||||
|
CefRefPtr<CefFrame> frame,
|
||||||
|
const CefString& target_url,
|
||||||
|
const CefString& target_frame_name,
|
||||||
|
cef_window_open_disposition_t target_disposition,
|
||||||
|
bool user_gesture,
|
||||||
|
const CefPopupFeatures& popupFeatures,
|
||||||
|
CefWindowInfo& windowInfo,
|
||||||
|
CefRefPtr<CefClient>& client,
|
||||||
|
CefBrowserSettings& settings,
|
||||||
|
bool* no_javascript_access) override {
|
||||||
|
const std::string& url = target_url;
|
||||||
|
EXPECT_LT(before_popup_ct_, kSimultPopupCount);
|
||||||
|
EXPECT_STREQ(popup_url_[before_popup_ct_].c_str(), url.c_str()) <<
|
||||||
|
before_popup_ct_;
|
||||||
|
before_popup_ct_++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
|
||||||
|
TestHandler::OnAfterCreated(browser);
|
||||||
|
|
||||||
|
if (browser->IsPopup()) {
|
||||||
|
EXPECT_LT(after_created_ct_, kSimultPopupCount);
|
||||||
|
browser_id_[after_created_ct_] = browser->GetIdentifier();
|
||||||
|
after_created_ct_++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
|
||||||
|
bool isLoading,
|
||||||
|
bool canGoBack,
|
||||||
|
bool canGoForward) override {
|
||||||
|
if (isLoading)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (browser->IsPopup()) {
|
||||||
|
const std::string& url = browser->GetMainFrame()->GetURL();
|
||||||
|
for (size_t i = 0; i < kSimultPopupCount; ++i) {
|
||||||
|
if (browser->GetIdentifier() == browser_id_[i]) {
|
||||||
|
EXPECT_STREQ(popup_url_[i].c_str(), url.c_str()) << i;
|
||||||
|
|
||||||
|
got_loading_state_change_[i].yes();
|
||||||
|
browser->GetHost()->CloseBrowser(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPECT_FALSE(true); // Not reached.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
|
||||||
|
TestHandler::OnBeforeClose(browser);
|
||||||
|
|
||||||
|
if (browser->IsPopup()) {
|
||||||
|
const std::string& url = browser->GetMainFrame()->GetURL();
|
||||||
|
for (size_t i = 0; i < kSimultPopupCount; ++i) {
|
||||||
|
if (browser->GetIdentifier() == browser_id_[i]) {
|
||||||
|
EXPECT_STREQ(popup_url_[i].c_str(), url.c_str()) << i;
|
||||||
|
|
||||||
|
got_before_close_[i].yes();
|
||||||
|
|
||||||
|
if (++before_close_ct_ == kSimultPopupCount)
|
||||||
|
DestroyTest();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPECT_FALSE(true); // Not reached.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DestroyTest() override {
|
||||||
|
EXPECT_EQ(kSimultPopupCount, before_popup_ct_);
|
||||||
|
EXPECT_EQ(kSimultPopupCount, after_created_ct_);
|
||||||
|
EXPECT_EQ(kSimultPopupCount, before_close_ct_);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < kSimultPopupCount; ++i) {
|
||||||
|
EXPECT_GT(browser_id_[i], 0) << i;
|
||||||
|
EXPECT_TRUE(got_loading_state_change_[i]) << i;
|
||||||
|
EXPECT_TRUE(got_before_close_[i]) << i;
|
||||||
|
}
|
||||||
|
|
||||||
|
TestHandler::DestroyTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool same_url_;
|
||||||
|
std::string popup_url_[kSimultPopupCount];
|
||||||
|
size_t before_popup_ct_;
|
||||||
|
int browser_id_[kSimultPopupCount];
|
||||||
|
size_t after_created_ct_;
|
||||||
|
TrackCallback got_loading_state_change_[kSimultPopupCount];
|
||||||
|
TrackCallback got_before_close_[kSimultPopupCount];
|
||||||
|
size_t before_close_ct_;
|
||||||
|
|
||||||
|
IMPLEMENT_REFCOUNTING(PopupSimultaneousTestHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Test simultaneous popups with different URLs.
|
||||||
|
TEST(NavigationTest, PopupSimultaneousDifferentUrl) {
|
||||||
|
CefRefPtr<PopupSimultaneousTestHandler> handler =
|
||||||
|
new PopupSimultaneousTestHandler(false);
|
||||||
|
handler->ExecuteTest();
|
||||||
|
ReleaseAndWaitForDestructor(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test simultaneous popups with the same URL.
|
||||||
|
TEST(NavigationTest, PopupSimultaneousSameUrl) {
|
||||||
|
CefRefPtr<PopupSimultaneousTestHandler> handler =
|
||||||
|
new PopupSimultaneousTestHandler(true);
|
||||||
|
handler->ExecuteTest();
|
||||||
|
ReleaseAndWaitForDestructor(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
const char kPopupJSOpenMainUrl[] = "http://www.tests-pjso.com/main.html";
|
||||||
|
const char kPopupJSOpenPopupUrl[] = "http://www.tests-pjso.com/popup.html";
|
||||||
|
|
||||||
|
// Test a popup where the URL is a JavaScript URI that opens another popup.
|
||||||
|
// See comments on CefBrowserInfoManager::FilterPendingPopupURL.
|
||||||
|
class PopupJSWindowOpenTestHandler : public TestHandler {
|
||||||
|
public:
|
||||||
|
PopupJSWindowOpenTestHandler()
|
||||||
|
: before_popup_ct_(0U),
|
||||||
|
after_created_ct_(0U),
|
||||||
|
load_end_ct_(0U),
|
||||||
|
before_close_ct_(0U) {}
|
||||||
|
|
||||||
|
void RunTest() override {
|
||||||
|
AddResource(kPopupJSOpenMainUrl, "<html>Main</html>", "text/html");
|
||||||
|
AddResource(kPopupJSOpenPopupUrl, "<html>Popup</html>", "text/html");
|
||||||
|
|
||||||
|
// Create the browser.
|
||||||
|
CreateBrowser(kPopupJSOpenMainUrl);
|
||||||
|
|
||||||
|
// Time out the test after a reasonable period of time.
|
||||||
|
SetTestTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
|
||||||
|
CefRefPtr<CefFrame> frame,
|
||||||
|
const CefString& target_url,
|
||||||
|
const CefString& target_frame_name,
|
||||||
|
cef_window_open_disposition_t target_disposition,
|
||||||
|
bool user_gesture,
|
||||||
|
const CefPopupFeatures& popupFeatures,
|
||||||
|
CefWindowInfo& windowInfo,
|
||||||
|
CefRefPtr<CefClient>& client,
|
||||||
|
CefBrowserSettings& settings,
|
||||||
|
bool* no_javascript_access) override {
|
||||||
|
before_popup_ct_++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override {
|
||||||
|
TestHandler::OnAfterCreated(browser);
|
||||||
|
|
||||||
|
if (browser->IsPopup())
|
||||||
|
after_created_ct_++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
|
||||||
|
bool isLoading,
|
||||||
|
bool canGoBack,
|
||||||
|
bool canGoForward) override {
|
||||||
|
if (isLoading)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (browser->IsPopup()) {
|
||||||
|
const std::string& url = browser->GetMainFrame()->GetURL();
|
||||||
|
if (load_end_ct_ == 0)
|
||||||
|
EXPECT_TRUE(url.empty());
|
||||||
|
else
|
||||||
|
EXPECT_STREQ(kPopupJSOpenPopupUrl, url.c_str());
|
||||||
|
|
||||||
|
load_end_ct_++;
|
||||||
|
browser->GetHost()->CloseBrowser(true);
|
||||||
|
} else if (browser->GetMainFrame()->GetURL() == kPopupJSOpenMainUrl) {
|
||||||
|
// Load the problematic JS URI.
|
||||||
|
// This will result in 2 popups being created:
|
||||||
|
// - An empty popup
|
||||||
|
// - A popup that loads kPopupJSOpenPopupUrl
|
||||||
|
browser->GetMainFrame()->LoadURL(
|
||||||
|
"javascript:window.open(\"javascript:window.open('" +
|
||||||
|
std::string(kPopupJSOpenPopupUrl) + "')\")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
|
||||||
|
TestHandler::OnBeforeClose(browser);
|
||||||
|
|
||||||
|
before_close_ct_++;
|
||||||
|
if (before_close_ct_ == 2U)
|
||||||
|
DestroyTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void DestroyTest() override {
|
||||||
|
EXPECT_EQ(2U, before_popup_ct_);
|
||||||
|
EXPECT_EQ(2U, after_created_ct_);
|
||||||
|
EXPECT_EQ(2U, load_end_ct_);
|
||||||
|
EXPECT_EQ(2U, before_close_ct_);
|
||||||
|
|
||||||
|
TestHandler::DestroyTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t before_popup_ct_;
|
||||||
|
size_t after_created_ct_;
|
||||||
|
size_t load_end_ct_;
|
||||||
|
size_t before_close_ct_;
|
||||||
|
|
||||||
|
IMPLEMENT_REFCOUNTING(PopupJSWindowOpenTestHandler);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
// Test a popup where the URL is a JavaScript URI that opens another popup.
|
||||||
|
TEST(NavigationTest, PopupJSWindowOpen) {
|
||||||
|
CefRefPtr<PopupJSWindowOpenTestHandler> handler =
|
||||||
|
new PopupJSWindowOpenTestHandler();
|
||||||
|
handler->ExecuteTest();
|
||||||
|
ReleaseAndWaitForDestructor(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
const char kBrowseNavPageUrl[] = "http://tests-browsenav/nav.html";
|
const char kBrowseNavPageUrl[] = "http://tests-browsenav/nav.html";
|
||||||
|
@ -85,7 +85,7 @@ const int kVerticalScrollbarWidth = GetSystemMetrics(SM_CXVSCROLL);
|
|||||||
const CefRect kEditBoxRect(442, 251, 46, 16);
|
const CefRect kEditBoxRect(442, 251, 46, 16);
|
||||||
const CefRect kNavigateButtonRect(375, 275, 130, 20);
|
const CefRect kNavigateButtonRect(375, 275, 130, 20);
|
||||||
const CefRect kSelectRect(461, 21, 87, 26);
|
const CefRect kSelectRect(461, 21, 87, 26);
|
||||||
const CefRect kExpandedSelectRect(466, 42, 76, 286);
|
const CefRect kExpandedSelectRect(466, 42, 78, 286);
|
||||||
const CefRect kDropDivRect(9, 330, 52, 52);
|
const CefRect kDropDivRect(9, 330, 52, 52);
|
||||||
const CefRect kDragDivRect(60, 330, 52, 52);
|
const CefRect kDragDivRect(60, 330, 52, 52);
|
||||||
const int kVerticalScrollbarWidth = 15;
|
const int kVerticalScrollbarWidth = 15;
|
||||||
@ -183,10 +183,15 @@ enum OSRTestType {
|
|||||||
OSR_TEST_DRAG_DROP_UPDATE_CURSOR,
|
OSR_TEST_DRAG_DROP_UPDATE_CURSOR,
|
||||||
// dropping element inside drop region will move the element
|
// dropping element inside drop region will move the element
|
||||||
OSR_TEST_DRAG_DROP_DROP,
|
OSR_TEST_DRAG_DROP_DROP,
|
||||||
|
|
||||||
|
// Define the range for popup tests.
|
||||||
|
OSR_TEST_POPUP_FIRST = OSR_TEST_POPUP_PAINT,
|
||||||
|
OSR_TEST_POPUP_LAST = OSR_TEST_POPUP_SCROLL_INSIDE,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Used in the browser process.
|
// Used in the browser process.
|
||||||
class OSRTestHandler : public RoutingTestHandler,
|
class OSRTestHandler : public RoutingTestHandler,
|
||||||
|
public CefFocusHandler,
|
||||||
public CefRenderHandler,
|
public CefRenderHandler,
|
||||||
public CefContextMenuHandler {
|
public CefContextMenuHandler {
|
||||||
public:
|
public:
|
||||||
@ -278,6 +283,10 @@ class OSRTestHandler : public RoutingTestHandler,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CefClient methods, providing handlers
|
// CefClient methods, providing handlers
|
||||||
|
CefRefPtr<CefFocusHandler> GetFocusHandler() override {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
CefRefPtr<CefRenderHandler> GetRenderHandler() override {
|
CefRefPtr<CefRenderHandler> GetRenderHandler() override {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -762,6 +771,23 @@ class OSRTestHandler : public RoutingTestHandler,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OnSetFocus(CefRefPtr<CefBrowser> browser,
|
||||||
|
FocusSource source) override {
|
||||||
|
if (source == FOCUS_SOURCE_NAVIGATION) {
|
||||||
|
got_navigation_focus_event_.yes();
|
||||||
|
|
||||||
|
// Ignore focus from the original navigation when we're testing focus
|
||||||
|
// event delivery.
|
||||||
|
if (test_type_ == OSR_TEST_FOCUS)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(source, FOCUS_SOURCE_SYSTEM);
|
||||||
|
got_system_focus_event_.yes();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void OnCursorChange(CefRefPtr<CefBrowser> browser,
|
void OnCursorChange(CefRefPtr<CefBrowser> browser,
|
||||||
CefCursorHandle cursor,
|
CefCursorHandle cursor,
|
||||||
CursorType type,
|
CursorType type,
|
||||||
@ -937,6 +963,23 @@ class OSRTestHandler : public RoutingTestHandler,
|
|||||||
CefPostTask(TID_UI, base::Bind(&OSRTestHandler::DestroyTest, this));
|
CefPostTask(TID_UI, base::Bind(&OSRTestHandler::DestroyTest, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DestroyTest() override {
|
||||||
|
// Always get the OnSetFocus call for the initial navigation.
|
||||||
|
EXPECT_TRUE(got_navigation_focus_event_);
|
||||||
|
|
||||||
|
if (test_type_ == OSR_TEST_FOCUS ||
|
||||||
|
(test_type_ >= OSR_TEST_POPUP_FIRST &&
|
||||||
|
test_type_ <= OSR_TEST_POPUP_LAST)) {
|
||||||
|
// SetFocus is called by the system when we explicitly set the focus and
|
||||||
|
// when popups are dismissed.
|
||||||
|
EXPECT_TRUE(got_system_focus_event_);
|
||||||
|
} else {
|
||||||
|
EXPECT_FALSE(got_system_focus_event_);
|
||||||
|
}
|
||||||
|
|
||||||
|
RoutingTestHandler::DestroyTest();
|
||||||
|
}
|
||||||
|
|
||||||
void ExpandDropDown() {
|
void ExpandDropDown() {
|
||||||
GetBrowser()->GetHost()->SendFocusEvent(true);
|
GetBrowser()->GetHost()->SendFocusEvent(true);
|
||||||
CefMouseEvent mouse_event;
|
CefMouseEvent mouse_event;
|
||||||
@ -1013,6 +1056,8 @@ class OSRTestHandler : public RoutingTestHandler,
|
|||||||
int event_total_;
|
int event_total_;
|
||||||
bool started_;
|
bool started_;
|
||||||
TrackCallback got_update_cursor_;
|
TrackCallback got_update_cursor_;
|
||||||
|
TrackCallback got_navigation_focus_event_;
|
||||||
|
TrackCallback got_system_focus_event_;
|
||||||
|
|
||||||
IMPLEMENT_REFCOUNTING(OSRTestHandler);
|
IMPLEMENT_REFCOUNTING(OSRTestHandler);
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user