diff --git a/include/capi/cef_browser_capi.h b/include/capi/cef_browser_capi.h index 0d5424b37..626a63f36 100644 --- a/include/capi/cef_browser_capi.h +++ b/include/capi/cef_browser_capi.h @@ -324,6 +324,23 @@ typedef struct _cef_browser_host_t { /// void (CEF_CALLBACK *print)(struct _cef_browser_host_t* self); + /// + // Search for |searchText|. |identifier| can be used to have multiple searches + // running simultaniously. |forward| indicates whether to search forward or + // backward within the page. |matchCase| indicates whether the search should + // be case-sensitive. |findNext| indicates whether this is the first request + // or a follow-up. + /// + void (CEF_CALLBACK *find)(struct _cef_browser_host_t* self, int identifier, + const cef_string_t* searchText, int forward, int matchCase, + int findNext); + + /// + // Cancel all searches that are currently going on. + /// + void (CEF_CALLBACK *stop_finding)(struct _cef_browser_host_t* self, + int clearSelection); + /// // Set whether mouse cursor change is disabled. /// diff --git a/include/cef_browser.h b/include/cef_browser.h index 09ecf511a..50f7fb255 100644 --- a/include/cef_browser.h +++ b/include/cef_browser.h @@ -372,6 +372,23 @@ class CefBrowserHost : public virtual CefBase { /*--cef()--*/ virtual void Print() =0; + /// + // Search for |searchText|. |identifier| can be used to have multiple searches + // running simultaniously. |forward| indicates whether to search forward or + // backward within the page. |matchCase| indicates whether the search should + // be case-sensitive. |findNext| indicates whether this is the first request + // or a follow-up. + /// + /*--cef()--*/ + virtual void Find(int identifier, const CefString& searchText, + bool forward, bool matchCase, bool findNext) =0; + + /// + // Cancel all searches that are currently going on. + /// + /*--cef()--*/ + virtual void StopFinding(bool clearSelection) =0; + /// // Set whether mouse cursor change is disabled. /// diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index 8b64b870a..57b07a55c 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -48,6 +48,7 @@ #include "content/public/browser/resource_request_info.h" #include "content/public/browser/web_contents_view.h" #include "content/public/common/file_chooser_params.h" +#include "third_party/WebKit/public/web/WebFindOptions.h" #include "ui/shell_dialogs/selected_file_info.h" namespace { @@ -616,6 +617,39 @@ void CefBrowserHostImpl::Print() { } } +void CefBrowserHostImpl::Find(int identifier, const CefString& searchText, + bool forward, bool matchCase, bool findNext) { + if (CEF_CURRENTLY_ON_UIT()) { + if (!web_contents_) + return; + + WebKit::WebFindOptions options; + options.forward = forward; + options.matchCase = matchCase; + options.findNext = findNext; + web_contents()->GetRenderViewHost()->Find(identifier, searchText, options); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::Find, this, identifier, searchText, + forward, matchCase, findNext)); + } +} + +void CefBrowserHostImpl::StopFinding(bool clearSelection) { + if (CEF_CURRENTLY_ON_UIT()) { + if (!web_contents_) + return; + + content::StopFindAction action = clearSelection ? + content::STOP_FIND_ACTION_CLEAR_SELECTION : + content::STOP_FIND_ACTION_KEEP_SELECTION; + web_contents()->GetRenderViewHost()->StopFinding(action); + } else { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefBrowserHostImpl::StopFinding, this, clearSelection)); + } +} + void CefBrowserHostImpl::SetMouseCursorChangeDisabled(bool disabled) { base::AutoLock lock_scope(state_lock_); mouse_cursor_change_disabled_ = disabled; diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index c3776d653..14aac4a58 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -125,6 +125,9 @@ class CefBrowserHostImpl : public CefBrowserHost, CefRefPtr callback) OVERRIDE; virtual void StartDownload(const CefString& url) OVERRIDE; virtual void Print() OVERRIDE; + virtual void Find(int identifier, const CefString& searchText, + bool forward, bool matchCase, bool findNext) OVERRIDE; + virtual void StopFinding(bool clearSelection) OVERRIDE; virtual void SetMouseCursorChangeDisabled(bool disabled) OVERRIDE; virtual bool IsMouseCursorChangeDisabled() OVERRIDE; virtual bool IsWindowRenderingDisabled() OVERRIDE; diff --git a/libcef_dll/cpptoc/browser_host_cpptoc.cc b/libcef_dll/cpptoc/browser_host_cpptoc.cc index 6ae077f26..e45cdc3ae 100644 --- a/libcef_dll/cpptoc/browser_host_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_host_cpptoc.cc @@ -313,6 +313,41 @@ void CEF_CALLBACK browser_host_print(struct _cef_browser_host_t* self) { CefBrowserHostCppToC::Get(self)->Print(); } +void CEF_CALLBACK browser_host_find(struct _cef_browser_host_t* self, + int identifier, const cef_string_t* searchText, int forward, int matchCase, + int findNext) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + // Verify param: searchText; type: string_byref_const + DCHECK(searchText); + if (!searchText) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->Find( + identifier, + CefString(searchText), + forward?true:false, + matchCase?true:false, + findNext?true:false); +} + +void CEF_CALLBACK browser_host_stop_finding(struct _cef_browser_host_t* self, + int clearSelection) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefBrowserHostCppToC::Get(self)->StopFinding( + clearSelection?true:false); +} + void CEF_CALLBACK browser_host_set_mouse_cursor_change_disabled( struct _cef_browser_host_t* self, int disabled) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING @@ -598,6 +633,8 @@ CefBrowserHostCppToC::CefBrowserHostCppToC(CefBrowserHost* cls) struct_.struct_.run_file_dialog = browser_host_run_file_dialog; struct_.struct_.start_download = browser_host_start_download; struct_.struct_.print = browser_host_print; + struct_.struct_.find = browser_host_find; + struct_.struct_.stop_finding = browser_host_stop_finding; struct_.struct_.set_mouse_cursor_change_disabled = browser_host_set_mouse_cursor_change_disabled; struct_.struct_.is_mouse_cursor_change_disabled = diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.cc b/libcef_dll/ctocpp/browser_host_ctocpp.cc index 5e60342cf..f55f230ec 100644 --- a/libcef_dll/ctocpp/browser_host_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_host_ctocpp.cc @@ -260,6 +260,38 @@ void CefBrowserHostCToCpp::Print() { struct_->print(struct_); } +void CefBrowserHostCToCpp::Find(int identifier, const CefString& searchText, + bool forward, bool matchCase, bool findNext) { + if (CEF_MEMBER_MISSING(struct_, find)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: searchText; type: string_byref_const + DCHECK(!searchText.empty()); + if (searchText.empty()) + return; + + // Execute + struct_->find(struct_, + identifier, + searchText.GetStruct(), + forward, + matchCase, + findNext); +} + +void CefBrowserHostCToCpp::StopFinding(bool clearSelection) { + if (CEF_MEMBER_MISSING(struct_, stop_finding)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->stop_finding(struct_, + clearSelection); +} + void CefBrowserHostCToCpp::SetMouseCursorChangeDisabled(bool disabled) { if (CEF_MEMBER_MISSING(struct_, set_mouse_cursor_change_disabled)) return; diff --git a/libcef_dll/ctocpp/browser_host_ctocpp.h b/libcef_dll/ctocpp/browser_host_ctocpp.h index 1bb59701c..40d7fd162 100644 --- a/libcef_dll/ctocpp/browser_host_ctocpp.h +++ b/libcef_dll/ctocpp/browser_host_ctocpp.h @@ -54,6 +54,9 @@ class CefBrowserHostCToCpp CefRefPtr callback) OVERRIDE; virtual void StartDownload(const CefString& url) OVERRIDE; virtual void Print() OVERRIDE; + virtual void Find(int identifier, const CefString& searchText, bool forward, + bool matchCase, bool findNext) OVERRIDE; + virtual void StopFinding(bool clearSelection) OVERRIDE; virtual void SetMouseCursorChangeDisabled(bool disabled) OVERRIDE; virtual bool IsMouseCursorChangeDisabled() OVERRIDE; virtual bool IsWindowRenderingDisabled() OVERRIDE; diff --git a/tests/cefclient/cefclient.rc b/tests/cefclient/cefclient.rc index 5ec1815f6..18b8c4f84 100644 --- a/tests/cefclient/cefclient.rc +++ b/tests/cefclient/cefclient.rc @@ -60,6 +60,8 @@ IDC_CEFCLIENT MENU BEGIN POPUP "&File" BEGIN + MENUITEM "&Find...", ID_FIND + MENUITEM SEPARATOR MENUITEM "E&xit", IDM_EXIT END POPUP "&Help" diff --git a/tests/cefclient/cefclient_win.cpp b/tests/cefclient/cefclient_win.cpp index 1c6652c77..22cba33a7 100644 --- a/tests/cefclient/cefclient_win.cpp +++ b/tests/cefclient/cefclient_win.cpp @@ -31,6 +31,8 @@ TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name TCHAR szOSRWindowClass[MAX_LOADSTRING]; // the OSR window class name char szWorkingDir[MAX_PATH]; // The current working directory +UINT uFindMsg; // Message identifier for find events. +HWND hFindDlg = NULL; // Handle for the find dialog. // Forward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); @@ -104,6 +106,9 @@ int APIENTRY wWinMain(HINSTANCE hInstance, hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CEFCLIENT)); + // Register the find event message. + uFindMsg = RegisterWindowMessage(FINDMSGSTRING); + int result = 0; if (!settings.multi_threaded_message_loop) { @@ -119,6 +124,10 @@ int APIENTRY wWinMain(HINSTANCE hInstance, // Run the application message loop. while (GetMessage(&msg, NULL, 0, 0)) { + // Allow processing of find dialog messages. + if (hFindDlg && IsDialogMessage(hFindDlg, &msg)) + continue; + if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); @@ -251,6 +260,47 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, return (LRESULT)CallWindowProc(editWndOldProc, hWnd, message, wParam, lParam); + } else if (message == uFindMsg) { + // Find event. + LPFINDREPLACE lpfr = (LPFINDREPLACE)lParam; + + if (lpfr->Flags & FR_DIALOGTERM) { + // The find dialog box has been dismissed so invalidate the handle and + // reset the search results. + hFindDlg = NULL; + if (g_handler.get()) { + g_handler->GetBrowser()->GetHost()->StopFinding(true); + szLastFindWhat[0] = 0; + findNext = false; + } + return 0; + } + + if ((lpfr->Flags & FR_FINDNEXT) && g_handler.get()) { + // Search for the requested string. + bool matchCase = (lpfr->Flags & FR_MATCHCASE?true:false); + if (matchCase != lastMatchCase || + (matchCase && wcsncmp(szFindWhat, szLastFindWhat, + sizeof(szLastFindWhat)/sizeof(WCHAR)) != 0) || + (!matchCase && _wcsnicmp(szFindWhat, szLastFindWhat, + sizeof(szLastFindWhat)/sizeof(WCHAR)) != 0)) { + // The search string has changed, so reset the search results. + if (szLastFindWhat[0] != 0) { + g_handler->GetBrowser()->GetHost()->StopFinding(true); + findNext = false; + } + lastMatchCase = matchCase; + wcscpy_s(szLastFindWhat, sizeof(szLastFindWhat)/sizeof(WCHAR), + szFindWhat); + } + + g_handler->GetBrowser()->GetHost()->Find(0, lpfr->lpstrFindWhat, + (lpfr->Flags & FR_DOWN)?true:false, matchCase, findNext); + if (!findNext) + findNext = true; + } + + return 0; } else { // Callback for the main window switch (message) { @@ -376,6 +426,22 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, MB_OK | MB_ICONINFORMATION); } return 0; + case ID_FIND: + if (!hFindDlg) { + // Create the find dialog. + ZeroMemory(&fr, sizeof(fr)); + fr.lStructSize = sizeof(fr); + fr.hwndOwner = hWnd; + fr.lpstrFindWhat = szFindWhat; + fr.wFindWhatLen = sizeof(szFindWhat); + fr.Flags = FR_HIDEWHOLEWORD | FR_DOWN; + + hFindDlg = FindText(&fr); + } else { + // Give focus to the existing find dialog. + ::SetFocus(hFindDlg); + } + return 0; case IDC_NAV_BACK: // Back button if (browser.get()) browser->GoBack(); diff --git a/tests/cefclient/resource.h b/tests/cefclient/resource.h index 7733866cc..d7a19f12a 100644 --- a/tests/cefclient/resource.h +++ b/tests/cefclient/resource.h @@ -26,6 +26,7 @@ #define ID_WARN_DOWNLOADCOMPLETE 32001 #define ID_WARN_DOWNLOADERROR 32002 #define ID_QUIT 32500 +#define ID_FIND 32501 #define ID_TESTS_GETSOURCE 32700 #define ID_TESTS_GETTEXT 32701 #define ID_TESTS_OTHER_TESTS 32702