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_info.cc',
|
||||
'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.h',
|
||||
'libcef/browser/browser_message_filter.cc',
|
||||
'libcef/browser/browser_message_filter.h',
|
||||
'libcef/browser/browser_message_loop.cc',
|
||||
'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.h',
|
||||
'libcef/browser/chrome_browser_process_stub.cc',
|
||||
@ -1022,26 +1027,42 @@
|
||||
'libcef/browser/extensions/pdf_web_contents_helper_client.h',
|
||||
'libcef/browser/extensions/url_request_util.cc',
|
||||
'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.h',
|
||||
'libcef/browser/geolocation_impl.cc',
|
||||
'libcef/browser/internal_scheme_handler.cc',
|
||||
'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.h',
|
||||
'libcef/browser/media_capture_devices_dispatcher.cc',
|
||||
'libcef/browser/media_capture_devices_dispatcher.h',
|
||||
'libcef/browser/menu_creator.cc',
|
||||
'libcef/browser/menu_creator.h',
|
||||
'libcef/browser/menu_manager.cc',
|
||||
'libcef/browser/menu_manager.h',
|
||||
'libcef/browser/menu_model_impl.cc',
|
||||
'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.h',
|
||||
'libcef/browser/navigation_entry_impl.cc',
|
||||
'libcef/browser/navigation_entry_impl.h',
|
||||
'libcef/browser/origin_whitelist_impl.cc',
|
||||
'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/pepper/browser_pepper_host_factory.cc',
|
||||
'libcef/browser/pepper/browser_pepper_host_factory.h',
|
||||
@ -1074,8 +1095,6 @@
|
||||
'libcef/browser/printing/print_view_manager_base.h',
|
||||
'libcef/browser/process_util_impl.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.h',
|
||||
'libcef/browser/resource_dispatcher_host_delegate.cc',
|
||||
@ -1087,8 +1106,6 @@
|
||||
'libcef/browser/scheme_handler.cc',
|
||||
'libcef/browser/scheme_handler.h',
|
||||
'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.h',
|
||||
'libcef/browser/ssl_cert_principal_impl.cc',
|
||||
@ -1121,8 +1138,6 @@
|
||||
'libcef/browser/url_request_interceptor.h',
|
||||
'libcef/browser/url_request_user_data.cc',
|
||||
'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.h',
|
||||
'libcef/browser/xml_reader_impl.cc',
|
||||
@ -1398,12 +1413,18 @@
|
||||
['OS=="win"', {
|
||||
'sources': [
|
||||
'<@(includes_win)',
|
||||
'libcef/browser/browser_host_impl_win.cc',
|
||||
'libcef/browser/browser_main_win.cc',
|
||||
'libcef/browser/javascript_dialog_win.cc',
|
||||
'libcef/browser/menu_creator_runner_win.cc',
|
||||
'libcef/browser/menu_creator_runner_win.h',
|
||||
'libcef/browser/render_widget_host_view_osr_win.cc',
|
||||
'libcef/browser/native/browser_platform_delegate_native_win.cc',
|
||||
'libcef/browser/native/browser_platform_delegate_native_win.h',
|
||||
'libcef/browser/native/file_dialog_runner_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.
|
||||
'libcef/utility/printing_handler.cc',
|
||||
'libcef/utility/printing_handler.h',
|
||||
@ -1418,13 +1439,19 @@
|
||||
[ 'OS=="mac"', {
|
||||
'sources': [
|
||||
'<@(includes_mac)',
|
||||
'libcef/browser/browser_host_impl_mac.mm',
|
||||
'libcef/browser/javascript_dialog_mac.mm',
|
||||
'libcef/browser/menu_creator_runner_mac.h',
|
||||
'libcef/browser/menu_creator_runner_mac.mm',
|
||||
'libcef/browser/render_widget_host_view_osr_mac.mm',
|
||||
'libcef/browser/text_input_client_osr_mac.mm',
|
||||
'libcef/browser/text_input_client_osr_mac.h',
|
||||
'libcef/browser/native/browser_platform_delegate_native_mac.h',
|
||||
'libcef/browser/native/browser_platform_delegate_native_mac.mm',
|
||||
'libcef/browser/native/file_dialog_runner_mac.h',
|
||||
'libcef/browser/native/file_dialog_runner_mac.mm',
|
||||
'libcef/browser/native/javascript_dialog_runner_mac.h',
|
||||
'libcef/browser/native/javascript_dialog_runner_mac.mm',
|
||||
'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.mm',
|
||||
# Include sources for spell checking support.
|
||||
@ -1442,15 +1469,17 @@
|
||||
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
|
||||
'sources': [
|
||||
'<@(includes_linux)',
|
||||
'libcef/browser/browser_host_impl_linux.cc',
|
||||
'libcef/browser/javascript_dialog_linux.cc',
|
||||
'libcef/browser/menu_creator_runner_linux.cc',
|
||||
'libcef/browser/menu_creator_runner_linux.h',
|
||||
'libcef/browser/native/browser_platform_delegate_native_linux.cc',
|
||||
'libcef/browser/native/browser_platform_delegate_native_linux.h',
|
||||
'libcef/browser/native/menu_runner_linux.cc',
|
||||
'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.h',
|
||||
'libcef/browser/render_widget_host_view_osr_linux.cc',
|
||||
'libcef/browser/window_x11.cc',
|
||||
'libcef/browser/window_x11.h',
|
||||
'libcef/browser/native/window_x11.cc',
|
||||
'libcef/browser/native/window_x11.h',
|
||||
],
|
||||
}],
|
||||
['os_posix == 1 and OS != "mac"', {
|
||||
@ -1469,8 +1498,8 @@
|
||||
'<(DEPTH)/ui/views/views.gyp:views',
|
||||
],
|
||||
'sources': [
|
||||
'libcef/browser/window_delegate_view.cc',
|
||||
'libcef/browser/window_delegate_view.h',
|
||||
'libcef/browser/native/window_delegate_view.cc',
|
||||
'libcef/browser/native/window_delegate_view.h',
|
||||
'<(DEPTH)/ui/views/test/desktop_test_views_delegate.h',
|
||||
'<(DEPTH)/ui/views/test/desktop_test_views_delegate_aura.cc',
|
||||
'<(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_frame.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/javascript_dialog_manager.h"
|
||||
#include "libcef/browser/menu_creator.h"
|
||||
#include "libcef/browser/menu_manager.h"
|
||||
#include "libcef/common/response_manager.h"
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
@ -29,42 +31,11 @@
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/browser/web_contents_delegate.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 {
|
||||
class DirectoryLister;
|
||||
class URLRequest;
|
||||
}
|
||||
|
||||
#if defined(USE_AURA)
|
||||
namespace views {
|
||||
class Widget;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(USE_X11)
|
||||
class CefWindowX11;
|
||||
#endif
|
||||
|
||||
struct Cef_DraggableRegion_Params;
|
||||
struct Cef_Request_Params;
|
||||
struct Cef_Response_Params;
|
||||
@ -100,18 +71,6 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
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;
|
||||
|
||||
// Create a new CefBrowserHostImpl instance.
|
||||
@ -120,7 +79,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
CefRefPtr<CefClient> client,
|
||||
const CefString& url,
|
||||
const CefBrowserSettings& settings,
|
||||
CefWindowHandle opener,
|
||||
CefRefPtr<CefBrowserHostImpl> opener,
|
||||
bool is_popup,
|
||||
CefRefPtr<CefRequestContext> request_context);
|
||||
|
||||
@ -239,8 +198,6 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
|
||||
// Returns true if windowless rendering is enabled.
|
||||
bool IsWindowless() const;
|
||||
// Returns true if transparent painting is enabled.
|
||||
bool IsTransparent() const;
|
||||
|
||||
// Called when the OS window hosting the browser is destroyed.
|
||||
void WindowDestroyed();
|
||||
@ -252,11 +209,11 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
// Cancel display of the context menu, if any.
|
||||
void CancelContextMenu();
|
||||
|
||||
// Returns the native view for the WebContents.
|
||||
gfx::NativeView GetContentView() const;
|
||||
|
||||
// Returns a pointer to the WebContents.
|
||||
content::WebContents* GetWebContents() const;
|
||||
#if defined(USE_AURA)
|
||||
// Returns the Widget owner for the browser window. Only used with windowed
|
||||
// rendering.
|
||||
views::Widget* GetWindowWidget() const;
|
||||
#endif
|
||||
|
||||
// Returns the frame associated with the specified URLRequest.
|
||||
CefRefPtr<CefFrame> GetFrameForRequest(net::URLRequest* request);
|
||||
@ -293,7 +250,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
bool user_initiated);
|
||||
|
||||
// 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.
|
||||
void HandleExternalProtocol(const GURL& url);
|
||||
@ -301,39 +258,23 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
// Set the frame that currently has focus.
|
||||
void SetFocusedFrame(int64 frame_id);
|
||||
|
||||
// Convert from view coordinates to screen coordinates.
|
||||
gfx::Point GetScreenPoint(const gfx::Point& view) const;
|
||||
|
||||
// Thread safe accessors.
|
||||
const CefBrowserSettings& settings() const { return settings_; }
|
||||
CefRefPtr<CefClient> client() const { return client_; }
|
||||
scoped_refptr<CefBrowserInfo> browser_info() const { return browser_info_; }
|
||||
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);
|
||||
|
||||
// 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
|
||||
// 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 FileChooserParams& params,
|
||||
const RunFileChooserCallback& callback);
|
||||
void RunFileChooser(
|
||||
const CefFileDialogRunner::FileChooserParams& params,
|
||||
const CefFileDialogRunner::RunFileChooserCallback& callback);
|
||||
|
||||
bool HandleContextMenu(
|
||||
content::WebContents* web_contents,
|
||||
@ -345,15 +286,6 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
// Otherwise, the browser's WebContents will be returned.
|
||||
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 {
|
||||
DESTRUCTION_STATE_NONE = 0,
|
||||
DESTRUCTION_STATE_PENDING,
|
||||
@ -488,13 +420,13 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
class DevToolsWebContentsObserver;
|
||||
|
||||
static CefRefPtr<CefBrowserHostImpl> CreateInternal(
|
||||
const CefWindowInfo& window_info,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefClient> client,
|
||||
content::WebContents* web_contents,
|
||||
scoped_refptr<CefBrowserInfo> browser_info,
|
||||
CefWindowHandle opener,
|
||||
CefRefPtr<CefRequestContext> request_context);
|
||||
CefRefPtr<CefBrowserHostImpl> opener,
|
||||
CefRefPtr<CefRequestContext> request_context,
|
||||
scoped_ptr<CefBrowserPlatformDelegate> platform_delegate);
|
||||
|
||||
// content::WebContentsObserver::OnMessageReceived() message handlers.
|
||||
void OnFrameIdentified(int64 frame_id,
|
||||
@ -516,13 +448,16 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
const content::NotificationSource& source,
|
||||
const content::NotificationDetails& details) override;
|
||||
|
||||
CefBrowserHostImpl(const CefWindowInfo& window_info,
|
||||
const CefBrowserSettings& settings,
|
||||
CefBrowserHostImpl(const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefClient> client,
|
||||
content::WebContents* web_contents,
|
||||
scoped_refptr<CefBrowserInfo> browser_info,
|
||||
CefWindowHandle opener,
|
||||
CefRefPtr<CefRequestContext> request_context);
|
||||
CefRefPtr<CefBrowserHostImpl> opener,
|
||||
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
|
||||
// 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.
|
||||
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,
|
||||
const GURL& url);
|
||||
void OnLoadStart(CefRefPtr<CefFrame> frame,
|
||||
@ -602,44 +484,18 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
void OnFullscreenModeChange(bool fullscreen);
|
||||
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();
|
||||
|
||||
CefWindowInfo window_info_;
|
||||
// Create the CefFileDialogManager if it doesn't already exist.
|
||||
void EnsureFileDialogManager();
|
||||
|
||||
CefBrowserSettings settings_;
|
||||
CefRefPtr<CefClient> client_;
|
||||
scoped_ptr<content::WebContents> web_contents_;
|
||||
scoped_refptr<CefBrowserInfo> browser_info_;
|
||||
CefWindowHandle opener_;
|
||||
CefRefPtr<CefRequestContext> request_context_;
|
||||
|
||||
// Pending popup information. Access must be protected by
|
||||
// |pending_popup_info_lock_|.
|
||||
base::Lock pending_popup_info_lock_;
|
||||
scoped_ptr<PendingPopupInfo> pending_popup_info_;
|
||||
scoped_ptr<CefBrowserPlatformDelegate> platform_delegate_;
|
||||
|
||||
// Volatile state information. All access must be protected by the state lock.
|
||||
base::Lock state_lock_;
|
||||
@ -694,11 +550,14 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
// Manages response registrations.
|
||||
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.
|
||||
scoped_ptr<CefJavaScriptDialogManager> dialog_manager_;
|
||||
scoped_ptr<CefJavaScriptDialogManager> javascript_dialog_manager_;
|
||||
|
||||
// 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
|
||||
// browser.
|
||||
@ -707,24 +566,8 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
||||
// destroyed.
|
||||
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);
|
||||
DISALLOW_EVIL_CONSTRUCTORS(CefBrowserHostImpl);
|
||||
DISALLOW_COPY_AND_ASSIGN(CefBrowserHostImpl);
|
||||
};
|
||||
|
||||
#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_host_impl.h"
|
||||
#include "libcef/browser/thread_util.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(
|
||||
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_,
|
||||
render_process_id,
|
||||
render_routing_id);
|
||||
}
|
||||
|
||||
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_,
|
||||
render_process_id,
|
||||
render_routing_id);
|
||||
@ -87,7 +88,7 @@ void CefBrowserInfo::RenderIDManager::remove_render_id(RenderIdSet* id_set,
|
||||
bool CefBrowserInfo::RenderIDManager::is_render_id_match(
|
||||
const RenderIdSet* id_set,
|
||||
int render_process_id,
|
||||
int render_routing_id) {
|
||||
int render_routing_id) const {
|
||||
base::AutoLock lock_scope(*lock_);
|
||||
|
||||
if (id_set->empty())
|
||||
@ -117,7 +118,7 @@ void CefBrowserInfo::set_windowless(bool windowless) {
|
||||
is_windowless_ = windowless;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowserHostImpl> CefBrowserInfo::browser() {
|
||||
CefRefPtr<CefBrowserHostImpl> CefBrowserInfo::browser() const {
|
||||
base::AutoLock lock_scope(lock_);
|
||||
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);
|
||||
|
||||
// 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_frame_id_match(int render_process_id, int render_routing_id);
|
||||
bool is_render_view_id_match(int render_process_id,
|
||||
int render_routing_id) const;
|
||||
bool is_render_frame_id_match(int render_process_id,
|
||||
int render_routing_id)const ;
|
||||
|
||||
private:
|
||||
typedef std::set<std::pair<int, int> > RenderIdSet;
|
||||
@ -50,9 +52,9 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
|
||||
int render_routing_id);
|
||||
bool is_render_id_match(const RenderIdSet* id_set,
|
||||
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_|.
|
||||
|
||||
@ -88,7 +90,7 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
|
||||
return &guest_render_id_manager_;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowserHostImpl> browser();
|
||||
CefRefPtr<CefBrowserHostImpl> browser() const;
|
||||
void set_browser(CefRefPtr<CefBrowserHostImpl> browser);
|
||||
|
||||
private:
|
||||
@ -100,7 +102,7 @@ class CefBrowserInfo : public base::RefCountedThreadSafe<CefBrowserInfo> {
|
||||
bool is_popup_;
|
||||
bool is_windowless_;
|
||||
|
||||
base::Lock lock_;
|
||||
mutable base::Lock 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 <Objbase.h>
|
||||
|
||||
#include "libcef/browser/browser_host_impl.h"
|
||||
#include "libcef/browser/browser_main.h"
|
||||
|
||||
#include "chrome/common/chrome_utility_messages.h"
|
||||
@ -45,9 +44,6 @@ void CefBrowserMainParts::PlatformInitialize() {
|
||||
// Start COM stuff.
|
||||
res = OleInitialize(NULL);
|
||||
DCHECK(SUCCEEDED(res));
|
||||
|
||||
// Register the browser window class.
|
||||
CefBrowserHostImpl::RegisterWindowClass();
|
||||
}
|
||||
|
||||
void CefBrowserMainParts::PlatformPreMainMessageLoopRun() {
|
||||
|
@ -6,8 +6,7 @@
|
||||
#include "libcef/browser/browser_message_filter.h"
|
||||
|
||||
#include "libcef/browser/browser_host_impl.h"
|
||||
#include "libcef/browser/browser_info.h"
|
||||
#include "libcef/browser/content_browser_client.h"
|
||||
#include "libcef/browser/browser_info_manager.h"
|
||||
#include "libcef/browser/context.h"
|
||||
#include "libcef/browser/origin_whitelist_impl.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_MESSAGE_HANDLER(CefProcessHostMsg_GetNewRenderThreadInfo,
|
||||
OnGetNewRenderThreadInfo)
|
||||
IPC_MESSAGE_HANDLER(CefProcessHostMsg_GetNewBrowserInfo,
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(CefProcessHostMsg_GetNewBrowserInfo,
|
||||
OnGetNewBrowserInfo)
|
||||
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_CreateWindow, OnCreateWindow)
|
||||
IPC_MESSAGE_UNHANDLED(handled = false)
|
||||
@ -87,33 +86,18 @@ void CefBrowserMessageFilter::OnGetNewRenderThreadInfo(
|
||||
void CefBrowserMessageFilter::OnGetNewBrowserInfo(
|
||||
int render_view_routing_id,
|
||||
int render_frame_routing_id,
|
||||
CefProcessHostMsg_GetNewBrowserInfo_Params* params) {
|
||||
DCHECK_GT(render_view_routing_id, 0);
|
||||
DCHECK_GT(render_frame_routing_id, 0);
|
||||
|
||||
// Popup windows may not have info yet.
|
||||
scoped_refptr<CefBrowserInfo> info =
|
||||
CefContentBrowserClient::Get()->GetOrCreateBrowserInfo(
|
||||
host_->GetID(),
|
||||
IPC::Message* reply_msg) {
|
||||
CefBrowserInfoManager::GetInstance()->OnGetNewBrowserInfo(
|
||||
host_,
|
||||
render_view_routing_id,
|
||||
host_->GetID(),
|
||||
render_frame_routing_id,
|
||||
¶ms->is_guest_view);
|
||||
params->browser_id = info->browser_id();
|
||||
params->is_popup = info->is_popup();
|
||||
params->is_windowless = info->is_windowless();
|
||||
reply_msg);
|
||||
}
|
||||
|
||||
void CefBrowserMessageFilter::OnCreateWindow(
|
||||
const ViewHostMsg_CreateWindow_Params& params,
|
||||
IPC::Message* reply_msg) {
|
||||
CefContentBrowserClient::LastCreateWindowParams lcwp;
|
||||
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);
|
||||
CefBrowserInfoManager::GetInstance()->OnCreateWindow(host_, params);
|
||||
|
||||
// Reply message is not used.
|
||||
delete reply_msg;
|
||||
|
@ -38,7 +38,7 @@ class CefBrowserMessageFilter : public IPC::MessageFilter {
|
||||
void OnGetNewBrowserInfo(
|
||||
int render_view_routing_id,
|
||||
int render_frame_routing_id,
|
||||
CefProcessHostMsg_GetNewBrowserInfo_Params* params);
|
||||
IPC::Message* reply_msg);
|
||||
void OnCreateWindow(const ViewHostMsg_CreateWindow_Params& params,
|
||||
IPC::Message* reply_msg);
|
||||
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 "libcef/browser/browser_info.h"
|
||||
#include "libcef/browser/browser_info_manager.h"
|
||||
#include "libcef/browser/browser_host_impl.h"
|
||||
#include "libcef/browser/browser_main.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/context.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/media_capture_devices_dispatcher.h"
|
||||
#include "libcef/browser/pepper/browser_pepper_host_factory.h"
|
||||
@ -277,37 +278,6 @@ class CefQuotaPermissionContext : public content::QuotaPermissionContext {
|
||||
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)
|
||||
breakpad::CrashHandlerHostLinux* CreateCrashHandlerHost(
|
||||
const std::string& process_type) {
|
||||
@ -436,13 +406,10 @@ void FindFrameHostForNavigationHandle(
|
||||
|
||||
|
||||
CefContentBrowserClient::CefContentBrowserClient()
|
||||
: browser_main_parts_(NULL),
|
||||
next_browser_id_(0) {
|
||||
: browser_main_parts_(NULL) {
|
||||
plugin_service_filter_.reset(new CefPluginServiceFilter);
|
||||
content::PluginServiceImpl::GetInstance()->SetFilter(
|
||||
plugin_service_filter_.get());
|
||||
|
||||
last_create_window_params_.opener_process_id = MSG_ROUTING_NONE;
|
||||
}
|
||||
|
||||
CefContentBrowserClient::~CefContentBrowserClient() {
|
||||
@ -454,178 +421,6 @@ CefContentBrowserClient* CefContentBrowserClient::Get() {
|
||||
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(
|
||||
const content::MainFunctionParams& parameters) {
|
||||
browser_main_parts_ = new CefBrowserMainParts(parameters);
|
||||
@ -662,6 +457,8 @@ void CefContentBrowserClient::RenderProcessWillLaunch(
|
||||
new extensions::ExtensionsGuestViewMessageFilter(id, browser_context));
|
||||
}
|
||||
|
||||
host->AddObserver(CefBrowserInfoManager::GetInstance());
|
||||
|
||||
host->Send(new CefProcessMsg_SetIsIncognitoProcess(
|
||||
browser_context->IsOffTheRecord()));
|
||||
}
|
||||
@ -959,102 +756,10 @@ bool CefContentBrowserClient::CanCreateWindow(
|
||||
CEF_REQUIRE_IOT();
|
||||
*no_javascript_access = false;
|
||||
|
||||
DCHECK_NE(last_create_window_params_.opener_process_id, MSG_ROUTING_NONE);
|
||||
if (last_create_window_params_.opener_process_id == MSG_ROUTING_NONE)
|
||||
return false;
|
||||
|
||||
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;
|
||||
return CefBrowserInfoManager::GetInstance()->CanCreateWindow(
|
||||
target_url, referrer, disposition, features, user_gesture,
|
||||
opener_suppressed, render_process_id, opener_render_view_id,
|
||||
opener_render_frame_id, no_javascript_access);
|
||||
}
|
||||
|
||||
void CefContentBrowserClient::ResourceDispatcherHostCreated() {
|
||||
@ -1198,12 +903,6 @@ void CefContentBrowserClient::RegisterCustomScheme(const std::string& 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>
|
||||
CefContentBrowserClient::browser_context() const {
|
||||
return browser_main_parts_->browser_context();
|
||||
|
@ -6,9 +6,6 @@
|
||||
#define CEF_LIBCEF_BROWSER_CONTENT_BROWSER_CLIENT_H_
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@ -19,13 +16,9 @@
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "content/public/browser/content_browser_client.h"
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
class CefBrowserHostImpl;
|
||||
class CefBrowserInfo;
|
||||
class CefBrowserMainParts;
|
||||
class CefDevToolsDelegate;
|
||||
class CefResourceDispatcherHostDelegate;
|
||||
@ -43,38 +36,6 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
|
||||
// Returns the singleton CefContentBrowserClient instance.
|
||||
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.
|
||||
content::BrowserMainParts* CreateBrowserMainParts(
|
||||
const content::MainFunctionParams& parameters) override;
|
||||
@ -162,17 +123,6 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
|
||||
// Perform browser process registration for the custom 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;
|
||||
CefDevToolsDelegate* devtools_delegate() const;
|
||||
|
||||
@ -182,16 +132,6 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
|
||||
scoped_ptr<content::PluginServiceFilter> plugin_service_filter_;
|
||||
scoped_ptr<CefResourceDispatcherHostDelegate>
|
||||
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_
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "libcef/browser/browser_context.h"
|
||||
#include "libcef/browser/browser_host_impl.h"
|
||||
#include "libcef/browser/browser_info.h"
|
||||
#include "libcef/browser/browser_info_manager.h"
|
||||
#include "libcef/browser/browser_main.h"
|
||||
#include "libcef/browser/browser_message_loop.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_runner_.reset(content::ContentMainRunner::Create());
|
||||
browser_info_manager_.reset(new CefBrowserInfoManager);
|
||||
|
||||
int exit_code;
|
||||
|
||||
@ -415,7 +417,7 @@ void CefContext::FinishShutdownOnUIThread(
|
||||
print_job_manager_->Shutdown();
|
||||
print_job_manager_.reset(NULL);
|
||||
|
||||
CefContentBrowserClient::Get()->DestroyAllBrowsers();
|
||||
browser_info_manager_->DestroyAllBrowsers();
|
||||
|
||||
if (trace_subscriber_.get())
|
||||
trace_subscriber_.reset(NULL);
|
||||
@ -436,6 +438,7 @@ void CefContext::FinalizeShutdown() {
|
||||
// Shut down the content runner.
|
||||
main_runner_->Shutdown();
|
||||
|
||||
browser_info_manager_.reset(NULL);
|
||||
main_runner_.reset(NULL);
|
||||
main_delegate_.reset(NULL);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ class PrintJobManager;
|
||||
}
|
||||
|
||||
class CefBrowserHostImpl;
|
||||
class CefBrowserInfoManager;
|
||||
class CefMainDelegate;
|
||||
class CefTraceSubscriber;
|
||||
|
||||
@ -97,6 +98,7 @@ class CefContext {
|
||||
scoped_ptr<CefMainDelegate> main_delegate_;
|
||||
scoped_ptr<content::ContentMainRunner> main_runner_;
|
||||
scoped_ptr<CefTraceSubscriber> trace_subscriber_;
|
||||
scoped_ptr<CefBrowserInfoManager> browser_info_manager_;
|
||||
|
||||
// Only accessed on the UI Thread.
|
||||
scoped_ptr<printing::PrintJobManager> print_job_manager_;
|
||||
|
@ -109,11 +109,10 @@ CefDevToolsFrontend* CefDevToolsFrontend::Show(
|
||||
CefRefPtr<CefBrowserHostImpl> frontend_browser =
|
||||
CefBrowserHostImpl::Create(windowInfo, client, CefString(),
|
||||
new_settings,
|
||||
inspected_browser->GetWindowHandle(), true,
|
||||
inspected_browser, true,
|
||||
inspected_browser->GetRequestContext());
|
||||
|
||||
content::WebContents* inspected_contents =
|
||||
inspected_browser->GetWebContents();
|
||||
content::WebContents* inspected_contents = inspected_browser->web_contents();
|
||||
if (!inspect_element_at.IsEmpty()) {
|
||||
scoped_refptr<content::DevToolsAgentHost> agent_host =
|
||||
content::DevToolsAgentHost::GetOrCreateFor(inspected_contents);
|
||||
@ -166,7 +165,7 @@ void CefDevToolsFrontend::DisconnectFromTarget() {
|
||||
CefDevToolsFrontend::CefDevToolsFrontend(
|
||||
CefRefPtr<CefBrowserHostImpl> frontend_browser,
|
||||
content::WebContents* inspected_contents)
|
||||
: WebContentsObserver(frontend_browser->GetWebContents()),
|
||||
: WebContentsObserver(frontend_browser->web_contents()),
|
||||
frontend_browser_(frontend_browser),
|
||||
inspected_contents_(inspected_contents),
|
||||
weak_factory_(this) {
|
||||
|
@ -142,7 +142,7 @@ class CefBeforeDownloadCallbackImpl : public CefBeforeDownloadCallback {
|
||||
if (browser.get()) {
|
||||
handled = true;
|
||||
|
||||
CefBrowserHostImpl::FileChooserParams params;
|
||||
CefFileDialogRunner::FileChooserParams params;
|
||||
params.mode = content::FileChooserParams::Save;
|
||||
if (!suggested_path.empty()) {
|
||||
params.default_file_name = suggested_path;
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
#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/common/extensions/extensions_util.h"
|
||||
|
||||
@ -72,7 +72,7 @@ CefRefPtr<CefBrowserHostImpl> GetOwnerBrowserForView(int render_process_id,
|
||||
} else {
|
||||
// Use the thread-safe approach.
|
||||
scoped_refptr<CefBrowserInfo> info =
|
||||
CefContentBrowserClient::Get()->GetBrowserInfoForView(
|
||||
CefBrowserInfoManager::GetInstance()->GetBrowserInfoForView(
|
||||
render_process_id, render_routing_id, is_guest_view);
|
||||
if (info.get()) {
|
||||
CefRefPtr<CefBrowserHostImpl> browser = info->browser();
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include "libcef/browser/browser_host_impl.h"
|
||||
#include "libcef/browser/browser_info.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/web_contents/web_contents_impl.h"
|
||||
@ -43,7 +43,7 @@ void CefMimeHandlerViewGuestDelegate::OverrideWebContentsCreateParams(
|
||||
|
||||
CefRefPtr<CefBrowserHostImpl> owner_browser = GetOwnerBrowser(guest_);
|
||||
if (owner_browser->IsWindowless()) {
|
||||
CefWebContentsViewOSR* view_osr = new CefWebContentsViewOSR();
|
||||
CefWebContentsViewOSR* view_osr = new CefWebContentsViewOSR(false);
|
||||
params->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/browser_host_impl.h"
|
||||
#include "libcef/browser/javascript_dialog.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
@ -68,13 +67,24 @@ class CefJSDialogCallbackImpl : public CefJSDialogCallback {
|
||||
|
||||
|
||||
CefJavaScriptDialogManager::CefJavaScriptDialogManager(
|
||||
CefBrowserHostImpl* browser)
|
||||
: browser_(browser) {
|
||||
CefBrowserHostImpl* browser,
|
||||
scoped_ptr<CefJavaScriptDialogRunner> runner)
|
||||
: browser_(browser),
|
||||
runner_(runner.Pass()),
|
||||
dialog_running_(false),
|
||||
weak_ptr_factory_(this) {
|
||||
}
|
||||
|
||||
CefJavaScriptDialogManager::~CefJavaScriptDialogManager() {
|
||||
}
|
||||
|
||||
void CefJavaScriptDialogManager::Destroy() {
|
||||
if (runner_.get()) {
|
||||
DCHECK(!dialog_running_);
|
||||
runner_.reset(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void CefJavaScriptDialogManager::RunJavaScriptDialog(
|
||||
content::WebContents* web_contents,
|
||||
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;
|
||||
|
||||
if (dialog_.get()) {
|
||||
// One dialog at a time, please.
|
||||
if (!runner_.get() || dialog_running_) {
|
||||
// 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;
|
||||
return;
|
||||
}
|
||||
|
||||
dialog_running_ = true;
|
||||
|
||||
base::string16 display_url =
|
||||
url_formatter::FormatUrlForSecurityDisplay(origin_url, accept_lang);
|
||||
|
||||
dialog_.reset(new CefJavaScriptDialog(this,
|
||||
message_type,
|
||||
display_url,
|
||||
message_text,
|
||||
runner_->Run(browser_, message_type, display_url, message_text,
|
||||
default_prompt_text,
|
||||
callback));
|
||||
#else
|
||||
// TODO(port): implement CefJavaScriptDialog for other platforms.
|
||||
*did_suppress_message = true;
|
||||
return;
|
||||
#endif
|
||||
base::Bind(&CefJavaScriptDialogManager::DialogClosed,
|
||||
weak_ptr_factory_.GetWeakPtr(), callback));
|
||||
}
|
||||
|
||||
void CefJavaScriptDialogManager::RunBeforeUnloadDialog(
|
||||
@ -166,29 +173,28 @@ void CefJavaScriptDialogManager::RunBeforeUnloadDialog(
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK)
|
||||
if (dialog_.get()) {
|
||||
// Seriously!?
|
||||
if (!runner_.get() || dialog_running_) {
|
||||
if (!runner_.get())
|
||||
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());
|
||||
return;
|
||||
}
|
||||
|
||||
dialog_running_ = true;
|
||||
|
||||
base::string16 new_message_text =
|
||||
message_text +
|
||||
base::ASCIIToUTF16("\n\nIs it OK to leave/reload this page?");
|
||||
|
||||
dialog_.reset(
|
||||
new CefJavaScriptDialog(this,
|
||||
runner_->Run(browser_,
|
||||
content::JAVASCRIPT_MESSAGE_TYPE_CONFIRM,
|
||||
base::string16(), // display_url
|
||||
new_message_text,
|
||||
base::string16(), // default_prompt_text
|
||||
callback));
|
||||
#else
|
||||
// TODO(port): implement CefJavaScriptDialog for other platforms.
|
||||
callback.Run(true, base::string16());
|
||||
return;
|
||||
#endif
|
||||
base::Bind(&CefJavaScriptDialogManager::DialogClosed,
|
||||
weak_ptr_factory_.GetWeakPtr(), callback));
|
||||
}
|
||||
|
||||
void CefJavaScriptDialogManager::CancelActiveAndPendingDialogs(
|
||||
@ -202,27 +208,31 @@ void CefJavaScriptDialogManager::CancelActiveAndPendingDialogs(
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK)
|
||||
if (dialog_.get()) {
|
||||
dialog_->Cancel();
|
||||
dialog_.reset();
|
||||
if (runner_.get() && dialog_running_) {
|
||||
runner_->Cancel();
|
||||
dialog_running_ = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void CefJavaScriptDialogManager::ResetDialogState(
|
||||
content::WebContents* web_contents) {
|
||||
}
|
||||
|
||||
void CefJavaScriptDialogManager::DialogClosed(CefJavaScriptDialog* dialog) {
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK)
|
||||
DCHECK_EQ(dialog, dialog_.get());
|
||||
dialog_.reset();
|
||||
void CefJavaScriptDialogManager::DialogClosed(
|
||||
const DialogClosedCallback& callback,
|
||||
bool success,
|
||||
const base::string16& user_input) {
|
||||
CefRefPtr<CefClient> client = browser_->GetClient();
|
||||
if (client.get()) {
|
||||
CefRefPtr<CefJSDialogHandler> handler = client->GetJSDialogHandler();
|
||||
if (handler.get())
|
||||
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 "libcef/browser/javascript_dialog_runner.h"
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "content/public/browser/javascript_dialog_manager.h"
|
||||
|
||||
class CefBrowserHostImpl;
|
||||
class CefJavaScriptDialog;
|
||||
|
||||
class CefJavaScriptDialogManager : public content::JavaScriptDialogManager {
|
||||
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;
|
||||
|
||||
// Delete the runner to free any platform constructs.
|
||||
void Destroy();
|
||||
|
||||
// JavaScriptDialogManager methods.
|
||||
void RunJavaScriptDialog(
|
||||
content::WebContents* web_contents,
|
||||
@ -31,32 +39,32 @@ class CefJavaScriptDialogManager : public content::JavaScriptDialogManager {
|
||||
const base::string16& default_prompt_text,
|
||||
const DialogClosedCallback& callback,
|
||||
bool* did_suppress_message) override;
|
||||
|
||||
void RunBeforeUnloadDialog(
|
||||
content::WebContents* web_contents,
|
||||
const base::string16& message_text,
|
||||
bool is_reload,
|
||||
const DialogClosedCallback& callback) override;
|
||||
|
||||
void CancelActiveAndPendingDialogs(
|
||||
content::WebContents* web_contents) override;
|
||||
|
||||
void ResetDialogState(
|
||||
content::WebContents* web_contents) override;
|
||||
|
||||
// Called by the CefJavaScriptDialog when it closes.
|
||||
void DialogClosed(CefJavaScriptDialog* dialog);
|
||||
|
||||
CefBrowserHostImpl* browser() const { return browser_; }
|
||||
|
||||
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_;
|
||||
|
||||
#if defined(OS_MACOSX) || defined(OS_WIN) || defined(TOOLKIT_GTK)
|
||||
// The dialog being shown. No queueing.
|
||||
scoped_ptr<CefJavaScriptDialog> dialog_;
|
||||
#endif
|
||||
scoped_ptr<CefJavaScriptDialogRunner> runner_;
|
||||
|
||||
// True if a dialog is currently running.
|
||||
bool dialog_running_;
|
||||
|
||||
// Must be the last member.
|
||||
base::WeakPtrFactory<CefJavaScriptDialogManager> weak_ptr_factory_;
|
||||
|
||||
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
|
||||
// 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/context_menu_params_impl.h"
|
||||
#include "libcef/browser/menu_runner.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
#include "libcef/common/content_client.h"
|
||||
|
||||
@ -15,14 +17,6 @@
|
||||
#include "content/public/browser/render_widget_host_view.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 {
|
||||
|
||||
CefString GetLabel(int message_id) {
|
||||
@ -93,24 +87,30 @@ class CefRunContextMenuCallbackImpl : public CefRunContextMenuCallback {
|
||||
|
||||
} // namespace
|
||||
|
||||
CefMenuCreator::CefMenuCreator(content::WebContents* web_contents,
|
||||
CefBrowserHostImpl* browser)
|
||||
: content::WebContentsObserver(web_contents),
|
||||
CefMenuManager::CefMenuManager(CefBrowserHostImpl* browser,
|
||||
scoped_ptr<CefMenuRunner> runner)
|
||||
: content::WebContentsObserver(browser->web_contents()),
|
||||
browser_(browser),
|
||||
runner_(runner.Pass()),
|
||||
custom_menu_callback_(NULL),
|
||||
weak_ptr_factory_(this) {
|
||||
DCHECK(web_contents);
|
||||
DCHECK(browser_);
|
||||
DCHECK(web_contents());
|
||||
DCHECK(runner_.get());
|
||||
model_ = new CefMenuModelImpl(this);
|
||||
}
|
||||
|
||||
CefMenuCreator::~CefMenuCreator() {
|
||||
CefMenuManager::~CefMenuManager() {
|
||||
// The model may outlive the delegate if the context menu is visible when the
|
||||
// application is closed.
|
||||
model_->set_delegate(NULL);
|
||||
}
|
||||
|
||||
bool CefMenuCreator::IsShowingContextMenu() {
|
||||
void CefMenuManager::Destroy() {
|
||||
CancelContextMenu();
|
||||
runner_.reset(NULL);
|
||||
}
|
||||
|
||||
bool CefMenuManager::IsShowingContextMenu() {
|
||||
if (!web_contents())
|
||||
return false;
|
||||
content::RenderWidgetHostView* view =
|
||||
@ -118,11 +118,8 @@ bool CefMenuCreator::IsShowingContextMenu() {
|
||||
return (view && view->IsShowingContextMenu());
|
||||
}
|
||||
|
||||
bool CefMenuCreator::CreateContextMenu(
|
||||
bool CefMenuManager::CreateContextMenu(
|
||||
const content::ContextMenuParams& params) {
|
||||
if (!CreateRunner())
|
||||
return true;
|
||||
|
||||
// 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
|
||||
// because mouse events are not forwarded once the context menu is showing.
|
||||
@ -162,7 +159,7 @@ bool CefMenuCreator::CreateContextMenu(
|
||||
if (model_->GetCount() > 0) {
|
||||
CefRefPtr<CefRunContextMenuCallbackImpl> callbackImpl(
|
||||
new CefRunContextMenuCallbackImpl(
|
||||
base::Bind(&CefMenuCreator::ExecuteCommandCallback,
|
||||
base::Bind(&CefMenuManager::ExecuteCommandCallback,
|
||||
weak_ptr_factory_.GetWeakPtr())));
|
||||
|
||||
// This reference will be cleared when the callback is executed or
|
||||
@ -198,10 +195,10 @@ bool CefMenuCreator::CreateContextMenu(
|
||||
|
||||
if (custom_menu)
|
||||
return true;
|
||||
return runner_->RunContextMenu(this);
|
||||
return runner_->RunContextMenu(browser_, model_->model(), params_);
|
||||
}
|
||||
|
||||
void CefMenuCreator::CancelContextMenu() {
|
||||
void CefMenuManager::CancelContextMenu() {
|
||||
if (IsShowingContextMenu()) {
|
||||
if (custom_menu_callback_)
|
||||
custom_menu_callback_->Cancel();
|
||||
@ -210,24 +207,7 @@ void CefMenuCreator::CancelContextMenu() {
|
||||
}
|
||||
}
|
||||
|
||||
bool CefMenuCreator::CreateRunner() {
|
||||
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,
|
||||
void CefMenuManager::ExecuteCommand(CefRefPtr<CefMenuModelImpl> source,
|
||||
int command_id,
|
||||
cef_event_flags_t event_flags) {
|
||||
// Give the client a chance to handle the command.
|
||||
@ -259,7 +239,7 @@ void CefMenuCreator::ExecuteCommand(CefRefPtr<CefMenuModelImpl> source,
|
||||
ExecuteDefaultCommand(command_id);
|
||||
}
|
||||
|
||||
void CefMenuCreator::MenuWillShow(CefRefPtr<CefMenuModelImpl> source) {
|
||||
void CefMenuManager::MenuWillShow(CefRefPtr<CefMenuModelImpl> source) {
|
||||
// May be called for sub-menus as well.
|
||||
if (source.get() != model_.get())
|
||||
return;
|
||||
@ -278,7 +258,7 @@ void CefMenuCreator::MenuWillShow(CefRefPtr<CefMenuModelImpl> source) {
|
||||
view->SetShowingContextMenu(true);
|
||||
}
|
||||
|
||||
void CefMenuCreator::MenuClosed(CefRefPtr<CefMenuModelImpl> source) {
|
||||
void CefMenuManager::MenuClosed(CefRefPtr<CefMenuModelImpl> source) {
|
||||
// May be called for sub-menus as well.
|
||||
if (source.get() != model_.get())
|
||||
return;
|
||||
@ -306,11 +286,11 @@ void CefMenuCreator::MenuClosed(CefRefPtr<CefMenuModelImpl> source) {
|
||||
web_contents()->NotifyContextMenuClosed(params_.custom_context);
|
||||
}
|
||||
|
||||
bool CefMenuCreator::FormatLabel(base::string16& label) {
|
||||
bool CefMenuManager::FormatLabel(base::string16& label) {
|
||||
return runner_->FormatLabel(label);
|
||||
}
|
||||
|
||||
void CefMenuCreator::ExecuteCommandCallback(int command_id,
|
||||
void CefMenuManager::ExecuteCommandCallback(int command_id,
|
||||
cef_event_flags_t event_flags) {
|
||||
DCHECK(IsShowingContextMenu());
|
||||
DCHECK(custom_menu_callback_);
|
||||
@ -320,7 +300,7 @@ void CefMenuCreator::ExecuteCommandCallback(int command_id,
|
||||
custom_menu_callback_ = NULL;
|
||||
}
|
||||
|
||||
void CefMenuCreator::CreateDefaultModel() {
|
||||
void CefMenuManager::CreateDefaultModel() {
|
||||
if (!params_.custom_items.empty()) {
|
||||
// Custom menu items originating from the renderer process. For example,
|
||||
// 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 (web_contents()) {
|
||||
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.
|
||||
if (command_id < MENU_ID_CUSTOM_FIRST || command_id > MENU_ID_CUSTOM_LAST)
|
||||
return false;
|
@ -8,6 +8,8 @@
|
||||
|
||||
#include "libcef/browser/menu_model_impl.h"
|
||||
|
||||
#include "libcef/browser/menu_runner.h"
|
||||
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
@ -18,24 +20,18 @@ class RenderFrameHost;
|
||||
class WebContents;
|
||||
};
|
||||
|
||||
class CefRunContextMenuCallback;
|
||||
class CefBrowserHostImpl;
|
||||
class CefRunContextMenuCallback;
|
||||
|
||||
class CefMenuCreator : public CefMenuModelImpl::Delegate,
|
||||
class CefMenuManager : public CefMenuModelImpl::Delegate,
|
||||
public content::WebContentsObserver {
|
||||
public:
|
||||
// Used for OS-specific menu implementations.
|
||||
class Runner {
|
||||
public:
|
||||
virtual ~Runner() {}
|
||||
virtual bool RunContextMenu(CefMenuCreator* manager) =0;
|
||||
virtual void CancelContextMenu() {}
|
||||
virtual bool FormatLabel(base::string16& label) { return false; }
|
||||
};
|
||||
CefMenuManager(CefBrowserHostImpl* browser,
|
||||
scoped_ptr<CefMenuRunner> runner);
|
||||
~CefMenuManager() override;
|
||||
|
||||
CefMenuCreator(content::WebContents* web_contents,
|
||||
CefBrowserHostImpl* browser);
|
||||
~CefMenuCreator() override;
|
||||
// Delete the runner to free any platform constructs.
|
||||
void Destroy();
|
||||
|
||||
// Returns true if the context menu is currently showing.
|
||||
bool IsShowingContextMenu();
|
||||
@ -44,14 +40,7 @@ class CefMenuCreator : public CefMenuModelImpl::Delegate,
|
||||
bool CreateContextMenu(const content::ContextMenuParams& params);
|
||||
void CancelContextMenu();
|
||||
|
||||
CefBrowserHostImpl* browser() { return browser_; }
|
||||
ui::MenuModel* model() { return model_->model(); }
|
||||
const content::ContextMenuParams& params() const { return params_; }
|
||||
|
||||
private:
|
||||
// Create the menu runner if it doesn't already exist.
|
||||
bool CreateRunner();
|
||||
|
||||
// CefMenuModelImpl::Delegate methods.
|
||||
void ExecuteCommand(CefRefPtr<CefMenuModelImpl> source,
|
||||
int command_id,
|
||||
@ -74,17 +63,18 @@ class CefMenuCreator : public CefMenuModelImpl::Delegate,
|
||||
// CefBrowserHostImpl pointer is guaranteed to outlive this object.
|
||||
CefBrowserHostImpl* browser_;
|
||||
|
||||
scoped_ptr<CefMenuRunner> runner_;
|
||||
|
||||
CefRefPtr<CefMenuModelImpl> model_;
|
||||
content::ContextMenuParams params_;
|
||||
scoped_ptr<Runner> runner_;
|
||||
|
||||
// Not owned by this class.
|
||||
CefRunContextMenuCallback* custom_menu_callback_;
|
||||
|
||||
// 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_
|
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.
|
||||
// Portions copyright (c) 2011 The Chromium Authors. All rights reserved.
|
||||
// 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_host_impl.h"
|
||||
#include "libcef/browser/native/browser_platform_delegate_native_linux.h"
|
||||
|
||||
// Include this first to avoid type conflict errors.
|
||||
#include "base/tracked_objects.h"
|
||||
#undef Status
|
||||
|
||||
#include <sys/sysinfo.h>
|
||||
#include <X11/cursorfont.h>
|
||||
|
||||
#include "libcef/browser/browser_host_impl.h"
|
||||
#include "libcef/browser/context.h"
|
||||
#include "libcef/browser/window_delegate_view.h"
|
||||
#include "libcef/browser/window_x11.h"
|
||||
#include "libcef/browser/native/menu_runner_linux.h"
|
||||
#include "libcef/browser/native/window_delegate_view.h"
|
||||
#include "libcef/browser/native/window_x11.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
#include "content/public/browser/native_web_keyboard_event.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 "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/widget.h"
|
||||
|
||||
@ -37,121 +35,27 @@ long GetSystemUptime() {
|
||||
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
|
||||
|
||||
ui::PlatformCursor CefBrowserHostImpl::GetPlatformCursor(
|
||||
blink::WebCursorInfo::Type type) {
|
||||
if (type == WebCursorInfo::TypeNone) {
|
||||
if (!invisible_cursor_) {
|
||||
invisible_cursor_.reset(
|
||||
new ui::XScopedCursor(ui::CreateInvisibleCursor(),
|
||||
gfx::GetXDisplay()));
|
||||
CefBrowserPlatformDelegateNativeLinux::CefBrowserPlatformDelegateNativeLinux(
|
||||
const CefWindowInfo& window_info)
|
||||
: CefBrowserPlatformDelegateNative(window_info),
|
||||
host_window_created_(false),
|
||||
window_widget_(nullptr),
|
||||
window_x11_(nullptr) {
|
||||
}
|
||||
return invisible_cursor_->get();
|
||||
} else {
|
||||
return ui::GetXCursor(ToCursorID(type));
|
||||
|
||||
void CefBrowserPlatformDelegateNativeLinux::BrowserDestroyed(
|
||||
CefBrowserHostImpl* browser) {
|
||||
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_widget_);
|
||||
|
||||
@ -165,11 +69,13 @@ bool CefBrowserHostImpl::PlatformCreateWindow() {
|
||||
|
||||
// Create a new window object. It will delete itself when the associated X11
|
||||
// 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();
|
||||
|
||||
// Add a reference that will be released in the destroy handler.
|
||||
AddRef();
|
||||
host_window_created_ = true;
|
||||
|
||||
// Add a reference that will be released in BrowserDestroyed().
|
||||
browser_->AddRef();
|
||||
|
||||
SkColor background_color = SK_ColorWHITE;
|
||||
const CefSettings& settings = CefContext::Get()->settings();
|
||||
@ -183,7 +89,7 @@ bool CefBrowserHostImpl::PlatformCreateWindow() {
|
||||
CefWindowDelegateView* delegate_view =
|
||||
new CefWindowDelegateView(background_color);
|
||||
delegate_view->Init(window_info_.window,
|
||||
web_contents(),
|
||||
browser_->web_contents(),
|
||||
gfx::Rect(gfx::Point(), rect.size()));
|
||||
|
||||
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
|
||||
// render widgets in webkit.
|
||||
content::RendererPreferences* prefs =
|
||||
web_contents_->GetMutableRendererPrefs();
|
||||
browser_->web_contents()->GetMutableRendererPrefs();
|
||||
prefs->focus_ring_color = SkColorSetARGB(255, 229, 151, 0);
|
||||
prefs->thumb_active_color = SkColorSetRGB(244, 244, 244);
|
||||
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_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;
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformCloseWindow() {
|
||||
void CefBrowserPlatformDelegateNativeLinux::CloseHostWindow() {
|
||||
if (window_x11_)
|
||||
window_x11_->Close();
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformSizeTo(int width, int height) {
|
||||
if (window_x11_) {
|
||||
window_x11_->SetBounds(
|
||||
gfx::Rect(window_x11_->bounds().origin(), gfx::Size(width, height)));
|
||||
}
|
||||
CefWindowHandle
|
||||
CefBrowserPlatformDelegateNativeLinux::GetHostWindowHandle() const {
|
||||
if (windowless_handler_)
|
||||
return windowless_handler_->GetParentWindowHandle();
|
||||
return window_info_.window;
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformSetFocus(bool focus) {
|
||||
if (!focus)
|
||||
views::Widget* CefBrowserPlatformDelegateNativeLinux::GetWindowWidget() const {
|
||||
return window_widget_;
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateNativeLinux::SendFocusEvent(bool setFocus) {
|
||||
if (!setFocus)
|
||||
return;
|
||||
|
||||
if (web_contents_) {
|
||||
if (browser_->web_contents()) {
|
||||
// Give logical focus to the RenderWidgetHostViewAura in the views
|
||||
// hierarchy. This does not change the native keyboard focus.
|
||||
web_contents_->Focus();
|
||||
browser_->web_contents()->Focus();
|
||||
}
|
||||
|
||||
if (window_x11_) {
|
||||
@ -238,26 +160,66 @@ void CefBrowserHostImpl::PlatformSetFocus(bool focus) {
|
||||
}
|
||||
}
|
||||
|
||||
CefWindowHandle CefBrowserHostImpl::PlatformGetWindowHandle() {
|
||||
return IsWindowless() ? window_info_.parent_window : window_info_.window;
|
||||
void CefBrowserPlatformDelegateNativeLinux::NotifyMoveOrResizeStarted() {
|
||||
// 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) {
|
||||
CEF_REQUIRE_UIT();
|
||||
void CefBrowserPlatformDelegateNativeLinux::SizeTo(int width, int height) {
|
||||
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";
|
||||
int fd = mkstemp(buff);
|
||||
|
||||
if (fd == -1)
|
||||
return false;
|
||||
return;
|
||||
|
||||
FILE* srcOutput = fdopen(fd, "w+");
|
||||
if (!srcOutput)
|
||||
return false;
|
||||
return;
|
||||
|
||||
if (fputs(text.c_str(), srcOutput) < 0) {
|
||||
fclose(srcOutput);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
fclose(srcOutput);
|
||||
@ -265,35 +227,26 @@ bool CefBrowserHostImpl::PlatformViewText(const std::string& text) {
|
||||
std::string newName(buff);
|
||||
newName.append(".txt");
|
||||
if (rename(buff, newName.c_str()) != 0)
|
||||
return false;
|
||||
return;
|
||||
|
||||
std::string openCommand("xdg-open ");
|
||||
openCommand += newName;
|
||||
|
||||
if (system(openCommand.c_str()) != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
system(openCommand.c_str());
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformHandleKeyboardEvent(
|
||||
void CefBrowserPlatformDelegateNativeLinux::HandleKeyboardEvent(
|
||||
const content::NativeWebKeyboardEvent& event) {
|
||||
// TODO(cef): Is something required here to handle shortcut keys?
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformRunFileChooser(
|
||||
const FileChooserParams& params,
|
||||
RunFileChooserCallback callback) {
|
||||
NOTIMPLEMENTED();
|
||||
callback.Run(0, std::vector<base::FilePath>());
|
||||
void CefBrowserPlatformDelegateNativeLinux::HandleExternalProtocol(
|
||||
const GURL& url) {
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformHandleExternalProtocol(const GURL& url) {
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformTranslateKeyEvent(
|
||||
void CefBrowserPlatformDelegateNativeLinux::TranslateKeyEvent(
|
||||
content::NativeWebKeyboardEvent& result,
|
||||
const CefKeyEvent& key_event) {
|
||||
const CefKeyEvent& key_event) const {
|
||||
result.timeStampSeconds = GetSystemUptime();
|
||||
|
||||
result.windowsKeyCode = key_event.windows_key_code;
|
||||
@ -322,12 +275,12 @@ void CefBrowserHostImpl::PlatformTranslateKeyEvent(
|
||||
result.modifiers |= TranslateModifiers(key_event.modifiers);
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformTranslateClickEvent(
|
||||
void CefBrowserPlatformDelegateNativeLinux::TranslateClickEvent(
|
||||
blink::WebMouseEvent& result,
|
||||
const CefMouseEvent& mouse_event,
|
||||
MouseButtonType type,
|
||||
bool mouseUp, int clickCount) {
|
||||
PlatformTranslateMouseEvent(result, mouse_event);
|
||||
CefBrowserHost::MouseButtonType type,
|
||||
bool mouseUp, int clickCount) const {
|
||||
TranslateMouseEvent(result, mouse_event);
|
||||
|
||||
switch (type) {
|
||||
case MBT_LEFT:
|
||||
@ -352,11 +305,11 @@ void CefBrowserHostImpl::PlatformTranslateClickEvent(
|
||||
result.clickCount = clickCount;
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformTranslateMoveEvent(
|
||||
void CefBrowserPlatformDelegateNativeLinux::TranslateMoveEvent(
|
||||
blink::WebMouseEvent& result,
|
||||
const CefMouseEvent& mouse_event,
|
||||
bool mouseLeave) {
|
||||
PlatformTranslateMouseEvent(result, mouse_event);
|
||||
bool mouseLeave) const {
|
||||
TranslateMouseEvent(result, mouse_event);
|
||||
|
||||
if (!mouseLeave) {
|
||||
result.type = blink::WebInputEvent::MouseMove;
|
||||
@ -376,12 +329,12 @@ void CefBrowserHostImpl::PlatformTranslateMoveEvent(
|
||||
result.clickCount = 0;
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::PlatformTranslateWheelEvent(
|
||||
void CefBrowserPlatformDelegateNativeLinux::TranslateWheelEvent(
|
||||
blink::WebMouseWheelEvent& result,
|
||||
const CefMouseEvent& mouse_event,
|
||||
int deltaX, int deltaY) {
|
||||
int deltaX, int deltaY) const {
|
||||
result = blink::WebMouseWheelEvent();
|
||||
PlatformTranslateMouseEvent(result, mouse_event);
|
||||
TranslateMouseEvent(result, mouse_event);
|
||||
|
||||
result.type = blink::WebInputEvent::MouseWheel;
|
||||
|
||||
@ -407,28 +360,30 @@ void CefBrowserHostImpl::PlatformTranslateWheelEvent(
|
||||
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,
|
||||
const CefMouseEvent& mouse_event) {
|
||||
const CefMouseEvent& mouse_event) const {
|
||||
// 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 if (window_x11_) {
|
||||
const gfx::Point& origin = window_x11_->bounds().origin();
|
||||
result.globalX += origin.x();
|
||||
result.globalY += origin.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);
|
||||
@ -437,25 +392,3 @@ void CefBrowserHostImpl::PlatformTranslateMouseEvent(
|
||||
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
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "libcef/browser/javascript_dialog.h"
|
||||
#include "libcef/browser/javascript_dialog_manager.h"
|
||||
#include "libcef/browser/native/javascript_dialog_runner_mac.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/utf_string_conversions.h"
|
||||
|
||||
@ -20,12 +19,11 @@
|
||||
NSTextField* textField_; // WEAK; owned by alert_
|
||||
|
||||
// Copies of the fields in CefJavaScriptDialog because they're private.
|
||||
CefJavaScriptDialogManager* creator_;
|
||||
content::JavaScriptDialogManager::DialogClosedCallback callback_;
|
||||
CefJavaScriptDialogRunner::DialogClosedCallback callback_;
|
||||
}
|
||||
|
||||
- (id)initHelperWithCreator:(CefJavaScriptDialogManager*)creator
|
||||
andCallback:(content::JavaScriptDialogManager::DialogClosedCallback)callback;
|
||||
- (id)initHelperWithCallback:
|
||||
(CefJavaScriptDialogRunner::DialogClosedCallback)callback;
|
||||
- (NSAlert*)alert;
|
||||
- (NSTextField*)textField;
|
||||
- (void)alertDidEnd:(NSAlert*)alert
|
||||
@ -37,12 +35,10 @@
|
||||
|
||||
@implementation CefJavaScriptDialogHelper
|
||||
|
||||
- (id)initHelperWithCreator:(CefJavaScriptDialogManager*)creator
|
||||
andCallback:(content::JavaScriptDialogManager::DialogClosedCallback)callback {
|
||||
if (self = [super init]) {
|
||||
creator_ = creator;
|
||||
- (id)initHelperWithCallback:
|
||||
(CefJavaScriptDialogRunner::DialogClosedCallback)callback {
|
||||
if (self = [super init])
|
||||
callback_ = callback;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
@ -73,10 +69,7 @@
|
||||
if (textField_)
|
||||
input = base::SysNSStringToUTF16([textField_ stringValue]);
|
||||
|
||||
CefJavaScriptDialog* native_dialog =
|
||||
reinterpret_cast<CefJavaScriptDialog*>(contextInfo);
|
||||
callback_.Run(success, input);
|
||||
creator_->DialogClosed(native_dialog);
|
||||
}
|
||||
|
||||
- (void)cancel {
|
||||
@ -86,23 +79,33 @@
|
||||
|
||||
@end
|
||||
|
||||
CefJavaScriptDialog::CefJavaScriptDialog(
|
||||
CefJavaScriptDialogManager* creator,
|
||||
CefJavaScriptDialogRunnerMac::CefJavaScriptDialogRunnerMac()
|
||||
: weak_ptr_factory_(this) {
|
||||
}
|
||||
|
||||
CefJavaScriptDialogRunnerMac::~CefJavaScriptDialogRunnerMac() {
|
||||
Cancel();
|
||||
}
|
||||
|
||||
void CefJavaScriptDialogRunnerMac::Run(
|
||||
CefBrowserHostImpl* browser,
|
||||
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) {
|
||||
const DialogClosedCallback& callback) {
|
||||
DCHECK(!helper_.get());
|
||||
callback_ = callback;
|
||||
|
||||
bool text_field =
|
||||
message_type == content::JAVASCRIPT_MESSAGE_TYPE_PROMPT;
|
||||
bool one_button =
|
||||
message_type == content::JAVASCRIPT_MESSAGE_TYPE_ALERT;
|
||||
|
||||
helper_ =
|
||||
[[CefJavaScriptDialogHelper alloc] initHelperWithCreator:creator
|
||||
andCallback:callback];
|
||||
helper_.reset(
|
||||
[[CefJavaScriptDialogHelper alloc] initHelperWithCallback:
|
||||
base::Bind(&CefJavaScriptDialogRunnerMac::DialogClosed,
|
||||
weak_ptr_factory_.GetWeakPtr())]);
|
||||
|
||||
// Show the modal dialog.
|
||||
NSAlert* alert = [helper_ alert];
|
||||
@ -147,10 +150,17 @@ CefJavaScriptDialog::CefJavaScriptDialog(
|
||||
[[alert window] makeFirstResponder:[alert accessoryView]];
|
||||
}
|
||||
|
||||
CefJavaScriptDialog::~CefJavaScriptDialog() {
|
||||
[helper_ release];
|
||||
void CefJavaScriptDialogRunnerMac::Cancel() {
|
||||
if (helper_.get()) {
|
||||
[helper_ cancel];
|
||||
helper_.reset(nil);
|
||||
}
|
||||
}
|
||||
|
||||
void CefJavaScriptDialog::Cancel() {
|
||||
[helper_ cancel];
|
||||
void CefJavaScriptDialogRunnerMac::DialogClosed(
|
||||
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
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "libcef/browser/javascript_dialog.h"
|
||||
#include "libcef/browser/javascript_dialog_manager.h"
|
||||
#include "libcef/browser/native/javascript_dialog_runner_win.h"
|
||||
|
||||
#include "libcef/browser/browser_host_impl.h"
|
||||
#include "libcef_dll/resource.h"
|
||||
|
||||
@ -13,20 +13,18 @@
|
||||
#include "base/strings/string_util.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
|
||||
class CefJavaScriptDialog;
|
||||
class CefJavaScriptDialogRunnerWin;
|
||||
|
||||
HHOOK CefJavaScriptDialog::msg_hook_ = NULL;
|
||||
int CefJavaScriptDialog::msg_hook_user_count_ = 0;
|
||||
HHOOK CefJavaScriptDialogRunnerWin::msg_hook_ = NULL;
|
||||
int CefJavaScriptDialogRunnerWin::msg_hook_user_count_ = 0;
|
||||
|
||||
INT_PTR CALLBACK CefJavaScriptDialog::DialogProc(HWND dialog,
|
||||
UINT message,
|
||||
WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
INT_PTR CALLBACK CefJavaScriptDialogRunnerWin::DialogProc(
|
||||
HWND dialog, UINT message, WPARAM wparam, LPARAM lparam) {
|
||||
switch (message) {
|
||||
case WM_INITDIALOG: {
|
||||
SetWindowLongPtr(dialog, DWLP_USER, static_cast<LONG_PTR>(lparam));
|
||||
CefJavaScriptDialog* owner =
|
||||
reinterpret_cast<CefJavaScriptDialog*>(lparam);
|
||||
CefJavaScriptDialogRunnerWin* owner =
|
||||
reinterpret_cast<CefJavaScriptDialogRunnerWin*>(lparam);
|
||||
owner->dialog_win_ = dialog;
|
||||
SetDlgItemText(dialog, IDC_DIALOGTEXT, owner->message_text_.c_str());
|
||||
if (owner->message_type_ == content::JAVASCRIPT_MESSAGE_TYPE_PROMPT)
|
||||
@ -35,12 +33,12 @@ INT_PTR CALLBACK CefJavaScriptDialog::DialogProc(HWND dialog,
|
||||
break;
|
||||
}
|
||||
case WM_CLOSE: {
|
||||
CefJavaScriptDialog* owner = reinterpret_cast<CefJavaScriptDialog*>(
|
||||
CefJavaScriptDialogRunnerWin* owner =
|
||||
reinterpret_cast<CefJavaScriptDialogRunnerWin*>(
|
||||
GetWindowLongPtr(dialog, DWLP_USER));
|
||||
if (owner) {
|
||||
owner->Cancel();
|
||||
owner->callback_.Run(false, base::string16());
|
||||
owner->creator_->DialogClosed(owner);
|
||||
|
||||
// No need for the system to call DestroyWindow() because it will be
|
||||
// called by the Cancel() method.
|
||||
@ -49,7 +47,8 @@ INT_PTR CALLBACK CefJavaScriptDialog::DialogProc(HWND dialog,
|
||||
break;
|
||||
}
|
||||
case WM_COMMAND: {
|
||||
CefJavaScriptDialog* owner = reinterpret_cast<CefJavaScriptDialog*>(
|
||||
CefJavaScriptDialogRunnerWin* owner =
|
||||
reinterpret_cast<CefJavaScriptDialogRunnerWin*>(
|
||||
GetWindowLongPtr(dialog, DWLP_USER));
|
||||
base::string16 user_input;
|
||||
bool finish = false;
|
||||
@ -75,7 +74,6 @@ INT_PTR CALLBACK CefJavaScriptDialog::DialogProc(HWND dialog,
|
||||
if (finish) {
|
||||
owner->Cancel();
|
||||
owner->callback_.Run(result, user_input);
|
||||
owner->creator_->DialogClosed(owner);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -85,19 +83,32 @@ INT_PTR CALLBACK CefJavaScriptDialog::DialogProc(HWND dialog,
|
||||
return 0;
|
||||
}
|
||||
|
||||
CefJavaScriptDialog::CefJavaScriptDialog(
|
||||
CefJavaScriptDialogManager* creator,
|
||||
CefJavaScriptDialogRunnerWin::CefJavaScriptDialogRunnerWin()
|
||||
: dialog_win_(NULL),
|
||||
parent_win_(NULL),
|
||||
hook_installed_(false) {
|
||||
}
|
||||
|
||||
CefJavaScriptDialogRunnerWin::~CefJavaScriptDialogRunnerWin() {
|
||||
Cancel();
|
||||
}
|
||||
|
||||
void CefJavaScriptDialogRunnerWin::Run(
|
||||
CefBrowserHostImpl* browser,
|
||||
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),
|
||||
message_type_(message_type),
|
||||
message_text_(message_text),
|
||||
default_prompt_text_(default_prompt_text) {
|
||||
const DialogClosedCallback& callback) {
|
||||
DCHECK(!dialog_win_);
|
||||
|
||||
message_type_ = message_type;
|
||||
message_text_ = message_text;
|
||||
default_prompt_text_ = default_prompt_text;
|
||||
callback_ = callback;
|
||||
|
||||
InstallMessageHook();
|
||||
hook_installed_ = true;
|
||||
|
||||
int dialog_type;
|
||||
if (message_type == content::JAVASCRIPT_MESSAGE_TYPE_ALERT)
|
||||
@ -117,7 +128,7 @@ CefJavaScriptDialog::CefJavaScriptDialog(
|
||||
hModule = ::GetModuleHandle(NULL);
|
||||
DCHECK(hModule);
|
||||
|
||||
parent_win_ = GetAncestor(creator->browser()->GetWindowHandle(), GA_ROOT);
|
||||
parent_win_ = GetAncestor(browser->GetWindowHandle(), GA_ROOT);
|
||||
dialog_win_ = CreateDialogParam(hModule,
|
||||
MAKEINTRESOURCE(dialog_type),
|
||||
parent_win_,
|
||||
@ -142,12 +153,7 @@ CefJavaScriptDialog::CefJavaScriptDialog(
|
||||
ShowWindow(dialog_win_, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
CefJavaScriptDialog::~CefJavaScriptDialog() {
|
||||
Cancel();
|
||||
UninstallMessageHook();
|
||||
}
|
||||
|
||||
void CefJavaScriptDialog::Cancel() {
|
||||
void CefJavaScriptDialogRunnerWin::Cancel() {
|
||||
HWND parent = NULL;
|
||||
|
||||
// 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.
|
||||
if (parent)
|
||||
SetFocus(parent);
|
||||
|
||||
if (hook_installed_) {
|
||||
UninstallMessageHook();
|
||||
hook_installed_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
LRESULT CALLBACK CefJavaScriptDialog::GetMsgProc(int code, WPARAM wparam,
|
||||
LPARAM lparam) {
|
||||
LRESULT CALLBACK CefJavaScriptDialogRunnerWin::GetMsgProc(
|
||||
int code, WPARAM wparam, LPARAM lparam) {
|
||||
// Mostly borrowed from http://support.microsoft.com/kb/q187988/
|
||||
// and http://www.codeproject.com/KB/atl/cdialogmessagehook.aspx.
|
||||
LPMSG msg = reinterpret_cast<LPMSG>(lparam);
|
||||
@ -196,7 +207,7 @@ LRESULT CALLBACK CefJavaScriptDialog::GetMsgProc(int code, WPARAM wparam,
|
||||
}
|
||||
|
||||
// static
|
||||
bool CefJavaScriptDialog::InstallMessageHook() {
|
||||
bool CefJavaScriptDialogRunnerWin::InstallMessageHook() {
|
||||
msg_hook_user_count_++;
|
||||
|
||||
// Make sure we only call this once.
|
||||
@ -204,7 +215,7 @@ bool CefJavaScriptDialog::InstallMessageHook() {
|
||||
return true;
|
||||
|
||||
msg_hook_ = ::SetWindowsHookEx(WH_GETMESSAGE,
|
||||
&CefJavaScriptDialog::GetMsgProc,
|
||||
&CefJavaScriptDialogRunnerWin::GetMsgProc,
|
||||
NULL,
|
||||
GetCurrentThreadId());
|
||||
DCHECK(msg_hook_ != NULL);
|
||||
@ -212,7 +223,7 @@ bool CefJavaScriptDialog::InstallMessageHook() {
|
||||
}
|
||||
|
||||
// static
|
||||
bool CefJavaScriptDialog::UninstallMessageHook() {
|
||||
bool CefJavaScriptDialogRunnerWin::UninstallMessageHook() {
|
||||
msg_hook_user_count_--;
|
||||
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
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_H_
|
||||
#define CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_H_
|
||||
#ifndef CEF_LIBCEF_BROWSER_NATIVE_JAVASCRIPT_DIALOG_RUNNER_WIN_H_
|
||||
#define CEF_LIBCEF_BROWSER_NATIVE_JAVASCRIPT_DIALOG_RUNNER_WIN_H_
|
||||
#pragma once
|
||||
|
||||
#include "content/public/browser/javascript_dialog_manager.h"
|
||||
#include "libcef/browser/javascript_dialog_runner.h"
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#if __OBJC__
|
||||
@class CefJavaScriptDialogHelper;
|
||||
#else
|
||||
class CefJavaScriptDialogHelper;
|
||||
#endif // __OBJC__
|
||||
#endif // defined(OS_MACOSX)
|
||||
|
||||
class CefJavaScriptDialogManager;
|
||||
|
||||
class CefJavaScriptDialog {
|
||||
class CefJavaScriptDialogRunnerWin : public CefJavaScriptDialogRunner {
|
||||
public:
|
||||
CefJavaScriptDialog(
|
||||
CefJavaScriptDialogManager* creator,
|
||||
CefJavaScriptDialogRunnerWin();
|
||||
~CefJavaScriptDialogRunnerWin() 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 content::JavaScriptDialogManager::DialogClosedCallback& callback);
|
||||
~CefJavaScriptDialog();
|
||||
|
||||
// Called to cancel a dialog mid-flight.
|
||||
void Cancel();
|
||||
|
||||
// Activate the dialog.
|
||||
void Activate();
|
||||
const DialogClosedCallback& callback) override;
|
||||
void Cancel() override;
|
||||
|
||||
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 parent_win_;
|
||||
|
||||
content::JavaScriptMessageType message_type_;
|
||||
base::string16 message_text_;
|
||||
base::string16 default_prompt_text_;
|
||||
DialogClosedCallback callback_;
|
||||
|
||||
bool hook_installed_;
|
||||
|
||||
static INT_PTR CALLBACK DialogProc(HWND dialog, UINT message, WPARAM wparam,
|
||||
LPARAM lparam);
|
||||
|
||||
@ -59,9 +46,6 @@ class CefJavaScriptDialog {
|
||||
static LRESULT CALLBACK GetMsgProc(int code, WPARAM wparam, LPARAM lparam);
|
||||
static HHOOK msg_hook_;
|
||||
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
|
||||
// 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 "ui/views/background.h"
|
@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be found
|
||||
// in the LICENSE file.
|
||||
|
||||
#ifndef CEF_LIBCEF_BROWSER_WINDOW_DELEGATE_VIEW_H_
|
||||
#define CEF_LIBCEF_BROWSER_WINDOW_DELEGATE_VIEW_H_
|
||||
#ifndef CEF_LIBCEF_BROWSER_NATIVE_WINDOW_DELEGATE_VIEW_H_
|
||||
#define CEF_LIBCEF_BROWSER_NATIVE_WINDOW_DELEGATE_VIEW_H_
|
||||
#pragma once
|
||||
|
||||
#include "ui/views/widget/widget_delegate.h"
|
||||
@ -47,4 +47,4 @@ class CefWindowDelegateView : public views::WidgetDelegateView {
|
||||
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
|
||||
// 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 <X11/extensions/XInput2.h>
|
@ -3,8 +3,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CEF_LIBCEF_BROWSER_WINDOW_X11_H_
|
||||
#define CEF_LIBCEF_BROWSER_WINDOW_X11_H_
|
||||
#ifndef CEF_LIBCEF_BROWSER_NATIVE_WINDOW_X11_H_
|
||||
#define CEF_LIBCEF_BROWSER_NATIVE_WINDOW_X11_H_
|
||||
#pragma once
|
||||
|
||||
#include <X11/Xlib.h>
|
||||
@ -75,4 +75,4 @@ class CefWindowX11 : public ui::PlatformEventDispatcher {
|
||||
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
|
||||
// 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/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 "base/callback_helpers.h"
|
||||
@ -34,10 +36,6 @@ namespace {
|
||||
|
||||
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.
|
||||
const int kFrameRetryLimit = 2;
|
||||
|
||||
@ -437,9 +435,11 @@ class CefBeginFrameTimer : public cc::DelayBasedTimeSourceClient {
|
||||
|
||||
|
||||
CefRenderWidgetHostViewOSR::CefRenderWidgetHostViewOSR(
|
||||
bool transparent,
|
||||
content::RenderWidgetHost* widget,
|
||||
CefRenderWidgetHostViewOSR* parent_host_view)
|
||||
: scale_factor_(kDefaultScaleFactor),
|
||||
: transparent_(transparent),
|
||||
scale_factor_(kDefaultScaleFactor),
|
||||
frame_rate_threshold_ms_(0),
|
||||
delegated_frame_host_(new content::DelegatedFrameHost(this)),
|
||||
compositor_widget_(gfx::kNullAcceleratedWidget),
|
||||
@ -767,7 +767,7 @@ void CefRenderWidgetHostViewOSR::UpdateCursor(
|
||||
// |web_cursor| owns the resulting |platform_cursor|.
|
||||
platform_cursor = web_cursor.GetPlatformCursor();
|
||||
} else {
|
||||
platform_cursor = browser_impl_->GetPlatformCursor(cursor_info.type);
|
||||
platform_cursor = GetPlatformCursor(cursor_info.type);
|
||||
}
|
||||
|
||||
handler->OnCursorChange(browser_impl_.get(), platform_cursor, cursor_type,
|
||||
@ -1003,8 +1003,7 @@ CefRenderWidgetHostViewOSR::CreateSoftwareOutputDevice(
|
||||
DCHECK(!copy_frame_generator_);
|
||||
DCHECK(!software_output_device_);
|
||||
software_output_device_ = new CefSoftwareOutputDeviceOSR(
|
||||
compositor,
|
||||
browser_impl_.get() ? browser_impl_->IsTransparent() : false,
|
||||
compositor, transparent_,
|
||||
base::Bind(&CefRenderWidgetHostViewOSR::OnPaint,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
return make_scoped_ptr<cc::SoftwareOutputDevice>(software_output_device_);
|
||||
@ -1070,7 +1069,7 @@ void CefRenderWidgetHostViewOSR::DelegatedFrameHostUpdateVSyncParameters(
|
||||
}
|
||||
|
||||
bool CefRenderWidgetHostViewOSR::InstallTransparency() {
|
||||
if (browser_impl_.get() && browser_impl_->IsTransparent()) {
|
||||
if (transparent_) {
|
||||
SetBackgroundColor(SkColorSetARGB(SK_AlphaTRANSPARENT, 0, 0, 0));
|
||||
compositor_->SetHostHasTransparentBackground(true);
|
||||
return true;
|
||||
@ -1284,15 +1283,6 @@ void CefRenderWidgetHostViewOSR::RemoveGuestHostView(
|
||||
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() {
|
||||
CefRefPtr<CefBrowserHostImpl> browser;
|
||||
if (parent_host_view_) {
|
||||
@ -1308,7 +1298,7 @@ void CefRenderWidgetHostViewOSR::SetFrameRate() {
|
||||
return;
|
||||
|
||||
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;
|
||||
|
||||
// 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
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CEF_LIBCEF_BROWSER_RENDER_WIDGET_HOST_VIEW_OSR_H_
|
||||
#define CEF_LIBCEF_BROWSER_RENDER_WIDGET_HOST_VIEW_OSR_H_
|
||||
#ifndef CEF_LIBCEF_BROWSER_OSR_RENDER_WIDGET_HOST_VIEW_OSR_H_
|
||||
#define CEF_LIBCEF_BROWSER_OSR_RENDER_WIDGET_HOST_VIEW_OSR_H_
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
@ -18,6 +18,10 @@
|
||||
#include "content/browser/renderer_host/render_widget_host_view_base.h"
|
||||
#include "ui/compositor/compositor.h"
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
#include "ui/base/x/x11_util.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
#include "content/browser/compositor/browser_compositor_view_mac.h"
|
||||
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
|
||||
@ -79,7 +83,8 @@ class CefRenderWidgetHostViewOSR
|
||||
public ui::CompositorDelegate,
|
||||
public content::DelegatedFrameHostClient {
|
||||
public:
|
||||
CefRenderWidgetHostViewOSR(content::RenderWidgetHost* widget,
|
||||
CefRenderWidgetHostViewOSR(const bool transparent,
|
||||
content::RenderWidgetHost* widget,
|
||||
CefRenderWidgetHostViewOSR* parent_host_view);
|
||||
~CefRenderWidgetHostViewOSR() override;
|
||||
|
||||
@ -284,8 +289,6 @@ class CefRenderWidgetHostViewOSR
|
||||
content::RenderWidgetHostImpl* render_widget_host() const
|
||||
{ return render_widget_host_; }
|
||||
|
||||
static int ClampFrameRate(int frame_rate);
|
||||
|
||||
private:
|
||||
void SetFrameRate();
|
||||
void SetDeviceScaleFactor();
|
||||
@ -328,6 +331,12 @@ class CefRenderWidgetHostViewOSR
|
||||
void PlatformCreateCompositorWidget();
|
||||
void PlatformDestroyCompositorWidget();
|
||||
|
||||
#if defined(USE_AURA)
|
||||
ui::PlatformCursor GetPlatformCursor(blink::WebCursorInfo::Type type);
|
||||
#endif
|
||||
|
||||
const bool transparent_;
|
||||
|
||||
float scale_factor_;
|
||||
int frame_rate_threshold_ms_;
|
||||
|
||||
@ -344,6 +353,7 @@ class CefRenderWidgetHostViewOSR
|
||||
scoped_ptr<content::BrowserCompositorMac> browser_compositor_;
|
||||
#elif defined(USE_X11)
|
||||
CefWindowX11* window_;
|
||||
scoped_ptr<ui::XScopedCursor> invisible_cursor_;
|
||||
#endif
|
||||
|
||||
// Used to control the VSync rate in subprocesses when BeginFrame scheduling
|
||||
@ -403,5 +413,5 @@ class 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
|
||||
// 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>
|
||||
|
||||
#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/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
|
||||
// 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/render_widget_host_view_osr.h"
|
||||
#include "libcef/browser/osr/render_widget_host_view_osr.h"
|
||||
#include "libcef/browser/thread_util.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
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CEF_LIBCEF_BROWSER_SOFTWARE_OUTPUT_DEVICE_OSR_H_
|
||||
#define CEF_LIBCEF_BROWSER_SOFTWARE_OUTPUT_DEVICE_OSR_H_
|
||||
#ifndef CEF_LIBCEF_BROWSER_OSR_SOFTWARE_OUTPUT_DEVICE_OSR_H_
|
||||
#define CEF_LIBCEF_BROWSER_OSR_SOFTWARE_OUTPUT_DEVICE_OSR_H_
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
@ -52,4 +52,4 @@ class CefSoftwareOutputDeviceOSR : public cc::SoftwareOutputDevice {
|
||||
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
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#ifndef CEF_LIBCEF_BROWSER_TEXT_INPUT_CLIENT_OSR_MAC_H_
|
||||
#define CEF_LIBCEF_BROWSER_TEXT_INPUT_CLIENT_OSR_MAC_H_
|
||||
#ifndef CEF_LIBCEF_BROWSER_OSR_TEXT_INPUT_CLIENT_OSR_MAC_H_
|
||||
#define CEF_LIBCEF_BROWSER_OSR_TEXT_INPUT_CLIENT_OSR_MAC_H_
|
||||
#pragma once
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#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/strings/string16.h"
|
||||
@ -73,4 +73,4 @@
|
||||
|
||||
@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
|
||||
// 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 "base/numerics/safe_conversions.h"
|
@ -3,9 +3,10 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// 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/render_widget_host_view_osr.h"
|
||||
#include "libcef/browser/osr/render_widget_host_view_osr.h"
|
||||
#include "libcef/common/drag_data_impl.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/user_metrics.h"
|
||||
|
||||
CefWebContentsViewOSR::CefWebContentsViewOSR()
|
||||
: web_contents_(NULL),
|
||||
CefWebContentsViewOSR::CefWebContentsViewOSR(bool transparent)
|
||||
: transparent_(transparent),
|
||||
web_contents_(NULL),
|
||||
view_(NULL),
|
||||
guest_(NULL) {
|
||||
}
|
||||
@ -126,7 +128,8 @@ content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget(
|
||||
embedder_web_contents->GetRenderViewHost()->GetWidget()->GetView());
|
||||
|
||||
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);
|
||||
|
||||
return new content::RenderWidgetHostViewGuest(
|
||||
@ -135,7 +138,8 @@ content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget(
|
||||
platform_widget->GetWeakPtr());
|
||||
}
|
||||
|
||||
view_ = new CefRenderWidgetHostViewOSR(render_widget_host, NULL);
|
||||
view_ = new CefRenderWidgetHostViewOSR(transparent_, render_widget_host,
|
||||
NULL);
|
||||
return view_;
|
||||
}
|
||||
|
||||
@ -143,7 +147,8 @@ content::RenderWidgetHostViewBase* CefWebContentsViewOSR::CreateViewForWidget(
|
||||
content::RenderWidgetHostViewBase*
|
||||
CefWebContentsViewOSR::CreateViewForPopupWidget(
|
||||
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) {
|
@ -3,8 +3,8 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CEF_LIBCEF_BROWSER_WEB_CONTENTS_VIEW_OSR_H_
|
||||
#define CEF_LIBCEF_BROWSER_WEB_CONTENTS_VIEW_OSR_H_
|
||||
#ifndef CEF_LIBCEF_BROWSER_OSR_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/web_contents/web_contents_view.h"
|
||||
@ -21,10 +21,11 @@ class CefRenderWidgetHostViewOSR;
|
||||
class CefWebContentsViewOSR : public content::WebContentsView,
|
||||
public content::RenderViewHostDelegateView {
|
||||
public:
|
||||
CefWebContentsViewOSR();
|
||||
explicit CefWebContentsViewOSR(bool transparent);
|
||||
~CefWebContentsViewOSR() override;
|
||||
|
||||
void set_web_contents(content::WebContents* web_contents);
|
||||
content::WebContents* web_contents() const { return web_contents_; }
|
||||
void set_guest(content::BrowserPluginGuest* guest);
|
||||
|
||||
// WebContentsView methods.
|
||||
@ -68,6 +69,8 @@ class CefWebContentsViewOSR : public content::WebContentsView,
|
||||
void UpdateDragCursor(blink::WebDragOperation operation) override;
|
||||
|
||||
private:
|
||||
const bool transparent_;
|
||||
|
||||
content::WebContents* web_contents_;
|
||||
CefRenderWidgetHostViewOSR* view_;
|
||||
|
||||
@ -77,4 +80,4 @@ class CefWebContentsViewOSR : public content::WebContentsView,
|
||||
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/metrics/user_metrics_action.h"
|
||||
#include "base/path_service.h"
|
||||
#include "base/stl_util.h"
|
||||
#include "base/strings/string_number_conversions.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "chrome/common/chrome_switches.h"
|
||||
@ -58,6 +59,7 @@
|
||||
#include "content/public/renderer/render_view.h"
|
||||
#include "content/public/renderer/render_view_visitor.h"
|
||||
#include "content/renderer/render_frame_impl.h"
|
||||
#include "content/renderer/render_widget.h"
|
||||
#include "extensions/renderer/renderer_extension_registry.h"
|
||||
#include "ipc/ipc_sync_channel.h"
|
||||
#include "media/base/media.h"
|
||||
@ -147,6 +149,20 @@ std::string GetPluginInstancePosterAttribute(
|
||||
|
||||
} // 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()
|
||||
: devtools_agent_count_(0),
|
||||
uncaught_exception_stack_size_(0),
|
||||
@ -162,6 +178,10 @@ CefContentRendererClient::CefContentRendererClient()
|
||||
}
|
||||
|
||||
CefContentRendererClient::~CefContentRendererClient() {
|
||||
if (!guest_views_.empty()) {
|
||||
STLDeleteContainerPairSecondPointers(guest_views_.begin(),
|
||||
guest_views_.end());
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
@ -209,6 +229,28 @@ void CefContentRendererClient::OnBrowserDestroyed(CefBrowserImpl* browser) {
|
||||
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() {
|
||||
const base::CommandLine* command_line =
|
||||
base::CommandLine::ForCurrentProcess();
|
||||
@ -769,24 +811,42 @@ blink::WebPlugin* CefContentRendererClient::CreatePlugin(
|
||||
void CefContentRendererClient::BrowserCreated(
|
||||
content::RenderView* render_view,
|
||||
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
|
||||
// the routing ids with the browser info object in the browser process.
|
||||
CefProcessHostMsg_GetNewBrowserInfo_Params params;
|
||||
content::RenderThread::Get()->Send(
|
||||
new CefProcessHostMsg_GetNewBrowserInfo(
|
||||
render_view->GetRoutingID(),
|
||||
render_frame->GetRoutingID(),
|
||||
render_view_routing_id,
|
||||
render_frame_routing_id,
|
||||
¶ms));
|
||||
DCHECK_GT(params.browser_id, 0);
|
||||
|
||||
if (params.is_guest_view) {
|
||||
// Don't create a CefBrowser for guest views.
|
||||
if (params.browser_id == 0) {
|
||||
// The request failed for some reason.
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't create another browser object if one already exists for the view.
|
||||
if (GetBrowserForView(render_view).get())
|
||||
if (params.is_guest_view) {
|
||||
// Don't create a CefBrowser for guest views.
|
||||
guest_views_.insert(
|
||||
std::make_pair(render_view, new CefGuestView(render_view)));
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(OS_MACOSX)
|
||||
// FIXME: It would be better if this API would be a callback from the
|
||||
|
@ -34,6 +34,7 @@ namespace web_cache {
|
||||
class WebCacheRenderProcessObserver;
|
||||
}
|
||||
|
||||
class CefGuestView;
|
||||
class CefRenderProcessObserver;
|
||||
struct Cef_CrossOriginWhiteListEntry_Params;
|
||||
struct CefViewHostMsg_GetPluginInfo_Output;
|
||||
@ -58,6 +59,12 @@ class CefContentRendererClient : public content::ContentRendererClient,
|
||||
// Called from CefBrowserImpl::OnDestruct().
|
||||
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.
|
||||
base::SequencedTaskRunner* render_task_runner() const {
|
||||
return render_task_runner_.get();
|
||||
@ -143,6 +150,10 @@ class CefContentRendererClient : public content::ContentRendererClient,
|
||||
typedef std::map<content::RenderView*, CefRefPtr<CefBrowserImpl> > BrowserMap;
|
||||
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.
|
||||
typedef std::vector<Cef_CrossOriginWhiteListEntry_Params> CrossOriginList;
|
||||
CrossOriginList cross_origin_whitelist_entries_;
|
||||
|
@ -220,11 +220,10 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
||||
gtk_file_chooser_set_show_hidden(GTK_FILE_CHOOSER(dialog),
|
||||
!(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;
|
||||
bool exists = false;
|
||||
|
||||
if (mode_type == FILE_DIALOG_SAVE) {
|
||||
struct stat sb;
|
||||
if (stat(file_path.c_str(), &sb) == 0 && S_ISREG(sb.st_mode)) {
|
||||
// Use the directory and name of the existing file.
|
||||
@ -232,7 +231,6 @@ bool ClientDialogHandlerGtk::OnFileDialog(
|
||||
file_path.data());
|
||||
exists = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!exists) {
|
||||
// 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 {
|
||||
|
||||
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 kNavigateButtonRect(375, 275, 130, 20);
|
||||
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 kDragDivRect(60, 330, 52, 52);
|
||||
const int kVerticalScrollbarWidth = 15;
|
||||
@ -183,10 +183,15 @@ enum OSRTestType {
|
||||
OSR_TEST_DRAG_DROP_UPDATE_CURSOR,
|
||||
// dropping element inside drop region will move the element
|
||||
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.
|
||||
class OSRTestHandler : public RoutingTestHandler,
|
||||
public CefFocusHandler,
|
||||
public CefRenderHandler,
|
||||
public CefContextMenuHandler {
|
||||
public:
|
||||
@ -278,6 +283,10 @@ class OSRTestHandler : public RoutingTestHandler,
|
||||
}
|
||||
|
||||
// CefClient methods, providing handlers
|
||||
CefRefPtr<CefFocusHandler> GetFocusHandler() override {
|
||||
return this;
|
||||
}
|
||||
|
||||
CefRefPtr<CefRenderHandler> GetRenderHandler() override {
|
||||
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,
|
||||
CefCursorHandle cursor,
|
||||
CursorType type,
|
||||
@ -937,6 +963,23 @@ class OSRTestHandler : public RoutingTestHandler,
|
||||
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() {
|
||||
GetBrowser()->GetHost()->SendFocusEvent(true);
|
||||
CefMouseEvent mouse_event;
|
||||
@ -1013,6 +1056,8 @@ class OSRTestHandler : public RoutingTestHandler,
|
||||
int event_total_;
|
||||
bool started_;
|
||||
TrackCallback got_update_cursor_;
|
||||
TrackCallback got_navigation_focus_event_;
|
||||
TrackCallback got_system_focus_event_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(OSRTestHandler);
|
||||
};
|
||||
|
Reference in New Issue
Block a user