From 71125f76d817c33b53f16d81a0104d98d6b9db02 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Thu, 12 Sep 2013 23:36:54 +0000 Subject: [PATCH] Expose CefLoadHandler in the render process (issue #1077). git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@1442 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- include/capi/cef_load_handler_capi.h | 3 +- .../capi/cef_render_process_handler_capi.h | 6 + include/cef_load_handler.h | 3 +- include/cef_render_process_handler.h | 9 + libcef/renderer/browser_impl.cc | 124 ++++++ libcef/renderer/browser_impl.h | 18 +- .../cpptoc/render_process_handler_cpptoc.cc | 18 + .../ctocpp/render_process_handler_ctocpp.cc | 14 + .../ctocpp/render_process_handler_ctocpp.h | 1 + tests/cefclient/client_app.cpp | 10 + tests/cefclient/client_app.h | 5 + tests/unittests/navigation_unittest.cc | 394 ++++++++++++++---- 12 files changed, 527 insertions(+), 78 deletions(-) diff --git a/include/capi/cef_load_handler_capi.h b/include/capi/cef_load_handler_capi.h index 2127642c9..6084f0f23 100644 --- a/include/capi/cef_load_handler_capi.h +++ b/include/capi/cef_load_handler_capi.h @@ -47,7 +47,8 @@ extern "C" { /// // Implement this structure to handle events related to browser load status. The -// functions of this structure will be called on the UI thread. +// functions of this structure will be called on the browser process UI thread +// or render process main thread (TID_RENDERER). /// typedef struct _cef_load_handler_t { /// diff --git a/include/capi/cef_render_process_handler_capi.h b/include/capi/cef_render_process_handler_capi.h index b59e117b7..2b15756bc 100644 --- a/include/capi/cef_render_process_handler_capi.h +++ b/include/capi/cef_render_process_handler_capi.h @@ -88,6 +88,12 @@ typedef struct _cef_render_process_handler_t { struct _cef_render_process_handler_t* self, struct _cef_browser_t* browser); + /// + // Return the handler for browser load status events. + /// + struct _cef_load_handler_t* (CEF_CALLBACK *get_load_handler)( + struct _cef_render_process_handler_t* self); + /// // Called before browser navigation. Return true (1) to cancel the navigation // or false (0) to allow the navigation to proceed. The |request| object diff --git a/include/cef_load_handler.h b/include/cef_load_handler.h index 2e290397b..02d9d9f1a 100644 --- a/include/cef_load_handler.h +++ b/include/cef_load_handler.h @@ -44,7 +44,8 @@ /// // Implement this interface to handle events related to browser load status. The -// methods of this class will be called on the UI thread. +// methods of this class will be called on the browser process UI thread or +// render process main thread (TID_RENDERER). /// /*--cef(source=client)--*/ class CefLoadHandler : public virtual CefBase { diff --git a/include/cef_render_process_handler.h b/include/cef_render_process_handler.h index 7ba767265..98ab391bc 100644 --- a/include/cef_render_process_handler.h +++ b/include/cef_render_process_handler.h @@ -42,6 +42,7 @@ #include "include/cef_browser.h" #include "include/cef_dom.h" #include "include/cef_frame.h" +#include "include/cef_load_handler.h" #include "include/cef_process_message.h" #include "include/cef_v8.h" #include "include/cef_values.h" @@ -85,6 +86,14 @@ class CefRenderProcessHandler : public virtual CefBase { /*--cef()--*/ virtual void OnBrowserDestroyed(CefRefPtr browser) {} + /// + // Return the handler for browser load status events. + /// + /*--cef()--*/ + virtual CefRefPtr GetLoadHandler() { + return NULL; + } + /// // Called before browser navigation. Return true to cancel the navigation or // false to allow the navigation to proceed. The |request| object cannot be diff --git a/libcef/renderer/browser_impl.cc b/libcef/renderer/browser_impl.cc index 30e8e922c..73b5ec046 100644 --- a/libcef/renderer/browser_impl.cc +++ b/libcef/renderer/browser_impl.cc @@ -24,9 +24,11 @@ #include "content/public/renderer/document_state.h" #include "content/public/renderer/navigation_state.h" #include "content/public/renderer/render_view.h" +#include "content/renderer/render_view_impl.h" #include "net/http/http_util.h" #include "third_party/WebKit/public/platform/WebString.h" #include "third_party/WebKit/public/platform/WebURL.h" +#include "third_party/WebKit/public/platform/WebURLError.h" #include "third_party/WebKit/public/platform/WebURLResponse.h" #include "third_party/WebKit/public/web/WebDataSource.h" #include "third_party/WebKit/public/web/WebDocument.h" @@ -443,6 +445,12 @@ void CefBrowserImpl::AddFrameObject(int64 frame_id, manager->Add(tracked_object); } +bool CefBrowserImpl::is_swapped_out() const { + content::RenderViewImpl* render_view_impl = + static_cast(render_view()); + return (!render_view_impl || render_view_impl->is_swapped_out()); +} + // RenderViewObserver methods. // ----------------------------------------------------------------------------- @@ -462,6 +470,21 @@ void CefBrowserImpl::OnDestruct() { CefContentRendererClient::Get()->OnBrowserDestroyed(this); } +void CefBrowserImpl::DidStartLoading() { + OnLoadingStateChange(true); +} + +void CefBrowserImpl::DidStopLoading() { + OnLoadingStateChange(false); +} + +void CefBrowserImpl::DidFailLoad( + WebKit::WebFrame* frame, + const WebKit::WebURLError& error) { + OnLoadError(frame, error); + OnLoadEnd(frame); +} + void CefBrowserImpl::DidFinishLoad(WebKit::WebFrame* frame) { WebKit::WebDataSource* ds = frame->dataSource(); Send(new CefHostMsg_DidFinishLoad(routing_id(), @@ -469,6 +492,7 @@ void CefBrowserImpl::DidFinishLoad(WebKit::WebFrame* frame) { ds->request().url(), !frame->parent(), ds->response().httpStatusCode())); + OnLoadEnd(frame); } void CefBrowserImpl::DidStartProvisionalLoad(WebKit::WebFrame* frame) { @@ -476,6 +500,17 @@ void CefBrowserImpl::DidStartProvisionalLoad(WebKit::WebFrame* frame) { GetWebFrameImpl(frame); } +void CefBrowserImpl::DidFailProvisionalLoad( + WebKit::WebFrame* frame, + const WebKit::WebURLError& error) { + OnLoadError(frame, error); +} + +void CefBrowserImpl::DidCommitProvisionalLoad(WebKit::WebFrame* frame, + bool is_new_navigation) { + OnLoadStart(frame); +} + void CefBrowserImpl::FrameDetached(WebFrame* frame) { int64 frame_id = frame->identifier(); @@ -713,3 +748,92 @@ void CefBrowserImpl::OnResponse(const Cef_Response_Params& params) { void CefBrowserImpl::OnResponseAck(int request_id) { response_manager_->RunAckHandler(request_id); } + +void CefBrowserImpl::OnLoadingStateChange(bool isLoading) { + content::RenderViewImpl* render_view_impl = + static_cast(render_view()); + if (is_swapped_out()) + return; + + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetRenderProcessHandler(); + if (handler.get()) { + CefRefPtr load_handler = handler->GetLoadHandler(); + if (load_handler.get()) { + WebView* web_view = render_view()->GetWebView(); + const bool canGoBack = webkit_glue::CanGoBack(web_view); + const bool canGoForward = webkit_glue::CanGoForward(web_view); + + load_handler->OnLoadingStateChange(this, isLoading, canGoBack, + canGoForward); + } + } + } +} + +void CefBrowserImpl::OnLoadStart(WebKit::WebFrame* frame) { + content::RenderViewImpl* render_view_impl = + static_cast(render_view()); + if (is_swapped_out()) + return; + + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetRenderProcessHandler(); + if (handler.get()) { + CefRefPtr load_handler = handler->GetLoadHandler(); + if (load_handler.get()) { + CefRefPtr cef_frame = GetWebFrameImpl(frame); + load_handler->OnLoadStart(this, cef_frame.get()); + } + } + } +} + +void CefBrowserImpl::OnLoadEnd(WebKit::WebFrame* frame) { + content::RenderViewImpl* render_view_impl = + static_cast(render_view()); + if (is_swapped_out()) + return; + + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetRenderProcessHandler(); + if (handler.get()) { + CefRefPtr load_handler = handler->GetLoadHandler(); + if (load_handler.get()) { + CefRefPtr cef_frame = GetWebFrameImpl(frame); + int httpStatusCode = frame->dataSource()->response().httpStatusCode(); + load_handler->OnLoadEnd(this, cef_frame.get(), httpStatusCode); + } + } + } +} + +void CefBrowserImpl::OnLoadError(WebKit::WebFrame* frame, + const WebKit::WebURLError& error) { + if (is_swapped_out()) + return; + + CefRefPtr app = CefContentClient::Get()->application(); + if (app.get()) { + CefRefPtr handler = + app->GetRenderProcessHandler(); + if (handler.get()) { + CefRefPtr load_handler = handler->GetLoadHandler(); + if (load_handler.get()) { + CefRefPtr cef_frame = GetWebFrameImpl(frame); + const cef_errorcode_t errorCode = + static_cast(error.reason); + const std::string& errorText = error.localizedDescription.utf8(); + const GURL& failedUrl = error.unreachableURL; + load_handler->OnLoadError(this, cef_frame.get(), errorCode, errorText, + failedUrl.spec()); + } + } + } +} diff --git a/libcef/renderer/browser_impl.h b/libcef/renderer/browser_impl.h index bda3685c4..2d646a200 100644 --- a/libcef/renderer/browser_impl.h +++ b/libcef/renderer/browser_impl.h @@ -103,15 +103,26 @@ class CefBrowserImpl : public CefBrowser, bool is_window_rendering_disabled() const { return is_window_rendering_disabled_; } - content::RenderView* render_view() { + content::RenderView* render_view() const { return content::RenderViewObserver::render_view(); } + bool is_swapped_out() const; + private: // RenderViewObserver methods. virtual void OnDestruct() OVERRIDE; + virtual void DidStartLoading() OVERRIDE; + virtual void DidStopLoading() OVERRIDE; + virtual void DidFailLoad(WebKit::WebFrame* frame, + const WebKit::WebURLError& error) OVERRIDE; virtual void DidFinishLoad(WebKit::WebFrame* frame) OVERRIDE; virtual void DidStartProvisionalLoad(WebKit::WebFrame* frame) OVERRIDE; + virtual void DidFailProvisionalLoad( + WebKit::WebFrame* frame, + const WebKit::WebURLError& error) OVERRIDE; + virtual void DidCommitProvisionalLoad(WebKit::WebFrame* frame, + bool is_new_navigation) OVERRIDE; virtual void FrameDetached(WebKit::WebFrame* frame) OVERRIDE; virtual void FocusedNodeChanged(const WebKit::WebNode& node) OVERRIDE; virtual void DidCreateDataSource(WebKit::WebFrame* frame, @@ -123,6 +134,11 @@ class CefBrowserImpl : public CefBrowser, void OnResponse(const Cef_Response_Params& params); void OnResponseAck(int request_id); + void OnLoadingStateChange(bool isLoading); + void OnLoadStart(WebKit::WebFrame* frame); + void OnLoadEnd(WebKit::WebFrame* frame); + void OnLoadError(WebKit::WebFrame* frame, const WebKit::WebURLError& error); + // ID of the browser that this RenderView is associated with. During loading // of cross-origin requests multiple RenderViews may be associated with the // same browser ID. diff --git a/libcef_dll/cpptoc/render_process_handler_cpptoc.cc b/libcef_dll/cpptoc/render_process_handler_cpptoc.cc index fb8bc84df..3e5bb67f2 100644 --- a/libcef_dll/cpptoc/render_process_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/render_process_handler_cpptoc.cc @@ -10,6 +10,7 @@ // for more information. // +#include "libcef_dll/cpptoc/load_handler_cpptoc.h" #include "libcef_dll/cpptoc/render_process_handler_cpptoc.h" #include "libcef_dll/ctocpp/browser_ctocpp.h" #include "libcef_dll/ctocpp/domnode_ctocpp.h" @@ -88,6 +89,22 @@ void CEF_CALLBACK render_process_handler_on_browser_destroyed( CefBrowserCToCpp::Wrap(browser)); } +cef_load_handler_t* CEF_CALLBACK render_process_handler_get_load_handler( + struct _cef_render_process_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = CefRenderProcessHandlerCppToC::Get( + self)->GetLoadHandler(); + + // Return type: refptr_same + return CefLoadHandlerCppToC::Wrap(_retval); +} + int CEF_CALLBACK render_process_handler_on_before_navigation( struct _cef_render_process_handler_t* self, cef_browser_t* browser, cef_frame_t* frame, struct _cef_request_t* request, @@ -282,6 +299,7 @@ CefRenderProcessHandlerCppToC::CefRenderProcessHandlerCppToC( render_process_handler_on_browser_created; struct_.struct_.on_browser_destroyed = render_process_handler_on_browser_destroyed; + struct_.struct_.get_load_handler = render_process_handler_get_load_handler; struct_.struct_.on_before_navigation = render_process_handler_on_before_navigation; struct_.struct_.on_context_created = diff --git a/libcef_dll/ctocpp/render_process_handler_ctocpp.cc b/libcef_dll/ctocpp/render_process_handler_ctocpp.cc index 4a66178fb..3ce7281cb 100644 --- a/libcef_dll/ctocpp/render_process_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/render_process_handler_ctocpp.cc @@ -19,6 +19,7 @@ #include "libcef_dll/cpptoc/v8context_cpptoc.h" #include "libcef_dll/cpptoc/v8exception_cpptoc.h" #include "libcef_dll/cpptoc/v8stack_trace_cpptoc.h" +#include "libcef_dll/ctocpp/load_handler_ctocpp.h" #include "libcef_dll/ctocpp/render_process_handler_ctocpp.h" @@ -85,6 +86,19 @@ void CefRenderProcessHandlerCToCpp::OnBrowserDestroyed( CefBrowserCppToC::Wrap(browser)); } +CefRefPtr CefRenderProcessHandlerCToCpp::GetLoadHandler() { + if (CEF_MEMBER_MISSING(struct_, get_load_handler)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_load_handler_t* _retval = struct_->get_load_handler(struct_); + + // Return type: refptr_same + return CefLoadHandlerCToCpp::Wrap(_retval); +} + bool CefRenderProcessHandlerCToCpp::OnBeforeNavigation( CefRefPtr browser, CefRefPtr frame, CefRefPtr request, NavigationType navigation_type, diff --git a/libcef_dll/ctocpp/render_process_handler_ctocpp.h b/libcef_dll/ctocpp/render_process_handler_ctocpp.h index b79385077..60e3e83c6 100644 --- a/libcef_dll/ctocpp/render_process_handler_ctocpp.h +++ b/libcef_dll/ctocpp/render_process_handler_ctocpp.h @@ -39,6 +39,7 @@ class CefRenderProcessHandlerCToCpp virtual void OnWebKitInitialized() OVERRIDE; virtual void OnBrowserCreated(CefRefPtr browser) OVERRIDE; virtual void OnBrowserDestroyed(CefRefPtr browser) OVERRIDE; + virtual CefRefPtr GetLoadHandler() OVERRIDE; virtual bool OnBeforeNavigation(CefRefPtr browser, CefRefPtr frame, CefRefPtr request, NavigationType navigation_type, bool is_redirect) OVERRIDE; diff --git a/tests/cefclient/client_app.cpp b/tests/cefclient/client_app.cpp index 4f892e163..39f8a354f 100644 --- a/tests/cefclient/client_app.cpp +++ b/tests/cefclient/client_app.cpp @@ -279,6 +279,16 @@ void ClientApp::OnBrowserDestroyed(CefRefPtr browser) { (*it)->OnBrowserDestroyed(this, browser); } +CefRefPtr ClientApp::GetLoadHandler() { + CefRefPtr load_handler; + + RenderDelegateSet::iterator it = render_delegates_.begin(); + for (; it != render_delegates_.end() && !load_handler.get(); ++it) + load_handler = (*it)->GetLoadHandler(this); + + return load_handler; +} + bool ClientApp::OnBeforeNavigation(CefRefPtr browser, CefRefPtr frame, CefRefPtr request, diff --git a/tests/cefclient/client_app.h b/tests/cefclient/client_app.h index 6a6ef1795..cafbbb149 100644 --- a/tests/cefclient/client_app.h +++ b/tests/cefclient/client_app.h @@ -51,6 +51,10 @@ class ClientApp : public CefApp, virtual void OnBrowserDestroyed(CefRefPtr app, CefRefPtr browser) {} + virtual CefRefPtr GetLoadHandler(CefRefPtr app) { + return NULL; + } + virtual bool OnBeforeNavigation(CefRefPtr app, CefRefPtr browser, CefRefPtr frame, @@ -151,6 +155,7 @@ class ClientApp : public CefApp, virtual void OnWebKitInitialized() OVERRIDE; virtual void OnBrowserCreated(CefRefPtr browser) OVERRIDE; virtual void OnBrowserDestroyed(CefRefPtr browser) OVERRIDE; + virtual CefRefPtr GetLoadHandler() OVERRIDE; virtual bool OnBeforeNavigation(CefRefPtr browser, CefRefPtr frame, CefRefPtr request, diff --git a/tests/unittests/navigation_unittest.cc b/tests/unittests/navigation_unittest.cc index ff6be9ec1..bc1c79594 100644 --- a/tests/unittests/navigation_unittest.cc +++ b/tests/unittests/navigation_unittest.cc @@ -69,7 +69,8 @@ class HistoryNavBrowserTest : public ClientApp::BrowserDelegate { }; // Renderer side. -class HistoryNavRendererTest : public ClientApp::RenderDelegate { +class HistoryNavRendererTest : public ClientApp::RenderDelegate, + public CefLoadHandler { public: HistoryNavRendererTest() : run_test_(false), @@ -90,6 +91,81 @@ class HistoryNavRendererTest : public ClientApp::RenderDelegate { run_test_ = true; } + virtual CefRefPtr GetLoadHandler( + CefRefPtr app) OVERRIDE { + if (!run_test_) + return NULL; + + return this; + } + + virtual void OnLoadingStateChange(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) OVERRIDE { + const NavListItem& item = kHNavList[nav_]; + + const std::string& url = browser->GetMainFrame()->GetURL(); + if (isLoading) { + got_loading_state_start_.yes(); + + EXPECT_STRNE(item.target, url.c_str()); + + if (nav_ > 0) { + const NavListItem& last_item = kHNavList[nav_ - 1]; + EXPECT_EQ(last_item.can_go_back, browser->CanGoBack()); + EXPECT_EQ(last_item.can_go_back, canGoBack); + EXPECT_EQ(last_item.can_go_forward, browser->CanGoForward()); + EXPECT_EQ(last_item.can_go_forward, canGoForward); + } else { + EXPECT_FALSE(browser->CanGoBack()); + EXPECT_FALSE(canGoBack); + EXPECT_FALSE(browser->CanGoForward()); + EXPECT_FALSE(canGoForward); + } + } else { + got_loading_state_end_.yes(); + + EXPECT_STREQ(item.target, url.c_str()); + + EXPECT_EQ(item.can_go_back, browser->CanGoBack()); + EXPECT_EQ(item.can_go_back, canGoBack); + EXPECT_EQ(item.can_go_forward, browser->CanGoForward()); + EXPECT_EQ(item.can_go_forward, canGoForward); + + SendTestResultsIfDone(browser); + } + } + + virtual void OnLoadStart(CefRefPtr browser, + CefRefPtr frame) OVERRIDE { + const NavListItem& item = kHNavList[nav_]; + + got_load_start_.yes(); + + const std::string& url = frame->GetURL(); + EXPECT_STREQ(item.target, url.c_str()); + + EXPECT_EQ(item.can_go_back, browser->CanGoBack()); + EXPECT_EQ(item.can_go_forward, browser->CanGoForward()); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + const NavListItem& item = kHNavList[nav_]; + + got_load_end_.yes(); + + const std::string& url = frame->GetURL(); + EXPECT_STREQ(item.target, url.c_str()); + + EXPECT_EQ(item.can_go_back, browser->CanGoBack()); + EXPECT_EQ(item.can_go_forward, browser->CanGoForward()); + + SendTestResultsIfDone(browser); + } + virtual bool OnBeforeNavigation(CefRefPtr app, CefRefPtr browser, CefRefPtr frame, @@ -121,15 +197,22 @@ class HistoryNavRendererTest : public ClientApp::RenderDelegate { EXPECT_FALSE(browser->CanGoForward()); } - SendTestResults(browser); - nav_++; - return false; } protected: + void SendTestResultsIfDone(CefRefPtr browser) { + if (got_load_end_ && got_loading_state_end_) + SendTestResults(browser); + } + // Send the test results. void SendTestResults(CefRefPtr browser) { + EXPECT_TRUE(got_loading_state_start_); + EXPECT_TRUE(got_loading_state_end_); + EXPECT_TRUE(got_load_start_); + EXPECT_TRUE(got_load_end_); + // Check if the test has failed. bool result = !TestFailed(); @@ -141,11 +224,24 @@ class HistoryNavRendererTest : public ClientApp::RenderDelegate { EXPECT_TRUE(args->SetInt(0, nav_)); EXPECT_TRUE(args->SetBool(1, result)); EXPECT_TRUE(browser->SendProcessMessage(PID_BROWSER, return_msg)); + + // Reset the test results for the next navigation. + got_loading_state_start_.reset(); + got_loading_state_end_.reset(); + got_load_start_.reset(); + got_load_end_.reset(); + + nav_++; } bool run_test_; int nav_; + TrackCallback got_loading_state_start_; + TrackCallback got_loading_state_end_; + TrackCallback got_load_start_; + TrackCallback got_load_end_; + IMPLEMENT_REFCOUNTING(HistoryNavRendererTest); }; @@ -859,13 +955,99 @@ class OrderNavBrowserTest : public ClientApp::BrowserDelegate { IMPLEMENT_REFCOUNTING(OrderNavBrowserTest); }; +class OrderNavLoadState { + public: + OrderNavLoadState(bool is_popup, bool browser_side) + : is_popup_(is_popup), + browser_side_(browser_side) {} + + void OnLoadingStateChange(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) { + if (isLoading) { + EXPECT_TRUE(Verify(false, false, false, false)); + + got_loading_state_start_.yes(); + } else { + EXPECT_TRUE(Verify(true, false, true, false)); + + got_loading_state_end_.yes(); + } + } + + void OnLoadStart(CefRefPtr browser, + CefRefPtr frame) { + EXPECT_TRUE(Verify(true, false, false, false)); + + got_load_start_.yes(); + } + + void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) { + EXPECT_TRUE(Verify(true, true, true, false)); + + got_load_end_.yes(); + } + + bool IsStarted() { + return got_loading_state_start_ || + got_loading_state_end_ || + got_load_start_ || + got_load_end_; + } + + bool IsDone() { + return got_loading_state_start_ && + got_loading_state_end_ && + got_load_start_ && + got_load_end_; + } + + private: + bool Verify(bool got_loading_state_start, + bool got_loading_state_end, + bool got_load_start, + bool got_load_end) { + EXPECT_EQ(got_loading_state_start, got_loading_state_start_) + << "Popup: " << is_popup_ + << "; Browser Side: " << browser_side_; + EXPECT_EQ(got_loading_state_end, got_loading_state_end_) + << "Popup: " << is_popup_ + << "; Browser Side: " << browser_side_; + EXPECT_EQ(got_load_start, got_load_start_) + << "Popup: " << is_popup_ + << "; Browser Side: " << browser_side_; + EXPECT_EQ(got_load_end, got_load_end_) + << "Popup: " << is_popup_ + << "; Browser Side: " << browser_side_; + + return got_loading_state_start == got_loading_state_start_ && + got_loading_state_end == got_loading_state_end_ && + got_load_start == got_load_start_ && + got_load_end == got_load_end_; + } + + bool is_popup_; + bool browser_side_; + + TrackCallback got_loading_state_start_; + TrackCallback got_loading_state_end_; + TrackCallback got_load_start_; + TrackCallback got_load_end_; +}; + // Renderer side. -class OrderNavRendererTest : public ClientApp::RenderDelegate { +class OrderNavRendererTest : public ClientApp::RenderDelegate, + public CefLoadHandler { public: OrderNavRendererTest() : run_test_(false), browser_id_main_(0), - browser_id_popup_(0) {} + browser_id_popup_(0), + state_main_(false, false), + state_popup_(true, false) {} virtual void OnRenderThreadCreated( CefRefPtr app, @@ -910,16 +1092,16 @@ class OrderNavRendererTest : public ClientApp::RenderDelegate { if (browser->IsPopup()) { EXPECT_FALSE(got_browser_created_popup_); - EXPECT_FALSE(got_before_navigation_popup_); EXPECT_FALSE(got_browser_destroyed_popup_); + EXPECT_FALSE(state_popup_.IsStarted()); got_browser_created_popup_.yes(); browser_id_popup_ = browser->GetIdentifier(); EXPECT_GT(browser->GetIdentifier(), 0); } else { EXPECT_FALSE(got_browser_created_main_); - EXPECT_FALSE(got_before_navigation_main_); EXPECT_FALSE(got_browser_destroyed_main_); + EXPECT_FALSE(state_main_.IsStarted()); got_browser_created_main_.yes(); browser_id_main_ = browser->GetIdentifier(); @@ -939,8 +1121,8 @@ class OrderNavRendererTest : public ClientApp::RenderDelegate { if (browser->IsPopup()) { EXPECT_TRUE(got_browser_created_popup_); - EXPECT_TRUE(got_before_navigation_popup_); EXPECT_FALSE(got_browser_destroyed_popup_); + EXPECT_TRUE(state_popup_.IsDone()); got_browser_destroyed_popup_.yes(); EXPECT_EQ(browser_id_popup_, browser->GetIdentifier()); @@ -950,8 +1132,8 @@ class OrderNavRendererTest : public ClientApp::RenderDelegate { SendTestResults(browser_main_, kOrderNavClosedMsg); } else { EXPECT_TRUE(got_browser_created_main_); - EXPECT_TRUE(got_before_navigation_main_); EXPECT_FALSE(got_browser_destroyed_main_); + EXPECT_TRUE(state_main_.IsDone()); got_browser_destroyed_main_.yes(); EXPECT_EQ(browser_id_main_, browser->GetIdentifier()); @@ -961,52 +1143,90 @@ class OrderNavRendererTest : public ClientApp::RenderDelegate { } } - virtual bool OnBeforeNavigation(CefRefPtr app, - CefRefPtr browser, - CefRefPtr frame, - CefRefPtr request, - cef_navigation_type_t navigation_type, - bool is_redirect) OVERRIDE { + virtual CefRefPtr GetLoadHandler( + CefRefPtr app) OVERRIDE { if (!run_test_) - return false; + return NULL; + return this; + } + + virtual void OnLoadingStateChange(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) OVERRIDE { EXPECT_TRUE(got_render_thread_created_); EXPECT_TRUE(got_webkit_initialized_); - EXPECT_EQ(RT_SUB_RESOURCE, request->GetResourceType()); - EXPECT_EQ(TT_EXPLICIT, request->GetTransitionType()); + if (browser->IsPopup()) { + EXPECT_TRUE(got_browser_created_popup_); + EXPECT_FALSE(got_browser_destroyed_popup_); + + state_popup_.OnLoadingStateChange(browser, isLoading, canGoBack, + canGoForward); + } else { + EXPECT_TRUE(got_browser_created_main_); + EXPECT_FALSE(got_browser_destroyed_main_); + + state_main_.OnLoadingStateChange(browser, isLoading, canGoBack, + canGoForward); + } + + if (!isLoading) + SendTestResultsIfDone(browser); + } + + virtual void OnLoadStart(CefRefPtr browser, + CefRefPtr frame) OVERRIDE { + EXPECT_TRUE(got_render_thread_created_); + EXPECT_TRUE(got_webkit_initialized_); if (browser->IsPopup()) { EXPECT_TRUE(got_browser_created_popup_); - EXPECT_FALSE(got_before_navigation_popup_); EXPECT_FALSE(got_browser_destroyed_popup_); - got_before_navigation_popup_.yes(); - EXPECT_EQ(browser_id_popup_, browser->GetIdentifier()); - EXPECT_GT(browser->GetIdentifier(), 0); + state_popup_.OnLoadStart(browser, frame); } else { EXPECT_TRUE(got_browser_created_main_); - EXPECT_FALSE(got_before_navigation_main_); EXPECT_FALSE(got_browser_destroyed_main_); - got_before_navigation_main_.yes(); - EXPECT_EQ(browser_id_main_, browser->GetIdentifier()); - EXPECT_GT(browser->GetIdentifier(), 0); + state_main_.OnLoadStart(browser, frame); + } + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + EXPECT_TRUE(got_render_thread_created_); + EXPECT_TRUE(got_webkit_initialized_); + + if (browser->IsPopup()) { + EXPECT_TRUE(got_browser_created_popup_); + EXPECT_FALSE(got_browser_destroyed_popup_); + + state_popup_.OnLoadEnd(browser, frame, httpStatusCode); + } else { + EXPECT_TRUE(got_browser_created_main_); + EXPECT_FALSE(got_browser_destroyed_main_); + + state_main_.OnLoadEnd(browser, frame, httpStatusCode); } - std::string url = request->GetURL(); - if (url == KONav1) - EXPECT_FALSE(browser->IsPopup()); - else if (url == KONav2) - EXPECT_TRUE(browser->IsPopup()); - else - EXPECT_TRUE(false); // not reached - - SendTestResults(browser, kOrderNavMsg); - return false; + SendTestResultsIfDone(browser); } protected: + void SendTestResultsIfDone(CefRefPtr browser) { + bool done = false; + if (browser->IsPopup()) + done = state_popup_.IsDone(); + else + done = state_main_.IsDone(); + + if (done) + SendTestResults(browser, kOrderNavMsg); + } + // Send the test results. void SendTestResults(CefRefPtr browser, const char* msg_name) { // Check if the test has failed. @@ -1034,10 +1254,11 @@ class OrderNavRendererTest : public ClientApp::RenderDelegate { TrackCallback got_webkit_initialized_; TrackCallback got_browser_created_main_; TrackCallback got_browser_destroyed_main_; - TrackCallback got_before_navigation_main_; TrackCallback got_browser_created_popup_; TrackCallback got_browser_destroyed_popup_; - TrackCallback got_before_navigation_popup_; + + OrderNavLoadState state_main_; + OrderNavLoadState state_popup_; IMPLEMENT_REFCOUNTING(OrderNavRendererTest); }; @@ -1048,8 +1269,9 @@ class OrderNavTestHandler : public TestHandler { OrderNavTestHandler() : browser_id_main_(0), browser_id_popup_(0), - got_message_(false), - got_load_end_(false) {} + state_main_(false, true), + state_popup_(true, true), + got_message_(false) {} virtual void RunTest() OVERRIDE { // Add the resources that we will navigate to/from. @@ -1061,11 +1283,18 @@ class OrderNavTestHandler : public TestHandler { } void ContinueIfReady(CefRefPtr browser) { - if (!got_message_ || !got_load_end_) + if (!got_message_) + return; + + bool done = false; + if (browser->IsPopup()) + done = state_popup_.IsDone(); + else + done = state_main_.IsDone(); + if (!done) return; got_message_ = false; - got_load_end_ = false; if (!browser->IsPopup()) { // Create the popup window. @@ -1137,14 +1366,28 @@ class OrderNavTestHandler : public TestHandler { return false; } + virtual void OnLoadingStateChange(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) OVERRIDE { + if (browser->IsPopup()) { + state_popup_.OnLoadingStateChange(browser, isLoading, canGoBack, + canGoForward); + } else { + state_main_.OnLoadingStateChange(browser, isLoading, canGoBack, + canGoForward); + } + + if (!isLoading) + ContinueIfReady(browser); + } + virtual void OnLoadStart(CefRefPtr browser, CefRefPtr frame) OVERRIDE { if (browser->IsPopup()) { - EXPECT_GT(browser->GetIdentifier(), 0); - EXPECT_EQ(browser_id_popup_, browser->GetIdentifier()); + state_popup_.OnLoadStart(browser, frame); } else { - EXPECT_GT(browser->GetIdentifier(), 0); - EXPECT_EQ(browser_id_main_, browser->GetIdentifier()); + state_main_.OnLoadStart(browser, frame); } } @@ -1152,14 +1395,11 @@ class OrderNavTestHandler : public TestHandler { CefRefPtr frame, int httpStatusCode) OVERRIDE { if (browser->IsPopup()) { - EXPECT_GT(browser->GetIdentifier(), 0); - EXPECT_EQ(browser_id_popup_, browser->GetIdentifier()); + state_popup_.OnLoadEnd(browser, frame, httpStatusCode); } else { - EXPECT_GT(browser->GetIdentifier(), 0); - EXPECT_EQ(browser_id_main_, browser->GetIdentifier()); + state_main_.OnLoadEnd(browser, frame, httpStatusCode); } - got_load_end_ = true; ContinueIfReady(browser); } @@ -1221,8 +1461,10 @@ class OrderNavTestHandler : public TestHandler { TrackCallback got_before_browse_main_; TrackCallback got_before_browse_popup_; + OrderNavLoadState state_main_; + OrderNavLoadState state_popup_; + bool got_message_; - bool got_load_end_; }; } // namespace @@ -1265,7 +1507,8 @@ class CrossOriginNavBrowserTest : public ClientApp::BrowserDelegate { }; // Renderer side. -class CrossOriginNavRendererTest : public ClientApp::RenderDelegate { +class CrossOriginNavRendererTest : public ClientApp::RenderDelegate, + public CefLoadHandler { public: CrossOriginNavRendererTest() : run_test_(false) {} @@ -1326,40 +1569,41 @@ class CrossOriginNavRendererTest : public ClientApp::RenderDelegate { EXPECT_TRUE(status); EXPECT_TRUE(status->got_browser_created); - EXPECT_TRUE(status->got_before_navigation); + EXPECT_TRUE(status->got_loading_state_end); EXPECT_EQ(status->browser_id, browser->GetIdentifier()); EXPECT_TRUE(RemoveStatus(browser)); } - virtual bool OnBeforeNavigation(CefRefPtr app, - CefRefPtr browser, - CefRefPtr frame, - CefRefPtr request, - cef_navigation_type_t navigation_type, - bool is_redirect) OVERRIDE { + virtual CefRefPtr GetLoadHandler( + CefRefPtr app) OVERRIDE { if (!run_test_) - return false; + return NULL; - EXPECT_TRUE(got_render_thread_created_); - EXPECT_TRUE(got_webkit_initialized_); + return this; + } - EXPECT_EQ(RT_SUB_RESOURCE, request->GetResourceType()); - EXPECT_EQ(TT_EXPLICIT, request->GetTransitionType()); + virtual void OnLoadingStateChange(CefRefPtr browser, + bool isLoading, + bool canGoBack, + bool canGoForward) OVERRIDE { + if (!isLoading) { + EXPECT_TRUE(got_render_thread_created_); + EXPECT_TRUE(got_webkit_initialized_); - Status* status = GetStatus(browser); - EXPECT_TRUE(status); + Status* status = GetStatus(browser); + EXPECT_TRUE(status); - EXPECT_TRUE(status->got_browser_created); - EXPECT_FALSE(status->got_before_navigation); + EXPECT_TRUE(status->got_browser_created); + EXPECT_FALSE(status->got_loading_state_end); - status->got_before_navigation.yes(); + status->got_loading_state_end.yes(); - EXPECT_EQ(status->browser_id, browser->GetIdentifier()); + EXPECT_EQ(status->browser_id, browser->GetIdentifier()); - SendTestResults(browser); - return false; + SendTestResults(browser); + } } protected: @@ -1389,7 +1633,7 @@ class CrossOriginNavRendererTest : public ClientApp::RenderDelegate { CefRefPtr browser; int browser_id; TrackCallback got_browser_created; - TrackCallback got_before_navigation; + TrackCallback got_loading_state_end; }; typedef std::list StatusList; StatusList status_list_;