diff --git a/cef.gyp b/cef.gyp index fdec26a85..80312b279 100644 --- a/cef.gyp +++ b/cef.gyp @@ -227,6 +227,7 @@ 'tests/cefclient/client_switches.h', 'tests/unittests/command_line_unittest.cc', 'tests/unittests/cookie_unittest.cc', + 'tests/unittests/jsdialog_unittest.cc', 'tests/unittests/navigation_unittest.cc', 'tests/unittests/process_message_unittest.cc', 'tests/unittests/request_unittest.cc', @@ -716,6 +717,9 @@ 'libcef/browser/download_manager_delegate.h', 'libcef/browser/frame_host_impl.cc', 'libcef/browser/frame_host_impl.h', + 'libcef/browser/javascript_dialog.h', + 'libcef/browser/javascript_dialog_creator.cc', + 'libcef/browser/javascript_dialog_creator.h', 'libcef/browser/navigate_params.cc', 'libcef/browser/navigate_params.h', 'libcef/browser/origin_whitelist_impl.cc', @@ -805,6 +809,7 @@ '<@(includes_win)', 'libcef/browser/browser_host_impl_win.cc', 'libcef/browser/browser_main_win.cc', + 'libcef/browser/javascript_dialog_win.cc', ], }], [ 'OS=="mac"', { @@ -814,6 +819,7 @@ 'libcef/browser/application_mac.mm', 'libcef/browser/browser_host_impl_mac.mm', 'libcef/browser/browser_main_mac.mm', + 'libcef/browser/javascript_dialog_mac.mm', # Include necessary Mozilla sources. Remove these lines once they're # included by content_browser.gypi. See crbug.com/120719. '<(DEPTH)/third_party/mozilla/NSString+Utils.h', diff --git a/cef_paths.gypi b/cef_paths.gypi index 4871c4596..61947c28b 100644 --- a/cef_paths.gypi +++ b/cef_paths.gypi @@ -21,6 +21,7 @@ 'include/cef_display_handler.h', 'include/cef_frame.h', 'include/cef_geolocation_handler.h', + 'include/cef_jsdialog_handler.h', 'include/cef_life_span_handler.h', 'include/cef_load_handler.h', 'include/cef_origin_whitelist.h', @@ -52,6 +53,7 @@ 'include/capi/cef_display_handler_capi.h', 'include/capi/cef_frame_capi.h', 'include/capi/cef_geolocation_handler_capi.h', + 'include/capi/cef_jsdialog_handler_capi.h', 'include/capi/cef_life_span_handler_capi.h', 'include/capi/cef_load_handler_capi.h', 'include/capi/cef_origin_whitelist_capi.h', @@ -104,6 +106,10 @@ 'libcef_dll/cpptoc/geolocation_callback_cpptoc.h', 'libcef_dll/ctocpp/geolocation_handler_ctocpp.cc', 'libcef_dll/ctocpp/geolocation_handler_ctocpp.h', + 'libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc', + 'libcef_dll/cpptoc/jsdialog_callback_cpptoc.h', + 'libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc', + 'libcef_dll/ctocpp/jsdialog_handler_ctocpp.h', 'libcef_dll/ctocpp/life_span_handler_ctocpp.cc', 'libcef_dll/ctocpp/life_span_handler_ctocpp.h', 'libcef_dll/cpptoc/list_value_cpptoc.cc', @@ -190,6 +196,10 @@ 'libcef_dll/ctocpp/geolocation_callback_ctocpp.h', 'libcef_dll/cpptoc/geolocation_handler_cpptoc.cc', 'libcef_dll/cpptoc/geolocation_handler_cpptoc.h', + 'libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc', + 'libcef_dll/ctocpp/jsdialog_callback_ctocpp.h', + 'libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc', + 'libcef_dll/cpptoc/jsdialog_handler_cpptoc.h', 'libcef_dll/cpptoc/life_span_handler_cpptoc.cc', 'libcef_dll/cpptoc/life_span_handler_cpptoc.h', 'libcef_dll/ctocpp/list_value_ctocpp.cc', diff --git a/cef_paths2.gypi b/cef_paths2.gypi index 860101fb1..3bd4ea87a 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -90,6 +90,7 @@ 'tests/cefclient/client_switches.cpp', 'tests/cefclient/client_switches.h', 'tests/cefclient/res/binding.html', + 'tests/cefclient/res/dialogs.html', 'tests/cefclient/res/localstorage.html', 'tests/cefclient/res/logo.png', 'tests/cefclient/res/xmlhttprequest.html', @@ -104,7 +105,7 @@ 'tests/cefclient/cefclient.rc', 'tests/cefclient/cefclient_win.cpp', 'tests/cefclient/client_handler_win.cpp', - 'tests/cefclient/Resource.h', + 'tests/cefclient/resource.h', 'tests/cefclient/res/cefclient.ico', 'tests/cefclient/res/logoball.png', 'tests/cefclient/res/small.ico', @@ -139,6 +140,7 @@ 'tests/cefclient/mac/English.lproj/MainMenu.xib', 'tests/cefclient/mac/Info.plist', 'tests/cefclient/res/binding.html', + 'tests/cefclient/res/dialogs.html', 'tests/cefclient/res/localstorage.html', 'tests/cefclient/res/logo.png', 'tests/cefclient/res/xmlhttprequest.html', diff --git a/include/capi/cef_client_capi.h b/include/capi/cef_client_capi.h index a969f9a8b..ba7e29f18 100644 --- a/include/capi/cef_client_capi.h +++ b/include/capi/cef_client_capi.h @@ -85,6 +85,13 @@ typedef struct _cef_client_t { struct _cef_geolocation_handler_t* (CEF_CALLBACK *get_geolocation_handler)( struct _cef_client_t* self); + /// + // Return the handler for JavaScript dialogs. If no handler is provided the + // default implementation will be used. + /// + struct _cef_jsdialog_handler_t* (CEF_CALLBACK *get_jsdialog_handler)( + struct _cef_client_t* self); + /// // Called when a new message is received from a different process. Return true // (1) if the message was handled or false (0) otherwise. Do not keep a diff --git a/include/capi/cef_jsdialog_handler_capi.h b/include/capi/cef_jsdialog_handler_capi.h new file mode 100644 index 000000000..a667b5a6b --- /dev/null +++ b/include/capi/cef_jsdialog_handler_capi.h @@ -0,0 +1,126 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool and should not edited +// by hand. See the translator.README.txt file in the tools directory for +// more information. +// + +#ifndef CEF_INCLUDE_CAPI_CEF_JSDIALOG_HANDLER_CAPI_H_ +#define CEF_INCLUDE_CAPI_CEF_JSDIALOG_HANDLER_CAPI_H_ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "include/capi/cef_base_capi.h" + + +/// +// Callback structure used for asynchronous continuation of JavaScript dialog +// requests. +/// +typedef struct _cef_jsdialog_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Continue the JS dialog request. Set |success| to true (1) if the OK button + // was pressed. The |user_input| value should be specified for prompt dialogs. + /// + void (CEF_CALLBACK *cont)(struct _cef_jsdialog_callback_t* self, int success, + const cef_string_t* user_input); +} cef_jsdialog_callback_t; + + +/// +// Implement this structure to handle events related to JavaScript dialogs. The +// functions of this structure will be called on the UI thread. +/// +typedef struct _cef_jsdialog_handler_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Called to run a JavaScript dialog. The |default_prompt_text| value will be + // specified for prompt dialogs only. Set |suppress_message| to true (1) and + // return false (0) to suppress the message (suppressing messages is + // preferable to immediately executing the callback as this is used to detect + // presumably malicious behavior like spamming alert messages in + // onbeforeunload). Set |suppress_message| to false (0) and return false (0) + // to use the default implementation (the default implementation will show one + // modal dialog at a time and suppress any additional dialog requests until + // the displayed dialog is dismissed). Return true (1) if the application will + // use a custom dialog or if the callback has been executed immediately. + // Custom dialogs may be either modal or modeless. If a custom dialog is used + // the application must execute |callback| once the custom dialog is + // dismissed. + /// + int (CEF_CALLBACK *on_jsdialog)(struct _cef_jsdialog_handler_t* self, + struct _cef_browser_t* browser, const cef_string_t* origin_url, + const cef_string_t* accept_lang, enum cef_jsdialog_type_t dialog_type, + const cef_string_t* message_text, + const cef_string_t* default_prompt_text, + struct _cef_jsdialog_callback_t* callback, int* suppress_message); + + /// + // Called to run a dialog asking the user if they want to leave a page. Return + // false (0) to use the default dialog implementation. Return true (1) if the + // application will use a custom dialog or if the callback has been executed + // immediately. Custom dialogs may be either modal or modeless. If a custom + // dialog is used the application must execute |callback| once the custom + // dialog is dismissed. + /// + int (CEF_CALLBACK *on_before_unload_dialog)( + struct _cef_jsdialog_handler_t* self, struct _cef_browser_t* browser, + const cef_string_t* message_text, int is_reload, + struct _cef_jsdialog_callback_t* callback); + + /// + // Called to cancel any pending dialogs and reset any saved dialog state. Will + // be called due to events like page navigation irregardless of whether any + // dialogs are currently pending. + /// + void (CEF_CALLBACK *on_reset_dialog_state)( + struct _cef_jsdialog_handler_t* self, struct _cef_browser_t* browser); +} cef_jsdialog_handler_t; + + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_CAPI_CEF_JSDIALOG_HANDLER_CAPI_H_ diff --git a/include/cef_client.h b/include/cef_client.h index 55bf97738..8ded85a79 100644 --- a/include/cef_client.h +++ b/include/cef_client.h @@ -41,6 +41,7 @@ #include "include/cef_base.h" #include "include/cef_display_handler.h" #include "include/cef_geolocation_handler.h" +#include "include/cef_jsdialog_handler.h" #include "include/cef_life_span_handler.h" #include "include/cef_load_handler.h" #include "include/cef_process_message.h" @@ -93,6 +94,15 @@ class CefClient : public virtual CefBase { return NULL; } + /// + // Return the handler for JavaScript dialogs. If no handler is provided the + // default implementation will be used. + /// + /*--cef()--*/ + virtual CefRefPtr GetJSDialogHandler() { + return NULL; + } + /// // Called when a new message is received from a different process. Return true // if the message was handled or false otherwise. Do not keep a reference to diff --git a/include/cef_jsdialog_handler.h b/include/cef_jsdialog_handler.h new file mode 100644 index 000000000..f2a4cf849 --- /dev/null +++ b/include/cef_jsdialog_handler.h @@ -0,0 +1,122 @@ +// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// --------------------------------------------------------------------------- +// +// The contents of this file must follow a specific format in order to +// support the CEF translator tool. See the translator.README.txt file in the +// tools directory for more information. +// + +#ifndef CEF_INCLUDE_CEF_JSDIALOG_HANDLER_H_ +#define CEF_INCLUDE_CEF_JSDIALOG_HANDLER_H_ +#pragma once + +#include "include/cef_base.h" +#include "include/cef_browser.h" + +/// +// Callback interface used for asynchronous continuation of JavaScript dialog +// requests. +/// +/*--cef(source=library)--*/ +class CefJSDialogCallback : public virtual CefBase { + public: + /// + // Continue the JS dialog request. Set |success| to true if the OK button was + // pressed. The |user_input| value should be specified for prompt dialogs. + /// + /*--cef(capi_name=cont,optional_param=user_input)--*/ + virtual void Continue(bool success, + const CefString& user_input) =0; +}; + + +/// +// Implement this interface to handle events related to JavaScript dialogs. The +// methods of this class will be called on the UI thread. +/// +/*--cef(source=client)--*/ +class CefJSDialogHandler : public virtual CefBase { + public: + typedef cef_jsdialog_type_t JSDialogType; + + /// + // Called to run a JavaScript dialog. The |default_prompt_text| value will be + // specified for prompt dialogs only. Set |suppress_message| to true and + // return false to suppress the message (suppressing messages is preferable + // to immediately executing the callback as this is used to detect presumably + // malicious behavior like spamming alert messages in onbeforeunload). Set + // |suppress_message| to false and return false to use the default + // implementation (the default implementation will show one modal dialog at a + // time and suppress any additional dialog requests until the displayed dialog + // is dismissed). Return true if the application will use a custom dialog or + // if the callback has been executed immediately. Custom dialogs may be either + // modal or modeless. If a custom dialog is used the application must execute + // |callback| once the custom dialog is dismissed. + /// + /*--cef(optional_param=accept_lang,optional_param=message_text, + optional_param=default_prompt_text)--*/ + virtual bool OnJSDialog(CefRefPtr browser, + const CefString& origin_url, + const CefString& accept_lang, + JSDialogType dialog_type, + const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message) { + return false; + } + + /// + // Called to run a dialog asking the user if they want to leave a page. Return + // false to use the default dialog implementation. Return true if the + // application will use a custom dialog or if the callback has been executed + // immediately. Custom dialogs may be either modal or modeless. If a custom + // dialog is used the application must execute |callback| once the custom + // dialog is dismissed. + /// + /*--cef(optional_param=message_text)--*/ + virtual bool OnBeforeUnloadDialog(CefRefPtr browser, + const CefString& message_text, + bool is_reload, + CefRefPtr callback) { + return false; + } + + /// + // Called to cancel any pending dialogs and reset any saved dialog state. Will + // be called due to events like page navigation irregardless of whether any + // dialogs are currently pending. + /// + /*--cef()--*/ + virtual void OnResetDialogState(CefRefPtr browser) {} +}; + +#endif // CEF_INCLUDE_CEF_JSDIALOG_HANDLER_H_ diff --git a/include/internal/cef_types.h b/include/internal/cef_types.h index 37c6381ff..f5b5f1700 100644 --- a/include/internal/cef_types.h +++ b/include/internal/cef_types.h @@ -769,6 +769,15 @@ enum cef_value_type_t { VTYPE_LIST, }; +/// +// Supported JavaScript dialog types. +/// +enum cef_jsdialog_type_t { + JSDIALOGTYPE_ALERT = 0, + JSDIALOGTYPE_CONFIRM, + JSDIALOGTYPE_PROMPT, +}; + /// // Supported XML encoding types. The parser supports ASCII, ISO-8859-1, and // UTF16 (LE and BE) by default. All other types must be translated to UTF8 diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index 52c47bece..81bc0e6f9 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -852,10 +852,10 @@ void CefBrowserHostImpl::DidNavigateMainFramePostCommit( } content::JavaScriptDialogCreator* -CefBrowserHostImpl::GetJavaScriptDialogCreator() { - // TODO(cef): Provide a custom JavaScriptDialogCreator implementation to - // support JavaScript alerts, prompts, etc. - return content::WebContentsDelegate::GetJavaScriptDialogCreator(); + CefBrowserHostImpl::GetJavaScriptDialogCreator() { + if (!dialog_creator_.get()) + dialog_creator_.reset(new CefJavaScriptDialogCreator(this)); + return dialog_creator_.get(); } void CefBrowserHostImpl::RunFileChooser( diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index 48f0219c6..57bd15f0e 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -16,6 +16,7 @@ #include "include/cef_client.h" #include "include/cef_frame.h" #include "libcef/browser/frame_host_impl.h" +#include "libcef/browser/javascript_dialog_creator.h" #include "libcef/browser/url_request_context_getter_proxy.h" #include "libcef/common/response_manager.h" @@ -353,6 +354,9 @@ class CefBrowserHostImpl : public CefBrowserHost, // Used for proxying cookie requests. scoped_refptr request_context_proxy_; + // Used for creating and managing JavaScript dialogs. + scoped_ptr dialog_creator_; + IMPLEMENT_REFCOUNTING(CefBrowserHostImpl); DISALLOW_EVIL_CONSTRUCTORS(CefBrowserHostImpl); }; diff --git a/libcef/browser/javascript_dialog.h b/libcef/browser/javascript_dialog.h new file mode 100644 index 000000000..bb6825468 --- /dev/null +++ b/libcef/browser/javascript_dialog.h @@ -0,0 +1,66 @@ +// 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_H_ +#define CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_H_ +#pragma once + +#include "content/public/browser/javascript_dialogs.h" + +#if defined(OS_MACOSX) +#if __OBJC__ +@class CefJavaScriptDialogHelper; +#else +class CefJavaScriptDialogHelper; +#endif // __OBJC__ +#endif // defined(OS_MACOSX) + +class CefJavaScriptDialogCreator; + +class CefJavaScriptDialog { + public: + CefJavaScriptDialog( + CefJavaScriptDialogCreator* creator, + ui::JavascriptMessageType javascript_message_type, + const string16& display_url, + const string16& message_text, + const string16& default_prompt_text, + const content::JavaScriptDialogCreator::DialogClosedCallback& callback); + ~CefJavaScriptDialog(); + + // Called to cancel a dialog mid-flight. + void Cancel(); + + // Activate the dialog. + void Activate(); + + private: + CefJavaScriptDialogCreator* creator_; + content::JavaScriptDialogCreator::DialogClosedCallback callback_; + +#if defined(OS_MACOSX) + CefJavaScriptDialogHelper* helper_; // owned +#elif defined(OS_WIN) + ui::JavascriptMessageType message_type_; + HWND dialog_win_; + HWND parent_win_; + string16 message_text_; + string16 default_prompt_text_; + static INT_PTR CALLBACK DialogProc(HWND dialog, UINT message, WPARAM wparam, + LPARAM lparam); + + // Since the message loop we expect to run in isn't going to be nicely + // calling IsDialogMessage(), we need to hook the wnd proc and call it + // ourselves. See http://support.microsoft.com/kb/q187988/ + static bool InstallMessageHook(); + static bool UninstallMessageHook(); + static LRESULT CALLBACK GetMsgProc(int code, WPARAM wparam, LPARAM lparam); + static HHOOK msg_hook_; +#endif + + DISALLOW_COPY_AND_ASSIGN(CefJavaScriptDialog); +}; + +#endif // CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_H_ diff --git a/libcef/browser/javascript_dialog_creator.cc b/libcef/browser/javascript_dialog_creator.cc new file mode 100644 index 000000000..5fd0e7693 --- /dev/null +++ b/libcef/browser/javascript_dialog_creator.cc @@ -0,0 +1,204 @@ +// 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_creator.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/javascript_dialog.h" +#include "libcef/browser/thread_util.h" + +#include "base/bind.h" +#include "base/logging.h" +#include "base/utf_string_conversions.h" +#include "net/base/net_util.h" + +namespace { + +class CefJSDialogCallbackImpl : public CefJSDialogCallback { + public: + CefJSDialogCallbackImpl( + const content::JavaScriptDialogCreator::DialogClosedCallback& callback) + : callback_(callback) { + } + ~CefJSDialogCallbackImpl() { + 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(&CefJSDialogCallbackImpl::CancelNow, callback_)); + } + } + } + + virtual void Continue(bool success, + const CefString& user_input) OVERRIDE { + if (CEF_CURRENTLY_ON_UIT()) { + if (!callback_.is_null()) { + callback_.Run(success, user_input); + callback_.Reset(); + } + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefJSDialogCallbackImpl::Continue, this, success, + user_input)); + } + } + + void Disconnect() { + callback_.Reset(); + } + + private: + static void CancelNow( + const content::JavaScriptDialogCreator::DialogClosedCallback& callback) { + CEF_REQUIRE_UIT(); + callback.Run(false, string16()); + } + + content::JavaScriptDialogCreator::DialogClosedCallback callback_; + + IMPLEMENT_REFCOUNTING(CefJSDialogCallbackImpl); +}; + +} // namespace + + +CefJavaScriptDialogCreator::CefJavaScriptDialogCreator( + CefBrowserHostImpl* browser) + : browser_(browser) { +} + +CefJavaScriptDialogCreator::~CefJavaScriptDialogCreator() { +} + +void CefJavaScriptDialogCreator::RunJavaScriptDialog( + content::WebContents* web_contents, + const GURL& origin_url, + const std::string& accept_lang, + ui::JavascriptMessageType javascript_message_type, + const string16& message_text, + const string16& default_prompt_text, + const DialogClosedCallback& callback, + bool* did_suppress_message) { + CefRefPtr client = browser_->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetJSDialogHandler(); + if (handler.get()) { + *did_suppress_message = false; + + CefRefPtr callbackPtr( + new CefJSDialogCallbackImpl(callback)); + + // Execute the user callback. + bool handled = handler->OnJSDialog(browser_, origin_url.spec(), + accept_lang, + static_cast(javascript_message_type), + message_text, default_prompt_text, callbackPtr.get(), + *did_suppress_message); + if (handled) + return; + + callbackPtr->Disconnect(); + if (*did_suppress_message) + return; + } + } + +#if defined(OS_MACOSX) || defined(OS_WIN) + *did_suppress_message = false; + + if (dialog_.get()) { + // One dialog at a time, please. + *did_suppress_message = true; + return; + } + + string16 display_url = net::FormatUrl(origin_url, accept_lang); + + dialog_.reset(new CefJavaScriptDialog(this, + javascript_message_type, + display_url, + message_text, + default_prompt_text, + callback)); +#else + // TODO(port): implement CefJavaScriptDialog for other platforms. + *did_suppress_message = true; + return; +#endif +} + +void CefJavaScriptDialogCreator::RunBeforeUnloadDialog( + content::WebContents* web_contents, + const string16& message_text, + bool is_reload, + const DialogClosedCallback& callback) { + CefRefPtr client = browser_->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetJSDialogHandler(); + if (handler.get()) { + CefRefPtr callbackPtr( + new CefJSDialogCallbackImpl(callback)); + + // Execute the user callback. + bool handled = handler->OnBeforeUnloadDialog(browser_, message_text, + is_reload, callbackPtr.get()); + if (handled) + return; + + callbackPtr->Disconnect(); + } + } + +#if defined(OS_MACOSX) || defined(OS_WIN) + if (dialog_.get()) { + // Seriously!? + callback.Run(true, string16()); + return; + } + + string16 new_message_text = + message_text + + ASCIIToUTF16("\n\nIs it OK to leave/reload this page?"); + + dialog_.reset(new CefJavaScriptDialog(this, + ui::JAVASCRIPT_MESSAGE_TYPE_CONFIRM, + string16(), // display_url + new_message_text, + string16(), // default_prompt_text + callback)); +#else + // TODO(port): implement CefJavaScriptDialog for other platforms. + callback.Run(true, string16()); + return; +#endif +} + +void CefJavaScriptDialogCreator::ResetJavaScriptState( + content::WebContents* web_contents) { + CefRefPtr client = browser_->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetJSDialogHandler(); + if (handler.get()) { + // Execute the user callback. + handler->OnResetDialogState(browser_); + } + } + +#if defined(OS_MACOSX) || defined(OS_WIN) + if (dialog_.get()) { + dialog_->Cancel(); + dialog_.reset(); + } +#endif +} + +void CefJavaScriptDialogCreator::DialogClosed(CefJavaScriptDialog* dialog) { +#if defined(OS_MACOSX) || defined(OS_WIN) + DCHECK_EQ(dialog, dialog_.get()); + dialog_.reset(); +#endif +} diff --git a/libcef/browser/javascript_dialog_creator.h b/libcef/browser/javascript_dialog_creator.h new file mode 100644 index 000000000..26ef2d427 --- /dev/null +++ b/libcef/browser/javascript_dialog_creator.h @@ -0,0 +1,61 @@ +// 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_CREATOR_H_ +#define CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_CREATOR_H_ +#pragma once + +#include + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "content/public/browser/javascript_dialogs.h" + +class CefBrowserHostImpl; +class CefJavaScriptDialog; + +class CefJavaScriptDialogCreator : public content::JavaScriptDialogCreator { + public: + explicit CefJavaScriptDialogCreator(CefBrowserHostImpl* browser); + virtual ~CefJavaScriptDialogCreator(); + + // JavaScriptDialogCreator methods. + virtual void RunJavaScriptDialog( + content::WebContents* web_contents, + const GURL& origin_url, + const std::string& accept_lang, + ui::JavascriptMessageType javascript_message_type, + const string16& message_text, + const string16& default_prompt_text, + const DialogClosedCallback& callback, + bool* did_suppress_message) OVERRIDE; + + virtual void RunBeforeUnloadDialog( + content::WebContents* web_contents, + const string16& message_text, + bool is_reload, + const DialogClosedCallback& callback) OVERRIDE; + + virtual void ResetJavaScriptState( + 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 CefJavaScriptDialogCreator. + CefBrowserHostImpl* browser_; + +#if defined(OS_MACOSX) || defined(OS_WIN) + // The dialog being shown. No queueing. + scoped_ptr dialog_; +#endif + + DISALLOW_COPY_AND_ASSIGN(CefJavaScriptDialogCreator); +}; + +#endif // CEF_LIBCEF_BROWSER_JAVASCRIPT_DIALOG_CREATOR_H_ diff --git a/libcef/browser/javascript_dialog_mac.mm b/libcef/browser/javascript_dialog_mac.mm new file mode 100644 index 000000000..bc31981a8 --- /dev/null +++ b/libcef/browser/javascript_dialog_mac.mm @@ -0,0 +1,156 @@ +// 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_creator.h" + +#import + +#import "base/mac/cocoa_protocols.h" +#import "base/memory/scoped_nsobject.h" +#include "base/sys_string_conversions.h" +#include "base/utf_string_conversions.h" + +// Helper object that receives the notification that the dialog/sheet is +// going away. Is responsible for cleaning itself up. +@interface CefJavaScriptDialogHelper : NSObject { + @private + scoped_nsobject alert_; + NSTextField* textField_; // WEAK; owned by alert_ + + // Copies of the fields in CefJavaScriptDialog because they're private. + CefJavaScriptDialogCreator* creator_; + content::JavaScriptDialogCreator::DialogClosedCallback callback_; +} + +- (id)initHelperWithCreator:(CefJavaScriptDialogCreator*)creator + andCallback:(content::JavaScriptDialogCreator::DialogClosedCallback)callback; +- (NSAlert*)alert; +- (NSTextField*)textField; +- (void)alertDidEnd:(NSAlert*)alert + returnCode:(int)returnCode + contextInfo:(void*)contextInfo; +- (void)cancel; + +@end + +@implementation CefJavaScriptDialogHelper + +- (id)initHelperWithCreator:(CefJavaScriptDialogCreator*)creator + andCallback:(content::JavaScriptDialogCreator::DialogClosedCallback)callback { + if (self = [super init]) { + creator_ = creator; + callback_ = callback; + } + + return self; +} + +- (NSAlert*)alert { + alert_.reset([[NSAlert alloc] init]); + return alert_; +} + +- (NSTextField*)textField { + textField_ = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 300, 22)]; + [[textField_ cell] setLineBreakMode:NSLineBreakByTruncatingTail]; + [alert_ setAccessoryView:textField_]; + [textField_ release]; + + return textField_; +} + +- (void)alertDidEnd:(NSAlert*)alert + returnCode:(int)returnCode + contextInfo:(void*)contextInfo { + if (returnCode == NSRunStoppedResponse) + return; + + bool success = returnCode == NSAlertFirstButtonReturn; + string16 input; + if (textField_) + input = base::SysNSStringToUTF16([textField_ stringValue]); + + CefJavaScriptDialog* native_dialog = + reinterpret_cast(contextInfo); + callback_.Run(success, input); + creator_->DialogClosed(native_dialog); +} + +- (void)cancel { + [NSApp endSheet:[alert_ window]]; + alert_.reset(); +} + +@end + +CefJavaScriptDialog::CefJavaScriptDialog( + CefJavaScriptDialogCreator* creator, + ui::JavascriptMessageType javascript_message_type, + const string16& display_url, + const string16& message_text, + const string16& default_prompt_text, + const content::JavaScriptDialogCreator::DialogClosedCallback& callback) + : creator_(creator), + callback_(callback) { + bool text_field = + javascript_message_type == ui::JAVASCRIPT_MESSAGE_TYPE_PROMPT; + bool one_button = + javascript_message_type == ui::JAVASCRIPT_MESSAGE_TYPE_ALERT; + + helper_ = + [[CefJavaScriptDialogHelper alloc] initHelperWithCreator:creator + andCallback:callback]; + + // Show the modal dialog. + NSAlert* alert = [helper_ alert]; + NSTextField* field = nil; + if (text_field) { + field = [helper_ textField]; + [field setStringValue:base::SysUTF16ToNSString(default_prompt_text)]; + } + [alert setDelegate:helper_]; + [alert setInformativeText:base::SysUTF16ToNSString(message_text)]; + + string16 label; + switch (javascript_message_type) { + case ui::JAVASCRIPT_MESSAGE_TYPE_ALERT: + label = ASCIIToUTF16("JavaScript Alert"); + break; + case ui::JAVASCRIPT_MESSAGE_TYPE_PROMPT: + label = ASCIIToUTF16("JavaScript Prompt"); + break; + case ui::JAVASCRIPT_MESSAGE_TYPE_CONFIRM: + label = ASCIIToUTF16("JavaScript Confirm"); + break; + } + if (!display_url.empty()) + label += ASCIIToUTF16(" - ") + display_url; + + [alert setMessageText:base::SysUTF16ToNSString(label)]; + + [alert addButtonWithTitle:@"OK"]; + if (!one_button) { + NSButton* other = [alert addButtonWithTitle:@"Cancel"]; + [other setKeyEquivalent:@"\e"]; + } + + [alert + beginSheetModalForWindow:nil // nil here makes it app-modal + modalDelegate:helper_ + didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) + contextInfo:this]; + + if ([alert accessoryView]) + [[alert window] makeFirstResponder:[alert accessoryView]]; +} + +CefJavaScriptDialog::~CefJavaScriptDialog() { + [helper_ release]; +} + +void CefJavaScriptDialog::Cancel() { + [helper_ cancel]; +} diff --git a/libcef/browser/javascript_dialog_win.cc b/libcef/browser/javascript_dialog_win.cc new file mode 100644 index 000000000..3e6cf1edf --- /dev/null +++ b/libcef/browser/javascript_dialog_win.cc @@ -0,0 +1,213 @@ +// 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_creator.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef_dll/resource.h" + +#include "base/file_path.h" +#include "base/path_service.h" +#include "base/string_util.h" +#include "base/utf_string_conversions.h" + +class CefJavaScriptDialog; + +HHOOK CefJavaScriptDialog::msg_hook_ = NULL; + +INT_PTR CALLBACK CefJavaScriptDialog::DialogProc(HWND dialog, UINT message, + WPARAM wparam, + LPARAM lparam) { + switch (message) { + case WM_INITDIALOG: { + SetWindowLongPtr(dialog, DWL_USER, static_cast(lparam)); + CefJavaScriptDialog* owner = + reinterpret_cast(lparam); + owner->dialog_win_ = dialog; + SetDlgItemText(dialog, IDC_DIALOGTEXT, owner->message_text_.c_str()); + if (owner->message_type_ == ui::JAVASCRIPT_MESSAGE_TYPE_PROMPT) + SetDlgItemText(dialog, IDC_PROMPTEDIT, + owner->default_prompt_text_.c_str()); + break; + } + case WM_CLOSE: { + CefJavaScriptDialog* owner = reinterpret_cast( + GetWindowLongPtr(dialog, DWL_USER)); + if (owner) { + owner->Cancel(); + owner->callback_.Run(false, string16()); + owner->creator_->DialogClosed(owner); + + // No need for the system to call DestroyWindow() because it will be + // called by the Cancel() method. + return 0; + } + break; + } + case WM_COMMAND: { + CefJavaScriptDialog* owner = reinterpret_cast( + GetWindowLongPtr(dialog, DWL_USER)); + string16 user_input; + bool finish = false; + bool result; + switch (LOWORD(wparam)) { + case IDOK: + finish = true; + result = true; + if (owner->message_type_ == ui::JAVASCRIPT_MESSAGE_TYPE_PROMPT) { + size_t length = + GetWindowTextLength(GetDlgItem(dialog, IDC_PROMPTEDIT)) + 1; + GetDlgItemText(dialog, IDC_PROMPTEDIT, + WriteInto(&user_input, length), length); + } + break; + case IDCANCEL: + finish = true; + result = false; + break; + } + if (finish) { + owner->Cancel(); + owner->callback_.Run(result, user_input); + owner->creator_->DialogClosed(owner); + } + break; + } + default: + return DefWindowProc(dialog, message, wparam, lparam); + } + return 0; +} + +CefJavaScriptDialog::CefJavaScriptDialog( + CefJavaScriptDialogCreator* creator, + ui::JavascriptMessageType javascript_message_type, + const string16& display_url, + const string16& message_text, + const string16& default_prompt_text, + const content::JavaScriptDialogCreator::DialogClosedCallback& callback) + : creator_(creator), + callback_(callback), + message_text_(message_text), + default_prompt_text_(default_prompt_text), + message_type_(javascript_message_type) { + InstallMessageHook(); + + int dialog_type; + if (javascript_message_type == ui::JAVASCRIPT_MESSAGE_TYPE_ALERT) + dialog_type = IDD_ALERT; + else if (javascript_message_type == ui::JAVASCRIPT_MESSAGE_TYPE_CONFIRM) + dialog_type = IDD_CONFIRM; + else // JAVASCRIPT_MESSAGE_TYPE_PROMPT + dialog_type = IDD_PROMPT; + + FilePath file_path; + HMODULE hModule = NULL; + + // Try to load the dialog from the DLL. + if (PathService::Get(base::FILE_MODULE, &file_path)) + hModule = ::GetModuleHandle(file_path.value().c_str()); + if (!hModule) + hModule = ::GetModuleHandle(NULL); + DCHECK(hModule); + + parent_win_ = GetAncestor(creator->browser()->GetWindowHandle(), GA_ROOT); + dialog_win_ = CreateDialogParam(hModule, + MAKEINTRESOURCE(dialog_type), + parent_win_, + DialogProc, + reinterpret_cast(this)); + DCHECK(dialog_win_); + + if (!display_url.empty()) { + // Add the display URL to the window title. + TCHAR text[64]; + GetWindowText(dialog_win_, text, sizeof(text)/sizeof(TCHAR)); + + string16 new_window_text = text + ASCIIToUTF16(" - ") + display_url; + SetWindowText(dialog_win_, new_window_text.c_str()); + } + + // Disable the parent window so the user can't interact with it. + if (IsWindowEnabled(parent_win_)) + EnableWindow(parent_win_, FALSE); + + ShowWindow(dialog_win_, SW_SHOWNORMAL); +} + +CefJavaScriptDialog::~CefJavaScriptDialog() { + Cancel(); + UninstallMessageHook(); +} + +void CefJavaScriptDialog::Cancel() { + HWND parent = NULL; + + // Re-enable the parent before closing the popup to avoid focus/activation/ + // z-order issues. + if (parent_win_ && IsWindow(parent_win_) && !IsWindowEnabled(parent_win_)) { + parent = parent_win_; + EnableWindow(parent_win_, TRUE); + parent_win_ = NULL; + } + + if (dialog_win_ && IsWindow(dialog_win_)) { + SetWindowLongPtr(dialog_win_, DWL_USER, NULL); + DestroyWindow(dialog_win_); + dialog_win_ = NULL; + } + + // Return focus to the parent window. + if (parent) + SetFocus(parent); +} + +// static +LRESULT CALLBACK CefJavaScriptDialog::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(lparam); + if (code >= 0 && wparam == PM_REMOVE && + msg->message >= WM_KEYFIRST && msg->message <= WM_KEYLAST) { + HWND hwnd = GetActiveWindow(); + if (::IsWindow(hwnd) && ::IsDialogMessage(hwnd, msg)) { + // The value returned from this hookproc is ignored, and it cannot + // be used to tell Windows the message has been handled. To avoid + // further processing, convert the message to WM_NULL before + // returning. + msg->hwnd = NULL; + msg->message = WM_NULL; + msg->lParam = 0L; + msg->wParam = 0; + } + } + + // Passes the hook information to the next hook procedure in + // the current hook chain. + return ::CallNextHookEx(msg_hook_, code, wparam, lparam); +} + +// static +bool CefJavaScriptDialog::InstallMessageHook() { + // Make sure we only call this once. + DCHECK(msg_hook_ == NULL); + msg_hook_ = ::SetWindowsHookEx(WH_GETMESSAGE, + &CefJavaScriptDialog::GetMsgProc, + NULL, + GetCurrentThreadId()); + DCHECK(msg_hook_ != NULL); + return msg_hook_ != NULL; +} + +// static +bool CefJavaScriptDialog::UninstallMessageHook() { + DCHECK(msg_hook_ != NULL); + BOOL result = ::UnhookWindowsHookEx(msg_hook_); + DCHECK(result); + msg_hook_ = NULL; + + return result != FALSE; +} diff --git a/libcef/browser/url_network_delegate.cc b/libcef/browser/url_network_delegate.cc index 51a629860..094ccbdb2 100644 --- a/libcef/browser/url_network_delegate.cc +++ b/libcef/browser/url_network_delegate.cc @@ -29,7 +29,7 @@ class CefAuthCallbackImpl : public CefAuthCallback { CancelNow(callback_); } else { CEF_POST_TASK(CEF_IOT, - base::Bind(&CefAuthCallbackImpl::CancelNow, callback_)); + base::Bind(&CefAuthCallbackImpl::CancelNow, callback_)); } } } diff --git a/libcef_dll/cpptoc/client_cpptoc.cc b/libcef_dll/cpptoc/client_cpptoc.cc index cc6e9d1fa..9e5f9e268 100644 --- a/libcef_dll/cpptoc/client_cpptoc.cc +++ b/libcef_dll/cpptoc/client_cpptoc.cc @@ -13,6 +13,7 @@ #include "libcef_dll/cpptoc/client_cpptoc.h" #include "libcef_dll/cpptoc/display_handler_cpptoc.h" #include "libcef_dll/cpptoc/geolocation_handler_cpptoc.h" +#include "libcef_dll/cpptoc/jsdialog_handler_cpptoc.h" #include "libcef_dll/cpptoc/life_span_handler_cpptoc.h" #include "libcef_dll/cpptoc/load_handler_cpptoc.h" #include "libcef_dll/cpptoc/request_handler_cpptoc.h" @@ -102,6 +103,22 @@ struct _cef_geolocation_handler_t* CEF_CALLBACK client_get_geolocation_handler( return CefGeolocationHandlerCppToC::Wrap(_retval); } +struct _cef_jsdialog_handler_t* CEF_CALLBACK client_get_jsdialog_handler( + struct _cef_client_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefClientCppToC::Get( + self)->GetJSDialogHandler(); + + // Return type: refptr_same + return CefJSDialogHandlerCppToC::Wrap(_retval); +} + int CEF_CALLBACK client_on_process_message_recieved(struct _cef_client_t* self, cef_browser_t* browser, enum cef_process_id_t source_process, struct _cef_process_message_t* message) { @@ -139,6 +156,7 @@ CefClientCppToC::CefClientCppToC(CefClient* cls) struct_.struct_.get_request_handler = client_get_request_handler; struct_.struct_.get_display_handler = client_get_display_handler; struct_.struct_.get_geolocation_handler = client_get_geolocation_handler; + struct_.struct_.get_jsdialog_handler = client_get_jsdialog_handler; struct_.struct_.on_process_message_recieved = client_on_process_message_recieved; } diff --git a/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc b/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc new file mode 100644 index 000000000..487d9a510 --- /dev/null +++ b/libcef_dll/cpptoc/jsdialog_callback_cpptoc.cc @@ -0,0 +1,46 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/jsdialog_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK jsdialog_callback_cont(struct _cef_jsdialog_callback_t* self, + int success, const cef_string_t* user_input) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Unverified params: user_input + + // Execute + CefJSDialogCallbackCppToC::Get(self)->Continue( + success?true:false, + CefString(user_input)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefJSDialogCallbackCppToC::CefJSDialogCallbackCppToC(CefJSDialogCallback* cls) + : CefCppToC(cls) { + struct_.struct_.cont = jsdialog_callback_cont; +} + +#ifndef NDEBUG +template<> long CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/jsdialog_callback_cpptoc.h b/libcef_dll/cpptoc/jsdialog_callback_cpptoc.h new file mode 100644 index 000000000..c6c7719ea --- /dev/null +++ b/libcef_dll/cpptoc/jsdialog_callback_cpptoc.h @@ -0,0 +1,37 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_jsdialog_handler.h" +#include "include/capi/cef_jsdialog_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefJSDialogCallbackCppToC + : public CefCppToC { + public: + explicit CefJSDialogCallbackCppToC(CefJSDialogCallback* cls); + virtual ~CefJSDialogCallbackCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc b/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc new file mode 100644 index 000000000..b75d13c3a --- /dev/null +++ b/libcef_dll/cpptoc/jsdialog_handler_cpptoc.cc @@ -0,0 +1,136 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/jsdialog_handler_cpptoc.h" +#include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/jsdialog_callback_ctocpp.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK jsdialog_handler_on_jsdialog( + struct _cef_jsdialog_handler_t* self, cef_browser_t* browser, + const cef_string_t* origin_url, const cef_string_t* accept_lang, + enum cef_jsdialog_type_t dialog_type, const cef_string_t* message_text, + const cef_string_t* default_prompt_text, cef_jsdialog_callback_t* callback, + int* suppress_message) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: origin_url; type: string_byref_const + DCHECK(origin_url); + if (!origin_url) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + // Verify param: suppress_message; type: bool_byref + DCHECK(suppress_message); + if (!suppress_message) + return 0; + // Unverified params: accept_lang, message_text, default_prompt_text + + // Translate param: suppress_message; type: bool_byref + bool suppress_messageBool = ( + suppress_message && *suppress_message)?true:false; + + // Execute + bool _retval = CefJSDialogHandlerCppToC::Get(self)->OnJSDialog( + CefBrowserCToCpp::Wrap(browser), + CefString(origin_url), + CefString(accept_lang), + dialog_type, + CefString(message_text), + CefString(default_prompt_text), + CefJSDialogCallbackCToCpp::Wrap(callback), + suppress_messageBool); + + // Restore param: suppress_message; type: bool_byref + if (suppress_message) + *suppress_message = suppress_messageBool?true:false; + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK jsdialog_handler_on_before_unload_dialog( + struct _cef_jsdialog_handler_t* self, cef_browser_t* browser, + const cef_string_t* message_text, int is_reload, + cef_jsdialog_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return 0; + // Verify param: callback; type: refptr_diff + DCHECK(callback); + if (!callback) + return 0; + // Unverified params: message_text + + // Execute + bool _retval = CefJSDialogHandlerCppToC::Get(self)->OnBeforeUnloadDialog( + CefBrowserCToCpp::Wrap(browser), + CefString(message_text), + is_reload?true:false, + CefJSDialogCallbackCToCpp::Wrap(callback)); + + // Return type: bool + return _retval; +} + +void CEF_CALLBACK jsdialog_handler_on_reset_dialog_state( + struct _cef_jsdialog_handler_t* self, cef_browser_t* browser) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return; + + // Execute + CefJSDialogHandlerCppToC::Get(self)->OnResetDialogState( + CefBrowserCToCpp::Wrap(browser)); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefJSDialogHandlerCppToC::CefJSDialogHandlerCppToC(CefJSDialogHandler* cls) + : CefCppToC(cls) { + struct_.struct_.on_jsdialog = jsdialog_handler_on_jsdialog; + struct_.struct_.on_before_unload_dialog = + jsdialog_handler_on_before_unload_dialog; + struct_.struct_.on_reset_dialog_state = + jsdialog_handler_on_reset_dialog_state; +} + +#ifndef NDEBUG +template<> long CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/jsdialog_handler_cpptoc.h b/libcef_dll/cpptoc/jsdialog_handler_cpptoc.h new file mode 100644 index 000000000..af58e7049 --- /dev/null +++ b/libcef_dll/cpptoc/jsdialog_handler_cpptoc.h @@ -0,0 +1,37 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_HANDLER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_HANDLER_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_jsdialog_handler.h" +#include "include/capi/cef_jsdialog_handler_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefJSDialogHandlerCppToC + : public CefCppToC { + public: + explicit CefJSDialogHandlerCppToC(CefJSDialogHandler* cls); + virtual ~CefJSDialogHandlerCppToC() {} +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_JSDIALOG_HANDLER_CPPTOC_H_ + diff --git a/libcef_dll/ctocpp/client_ctocpp.cc b/libcef_dll/ctocpp/client_ctocpp.cc index 970674fbc..7ba9819c7 100644 --- a/libcef_dll/ctocpp/client_ctocpp.cc +++ b/libcef_dll/ctocpp/client_ctocpp.cc @@ -15,6 +15,7 @@ #include "libcef_dll/ctocpp/client_ctocpp.h" #include "libcef_dll/ctocpp/display_handler_ctocpp.h" #include "libcef_dll/ctocpp/geolocation_handler_ctocpp.h" +#include "libcef_dll/ctocpp/jsdialog_handler_ctocpp.h" #include "libcef_dll/ctocpp/life_span_handler_ctocpp.h" #include "libcef_dll/ctocpp/load_handler_ctocpp.h" #include "libcef_dll/ctocpp/request_handler_ctocpp.h" @@ -88,6 +89,19 @@ CefRefPtr CefClientCToCpp::GetGeolocationHandler() { return CefGeolocationHandlerCToCpp::Wrap(_retval); } +CefRefPtr CefClientCToCpp::GetJSDialogHandler() { + if (CEF_MEMBER_MISSING(struct_, get_jsdialog_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_jsdialog_handler_t* _retval = struct_->get_jsdialog_handler(struct_); + + // Return type: refptr_same + return CefJSDialogHandlerCToCpp::Wrap(_retval); +} + bool CefClientCToCpp::OnProcessMessageRecieved(CefRefPtr browser, CefProcessId source_process, CefRefPtr message) { if (CEF_MEMBER_MISSING(struct_, on_process_message_recieved)) diff --git a/libcef_dll/ctocpp/client_ctocpp.h b/libcef_dll/ctocpp/client_ctocpp.h index 8cfba321b..680f5a568 100644 --- a/libcef_dll/ctocpp/client_ctocpp.h +++ b/libcef_dll/ctocpp/client_ctocpp.h @@ -37,6 +37,7 @@ class CefClientCToCpp virtual CefRefPtr GetRequestHandler() OVERRIDE; virtual CefRefPtr GetDisplayHandler() OVERRIDE; virtual CefRefPtr GetGeolocationHandler() OVERRIDE; + virtual CefRefPtr GetJSDialogHandler() OVERRIDE; virtual bool OnProcessMessageRecieved(CefRefPtr browser, CefProcessId source_process, CefRefPtr message) OVERRIDE; diff --git a/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc b/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc new file mode 100644 index 000000000..1930adc63 --- /dev/null +++ b/libcef_dll/ctocpp/jsdialog_callback_ctocpp.cc @@ -0,0 +1,38 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/jsdialog_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefJSDialogCallbackCToCpp::Continue(bool success, + const CefString& user_input) { + if (CEF_MEMBER_MISSING(struct_, cont)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: user_input + + // Execute + struct_->cont(struct_, + success, + user_input.GetStruct()); +} + + +#ifndef NDEBUG +template<> long CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/jsdialog_callback_ctocpp.h b/libcef_dll/ctocpp/jsdialog_callback_ctocpp.h new file mode 100644 index 000000000..4c20701e4 --- /dev/null +++ b/libcef_dll/ctocpp/jsdialog_callback_ctocpp.h @@ -0,0 +1,42 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_jsdialog_handler.h" +#include "include/capi/cef_jsdialog_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefJSDialogCallbackCToCpp + : public CefCToCpp { + public: + explicit CefJSDialogCallbackCToCpp(cef_jsdialog_callback_t* str) + : CefCToCpp(str) {} + virtual ~CefJSDialogCallbackCToCpp() {} + + // CefJSDialogCallback methods + virtual void Continue(bool success, const CefString& user_input) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc b/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc new file mode 100644 index 000000000..971222994 --- /dev/null +++ b/libcef_dll/ctocpp/jsdialog_handler_ctocpp.cc @@ -0,0 +1,116 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/jsdialog_callback_cpptoc.h" +#include "libcef_dll/ctocpp/jsdialog_handler_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefJSDialogHandlerCToCpp::OnJSDialog(CefRefPtr browser, + const CefString& origin_url, const CefString& accept_lang, + JSDialogType dialog_type, const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, bool& suppress_message) { + if (CEF_MEMBER_MISSING(struct_, on_jsdialog)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: origin_url; type: string_byref_const + DCHECK(!origin_url.empty()); + if (origin_url.empty()) + return false; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + // Unverified params: accept_lang, message_text, default_prompt_text + + // Translate param: suppress_message; type: bool_byref + int suppress_messageInt = suppress_message; + + // Execute + int _retval = struct_->on_jsdialog(struct_, + CefBrowserCppToC::Wrap(browser), + origin_url.GetStruct(), + accept_lang.GetStruct(), + dialog_type, + message_text.GetStruct(), + default_prompt_text.GetStruct(), + CefJSDialogCallbackCppToC::Wrap(callback), + &suppress_messageInt); + + // Restore param:suppress_message; type: bool_byref + suppress_message = suppress_messageInt?true:false; + + // Return type: bool + return _retval?true:false; +} + +bool CefJSDialogHandlerCToCpp::OnBeforeUnloadDialog( + CefRefPtr browser, const CefString& message_text, + bool is_reload, CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, on_before_unload_dialog)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return false; + // Verify param: callback; type: refptr_diff + DCHECK(callback.get()); + if (!callback.get()) + return false; + // Unverified params: message_text + + // Execute + int _retval = struct_->on_before_unload_dialog(struct_, + CefBrowserCppToC::Wrap(browser), + message_text.GetStruct(), + is_reload, + CefJSDialogCallbackCppToC::Wrap(callback)); + + // Return type: bool + return _retval?true:false; +} + +void CefJSDialogHandlerCToCpp::OnResetDialogState( + CefRefPtr browser) { + if (CEF_MEMBER_MISSING(struct_, on_reset_dialog_state)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return; + + // Execute + struct_->on_reset_dialog_state(struct_, + CefBrowserCppToC::Wrap(browser)); +} + + +#ifndef NDEBUG +template<> long CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/jsdialog_handler_ctocpp.h b/libcef_dll/ctocpp/jsdialog_handler_ctocpp.h new file mode 100644 index 000000000..69a046d8b --- /dev/null +++ b/libcef_dll/ctocpp/jsdialog_handler_ctocpp.h @@ -0,0 +1,51 @@ +// 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. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_HANDLER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_HANDLER_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_jsdialog_handler.h" +#include "include/capi/cef_jsdialog_handler_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefJSDialogHandlerCToCpp + : public CefCToCpp { + public: + explicit CefJSDialogHandlerCToCpp(cef_jsdialog_handler_t* str) + : CefCToCpp(str) {} + virtual ~CefJSDialogHandlerCToCpp() {} + + // CefJSDialogHandler methods + virtual bool OnJSDialog(CefRefPtr browser, + const CefString& origin_url, const CefString& accept_lang, + JSDialogType dialog_type, const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message) OVERRIDE; + virtual bool OnBeforeUnloadDialog(CefRefPtr browser, + const CefString& message_text, bool is_reload, + CefRefPtr callback) OVERRIDE; + virtual void OnResetDialogState(CefRefPtr browser) OVERRIDE; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_JSDIALOG_HANDLER_CTOCPP_H_ + diff --git a/libcef_dll/libcef_dll.cc b/libcef_dll/libcef_dll.cc index 98a48ad28..9f421a822 100644 --- a/libcef_dll/libcef_dll.cc +++ b/libcef_dll/libcef_dll.cc @@ -31,6 +31,7 @@ #include "libcef_dll/cpptoc/dictionary_value_cpptoc.h" #include "libcef_dll/cpptoc/frame_cpptoc.h" #include "libcef_dll/cpptoc/geolocation_callback_cpptoc.h" +#include "libcef_dll/cpptoc/jsdialog_callback_cpptoc.h" #include "libcef_dll/cpptoc/list_value_cpptoc.h" #include "libcef_dll/cpptoc/post_data_cpptoc.h" #include "libcef_dll/cpptoc/post_data_element_cpptoc.h" @@ -48,6 +49,7 @@ #include "libcef_dll/ctocpp/cookie_visitor_ctocpp.h" #include "libcef_dll/ctocpp/display_handler_ctocpp.h" #include "libcef_dll/ctocpp/geolocation_handler_ctocpp.h" +#include "libcef_dll/ctocpp/jsdialog_handler_ctocpp.h" #include "libcef_dll/ctocpp/life_span_handler_ctocpp.h" #include "libcef_dll/ctocpp/load_handler_ctocpp.h" #include "libcef_dll/ctocpp/proxy_handler_ctocpp.h" @@ -143,6 +145,8 @@ CEF_EXPORT void cef_shutdown() { DCHECK_EQ(CefFrameCppToC::DebugObjCt, 0); DCHECK_EQ(CefGeolocationCallbackCppToC::DebugObjCt, 0); DCHECK_EQ(CefGeolocationHandlerCToCpp::DebugObjCt, 0); + DCHECK_EQ(CefJSDialogCallbackCppToC::DebugObjCt, 0); + DCHECK_EQ(CefJSDialogHandlerCToCpp::DebugObjCt, 0); DCHECK_EQ(CefLifeSpanHandlerCToCpp::DebugObjCt, 0); DCHECK_EQ(CefListValueCppToC::DebugObjCt, 0); DCHECK_EQ(CefLoadHandlerCToCpp::DebugObjCt, 0); diff --git a/libcef_dll/libcef_dll.rc b/libcef_dll/libcef_dll.rc index 871b9a4c2..569469e9b 100644 --- a/libcef_dll/libcef_dll.rc +++ b/libcef_dll/libcef_dll.rc @@ -53,6 +53,42 @@ END #endif // APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ALERT DIALOGEX 0, 0, 241, 76 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "JavaScript Alert" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,184,55,50,14 + LTEXT "",IDC_DIALOGTEXT,16,17,210,30 +END + +IDD_CONFIRM DIALOGEX 0, 0, 241, 76 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "JavaScript Confirm" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + PUSHBUTTON "Cancel",IDCANCEL,184,55,50,14 + DEFPUSHBUTTON "OK",IDOK,131,55,50,14 + LTEXT "",IDC_DIALOGTEXT,16,17,210,30 +END + +IDD_PROMPT DIALOGEX 0, 0, 241, 76 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "JavaScript Prompt" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + DEFPUSHBUTTON "OK",IDOK,131,55,50,14 + LTEXT "",IDC_DIALOGTEXT,16,17,210,18 + PUSHBUTTON "Cancel",IDCANCEL,184,55,50,14 + EDITTEXT IDC_PROMPTEDIT,15,33,210,14,ES_AUTOHSCROLL +END + + ///////////////////////////////////////////////////////////////////////////// // // Version diff --git a/libcef_dll/resource.h b/libcef_dll/resource.h index 9553e1997..cbeef193d 100644 --- a/libcef_dll/resource.h +++ b/libcef_dll/resource.h @@ -6,6 +6,13 @@ // Avoid files associated with MacOS #define _X86_ +#define IDD_ALERT 130 +#define IDD_CONFIRM 131 +#define IDD_PROMPT 132 +#define IDC_PROMPTEDIT 1000 +#define IDC_DIALOGTEXT 1001 + + // Next default values for new objects // #ifdef APSTUDIO_INVOKED diff --git a/libcef_dll/wrapper/libcef_dll_wrapper.cc b/libcef_dll/wrapper/libcef_dll_wrapper.cc index f97f670c4..fd1481153 100644 --- a/libcef_dll/wrapper/libcef_dll_wrapper.cc +++ b/libcef_dll/wrapper/libcef_dll_wrapper.cc @@ -27,6 +27,7 @@ #include "libcef_dll/cpptoc/cookie_visitor_cpptoc.h" #include "libcef_dll/cpptoc/display_handler_cpptoc.h" #include "libcef_dll/cpptoc/geolocation_handler_cpptoc.h" +#include "libcef_dll/cpptoc/jsdialog_handler_cpptoc.h" #include "libcef_dll/cpptoc/life_span_handler_cpptoc.h" #include "libcef_dll/cpptoc/load_handler_cpptoc.h" #include "libcef_dll/cpptoc/proxy_handler_cpptoc.h" @@ -50,6 +51,7 @@ #include "libcef_dll/ctocpp/dictionary_value_ctocpp.h" #include "libcef_dll/ctocpp/frame_ctocpp.h" #include "libcef_dll/ctocpp/geolocation_callback_ctocpp.h" +#include "libcef_dll/ctocpp/jsdialog_callback_ctocpp.h" #include "libcef_dll/ctocpp/list_value_ctocpp.h" #include "libcef_dll/ctocpp/post_data_ctocpp.h" #include "libcef_dll/ctocpp/post_data_element_ctocpp.h" @@ -135,6 +137,8 @@ CEF_GLOBAL void CefShutdown() { DCHECK_EQ(CefFrameCToCpp::DebugObjCt, 0); DCHECK_EQ(CefGeolocationCallbackCToCpp::DebugObjCt, 0); DCHECK_EQ(CefGeolocationHandlerCppToC::DebugObjCt, 0); + DCHECK_EQ(CefJSDialogCallbackCToCpp::DebugObjCt, 0); + DCHECK_EQ(CefJSDialogHandlerCppToC::DebugObjCt, 0); DCHECK_EQ(CefLifeSpanHandlerCppToC::DebugObjCt, 0); DCHECK_EQ(CefListValueCToCpp::DebugObjCt, 0); DCHECK_EQ(CefLoadHandlerCppToC::DebugObjCt, 0); diff --git a/tests/cefclient/cefclient.cpp b/tests/cefclient/cefclient.cpp index 65d7ef516..92d0e62d1 100644 --- a/tests/cefclient/cefclient.cpp +++ b/tests/cefclient/cefclient.cpp @@ -322,6 +322,10 @@ void RunPopupTest(CefRefPtr browser) { "window.open('http://www.google.com');", "about:blank", 0); } +void RunDialogTest(CefRefPtr browser) { + browser->GetMainFrame()->LoadURL("http://tests/dialogs"); +} + void RunLocalStorageTest(CefRefPtr browser) { browser->GetMainFrame()->LoadURL("http://tests/localstorage"); } diff --git a/tests/cefclient/cefclient.h b/tests/cefclient/cefclient.h index ca09c7d91..3c5965e48 100644 --- a/tests/cefclient/cefclient.h +++ b/tests/cefclient/cefclient.h @@ -40,6 +40,7 @@ void RunGetSourceTest(CefRefPtr browser); void RunGetTextTest(CefRefPtr browser); void RunRequestTest(CefRefPtr browser); void RunPopupTest(CefRefPtr browser); +void RunDialogTest(CefRefPtr browser); void RunLocalStorageTest(CefRefPtr browser); void RunAccelerated2DCanvasTest(CefRefPtr browser); void RunAcceleratedLayersTest(CefRefPtr browser); diff --git a/tests/cefclient/cefclient.rc b/tests/cefclient/cefclient.rc index 2fd97a390..0b04530d0 100644 --- a/tests/cefclient/cefclient.rc +++ b/tests/cefclient/cefclient.rc @@ -29,6 +29,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US // IDS_BINDING BINARY "res\\binding.html" +IDS_DIALOGS BINARY "res\\dialogs.html" IDS_LOGO BINARY "res\\logo.png" IDS_LOGOBALL BINARY "res\\logoball.png" IDS_LOCALSTORAGE BINARY "res\\localstorage.html" @@ -67,6 +68,7 @@ BEGIN MENUITEM "Request", ID_TESTS_REQUEST MENUITEM "Scheme Handler", ID_TESTS_SCHEME_HANDLER MENUITEM "JavaScript Binding", ID_TESTS_BINDING + MENUITEM "JavaScript Dialogs", ID_TESTS_DIALOGS MENUITEM "Local Storage", ID_TESTS_LOCALSTORAGE MENUITEM "XMLHttpRequest", ID_TESTS_XMLHTTPREQUEST MENUITEM "Accelerated 2D Canvas", ID_TESTS_ACCELERATED2DCANVAS diff --git a/tests/cefclient/cefclient_mac.mm b/tests/cefclient/cefclient_mac.mm index f89190148..6749330f7 100644 --- a/tests/cefclient/cefclient_mac.mm +++ b/tests/cefclient/cefclient_mac.mm @@ -230,6 +230,7 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) { - (IBAction)testXMLHttpRequest:(id)sender; - (IBAction)testSchemeHandler:(id)sender; - (IBAction)testBinding:(id)sender; +- (IBAction)testDialogs:(id)sender; - (IBAction)testPopupWindow:(id)sender; - (IBAction)testAccelerated2DCanvas:(id)sender; - (IBAction)testAcceleratedLayers:(id)sender; @@ -272,6 +273,9 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) { [testMenu addItemWithTitle:@"JavaScript Binding" action:@selector(testBinding:) keyEquivalent:@""]; + [testMenu addItemWithTitle:@"JavaScript Dialogs" + action:@selector(testDialogs:) + keyEquivalent:@""]; [testMenu addItemWithTitle:@"Local Storage" action:@selector(testLocalStorage:) keyEquivalent:@""]; @@ -419,6 +423,11 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) { binding_test::RunTest(g_handler->GetBrowser()); } +- (IBAction)testDialogs:(id)sender { + if (g_handler.get() && g_handler->GetBrowserId()) + RunDialogTest(g_handler->GetBrowser()); +} + - (IBAction)testPopupWindow:(id)sender { if (g_handler.get() && g_handler->GetBrowserId()) RunPopupTest(g_handler->GetBrowser()); diff --git a/tests/cefclient/cefclient_win.cpp b/tests/cefclient/cefclient_win.cpp index 3a0633dc3..3a2032632 100644 --- a/tests/cefclient/cefclient_win.cpp +++ b/tests/cefclient/cefclient_win.cpp @@ -377,6 +377,10 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, if (browser.get()) binding_test::RunTest(browser); return 0; + case ID_TESTS_DIALOGS: // Test JavaScript dialofs + if (browser.get()) + RunDialogTest(browser); + return 0; case ID_TESTS_LOCALSTORAGE: // Test localStorage if (browser.get()) RunLocalStorageTest(browser); diff --git a/tests/cefclient/client_handler.cpp b/tests/cefclient/client_handler.cpp index 21482d2da..313170423 100644 --- a/tests/cefclient/client_handler.cpp +++ b/tests/cefclient/client_handler.cpp @@ -137,6 +137,12 @@ CefRefPtr ClientHandler::GetResourceHandler( dump.size()); ASSERT(stream.get()); return new CefStreamResourceHandler("text/plain", stream); + } else if (url == "http://tests/dialogs") { + // Show the dialogs contents + CefRefPtr stream = + GetBinaryResourceReader("dialogs.html"); + ASSERT(stream.get()); + return new CefStreamResourceHandler("text/html", stream); } else if (url == "http://tests/localstorage") { // Show the localstorage contents CefRefPtr stream = diff --git a/tests/cefclient/res/dialogs.html b/tests/cefclient/res/dialogs.html new file mode 100644 index 000000000..1bce8e475 --- /dev/null +++ b/tests/cefclient/res/dialogs.html @@ -0,0 +1,45 @@ + + +Dialog Test + + + +
+Click a button to show the associated dialog type. +
+
+
+

+
+ + diff --git a/tests/cefclient/resource.h b/tests/cefclient/resource.h index de494b8e4..b77c814e6 100644 --- a/tests/cefclient/resource.h +++ b/tests/cefclient/resource.h @@ -38,12 +38,14 @@ #define ID_TESTS_DRAGDROP 32771 #define ID_TESTS_GEOLOCATION 32772 #define ID_TESTS_BINDING 32773 +#define ID_TESTS_DIALOGS 32774 #define IDC_STATIC -1 #define IDS_BINDING 1000 -#define IDS_LOGO 1001 -#define IDS_LOGOBALL 1002 -#define IDS_LOCALSTORAGE 1003 -#define IDS_XMLHTTPREQUEST 1004 +#define IDS_DIALOGS 1001 +#define IDS_LOGO 1002 +#define IDS_LOGOBALL 1003 +#define IDS_LOCALSTORAGE 1004 +#define IDS_XMLHTTPREQUEST 1005 // Avoid files associated with MacOS #define _X86_ diff --git a/tests/cefclient/resource_util_win.cpp b/tests/cefclient/resource_util_win.cpp index bdf9b0e38..c35438d9d 100644 --- a/tests/cefclient/resource_util_win.cpp +++ b/tests/cefclient/resource_util_win.cpp @@ -35,6 +35,7 @@ CefRefPtr GetBinaryResourceReader(int binaryId) { new CefByteReadHandler(pBytes, dwSize, NULL)); } + ASSERT(FALSE); // The resource should be found. return NULL; } @@ -45,6 +46,7 @@ CefRefPtr GetBinaryResourceReader(const char* resource_name) { int id; } resource_map[] = { {"binding.html", IDS_BINDING}, + {"dialogs.html", IDS_DIALOGS}, {"localstorage.html", IDS_LOCALSTORAGE}, {"xmlhttprequest.html", IDS_XMLHTTPREQUEST}, }; diff --git a/tests/unittests/jsdialog_unittest.cc b/tests/unittests/jsdialog_unittest.cc new file mode 100644 index 000000000..df5312152 --- /dev/null +++ b/tests/unittests/jsdialog_unittest.cc @@ -0,0 +1,413 @@ +// 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 "include/cef_runnable.h" +#include "tests/unittests/test_handler.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace { + +const char* kStartUrl = "http://tests/JSDialogTestHandler.Start"; +const char* kEndUrl = "http://tests/JSDialogTestHandler.End?r="; + +class JSDialogTestHandler : public TestHandler { + public: + enum TestType { + TYPE_ALERT, + TYPE_CONFIRM, + TYPE_PROMPT, + TYPE_ONBEFOREUNLOAD, + }; + enum TestMode { + MODE_SUPPRESS, + MODE_RUN_IMMEDIATE, + MODE_RUN_DELAYED, + }; + + JSDialogTestHandler(TestType type, + TestMode mode, + bool success, + const std::string& user_input, + const std::string& result) + : type_(type), + mode_(mode), + success_(success), + user_input_(user_input), + result_(result) { + } + + virtual void RunTest() OVERRIDE { + std::string content = "START"; + + AddResource(kStartUrl, content, "text/html"); + AddResource(kEndUrl, "END", "text/html"); + + // Create the browser + CreateBrowser(kStartUrl); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + if (!frame->IsMain()) + return; + + std::string url = frame->GetURL(); + if (url.find(kEndUrl) == 0) { + got_onloadend_.yes(); + + std::string result = url.substr(strlen(kEndUrl)); + EXPECT_STREQ(result_.c_str(), result.c_str()); + + DestroyTest(); + } else if (type_ == TYPE_ONBEFOREUNLOAD) { + // Trigger the onunload handler. + frame->LoadURL(kEndUrl); + } + } + + virtual void Continue(CefRefPtr callback) { + callback->Continue(success_, user_input_); + } + + virtual bool OnJSDialog(CefRefPtr browser, + const CefString& origin_url, + const CefString& accept_lang, + JSDialogType dialog_type, + const CefString& message_text, + const CefString& default_prompt_text, + CefRefPtr callback, + bool& suppress_message) OVERRIDE { + got_onjsdialog_.yes(); + + EXPECT_STREQ("http://tests/", origin_url.ToString().c_str()); + EXPECT_TRUE(accept_lang.empty()); + + if (type_ == TYPE_ALERT) { + EXPECT_EQ(JSDIALOGTYPE_ALERT, dialog_type); + EXPECT_STREQ("My alert message", message_text.ToString().c_str()); + EXPECT_TRUE(default_prompt_text.empty()); + } else if (type_ == TYPE_CONFIRM) { + EXPECT_EQ(JSDIALOGTYPE_CONFIRM, dialog_type); + EXPECT_STREQ("My confirm message", message_text.ToString().c_str()); + EXPECT_TRUE(default_prompt_text.empty()); + } else if (type_ == TYPE_PROMPT) { + EXPECT_EQ(JSDIALOGTYPE_PROMPT, dialog_type); + EXPECT_STREQ("My prompt message", message_text.ToString().c_str()); + EXPECT_STREQ("my default", default_prompt_text.ToString().c_str()); + } + + EXPECT_FALSE(suppress_message); + + if (mode_ == MODE_SUPPRESS) { + // Suppress the dialog. + suppress_message = true; + return false; + } else if (mode_ == MODE_RUN_IMMEDIATE) { + // Continue immediately. + callback->Continue(success_, user_input_); + } else if (mode_ == MODE_RUN_DELAYED) { + // Continue asynchronously. + CefPostTask(TID_UI, + NewCefRunnableMethod(this, &JSDialogTestHandler::Continue, callback)); + } + + return true; + } + + virtual bool OnBeforeUnloadDialog(CefRefPtr browser, + const CefString& message_text, + bool is_reload, + CefRefPtr callback) + OVERRIDE { + got_onbeforeunloaddialog_.yes(); + + if (type_ == TYPE_ONBEFOREUNLOAD) { + EXPECT_STREQ("My unload message", message_text.ToString().c_str()); + EXPECT_FALSE(is_reload); + } + + if (mode_ == MODE_RUN_IMMEDIATE) { + // Continue immediately. + callback->Continue(success_, user_input_); + } else if (mode_ == MODE_RUN_DELAYED) { + // Continue asynchronously. + CefPostTask(TID_UI, + NewCefRunnableMethod(this, &JSDialogTestHandler::Continue, callback)); + } + + return true; + } + + virtual void OnResetDialogState(CefRefPtr browser) OVERRIDE { + got_onresetdialogstate_.yes(); + } + + TestType type_; + TestMode mode_; + bool success_; + std::string user_input_; + std::string result_; + + TrackCallback got_onjsdialog_; + TrackCallback got_onbeforeunloaddialog_; + TrackCallback got_onresetdialogstate_; + TrackCallback got_onloadend_; +}; + +} // namespace + +// Alert dialog with suppression. +TEST(JSDialogTest, AlertSuppress) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_ALERT, + JSDialogTestHandler::MODE_SUPPRESS, + true, // success + "", // user_input + ""); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Alert dialog with immediate callback. +TEST(JSDialogTest, AlertRunImmediate) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_ALERT, + JSDialogTestHandler::MODE_RUN_IMMEDIATE, + true, // success + "", // user_input + ""); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Alert dialog with delayed callback. +TEST(JSDialogTest, AlertRunDelayed) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_ALERT, + JSDialogTestHandler::MODE_RUN_DELAYED, + true, // success + "", // user_input + ""); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Confirm dialog with suppression. +TEST(JSDialogTest, ConfirmSuppress) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM, + JSDialogTestHandler::MODE_SUPPRESS, + true, // success + "", // user_input + "cancel"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Confirm dialog run immediately return OK. +TEST(JSDialogTest, ConfirmRunImmediateOk) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM, + JSDialogTestHandler::MODE_RUN_IMMEDIATE, + true, // success + "", // user_input + "ok"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Confirm dialog run immediately return Cancel. +TEST(JSDialogTest, ConfirmRunImmediateCancel) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM, + JSDialogTestHandler::MODE_RUN_IMMEDIATE, + false, // success + "", // user_input + "cancel"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Confirm dialog run delayed return OK. +TEST(JSDialogTest, ConfirmRunDelayedOk) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM, + JSDialogTestHandler::MODE_RUN_DELAYED, + true, // success + "", // user_input + "ok"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Confirm dialog run delayed return Cancel. +TEST(JSDialogTest, ConfirmRunDelayedCancel) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_CONFIRM, + JSDialogTestHandler::MODE_RUN_DELAYED, + false, // success + "", // user_input + "cancel"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Prompt dialog with suppression. +TEST(JSDialogTest, PromptSuppress) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_PROMPT, + JSDialogTestHandler::MODE_SUPPRESS, + true, // success + "some_value", // user_input + "null"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Prompt dialog run immediately return OK. +TEST(JSDialogTest, PromptRunImmediateOk) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_PROMPT, + JSDialogTestHandler::MODE_RUN_IMMEDIATE, + true, // success + "some_value", // user_input + "some_value"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Prompt dialog run immediately return Cancel. +TEST(JSDialogTest, PromptRunImmediateCancel) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_PROMPT, + JSDialogTestHandler::MODE_RUN_IMMEDIATE, + false, // success + "some_value", // user_input + "null"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Prompt dialog run delayed return OK. +TEST(JSDialogTest, PromptRunDelayedOk) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_PROMPT, + JSDialogTestHandler::MODE_RUN_DELAYED, + true, // success + "some_value", // user_input + "some_value"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// Prompt dialog run delayed return Cancel. +TEST(JSDialogTest, PromptRunDelayedCancel) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_PROMPT, + JSDialogTestHandler::MODE_RUN_DELAYED, + false, // success + "some_value", // user_input + "null"); // result + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_onjsdialog_); + EXPECT_FALSE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// OnBeforeUnload dialog with immediate callback. +TEST(JSDialogTest, OnBeforeUnloadRunImmediate) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_ONBEFOREUNLOAD, + JSDialogTestHandler::MODE_RUN_IMMEDIATE, + true, // success + "", // user_input + ""); // result + handler->ExecuteTest(); + + EXPECT_FALSE(handler->got_onjsdialog_); + EXPECT_TRUE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} + +// OnBeforeUnload dialog with delayed callback. +TEST(JSDialogTest, OnBeforeUnloadRunDelayed) { + CefRefPtr handler = + new JSDialogTestHandler(JSDialogTestHandler::TYPE_ONBEFOREUNLOAD, + JSDialogTestHandler::MODE_RUN_DELAYED, + true, // success + "", // user_input + ""); // result + handler->ExecuteTest(); + + EXPECT_FALSE(handler->got_onjsdialog_); + EXPECT_TRUE(handler->got_onbeforeunloaddialog_); + EXPECT_TRUE(handler->got_onresetdialogstate_); + EXPECT_TRUE(handler->got_onloadend_); +} diff --git a/tests/unittests/test_handler.cc b/tests/unittests/test_handler.cc index d46da6f2b..0ae843f98 100644 --- a/tests/unittests/test_handler.cc +++ b/tests/unittests/test_handler.cc @@ -56,7 +56,14 @@ CefRefPtr TestHandler::GetResourceHandler( if (resource_map_.size() > 0) { CefString url = request->GetURL(); - ResourceMap::const_iterator it = resource_map_.find(url); + + // Ignore the query component, if any. + std::string urlStr = url; + int idx = urlStr.find('?'); + if (idx > 0) + urlStr = urlStr.substr(0, idx); + + ResourceMap::const_iterator it = resource_map_.find(urlStr); if (it != resource_map_.end()) { // Return the previously mapped resource CefRefPtr stream = @@ -97,10 +104,17 @@ void TestHandler::CreateBrowser(const CefString& url) { CefBrowserHost::CreateBrowser(windowInfo, this, url, settings); } -void TestHandler::AddResource(const CefString& url, +void TestHandler::AddResource(const std::string& url, const std::string& content, - const CefString& mimeType) { - resource_map_.insert(std::make_pair(url, std::make_pair(content, mimeType))); + const std::string& mimeType) { + // Ignore the query component, if any. + std::string urlStr = url; + int idx = urlStr.find('?'); + if (idx > 0) + urlStr = urlStr.substr(0, idx); + + resource_map_.insert( + std::make_pair(urlStr, std::make_pair(content, mimeType))); } void TestHandler::ClearResources() { diff --git a/tests/unittests/test_handler.h b/tests/unittests/test_handler.h index cf40726aa..98ff0f193 100644 --- a/tests/unittests/test_handler.h +++ b/tests/unittests/test_handler.h @@ -32,6 +32,7 @@ class TrackCallback { // by test cases. class TestHandler : public CefClient, public CefDisplayHandler, + public CefJSDialogHandler, public CefLifeSpanHandler, public CefLoadHandler, public CefRequestHandler { @@ -46,6 +47,9 @@ class TestHandler : public CefClient, virtual CefRefPtr GetDisplayHandler() OVERRIDE { return this; } + virtual CefRefPtr GetJSDialogHandler() OVERRIDE { + return this; + } virtual CefRefPtr GetLifeSpanHandler() OVERRIDE { return this; } @@ -81,9 +85,9 @@ class TestHandler : public CefClient, void CreateBrowser(const CefString& url); - void AddResource(const CefString& url, + void AddResource(const std::string& url, const std::string& content, - const CefString& mimeType); + const std::string& mimeType); void ClearResources(); private: @@ -97,7 +101,8 @@ class TestHandler : public CefClient, base::WaitableEvent completion_event_; // Map of resources that can be automatically loaded - typedef std::map > ResourceMap; + typedef std::map > + ResourceMap; ResourceMap resource_map_; // Include the default reference counting implementation.