diff --git a/cef_paths2.gypi b/cef_paths2.gypi index 0d538bf65..2431a4b0a 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -156,6 +156,8 @@ 'tests/cefclient/client_app_delegates.cc', 'tests/cefclient/client_handler.cc', 'tests/cefclient/client_handler.h', + 'tests/cefclient/client_handler_shared.cc', + 'tests/cefclient/client_handler_shared.h', 'tests/cefclient/client_renderer.cc', 'tests/cefclient/client_renderer.h', 'tests/cefclient/client_switches.cc', @@ -190,7 +192,7 @@ 'tests/cefclient/cefclient.exe.manifest', 'tests/cefclient/cefclient.rc', 'tests/cefclient/cefclient_win.cc', - 'tests/cefclient/client_handler_win.cc', + 'tests/cefclient/client_handler_shared_win.cc', 'tests/cefclient/main_context_impl_win.cc', 'tests/cefclient/main_message_loop_multithreaded_win.h', 'tests/cefclient/main_message_loop_multithreaded_win.cc', @@ -208,7 +210,7 @@ ], 'cefclient_sources_mac': [ 'tests/cefclient/cefclient_mac.mm', - 'tests/cefclient/client_handler_mac.mm', + 'tests/cefclient/client_handler_shared_mac.mm', 'tests/cefclient/main_context_impl_posix.cc', 'tests/cefclient/osr_widget_mac.h', 'tests/cefclient/osr_widget_mac.mm', @@ -224,7 +226,6 @@ 'tests/cefclient/client_app_delegates.cc', 'tests/cefclient/client_handler.cc', 'tests/cefclient/client_handler.h', - 'tests/cefclient/client_handler_mac.mm', 'tests/cefclient/client_renderer.cc', 'tests/cefclient/client_renderer.h', 'tests/cefclient/client_switches.cc', @@ -260,7 +261,7 @@ ], 'cefclient_sources_linux': [ 'tests/cefclient/cefclient_gtk.cc', - 'tests/cefclient/client_handler_gtk.cc', + 'tests/cefclient/client_handler_shared_gtk.cc', 'tests/cefclient/dialog_handler_gtk.cc', 'tests/cefclient/dialog_handler_gtk.h', 'tests/cefclient/main_context_impl_posix.cc', diff --git a/tests/cefclient/cefclient_gtk.cc b/tests/cefclient/cefclient_gtk.cc index 4ff14f01f..502cc9af4 100644 --- a/tests/cefclient/cefclient_gtk.cc +++ b/tests/cefclient/cefclient_gtk.cc @@ -22,7 +22,7 @@ #include "include/cef_frame.h" #include "include/wrapper/cef_helpers.h" #include "cefclient/client_app.h" -#include "cefclient/client_handler.h" +#include "cefclient/client_handler_shared.h" #include "cefclient/client_switches.h" #include "cefclient/main_context_impl.h" #include "cefclient/main_message_loop_std.h" @@ -33,8 +33,8 @@ namespace client { namespace { -// The global ClientHandler reference. -CefRefPtr g_handler; +// The global ClientHandlerShared reference. +CefRefPtr g_handler; // Height of the buttons at the top of the GTK window. int g_toolbar_height = 0; @@ -427,11 +427,10 @@ int RunMain(int argc, char* argv[]) { G_CALLBACK(delete_event), window); // Create the handler. - g_handler = new ClientHandler(); + g_handler = new ClientHandlerShared(); g_handler->SetMainWindowHandle(vbox); - g_handler->SetEditWindowHandle(entry); - g_handler->SetButtonWindowHandles(GTK_WIDGET(back), GTK_WIDGET(forward), - GTK_WIDGET(reload), GTK_WIDGET(stop)); + g_handler->SetUXWindowHandles(entry, GTK_WIDGET(back), GTK_WIDGET(forward), + GTK_WIDGET(reload), GTK_WIDGET(stop)); CefWindowInfo window_info; CefBrowserSettings browserSettings; @@ -439,9 +438,9 @@ int RunMain(int argc, char* argv[]) { // Populate the browser settings based on command line arguments. context->PopulateBrowserSettings(&browserSettings); - CefRefPtr command_line = - CefCommandLine::GetGlobalCommandLine(); - if (command_line->HasSwitch(switches::kOffScreenRenderingEnabled)) { + if (g_handler->is_osr()) { + CefRefPtr command_line = + CefCommandLine::GetGlobalCommandLine(); const bool transparent = command_line->HasSwitch(switches::kTransparentPaintingEnabled); const bool show_update_rect = @@ -473,7 +472,7 @@ int RunMain(int argc, char* argv[]) { // Create the browser window. CefBrowserHost::CreateBrowserSync( window_info, g_handler.get(), - g_handler->GetStartupURL(), browserSettings, NULL); + g_handler->startup_url(), browserSettings, NULL); // Install a signal handler so we clean up after ourselves. signal(SIGINT, TerminationSignalHandler); diff --git a/tests/cefclient/cefclient_mac.mm b/tests/cefclient/cefclient_mac.mm index f430b7c1b..99ba79cc2 100644 --- a/tests/cefclient/cefclient_mac.mm +++ b/tests/cefclient/cefclient_mac.mm @@ -21,8 +21,8 @@ namespace { -// The global ClientHandler reference. -CefRefPtr g_handler; +// The global ClientHandlerShared reference. +CefRefPtr g_handler; // Used by off-screen rendering to find the associated CefBrowser. class MainBrowserProvider : public client::OSRBrowserProvider { @@ -232,8 +232,7 @@ void AddMenuItem(NSMenu *menu, NSString* label, int idval) { if (g_handler.get()) { CefRefPtr browser = g_handler->GetBrowser(); if (browser.get()) { - if (CefCommandLine::GetGlobalCommandLine()->HasSwitch( - client::switches::kOffScreenRenderingEnabled)) { + if (g_handler->is_osr())) { browser->GetHost()->SendFocusEvent(true); } else { browser->GetHost()->SetFocus(true); @@ -247,8 +246,7 @@ void AddMenuItem(NSMenu *menu, NSString* label, int idval) { if (g_handler.get()) { CefRefPtr browser = g_handler->GetBrowser(); if (browser.get()) { - if (CefCommandLine::GetGlobalCommandLine()->HasSwitch( - client::switches::kOffScreenRenderingEnabled)) { + if (g_handler->is_osr()) { browser->GetHost()->SendFocusEvent(false); } else { browser->GetHost()->SetFocus(false); @@ -402,21 +400,25 @@ void AddMenuItem(NSMenu *menu, NSString* label, int idval) { button_rect.origin.x += BUTTON_MARGIN; button_rect.size.width = BUTTON_WIDTH; - NSButton* button = MakeButton(&button_rect, @"Back", contentView); - [button setTarget:delegate]; - [button setAction:@selector(goBack:)]; + NSButton* backButton = MakeButton(&button_rect, @"Back", contentView); + [backButton setTarget:delegate]; + [backButton setAction:@selector(goBack:)]; + [backButton setEnabled:NO]; - button = MakeButton(&button_rect, @"Forward", contentView); - [button setTarget:delegate]; - [button setAction:@selector(goForward:)]; + NSButton* forwardButton = MakeButton(&button_rect, @"Forward", contentView); + [forwardButton setTarget:delegate]; + [forwardButton setAction:@selector(goForward:)]; + [forwardButton setEnabled:NO]; - button = MakeButton(&button_rect, @"Reload", contentView); - [button setTarget:delegate]; - [button setAction:@selector(reload:)]; + NSButton* reloadButton = MakeButton(&button_rect, @"Reload", contentView); + [reloadButton setTarget:delegate]; + [reloadButton setAction:@selector(reload:)]; + [reloadButton setEnabled:NO]; - button = MakeButton(&button_rect, @"Stop", contentView); - [button setTarget:delegate]; - [button setAction:@selector(stopLoading:)]; + NSButton* stopButton = MakeButton(&button_rect, @"Stop", contentView); + [stopButton setTarget:delegate]; + [stopButton setAction:@selector(stopLoading:)]; + [stopButton setEnabled:NO]; // Create the URL text field. button_rect.origin.x += BUTTON_MARGIN; @@ -427,13 +429,15 @@ void AddMenuItem(NSMenu *menu, NSString* label, int idval) { [editWnd setAutoresizingMask:(NSViewWidthSizable | NSViewMinYMargin)]; [editWnd setTarget:delegate]; [editWnd setAction:@selector(takeURLStringValueFrom:)]; + [editWnd setEnabled:NO]; [[editWnd cell] setWraps:NO]; [[editWnd cell] setScrollable:YES]; // Create the handler. - g_handler = new client::ClientHandler(); + g_handler = new client::ClientHandlerShared(); g_handler->SetMainWindowHandle(contentView); - g_handler->SetEditWindowHandle(editWnd); + g_handler->SetUXWindowHandles(editWnd, backButton, forwardButton, + reloadButton, stopButton); // Create the browser view. CefWindowInfo window_info; @@ -442,9 +446,9 @@ void AddMenuItem(NSMenu *menu, NSString* label, int idval) { // Populate the browser settings based on command line arguments. client::MainContext::Get()->PopulateBrowserSettings(&settings); - CefRefPtr command_line = - CefCommandLine::GetGlobalCommandLine(); - if (command_line->HasSwitch(client::switches::kOffScreenRenderingEnabled)) { + if (g_handler->is_osr()) { + CefRefPtr command_line = + CefCommandLine::GetGlobalCommandLine(); const bool transparent = command_line->HasSwitch(client::switches::kTransparentPaintingEnabled); const bool show_update_rect = @@ -462,7 +466,7 @@ void AddMenuItem(NSMenu *menu, NSString* label, int idval) { } CefBrowserHost::CreateBrowser(window_info, g_handler.get(), - g_handler->GetStartupURL(), settings, NULL); + g_handler->startup_url(), settings, NULL); // Show the window. [mainWnd makeKeyAndOrderFront: nil]; diff --git a/tests/cefclient/cefclient_win.cc b/tests/cefclient/cefclient_win.cc index 1534e8536..3524ddd98 100644 --- a/tests/cefclient/cefclient_win.cc +++ b/tests/cefclient/cefclient_win.cc @@ -17,7 +17,7 @@ #include "include/cef_sandbox_win.h" #include "include/wrapper/cef_closure_task.h" #include "cefclient/client_app.h" -#include "cefclient/client_handler.h" +#include "cefclient/client_handler_shared.h" #include "cefclient/client_switches.h" #include "cefclient/main_context_impl.h" #include "cefclient/main_message_loop_multithreaded_win.h" @@ -63,8 +63,8 @@ LRESULT CALLBACK MainWndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK FindWndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK AboutWndProc(HWND, UINT, WPARAM, LPARAM); -// The global ClientHandler reference. -CefRefPtr g_handler; +// The global ClientHandlerShared reference. +CefRefPtr g_handler; // Used by off-screen rendering to find the associated CefBrowser. class MainBrowserProvider : public OSRBrowserProvider { @@ -197,11 +197,10 @@ static void SetFocusToBrowser(CefRefPtr browser) { if (!g_handler) return; - if (CefCommandLine::GetGlobalCommandLine()->HasSwitch( - switches::kOffScreenRenderingEnabled)) { + if (g_handler->is_osr()) { // Give focus to the OSR window. CefRefPtr osr_window = - static_cast(g_handler->GetOSRHandler().get()); + OSRWindow::From(g_handler->GetOSRHandler()); if (osr_window) ::SetFocus(osr_window->hwnd()); } else { @@ -295,7 +294,7 @@ LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, switch (message) { case WM_CREATE: { // Create the single static handler class instance - g_handler = new ClientHandler(); + g_handler = new ClientHandlerShared(); g_handler->SetMainWindowHandle(hWnd); // Create the child windows used for navigation @@ -342,9 +341,8 @@ LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, reinterpret_cast(GetWindowLongPtr(editWnd, GWLP_WNDPROC)); SetWindowLongPtr(editWnd, GWLP_WNDPROC, reinterpret_cast(MainWndProc)); - g_handler->SetEditWindowHandle(editWnd); - g_handler->SetButtonWindowHandles( - backWnd, forwardWnd, reloadWnd, stopWnd); + g_handler->SetUXWindowHandles( + editWnd, backWnd, forwardWnd, reloadWnd, stopWnd); rect.top += URLBAR_HEIGHT; @@ -354,9 +352,9 @@ LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, // Populate the browser settings based on command line arguments. MainContext::Get()->PopulateBrowserSettings(&settings); - CefRefPtr command_line = - CefCommandLine::GetGlobalCommandLine(); - if (command_line->HasSwitch(switches::kOffScreenRenderingEnabled)) { + if (g_handler->is_osr()) { + CefRefPtr command_line = + CefCommandLine::GetGlobalCommandLine(); const bool transparent = command_line->HasSwitch(switches::kTransparentPaintingEnabled); const bool show_update_rect = @@ -375,7 +373,7 @@ LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, // Creat the new child browser window CefBrowserHost::CreateBrowser(info, g_handler.get(), - g_handler->GetStartupURL(), settings, NULL); + g_handler->startup_url(), settings, NULL); return 0; } @@ -463,11 +461,10 @@ LRESULT CALLBACK MainWndProc(HWND hWnd, UINT message, WPARAM wParam, // For off-screen browsers when the frame window is minimized set the // browser as hidden to reduce resource usage. - const bool offscreen = CefCommandLine::GetGlobalCommandLine()->HasSwitch( - switches::kOffScreenRenderingEnabled); + const bool offscreen = g_handler->is_osr(); if (offscreen) { CefRefPtr osr_window = - static_cast(g_handler->GetOSRHandler().get()); + OSRWindow::From(g_handler->GetOSRHandler()); if (osr_window) osr_window->WasHidden(wParam == SIZE_MINIMIZED); } diff --git a/tests/cefclient/client_handler.cc b/tests/cefclient/client_handler.cc index 2861dd6da..ffeb8421e 100644 --- a/tests/cefclient/client_handler.cc +++ b/tests/cefclient/client_handler.cc @@ -3,33 +3,22 @@ // can be found in the LICENSE file. #include "cefclient/client_handler.h" + #include #include -#include #include #include -#include #include "include/base/cef_bind.h" #include "include/cef_browser.h" #include "include/cef_frame.h" -#include "include/cef_path_util.h" -#include "include/cef_process_util.h" -#include "include/cef_trace.h" -#include "include/cef_url.h" #include "include/wrapper/cef_closure_task.h" -#include "include/wrapper/cef_stream_resource_handler.h" #include "cefclient/client_renderer.h" #include "cefclient/client_switches.h" #include "cefclient/main_context.h" -#include "cefclient/main_message_loop.h" #include "cefclient/resource_util.h" #include "cefclient/test_runner.h" -#if defined(OS_LINUX) -#include "cefclient/dialog_handler_gtk.h" -#endif - namespace client { #if defined(OS_WIN) @@ -54,18 +43,12 @@ enum client_menu_ids { } // namespace -int ClientHandler::browser_count_ = 0; - -ClientHandler::ClientHandler() - : startup_url_(MainContext::Get()->GetMainURL()), - browser_id_(0), - is_closing_(false), +ClientHandler::ClientHandler(const std::string& startup_url, + bool is_osr) + : startup_url_(startup_url), + is_osr_(is_osr), + browser_count_(0), main_handle_(NULL), - edit_handle_(NULL), - back_handle_(NULL), - forward_handle_(NULL), - stop_handle_(NULL), - reload_handle_(NULL), console_log_file_(MainContext::Get()->GetConsoleLogPath()), first_console_message_(true), focus_on_editable_field_(false) { @@ -73,10 +56,7 @@ ClientHandler::ClientHandler() #if defined(OS_LINUX) // Provide the GTK-based dialog implementation on Linux. - CefRefPtr dialog_handler = - new ClientDialogHandlerGtk(); - dialog_handler_ = dialog_handler.get(); - jsdialog_handler_ = dialog_handler.get(); + dialog_handler_ = new ClientDialogHandlerGtk(); #endif // Read command line settings. @@ -160,6 +140,23 @@ bool ClientHandler::OnContextMenuCommand( } } +void ClientHandler::OnAddressChange(CefRefPtr browser, + CefRefPtr frame, + const CefString& url) { + CEF_REQUIRE_UI_THREAD(); + + // Only update the address for the main (top-level) frame. + if (frame->IsMain()) + SetAddress(browser, url); +} + +void ClientHandler::OnTitleChange(CefRefPtr browser, + const CefString& title) { + CEF_REQUIRE_UI_THREAD(); + + SetTitle(browser, title); +} + bool ClientHandler::OnConsoleMessage(CefRefPtr browser, const CefString& message, const CefString& source, @@ -247,10 +244,8 @@ bool ClientHandler::OnPreKeyEvent(CefRefPtr browser, // being processed in the renderer. If we instead handled the event in the // OnKeyEvent() method the space key would cause the window to scroll in // addition to showing the alert box. - if (event.type == KEYEVENT_RAWKEYDOWN) { - browser->GetMainFrame()->ExecuteJavaScript( - "alert('You pressed the space bar!');", "", 0); - } + if (event.type == KEYEVENT_RAWKEYDOWN) + test_runner::Alert(browser, "You pressed the space bar!"); return true; } @@ -268,16 +263,15 @@ bool ClientHandler::OnBeforePopup(CefRefPtr browser, bool* no_javascript_access) { CEF_REQUIRE_IO_THREAD(); - if (browser->GetHost()->IsWindowRenderingDisabled()) { - // Cancel popups in off-screen rendering mode. - return true; - } - return false; + // Return true to cancel the popup window. + return !CreatePopupWindow(false, popupFeatures, windowInfo, client, settings); } void ClientHandler::OnAfterCreated(CefRefPtr browser) { CEF_REQUIRE_UI_THREAD(); + browser_count_++; + if (!message_router_) { // Create the browser-side router for query handling. CefMessageRouterConfig config; @@ -294,35 +288,13 @@ void ClientHandler::OnAfterCreated(CefRefPtr browser) { if (mouse_cursor_change_disabled_) browser->GetHost()->SetMouseCursorChangeDisabled(true); - if (!GetBrowser()) { - base::AutoLock lock_scope(lock_); - // We need to keep the main child window, but not popup windows - browser_ = browser; - browser_id_ = browser->GetIdentifier(); - } else if (browser->IsPopup()) { - // Add to the list of popup browsers. - popup_browsers_.push_back(browser); - - // Give focus to the popup browser. Perform asynchronously because the - // parent window may attempt to keep focus after launching the popup. - CefPostTask(TID_UI, - base::Bind(&CefBrowserHost::SetFocus, browser->GetHost().get(), true)); - } - - browser_count_++; + BrowserCreated(browser); } bool ClientHandler::DoClose(CefRefPtr browser) { CEF_REQUIRE_UI_THREAD(); - // Closing the main window requires special handling. See the DoClose() - // documentation in the CEF header for a detailed destription of this - // process. - if (GetBrowserId() == browser->GetIdentifier()) { - base::AutoLock lock_scope(lock_); - // Set a flag to indicate that the window close should be allowed. - is_closing_ = true; - } + BrowserClosing(browser); // Allow the close. For windowed browsers this will result in the OS close // event being sent. @@ -332,44 +304,19 @@ bool ClientHandler::DoClose(CefRefPtr browser) { void ClientHandler::OnBeforeClose(CefRefPtr browser) { CEF_REQUIRE_UI_THREAD(); - message_router_->OnBeforeClose(browser); - - if (GetBrowserId() == browser->GetIdentifier()) { - { - base::AutoLock lock_scope(lock_); - // Free the browser pointer so that the browser can be destroyed - browser_ = NULL; - } - - if (osr_handler_.get()) { - osr_handler_->OnBeforeClose(browser); - osr_handler_ = NULL; - } - } else if (browser->IsPopup()) { - // Remove from the browser popup list. - BrowserList::iterator bit = popup_browsers_.begin(); - for (; bit != popup_browsers_.end(); ++bit) { - if ((*bit)->IsSame(browser)) { - popup_browsers_.erase(bit); - break; - } - } - } - if (--browser_count_ == 0) { - // All browser windows have closed. // Remove and delete message router handlers. - MessageHandlerSet::const_iterator it = message_handler_set_.begin(); + MessageHandlerSet::const_iterator it = + message_handler_set_.begin(); for (; it != message_handler_set_.end(); ++it) { message_router_->RemoveHandler(*(it)); delete *(it); } message_handler_set_.clear(); message_router_ = NULL; - - // Quit the application message loop. - MainMessageLoop::Get()->Quit(); } + + BrowserClosed(browser); } void ClientHandler::OnLoadingStateChange(CefRefPtr browser, @@ -378,8 +325,7 @@ void ClientHandler::OnLoadingStateChange(CefRefPtr browser, bool canGoForward) { CEF_REQUIRE_UI_THREAD(); - SetLoading(isLoading); - SetNavState(canGoBack, canGoForward); + SetLoadingState(browser, isLoading, canGoBack, canGoForward); } void ClientHandler::OnLoadError(CefRefPtr browser, @@ -425,6 +371,7 @@ CefRefPtr ClientHandler::GetResourceHandler( CefRefPtr frame, CefRefPtr request) { CEF_REQUIRE_IO_THREAD(); + return test_runner::GetResourceHandler(browser, frame, request); } @@ -459,106 +406,30 @@ void ClientHandler::OnRenderProcessTerminated(CefRefPtr browser, message_router_->OnRenderProcessTerminated(browser); - // Load the startup URL if that's not the website that we terminated on. + // Don't reload if there's no start URL, or if the crash URL was specified. + if (startup_url_.empty() || startup_url_ == "chrome://crash") + return; + CefRefPtr frame = browser->GetMainFrame(); std::string url = frame->GetURL(); + + // Don't reload if the termination occurred before any URL had successfully + // loaded. + if (url.empty()) + return; + + std::string start_url = startup_url_; + + // Convert URLs to lowercase for easier comparison. std::transform(url.begin(), url.end(), url.begin(), tolower); + std::transform(start_url.begin(), start_url.end(), start_url.begin(), + tolower); - std::string startupURL = GetStartupURL(); - if (startupURL != "chrome://crash" && !url.empty() && - url.find(startupURL) != 0) { - frame->LoadURL(startupURL); - } -} - -bool ClientHandler::GetRootScreenRect(CefRefPtr browser, - CefRect& rect) { - CEF_REQUIRE_UI_THREAD(); - if (!osr_handler_.get()) - return false; - return osr_handler_->GetRootScreenRect(browser, rect); -} - -bool ClientHandler::GetViewRect(CefRefPtr browser, CefRect& rect) { - CEF_REQUIRE_UI_THREAD(); - if (!osr_handler_.get()) - return false; - return osr_handler_->GetViewRect(browser, rect); -} - -bool ClientHandler::GetScreenPoint(CefRefPtr browser, - int viewX, - int viewY, - int& screenX, - int& screenY) { - CEF_REQUIRE_UI_THREAD(); - if (!osr_handler_.get()) - return false; - return osr_handler_->GetScreenPoint(browser, viewX, viewY, screenX, screenY); -} - -bool ClientHandler::GetScreenInfo(CefRefPtr browser, - CefScreenInfo& screen_info) { - CEF_REQUIRE_UI_THREAD(); - if (!osr_handler_.get()) - return false; - return osr_handler_->GetScreenInfo(browser, screen_info); -} - -void ClientHandler::OnPopupShow(CefRefPtr browser, - bool show) { - CEF_REQUIRE_UI_THREAD(); - if (!osr_handler_.get()) + // Don't reload the URL that just resulted in termination. + if (url.find(start_url) == 0) return; - return osr_handler_->OnPopupShow(browser, show); -} -void ClientHandler::OnPopupSize(CefRefPtr browser, - const CefRect& rect) { - CEF_REQUIRE_UI_THREAD(); - if (!osr_handler_.get()) - return; - return osr_handler_->OnPopupSize(browser, rect); -} - -void ClientHandler::OnPaint(CefRefPtr browser, - PaintElementType type, - const RectList& dirtyRects, - const void* buffer, - int width, - int height) { - CEF_REQUIRE_UI_THREAD(); - if (!osr_handler_.get()) - return; - osr_handler_->OnPaint(browser, type, dirtyRects, buffer, width, height); -} - -void ClientHandler::OnCursorChange(CefRefPtr browser, - CefCursorHandle cursor, - CursorType type, - const CefCursorInfo& custom_cursor_info) { - CEF_REQUIRE_UI_THREAD(); - if (!osr_handler_.get()) - return; - osr_handler_->OnCursorChange(browser, cursor, type, custom_cursor_info); -} - -bool ClientHandler::StartDragging(CefRefPtr browser, - CefRefPtr drag_data, - CefRenderHandler::DragOperationsMask allowed_ops, - int x, int y) { - CEF_REQUIRE_UI_THREAD(); - if (!osr_handler_.get()) - return false; - return osr_handler_->StartDragging(browser, drag_data, allowed_ops, x, y); -} - -void ClientHandler::UpdateDragCursor(CefRefPtr browser, - CefRenderHandler::DragOperation operation) { - CEF_REQUIRE_UI_THREAD(); - if (!osr_handler_.get()) - return; - osr_handler_->UpdateDragCursor(browser, operation); + frame->LoadURL(startup_url_); } void ClientHandler::SetMainWindowHandle(ClientWindowHandle handle) { @@ -573,8 +444,7 @@ void ClientHandler::SetMainWindowHandle(ClientWindowHandle handle) { #if defined(OS_LINUX) // Associate |handle| with the GTK dialog handler. - static_cast(dialog_handler_.get())->set_parent( - handle); + dialog_handler_->set_parent(handle); #endif } @@ -583,122 +453,28 @@ ClientWindowHandle ClientHandler::GetMainWindowHandle() const { return main_handle_; } -void ClientHandler::SetEditWindowHandle(ClientWindowHandle handle) { - if (!CefCurrentlyOn(TID_UI)) { - // Execute on the UI thread. - CefPostTask(TID_UI, - base::Bind(&ClientHandler::SetEditWindowHandle, this, handle)); - return; - } - - edit_handle_ = handle; -} - -void ClientHandler::SetButtonWindowHandles(ClientWindowHandle backHandle, - ClientWindowHandle forwardHandle, - ClientWindowHandle reloadHandle, - ClientWindowHandle stopHandle) { - if (!CefCurrentlyOn(TID_UI)) { - // Execute on the UI thread. - CefPostTask(TID_UI, - base::Bind(&ClientHandler::SetButtonWindowHandles, this, - backHandle, forwardHandle, reloadHandle, stopHandle)); - return; - } - - back_handle_ = backHandle; - forward_handle_ = forwardHandle; - reload_handle_ = reloadHandle; - stop_handle_ = stopHandle; -} - -void ClientHandler::SetOSRHandler(CefRefPtr handler) { - if (!CefCurrentlyOn(TID_UI)) { - // Execute on the UI thread. - CefPostTask(TID_UI, - base::Bind(&ClientHandler::SetOSRHandler, this, handler)); - return; - } - - osr_handler_ = handler; -} - -CefRefPtr ClientHandler::GetOSRHandler() const { - return osr_handler_; -} - -CefRefPtr ClientHandler::GetBrowser() const { - base::AutoLock lock_scope(lock_); - return browser_; -} - -int ClientHandler::GetBrowserId() const { - base::AutoLock lock_scope(lock_); - return browser_id_; -} - -void ClientHandler::CloseAllBrowsers(bool force_close) { - if (!CefCurrentlyOn(TID_UI)) { - // Execute on the UI thread. - CefPostTask(TID_UI, - base::Bind(&ClientHandler::CloseAllBrowsers, this, force_close)); - return; - } - - if (!popup_browsers_.empty()) { - // Request that any popup browsers close. - BrowserList::const_iterator it = popup_browsers_.begin(); - for (; it != popup_browsers_.end(); ++it) - (*it)->GetHost()->CloseBrowser(force_close); - } - - if (browser_.get()) { - // Request that the main browser close. - browser_->GetHost()->CloseBrowser(force_close); - } -} - -bool ClientHandler::IsClosing() const { - base::AutoLock lock_scope(lock_); - return is_closing_; +int ClientHandler::GetBrowserCount() const { + CEF_REQUIRE_UI_THREAD(); + return browser_count_; } void ClientHandler::ShowDevTools(CefRefPtr browser, const CefPoint& inspect_element_at) { CefWindowInfo windowInfo; + CefRefPtr client; CefBrowserSettings settings; -#if defined(OS_WIN) - windowInfo.SetAsPopup(browser->GetHost()->GetWindowHandle(), "DevTools"); -#endif - - browser->GetHost()->ShowDevTools(windowInfo, this, settings, - inspect_element_at); + if (CreatePopupWindow(true, CefPopupFeatures(), windowInfo, client, + settings)) { + browser->GetHost()->ShowDevTools(windowInfo, client, settings, + inspect_element_at); + } } void ClientHandler::CloseDevTools(CefRefPtr browser) { browser->GetHost()->CloseDevTools(); } -std::string ClientHandler::GetStartupURL() const { - return startup_url_; -} - -bool ClientHandler::Save(const std::string& path, const std::string& data) { - FILE* f = fopen(path.c_str(), "w"); - if (!f) - return false; - size_t total = 0; - do { - size_t write = fwrite(data.c_str() + total, 1, data.size() - total, f); - if (write == 0) - break; - total += write; - } while (total < data.size()); - fclose(f); - return true; -} - void ClientHandler::BuildTestMenu(CefRefPtr model) { if (model->GetCount() > 0) model->AddSeparator(); diff --git a/tests/cefclient/client_handler.h b/tests/cefclient/client_handler.h index 901b39a01..aa99bd233 100644 --- a/tests/cefclient/client_handler.h +++ b/tests/cefclient/client_handler.h @@ -6,31 +6,27 @@ #define CEF_TESTS_CEFCLIENT_CLIENT_HANDLER_H_ #pragma once -#include -#include #include #include -#include "include/base/cef_lock.h" #include "include/cef_client.h" #include "include/wrapper/cef_helpers.h" #include "include/wrapper/cef_message_router.h" #if defined(OS_LINUX) -// The Linux client uses GTK instead of the underlying platform type (X11). #include +#include "cefclient/dialog_handler_gtk.h" + +// The Linux client uses GTK instead of the underlying platform type (X11). #define ClientWindowHandle GtkWidget* #else #define ClientWindowHandle CefWindowHandle #endif -// Define this value to redirect all popup URLs to the main application browser -// window. -// #define TEST_REDIRECT_POPUP_URLS - namespace client { -// ClientHandler implementation. +// Client handler abstract base class. Provides common functionality shared by +// all concrete client handler implementations. class ClientHandler : public CefClient, public CefContextMenuHandler, public CefDisplayHandler, @@ -40,27 +36,18 @@ class ClientHandler : public CefClient, public CefKeyboardHandler, public CefLifeSpanHandler, public CefLoadHandler, - public CefRenderHandler, public CefRequestHandler { public: - // Interface implemented to handle off-screen rendering. - class RenderHandler : public CefRenderHandler { - public: - virtual void OnBeforeClose(CefRefPtr browser) =0; - }; - typedef std::set MessageHandlerSet; - ClientHandler(); + ClientHandler(const std::string& startup_url, + bool is_osr); ~ClientHandler(); // CefClient methods CefRefPtr GetContextMenuHandler() OVERRIDE { return this; } - CefRefPtr GetDialogHandler() OVERRIDE { - return dialog_handler_; - } CefRefPtr GetDisplayHandler() OVERRIDE { return this; } @@ -73,9 +60,6 @@ class ClientHandler : public CefClient, CefRefPtr GetGeolocationHandler() OVERRIDE { return this; } - CefRefPtr GetJSDialogHandler() OVERRIDE { - return jsdialog_handler_; - } CefRefPtr GetKeyboardHandler() OVERRIDE { return this; } @@ -85,9 +69,6 @@ class ClientHandler : public CefClient, CefRefPtr GetLoadHandler() OVERRIDE { return this; } - CefRefPtr GetRenderHandler() OVERRIDE { - return this; - } CefRefPtr GetRequestHandler() OVERRIDE { return this; } @@ -95,6 +76,15 @@ class ClientHandler : public CefClient, CefProcessId source_process, CefRefPtr message) OVERRIDE; +#if defined(OS_LINUX) + CefRefPtr GetDialogHandler() OVERRIDE { + return dialog_handler_; + } + CefRefPtr GetJSDialogHandler() OVERRIDE { + return dialog_handler_; + } +#endif + // CefContextMenuHandler methods void OnBeforeContextMenu(CefRefPtr browser, CefRefPtr frame, @@ -190,158 +180,120 @@ class ClientHandler : public CefClient, void OnRenderProcessTerminated(CefRefPtr browser, TerminationStatus status) OVERRIDE; - // CefRenderHandler methods - bool GetRootScreenRect(CefRefPtr browser, - CefRect& rect) OVERRIDE; - bool GetViewRect(CefRefPtr browser, - CefRect& rect) OVERRIDE; - bool GetScreenPoint(CefRefPtr browser, - int viewX, - int viewY, - int& screenX, - int& screenY) OVERRIDE; - bool GetScreenInfo(CefRefPtr browser, - CefScreenInfo& screen_info) OVERRIDE; - void OnPopupShow(CefRefPtr browser, bool show) OVERRIDE; - void OnPopupSize(CefRefPtr browser, - const CefRect& rect) OVERRIDE; - void OnPaint(CefRefPtr browser, - PaintElementType type, - const RectList& dirtyRects, - const void* buffer, - int width, - int height) OVERRIDE; - void OnCursorChange(CefRefPtr browser, - CefCursorHandle cursor, - CursorType type, - const CefCursorInfo& custom_cursor_info) OVERRIDE; - bool StartDragging(CefRefPtr browser, - CefRefPtr drag_data, - CefRenderHandler::DragOperationsMask allowed_ops, - int x, int y) OVERRIDE; - void UpdateDragCursor(CefRefPtr browser, - CefRenderHandler::DragOperation operation) OVERRIDE; - + // Set the main frame window handle. void SetMainWindowHandle(ClientWindowHandle handle); + + // Get the main frame window handle. Can only be called on the CEF UI thread. ClientWindowHandle GetMainWindowHandle() const; - void SetEditWindowHandle(ClientWindowHandle handle); - void SetButtonWindowHandles(ClientWindowHandle backHandle, - ClientWindowHandle forwardHandle, - ClientWindowHandle reloadHandle, - ClientWindowHandle stopHandle); - void SetOSRHandler(CefRefPtr handler); - CefRefPtr GetOSRHandler() const; - - CefRefPtr GetBrowser() const; - int GetBrowserId() const; - - // Request that all existing browser windows close. - void CloseAllBrowsers(bool force_close); - - // Returns true if the main browser window is currently closing. Used in - // combination with DoClose() and the OS close notification to properly handle - // 'onbeforeunload' JavaScript events during window close. - bool IsClosing() const; + // Returns the number of browsers currently using this handler. Can only be + // called on the CEF UI thread. + int GetBrowserCount() const; + // Show a new DevTools popup window. void ShowDevTools(CefRefPtr browser, const CefPoint& inspect_element_at); + + // Close the existing DevTools popup window, if any. void CloseDevTools(CefRefPtr browser); // Returns the startup URL. - std::string GetStartupURL() const; + std::string startup_url() const { return startup_url_; } - bool Save(const std::string& path, const std::string& data); + // Returns true if this handler uses off-screen rendering. + bool is_osr() const { return is_osr_; } + + protected: + // The following virtual methods are called on the CEF UI thread unless + // otherwise indicated. + + // A browser has been created. + virtual void BrowserCreated(CefRefPtr browser) = 0; + + // A browser is closing. + virtual void BrowserClosing(CefRefPtr browser) = 0; + + // A browser has been closed. + virtual void BrowserClosed(CefRefPtr browser) = 0; + + // Set the window URL address. + virtual void SetAddress(CefRefPtr browser, + const CefString& url) = 0; + + // Set the window title. + virtual void SetTitle(CefRefPtr browser, + const CefString& title) = 0; + + // Set the loading state. + virtual void SetLoadingState(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) = 0; + + // Create a new popup window using the specified information. |is_devtools| + // will be true if the window will be used for DevTools. Return true to + // proceed with popup browser creation or false to cancel the popup browser. + // May be called on any thead. + virtual bool CreatePopupWindow( + bool is_devtools, + const CefPopupFeatures& popupFeatures, + CefWindowInfo& windowInfo, + CefRefPtr& client, + CefBrowserSettings& settings) = 0; private: - void SetLoading(bool isLoading); - void SetNavState(bool canGoBack, bool canGoForward); - // Test context menu creation. void BuildTestMenu(CefRefPtr model); bool ExecuteTestMenu(int command_id); + + // THREAD SAFE MEMBERS + // The following members may be accessed from any thread. + + // The startup URL. + const std::string startup_url_; + + // True if this handler uses off-screen rendering. + const bool is_osr_; + + // True if mouse cursor change is disabled. + bool mouse_cursor_change_disabled_; + +#if defined(OS_LINUX) + // Custom dialog handler for GTK. + CefRefPtr dialog_handler_; +#endif + + // Handles the browser side of query routing. The renderer side is handled + // in client_renderer.cc. + CefRefPtr message_router_; + + // UI THREAD MEMBERS + // The following members will only be accessed on the CEF UI thread. + + // Track state information for the text context menu. struct TestMenuState { TestMenuState() : check_item(true), radio_item(0) {} bool check_item; int radio_item; } test_menu_state_; - // START THREAD SAFE MEMBERS - // The following members are thread-safe because they're initialized during - // object construction and not changed thereafter. - - // The startup URL. - std::string startup_url_; - - // True if mouse cursor change is disabled. - bool mouse_cursor_change_disabled_; - - CefRefPtr dialog_handler_; - CefRefPtr jsdialog_handler_; - // END THREAD SAFE MEMBERS - - // Lock used to protect members accessed on multiple threads. Make it mutable - // so that it can be used from const methods. - mutable base::Lock lock_; - - // START LOCK PROTECTED MEMBERS - // The following members are accessed on multiple threads and must be - // protected by |lock_|. - - // The child browser window. - CefRefPtr browser_; - - // The child browser id. - int browser_id_; - - // True if the main browser window is currently closing. - bool is_closing_; - // END LOCK PROTECTED MEMBERS - - // START UI THREAD ACCESS ONLY MEMBERS - // The following members will only be accessed on the CEF UI thread. - - // List of any popup browser windows. - typedef std::list > BrowserList; - BrowserList popup_browsers_; + // The current number of browsers using this handler. + int browser_count_; // The main frame window handle. ClientWindowHandle main_handle_; - // The edit window handle. - ClientWindowHandle edit_handle_; - - // The button window handles. - ClientWindowHandle back_handle_; - ClientWindowHandle forward_handle_; - ClientWindowHandle stop_handle_; - ClientWindowHandle reload_handle_; - - // The handler for off-screen rendering, if any. - CefRefPtr osr_handler_; - - // Used for console logging purposes. + // Console logging state. const std::string console_log_file_; bool first_console_message_; // True if an editable field currently has focus. bool focus_on_editable_field_; - // Handles the browser side of query routing. The renderer side is handled - // in client_renderer.cc. - CefRefPtr message_router_; - // Set of Handlers registered with the message router. MessageHandlerSet message_handler_set_; - // Number of currently existing browser windows. The application will exit - // when the number of windows reaches 0. - static int browser_count_; - - // END UI THREAD ACCESS ONLY MEMBERS - - // Include the default reference counting implementation. - IMPLEMENT_REFCOUNTING(ClientHandler); + DISALLOW_COPY_AND_ASSIGN(ClientHandler); }; } // namespace client diff --git a/tests/cefclient/client_handler_mac.mm b/tests/cefclient/client_handler_mac.mm deleted file mode 100644 index f80bbe424..000000000 --- a/tests/cefclient/client_handler_mac.mm +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) 2011 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. - -#import - -#include "cefclient/client_handler.h" -#include "include/cef_browser.h" -#include "include/cef_frame.h" - -namespace client { - -void ClientHandler::OnAddressChange(CefRefPtr browser, - CefRefPtr frame, - const CefString& url) { - CEF_REQUIRE_UI_THREAD(); - - if (GetBrowserId() == browser->GetIdentifier() && frame->IsMain()) { - // Set the edit window text - NSTextField* textField = (NSTextField*)edit_handle_; - std::string urlStr(url); - NSString* str = [NSString stringWithUTF8String:urlStr.c_str()]; - [textField setStringValue:str]; - } -} - -void ClientHandler::OnTitleChange(CefRefPtr browser, - const CefString& title) { - CEF_REQUIRE_UI_THREAD(); - - // Set the frame window title bar - NSView* view = (NSView*)browser->GetHost()->GetWindowHandle(); - NSWindow* window = [view window]; - std::string titleStr(title); - NSString* str = [NSString stringWithUTF8String:titleStr.c_str()]; - [window setTitle:str]; -} - -void ClientHandler::SetLoading(bool isLoading) { - // TODO(port): Change button status. -} - -void ClientHandler::SetNavState(bool canGoBack, bool canGoForward) { - // TODO(port): Change button status. -} - -} // namespace client diff --git a/tests/cefclient/client_handler_shared.cc b/tests/cefclient/client_handler_shared.cc new file mode 100644 index 000000000..0c9358520 --- /dev/null +++ b/tests/cefclient/client_handler_shared.cc @@ -0,0 +1,235 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "cefclient/client_handler_shared.h" + +#include +#include +#include + +#include "include/base/cef_bind.h" +#include "include/cef_command_line.h" +#include "include/wrapper/cef_closure_task.h" +#include "cefclient/client_switches.h" +#include "cefclient/main_context.h" +#include "cefclient/main_message_loop.h" +#include "cefclient/test_runner.h" + +namespace client { + +ClientHandlerShared::ClientHandlerShared() + : ClientHandler(MainContext::Get()->GetMainURL(), + CefCommandLine::GetGlobalCommandLine()->HasSwitch( + switches::kOffScreenRenderingEnabled)), + is_closing_(false), + browser_id_(0), + edit_handle_(NULL), + back_handle_(NULL), + forward_handle_(NULL), + stop_handle_(NULL), + reload_handle_(NULL) { +} + +ClientHandlerShared::~ClientHandlerShared() { +} + +void ClientHandlerShared::BrowserCreated(CefRefPtr browser) { + CEF_REQUIRE_UI_THREAD(); + + if (browser_id_ == 0) { + // Keep references to the browser hosted in the main window. + browser_id_ = browser->GetIdentifier(); + { + // Protect modification of |browser_| with a lock because it may be + // accessed from different threads. + base::AutoLock lock_scope(lock_); + browser_ = browser; + } + } else if (browser->IsPopup()) { + // Add to the list of popup browsers. + popup_browsers_.push_back(browser); + + // Give focus to the popup browser. Perform asynchronously because the + // parent window may attempt to keep focus after launching the popup. + CefPostTask(TID_UI, + base::Bind(&CefBrowserHost::SetFocus, browser->GetHost().get(), true)); + } +} + +void ClientHandlerShared::BrowserClosing(CefRefPtr browser) { + CEF_REQUIRE_UI_THREAD(); + + // Closing the main window requires special handling. See the DoClose() + // documentation in the CEF header for a detailed destription of this + // process. + if (browser_id_ == browser->GetIdentifier()) { + // Protect modification of |is_closing_| with a lock because it may be + // accessed from different threads. + base::AutoLock lock_scope(lock_); + // Set a flag to indicate that the window close should be allowed. + is_closing_ = true; + } +} + +void ClientHandlerShared::BrowserClosed(CefRefPtr browser) { + CEF_REQUIRE_UI_THREAD(); + + if (browser_id_ == browser->GetIdentifier()) { + { + // Protect modification of |browser_| with a lock because it may be + // accessed from different threads. + base::AutoLock lock_scope(lock_); + // Free the browser pointer so that the browser can be destroyed. + browser_ = NULL; + } + + if (osr_handler_.get()) { + osr_handler_->OnBeforeClose(browser); + + // Protect modification of |osr_handler_| with a lock because it may be + // accessed from different threads. + base::AutoLock lock_scope(lock_); + osr_handler_ = NULL; + } + + browser_id_ = 0; + } else if (browser->IsPopup()) { + // Remove from the browser popup list. + BrowserList::iterator bit = popup_browsers_.begin(); + for (; bit != popup_browsers_.end(); ++bit) { + if ((*bit)->IsSame(browser)) { + popup_browsers_.erase(bit); + break; + } + } + } + + if (GetBrowserCount() == 0) { + // Quit the main message loop. + MainMessageLoop::Get()->Quit(); + } +} + +bool ClientHandlerShared::CreatePopupWindow( + bool is_devtools, + const CefPopupFeatures& popupFeatures, + CefWindowInfo& windowInfo, + CefRefPtr& client, + CefBrowserSettings& settings) { + // Note: This method will be called on multiple threads. + + if (is_devtools) { + // Create DevTools as a windowed popup browser using the same client. +#if defined(OS_WIN) + windowInfo.SetAsPopup(GetMainWindowHandle(), "DevTools"); +#endif + client = this; + } else if (is_osr()) { + CefPostTask(TID_UI, + base::Bind(test_runner::Alert, GetBrowser(), + "Popup windows are disabled with off-screen rendering.")); + + // Cancel popups in off-screen rendering mode. + return false; + } + + return true; +} + +void ClientHandlerShared::SetUXWindowHandles( + ClientWindowHandle editHandle, + ClientWindowHandle backHandle, + ClientWindowHandle forwardHandle, + ClientWindowHandle reloadHandle, + ClientWindowHandle stopHandle) { + if (!CefCurrentlyOn(TID_UI)) { + // Execute on the UI thread. + CefPostTask(TID_UI, + base::Bind(&ClientHandlerShared::SetUXWindowHandles, this, + editHandle, backHandle, forwardHandle, reloadHandle, + stopHandle)); + return; + } + + edit_handle_ = editHandle; + back_handle_ = backHandle; + forward_handle_ = forwardHandle; + reload_handle_ = reloadHandle; + stop_handle_ = stopHandle; +} + +CefRefPtr + ClientHandlerShared::GetOSRHandler() const { + if (CefCurrentlyOn(TID_UI)) { + // No need for locking because |osr_handler_| will only be modified on this + // thread. + return osr_handler_; + } else { + // Use a lock to protect |osr_handler_| from being modified while we're + // accessing it from a different thread. + base::AutoLock lock_scope(lock_); + return osr_handler_; + } +} + +void ClientHandlerShared::SetOSRHandler(CefRefPtr handler) { + // Protect modification of |osr_handler_| with a lock because it may be + // accessed from different threads. + base::AutoLock lock_scope(lock_); + osr_handler_ = handler; +} + +CefRefPtr ClientHandlerShared::GetBrowser() const { + if (CefCurrentlyOn(TID_UI)) { + // No need for locking because |browser_| will only be modified on this + // thread. + return browser_; + } else { + // Use a lock to protect |browser_| from being modified while we're + // accessing it from a different thread. + base::AutoLock lock_scope(lock_); + return browser_; + } +} + +int ClientHandlerShared::GetBrowserId() const { + CEF_REQUIRE_UI_THREAD(); + return browser_id_; +} + +void ClientHandlerShared::CloseAllBrowsers(bool force_close) { + if (!CefCurrentlyOn(TID_UI)) { + // Execute on the UI thread. + CefPostTask(TID_UI, + base::Bind(&ClientHandlerShared::CloseAllBrowsers, this, force_close)); + return; + } + + if (!popup_browsers_.empty()) { + // Request that any popup browsers close. + BrowserList::const_iterator it = popup_browsers_.begin(); + for (; it != popup_browsers_.end(); ++it) + (*it)->GetHost()->CloseBrowser(force_close); + } + + if (browser_.get()) { + // Request that the main browser close. + browser_->GetHost()->CloseBrowser(force_close); + } +} + +bool ClientHandlerShared::IsClosing() const { + if (CefCurrentlyOn(TID_UI)) { + // No need for locking because |is_closing_| will only be modified on this + // thread. + return is_closing_; + } else { + // Use a lock to protect |is_closing_| from being modified while we're + // accessing it from a different thread. + base::AutoLock lock_scope(lock_); + return is_closing_; + } +} + +} // namespace client diff --git a/tests/cefclient/client_handler_shared.h b/tests/cefclient/client_handler_shared.h new file mode 100644 index 000000000..6714dbeee --- /dev/null +++ b/tests/cefclient/client_handler_shared.h @@ -0,0 +1,126 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#ifndef CEF_TESTS_CEFCLIENT_CLIENT_HANDLER_SHARED_H_ +#define CEF_TESTS_CEFCLIENT_CLIENT_HANDLER_SHARED_H_ +#pragma once + +#include +#include + +#include "include/base/cef_lock.h" +#include "cefclient/client_handler.h" + +namespace client { + +// Client handler implementation that is shared by all existing browsers. +class ClientHandlerShared : public ClientHandler { + public: + // Interface implemented to handle off-screen rendering. + class RenderHandler : public CefRenderHandler { + public: + virtual void OnBeforeClose(CefRefPtr browser) =0; + }; + + ClientHandlerShared(); + ~ClientHandlerShared(); + + // CefClient methods + CefRefPtr GetRenderHandler() OVERRIDE { + return osr_handler_; + } + + // ClientHandler methods + void BrowserCreated(CefRefPtr browser) OVERRIDE; + void BrowserClosing(CefRefPtr browser) OVERRIDE; + void BrowserClosed(CefRefPtr browser) OVERRIDE; + void SetAddress(CefRefPtr browser, + const CefString& url) OVERRIDE; + void SetTitle(CefRefPtr browser, + const CefString& title) OVERRIDE; + void SetLoadingState(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) OVERRIDE; + bool CreatePopupWindow( + bool is_devtools, + const CefPopupFeatures& popupFeatures, + CefWindowInfo& windowInfo, + CefRefPtr& client, + CefBrowserSettings& settings) OVERRIDE; + + void SetUXWindowHandles(ClientWindowHandle editHandle, + ClientWindowHandle backHandle, + ClientWindowHandle forwardHandle, + ClientWindowHandle reloadHandle, + ClientWindowHandle stopHandle); + + CefRefPtr GetOSRHandler() const; + void SetOSRHandler(CefRefPtr handler); + + // Get the main (non-popup) browser associated with this client. Safe to call + // on any thread. + CefRefPtr GetBrowser() const; + + // Get the main (non-popup) browser ID. Will return non-0 if the main browser + // currently exists. Should only be called on the CEF UI thread. + int GetBrowserId() const; + + // Request that all existing browser windows close. + void CloseAllBrowsers(bool force_close); + + // Returns true if the main browser window is currently closing. Used in + // combination with DoClose() and the OS close notification to properly handle + // 'onbeforeunload' JavaScript events during window close. Safe to call on any + // thread. + bool IsClosing() const; + + private: + // Lock used to protect members accessed on multiple threads. Make it mutable + // so that it can be used from const methods. + mutable base::Lock lock_; + + // LOCK PROTECTED MEMBERS + // Setting the following members or accessing them from a thread other than + // the CEF UI thread must be protected by |lock_|. Most platforms will only + // access them from the UI thread but on Windows they will be accessed from + // the main application thread when using using multi-threaded message loop + // mode. + + // The handler for off-screen rendering, if any. + CefRefPtr osr_handler_; + + // The child browser window. + CefRefPtr browser_; + + // True if the main browser window is currently closing. + bool is_closing_; + + // UI THREAD MEMBERS + // The following members will only be accessed on the CEF UI thread. + + // The child browser id. + int browser_id_; + + // List of any popup browser windows. + typedef std::list > BrowserList; + BrowserList popup_browsers_; + + // The edit window handle. + ClientWindowHandle edit_handle_; + + // The button window handles. + ClientWindowHandle back_handle_; + ClientWindowHandle forward_handle_; + ClientWindowHandle stop_handle_; + ClientWindowHandle reload_handle_; + + // Include the default reference counting implementation. + IMPLEMENT_REFCOUNTING(ClientHandlerShared); + DISALLOW_COPY_AND_ASSIGN(ClientHandlerShared); +}; + +} // namespace client + +#endif // CEF_TESTS_CEFCLIENT_CLIENT_HANDLER_SHARED_H_ diff --git a/tests/cefclient/client_handler_gtk.cc b/tests/cefclient/client_handler_shared_gtk.cc similarity index 76% rename from tests/cefclient/client_handler_gtk.cc rename to tests/cefclient/client_handler_shared_gtk.cc index ec447a1a9..0e4f232bb 100644 --- a/tests/cefclient/client_handler_gtk.cc +++ b/tests/cefclient/client_handler_shared_gtk.cc @@ -10,33 +10,31 @@ #include -#include "cefclient/client_handler.h" +#include "cefclient/client_handler_shared.h" #include "include/cef_browser.h" -#include "include/cef_frame.h" namespace client { -void ClientHandler::OnAddressChange(CefRefPtr browser, - CefRefPtr frame, - const CefString& url) { +void ClientHandlerShared::SetAddress(CefRefPtr browser, + const CefString& url) { CEF_REQUIRE_UI_THREAD(); - if (GetBrowserId() == browser->GetIdentifier() && frame->IsMain()) { - // Set the edit window text + if (browser_id_ == browser->GetIdentifier()) { + // Set the edit window text. std::string urlStr(url); gtk_entry_set_text(GTK_ENTRY(edit_handle_), urlStr.c_str()); } } -void ClientHandler::OnTitleChange(CefRefPtr browser, - const CefString& title) { +void ClientHandlerShared::SetTitle(CefRefPtr browser, + const CefString& title) { CEF_REQUIRE_UI_THREAD(); std::string titleStr(title); if (!browser->IsPopup()) { // Set the GTK parent window title. - GtkWidget* window = gtk_widget_get_ancestor(main_handle_, + GtkWidget* window = gtk_widget_get_ancestor(GetMainWindowHandle(), GTK_TYPE_WINDOW); gtk_window_set_title(GTK_WINDOW(window), titleStr.c_str()); } else { @@ -78,17 +76,20 @@ void ClientHandler::OnTitleChange(CefRefPtr browser, } } -void ClientHandler::SetLoading(bool isLoading) { +void ClientHandlerShared::SetLoadingState(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) { CEF_REQUIRE_UI_THREAD(); + // Nothing to do for popup windows. + if (browser_id_ != browser->GetIdentifier()) + return; + if (isLoading) gtk_widget_set_sensitive(GTK_WIDGET(stop_handle_), true); else gtk_widget_set_sensitive(GTK_WIDGET(stop_handle_), false); -} - -void ClientHandler::SetNavState(bool canGoBack, bool canGoForward) { - CEF_REQUIRE_UI_THREAD(); if (canGoBack) gtk_widget_set_sensitive(GTK_WIDGET(back_handle_), true); diff --git a/tests/cefclient/client_handler_shared_mac.mm b/tests/cefclient/client_handler_shared_mac.mm new file mode 100644 index 000000000..951122453 --- /dev/null +++ b/tests/cefclient/client_handler_shared_mac.mm @@ -0,0 +1,53 @@ +// Copyright (c) 2011 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. + +#import + +#include "cefclient/client_handler_shared.h" +#include "include/cef_browser.h" + +namespace client { + +void ClientHandlerShared::SetAddress(CefRefPtr browser, + const CefString& url) { + CEF_REQUIRE_UI_THREAD(); + + if (browser_id_ == browser->GetIdentifier()) { + // Set edit window text for the main window. + NSTextField* textField = (NSTextField*)edit_handle_; + std::string urlStr(url); + NSString* str = [NSString stringWithUTF8String:urlStr.c_str()]; + [textField setStringValue:str]; + } +} + +void ClientHandlerShared::SetTitle(CefRefPtr browser, + const CefString& title) { + CEF_REQUIRE_UI_THREAD(); + + // Set the frame window title bar. + NSView* view = (NSView*)browser->GetHost()->GetWindowHandle(); + NSWindow* window = [view window]; + std::string titleStr(title); + NSString* str = [NSString stringWithUTF8String:titleStr.c_str()]; + [window setTitle:str]; +} + +void ClientHandlerShared::SetLoadingState(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) { + CEF_REQUIRE_UI_THREAD(); + + if (browser_id_ == browser->GetIdentifier()) { + // Set UX control state for the main window. + [(NSTextField*)edit_handle_ setEnabled:YES]; + [(NSButton*)reload_handle_ setEnabled:!isLoading]; + [(NSButton*)stop_handle_ setEnabled:isLoading]; + [(NSButton*)back_handle_ setEnabled:canGoBack]; + [(NSButton*)forward_handle_ setEnabled:canGoForward]; + } +} + +} // namespace client diff --git a/tests/cefclient/client_handler_shared_win.cc b/tests/cefclient/client_handler_shared_win.cc new file mode 100644 index 000000000..23fff1464 --- /dev/null +++ b/tests/cefclient/client_handler_shared_win.cc @@ -0,0 +1,55 @@ +// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. + +#include "cefclient/client_handler_shared.h" + +#include +#include + +#include "include/cef_browser.h" +#include "cefclient/resource.h" + +namespace client { + +void ClientHandlerShared::SetAddress(CefRefPtr browser, + const CefString& url) { + CEF_REQUIRE_UI_THREAD(); + + if (browser_id_ == browser->GetIdentifier()) { + // Set the edit window text for the main (top-level) browser. + SetWindowText(edit_handle_, std::wstring(url).c_str()); + } +} + +void ClientHandlerShared::SetTitle(CefRefPtr browser, + const CefString& title) { + CEF_REQUIRE_UI_THREAD(); + + // Set the frame window title bar. + CefWindowHandle hwnd = browser->GetHost()->GetWindowHandle(); + if (browser_id_ == browser->GetIdentifier()) { + // For the main (top-level) browser the frame window will be the parent of + // the browser window. + hwnd = GetParent(hwnd); + } + SetWindowText(hwnd, std::wstring(title).c_str()); +} + +void ClientHandlerShared::SetLoadingState(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) { + CEF_REQUIRE_UI_THREAD(); + + if (browser_id_ == browser->GetIdentifier()) { + // Set UX control state for the main (top-level) browser. + EnableWindow(edit_handle_, TRUE); + EnableWindow(reload_handle_, !isLoading); + EnableWindow(stop_handle_, isLoading); + EnableWindow(back_handle_, canGoBack); + EnableWindow(forward_handle_, canGoForward); + } +} + +} // namespace client diff --git a/tests/cefclient/client_handler_win.cc b/tests/cefclient/client_handler_win.cc deleted file mode 100644 index 9dbb455eb..000000000 --- a/tests/cefclient/client_handler_win.cc +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -#include "cefclient/client_handler.h" - -#include -#include - -#include "include/cef_browser.h" -#include "include/cef_frame.h" -#include "cefclient/resource.h" - -namespace client { - -void ClientHandler::OnAddressChange(CefRefPtr browser, - CefRefPtr frame, - const CefString& url) { - CEF_REQUIRE_UI_THREAD(); - - if (GetBrowserId() == browser->GetIdentifier() && frame->IsMain()) { - // Set the edit window text - SetWindowText(edit_handle_, std::wstring(url).c_str()); - } -} - -void ClientHandler::OnTitleChange(CefRefPtr browser, - const CefString& title) { - CEF_REQUIRE_UI_THREAD(); - - // Set the frame window title bar - CefWindowHandle hwnd = browser->GetHost()->GetWindowHandle(); - if (GetBrowserId() == browser->GetIdentifier()) { - // The frame window will be the parent of the browser window - hwnd = GetParent(hwnd); - } - SetWindowText(hwnd, std::wstring(title).c_str()); -} - -void ClientHandler::SetLoading(bool isLoading) { - DCHECK(edit_handle_ != NULL && reload_handle_ != NULL && - stop_handle_ != NULL); - EnableWindow(edit_handle_, TRUE); - EnableWindow(reload_handle_, !isLoading); - EnableWindow(stop_handle_, isLoading); -} - -void ClientHandler::SetNavState(bool canGoBack, bool canGoForward) { - DCHECK(back_handle_ != NULL && forward_handle_ != NULL); - EnableWindow(back_handle_, canGoBack); - EnableWindow(forward_handle_, canGoForward); -} - -} // namespace client diff --git a/tests/cefclient/osr_widget_gtk.cc b/tests/cefclient/osr_widget_gtk.cc index a4e171648..b43fafeeb 100644 --- a/tests/cefclient/osr_widget_gtk.cc +++ b/tests/cefclient/osr_widget_gtk.cc @@ -1110,7 +1110,7 @@ CefRefPtr OSRWindow::Create(OSRBrowserProvider* browser_provider, // static CefRefPtr OSRWindow::From( - CefRefPtr renderHandler) { + CefRefPtr renderHandler) { return static_cast(renderHandler.get()); } diff --git a/tests/cefclient/osr_widget_gtk.h b/tests/cefclient/osr_widget_gtk.h index 7967d2e15..6638bfd46 100644 --- a/tests/cefclient/osr_widget_gtk.h +++ b/tests/cefclient/osr_widget_gtk.h @@ -7,7 +7,7 @@ #pragma once #include "include/cef_render_handler.h" -#include "cefclient/client_handler.h" +#include "cefclient/client_handler_shared.h" #include "cefclient/osr_renderer.h" namespace client { @@ -20,7 +20,7 @@ class OSRBrowserProvider { virtual ~OSRBrowserProvider() {} }; -class OSRWindow : public ClientHandler::RenderHandler { +class OSRWindow : public ClientHandlerShared::RenderHandler { public: // Create a new OSRWindow instance. |browser_provider| must outlive this // object. @@ -30,7 +30,7 @@ class OSRWindow : public ClientHandler::RenderHandler { ClientWindowHandle parentView); static CefRefPtr From( - CefRefPtr renderHandler); + CefRefPtr renderHandler); ClientWindowHandle GetWindowHandle() const { return glarea_; @@ -41,7 +41,7 @@ class OSRWindow : public ClientHandler::RenderHandler { return NULL; } - // ClientHandler::RenderHandler methods + // ClientHandlerShared::RenderHandler methods void OnBeforeClose(CefRefPtr browser) OVERRIDE; // CefRenderHandler methods @@ -93,6 +93,7 @@ class OSRWindow : public ClientHandler::RenderHandler { bool render_task_pending_; IMPLEMENT_REFCOUNTING(OSRWindow); + DISALLOW_COPY_AND_ASSIGN(OSRWindow); }; } // namespace client diff --git a/tests/cefclient/osr_widget_mac.h b/tests/cefclient/osr_widget_mac.h index 26529a311..68fe1fe19 100644 --- a/tests/cefclient/osr_widget_mac.h +++ b/tests/cefclient/osr_widget_mac.h @@ -6,7 +6,7 @@ #define CEF_TESTS_CEFCLIENT_OSR_WIDGET_MAC_H_ #include "include/cef_client.h" -#include "cefclient/client_handler.h" +#include "cefclient/client_handler_shared.h" namespace client { class OSRBrowserProvider; @@ -61,7 +61,7 @@ class OSRBrowserProvider { }; // Handler for off-screen rendering windows. -class ClientOSRHandler : public ClientHandler::RenderHandler { +class ClientOSRHandler : public ClientHandlerShared::RenderHandler { public: explicit ClientOSRHandler(ClientOpenGLView* view, OSRBrowserProvider* browser_provider); @@ -69,7 +69,7 @@ class ClientOSRHandler : public ClientHandler::RenderHandler { void Disconnect(); - // ClientHandler::RenderHandler + // ClientHandlerShared::RenderHandler methods void OnBeforeClose(CefRefPtr browser) OVERRIDE; // CefRenderHandler methods @@ -124,7 +124,7 @@ class OSRWindow { CefWindowHandle parentView, const CefRect& frame); - CefRefPtr GetRenderHandler() { + CefRefPtr GetRenderHandler() { return render_client.get(); } @@ -142,6 +142,7 @@ class OSRWindow { CefWindowHandle view_; IMPLEMENT_REFCOUNTING(OSRWindow); + DISALLOW_COPY_AND_ASSIGN(OSRWindow); }; } // namespace client diff --git a/tests/cefclient/osr_widget_win.cc b/tests/cefclient/osr_widget_win.cc index 35c69e9bb..cbb39168b 100644 --- a/tests/cefclient/osr_widget_win.cc +++ b/tests/cefclient/osr_widget_win.cc @@ -55,7 +55,7 @@ CefRefPtr OSRWindow::Create( // static CefRefPtr OSRWindow::From( - CefRefPtr renderHandler) { + CefRefPtr renderHandler) { return static_cast(renderHandler.get()); } diff --git a/tests/cefclient/osr_widget_win.h b/tests/cefclient/osr_widget_win.h index 101dfc81f..6c36cf8aa 100644 --- a/tests/cefclient/osr_widget_win.h +++ b/tests/cefclient/osr_widget_win.h @@ -7,7 +7,7 @@ #pragma once #include "include/cef_render_handler.h" -#include "cefclient/client_handler.h" +#include "cefclient/client_handler_shared.h" #include "cefclient/osr_dragdrop_win.h" #include "cefclient/osr_renderer.h" @@ -21,7 +21,7 @@ class OSRBrowserProvider { virtual ~OSRBrowserProvider() {} }; -class OSRWindow : public ClientHandler::RenderHandler +class OSRWindow : public ClientHandlerShared::RenderHandler #if defined(CEF_USE_ATL) , public OsrDragEvents #endif @@ -34,7 +34,7 @@ class OSRWindow : public ClientHandler::RenderHandler bool show_update_rect); static CefRefPtr From( - CefRefPtr renderHandler); + CefRefPtr renderHandler); // Create the underlying window. bool CreateWidget(HWND hWndParent, const RECT& rect, @@ -47,7 +47,7 @@ class OSRWindow : public ClientHandler::RenderHandler return hWnd_; } - // ClientHandler::RenderHandler methods + // ClientHandlerShared::RenderHandler methods void OnBeforeClose(CefRefPtr browser) OVERRIDE; // CefRenderHandler methods @@ -132,6 +132,7 @@ class OSRWindow : public ClientHandler::RenderHandler bool hidden_; IMPLEMENT_REFCOUNTING(OSRWindow); + DISALLOW_COPY_AND_ASSIGN(OSRWindow); }; } // namespace client