Add a new CefRequestHandler::OnOpenURLFromTab method for handling certain limited cases where navigating a new or different browser might be desirable (issue #1526).
git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@2054 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
parent
5de989e306
commit
c49473729d
|
@ -118,6 +118,27 @@ typedef struct _cef_request_handler_t {
|
|||
struct _cef_browser_t* browser, struct _cef_frame_t* frame,
|
||||
struct _cef_request_t* request, int is_redirect);
|
||||
|
||||
///
|
||||
// Called on the UI thread before OnBeforeBrowse in certain limited cases
|
||||
// where navigating a new or different browser might be desirable. This
|
||||
// includes user-initiated navigation that might open in a special way (e.g.
|
||||
// links clicked via middle-click or ctrl + left-click) and certain types of
|
||||
// cross-origin navigation initiated from the renderer process (e.g.
|
||||
// navigating the top-level frame to/from a file URL). The |browser| and
|
||||
// |frame| values represent the source of the navigation. The
|
||||
// |target_disposition| value indicates where the user intended to navigate
|
||||
// the browser based on standard Chromium behaviors (e.g. current tab, new
|
||||
// tab, etc). The |user_gesture| value will be true (1) if the browser
|
||||
// navigated via explicit user gesture (e.g. clicking a link) or false (0) if
|
||||
// it navigated automatically (e.g. via the DomContentLoaded event). Return
|
||||
// true (1) to cancel the navigation or false (0) to allow the navigation to
|
||||
// proceed in the source browser's top-level frame.
|
||||
///
|
||||
int (CEF_CALLBACK *on_open_urlfrom_tab)(struct _cef_request_handler_t* self,
|
||||
struct _cef_browser_t* browser, struct _cef_frame_t* frame,
|
||||
const cef_string_t* target_url,
|
||||
cef_window_open_disposition_t target_disposition, int user_gesture);
|
||||
|
||||
///
|
||||
// Called on the IO thread before a resource request is loaded. The |request|
|
||||
// object may be modified. To cancel the request return true (1) otherwise
|
||||
|
|
|
@ -93,6 +93,7 @@ class CefAllowCertificateErrorCallback : public virtual CefBase {
|
|||
class CefRequestHandler : public virtual CefBase {
|
||||
public:
|
||||
typedef cef_termination_status_t TerminationStatus;
|
||||
typedef cef_window_open_disposition_t WindowOpenDisposition;
|
||||
|
||||
///
|
||||
// Called on the UI thread before browser navigation. Return true to cancel
|
||||
|
@ -112,6 +113,31 @@ class CefRequestHandler : public virtual CefBase {
|
|||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
// Called on the UI thread before OnBeforeBrowse in certain limited cases
|
||||
// where navigating a new or different browser might be desirable. This
|
||||
// includes user-initiated navigation that might open in a special way (e.g.
|
||||
// links clicked via middle-click or ctrl + left-click) and certain types of
|
||||
// cross-origin navigation initiated from the renderer process (e.g.
|
||||
// navigating the top-level frame to/from a file URL). The |browser| and
|
||||
// |frame| values represent the source of the navigation. The
|
||||
// |target_disposition| value indicates where the user intended to navigate
|
||||
// the browser based on standard Chromium behaviors (e.g. current tab,
|
||||
// new tab, etc). The |user_gesture| value will be true if the browser
|
||||
// navigated via explicit user gesture (e.g. clicking a link) or false if it
|
||||
// navigated automatically (e.g. via the DomContentLoaded event). Return true
|
||||
// to cancel the navigation or false to allow the navigation to proceed in the
|
||||
// source browser's top-level frame.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual bool OnOpenURLFromTab(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
WindowOpenDisposition target_disposition,
|
||||
bool user_gesture) {
|
||||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
// Called on the IO thread before a resource request is loaded. The |request|
|
||||
// object may be modified. To cancel the request return true otherwise return
|
||||
|
|
|
@ -2005,12 +2005,30 @@ void CefBrowserHostImpl::DragSourceEndedAt(
|
|||
content::WebContents* CefBrowserHostImpl::OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
const content::OpenURLParams& params) {
|
||||
// Start a navigation that will result in the creation of a new render
|
||||
// process.
|
||||
LoadURL(CefFrameHostImpl::kMainFrameId, params.url.spec(), params.referrer,
|
||||
params.transition, params.extra_headers);
|
||||
bool cancel = false;
|
||||
|
||||
return source;
|
||||
if (client_.get()) {
|
||||
CefRefPtr<CefRequestHandler> handler = client_->GetRequestHandler();
|
||||
if (handler.get()) {
|
||||
cancel = handler->OnOpenURLFromTab(
|
||||
this,
|
||||
GetFrame(params.frame_tree_node_id),
|
||||
params.url.spec(),
|
||||
static_cast<cef_window_open_disposition_t>(params.disposition),
|
||||
params.user_gesture);
|
||||
}
|
||||
}
|
||||
|
||||
if (!cancel) {
|
||||
// Start a navigation in the current browser that will result in the
|
||||
// creation of a new render process.
|
||||
LoadURL(CefFrameHostImpl::kMainFrameId, params.url.spec(), params.referrer,
|
||||
params.transition, params.extra_headers);
|
||||
return source;
|
||||
}
|
||||
|
||||
// We don't know where the navigation, if any, will occur.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CefBrowserHostImpl::LoadingStateChanged(content::WebContents* source,
|
||||
|
|
|
@ -56,6 +56,40 @@ int CEF_CALLBACK request_handler_on_before_browse(
|
|||
return _retval;
|
||||
}
|
||||
|
||||
int CEF_CALLBACK request_handler_on_open_urlfrom_tab(
|
||||
struct _cef_request_handler_t* self, cef_browser_t* browser,
|
||||
cef_frame_t* frame, const cef_string_t* target_url,
|
||||
cef_window_open_disposition_t target_disposition, int user_gesture) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return 0;
|
||||
// Verify param: browser; type: refptr_diff
|
||||
DCHECK(browser);
|
||||
if (!browser)
|
||||
return 0;
|
||||
// Verify param: frame; type: refptr_diff
|
||||
DCHECK(frame);
|
||||
if (!frame)
|
||||
return 0;
|
||||
// Verify param: target_url; type: string_byref_const
|
||||
DCHECK(target_url);
|
||||
if (!target_url)
|
||||
return 0;
|
||||
|
||||
// Execute
|
||||
bool _retval = CefRequestHandlerCppToC::Get(self)->OnOpenURLFromTab(
|
||||
CefBrowserCToCpp::Wrap(browser),
|
||||
CefFrameCToCpp::Wrap(frame),
|
||||
CefString(target_url),
|
||||
target_disposition,
|
||||
user_gesture?true:false);
|
||||
|
||||
// Return type: bool
|
||||
return _retval;
|
||||
}
|
||||
|
||||
int CEF_CALLBACK request_handler_on_before_resource_load(
|
||||
struct _cef_request_handler_t* self, cef_browser_t* browser,
|
||||
cef_frame_t* frame, cef_request_t* request) {
|
||||
|
@ -389,6 +423,7 @@ CefRequestHandlerCppToC::CefRequestHandlerCppToC(CefRequestHandler* cls)
|
|||
: CefCppToC<CefRequestHandlerCppToC, CefRequestHandler,
|
||||
cef_request_handler_t>(cls) {
|
||||
struct_.struct_.on_before_browse = request_handler_on_before_browse;
|
||||
struct_.struct_.on_open_urlfrom_tab = request_handler_on_open_urlfrom_tab;
|
||||
struct_.struct_.on_before_resource_load =
|
||||
request_handler_on_before_resource_load;
|
||||
struct_.struct_.get_resource_handler = request_handler_get_resource_handler;
|
||||
|
|
|
@ -56,6 +56,39 @@ bool CefRequestHandlerCToCpp::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
|
|||
return _retval?true:false;
|
||||
}
|
||||
|
||||
bool CefRequestHandlerCToCpp::OnOpenURLFromTab(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame, const CefString& target_url,
|
||||
WindowOpenDisposition target_disposition, bool user_gesture) {
|
||||
if (CEF_MEMBER_MISSING(struct_, on_open_urlfrom_tab))
|
||||
return false;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: browser; type: refptr_diff
|
||||
DCHECK(browser.get());
|
||||
if (!browser.get())
|
||||
return false;
|
||||
// Verify param: frame; type: refptr_diff
|
||||
DCHECK(frame.get());
|
||||
if (!frame.get())
|
||||
return false;
|
||||
// Verify param: target_url; type: string_byref_const
|
||||
DCHECK(!target_url.empty());
|
||||
if (target_url.empty())
|
||||
return false;
|
||||
|
||||
// Execute
|
||||
int _retval = struct_->on_open_urlfrom_tab(struct_,
|
||||
CefBrowserCppToC::Wrap(browser),
|
||||
CefFrameCppToC::Wrap(frame),
|
||||
target_url.GetStruct(),
|
||||
target_disposition,
|
||||
user_gesture);
|
||||
|
||||
// Return type: bool
|
||||
return _retval?true:false;
|
||||
}
|
||||
|
||||
bool CefRequestHandlerCToCpp::OnBeforeResourceLoad(
|
||||
CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) {
|
||||
|
|
|
@ -35,6 +35,9 @@ class CefRequestHandlerCToCpp
|
|||
// CefRequestHandler methods
|
||||
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser, CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request, bool is_redirect) override;
|
||||
bool OnOpenURLFromTab(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame, const CefString& target_url,
|
||||
WindowOpenDisposition target_disposition, bool user_gesture) override;
|
||||
bool OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame, CefRefPtr<CefRequest> request) override;
|
||||
CefRefPtr<CefResourceHandler> GetResourceHandler(
|
||||
|
|
|
@ -322,17 +322,18 @@ bool ClientHandler::OnPreKeyEvent(CefRefPtr<CefBrowser> browser,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ClientHandler::OnBeforePopup(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
const CefString& target_frame_name,
|
||||
WindowOpenDisposition target_disposition,
|
||||
bool user_gesture,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings,
|
||||
bool* no_javascript_access) {
|
||||
bool ClientHandler::OnBeforePopup(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
const CefString& target_frame_name,
|
||||
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
|
||||
bool user_gesture,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings,
|
||||
bool* no_javascript_access) {
|
||||
CEF_REQUIRE_IO_THREAD();
|
||||
|
||||
// Return true to cancel the popup window.
|
||||
|
@ -434,6 +435,24 @@ bool ClientHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool ClientHandler::OnOpenURLFromTab(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
CefRequestHandler::WindowOpenDisposition target_disposition,
|
||||
bool user_gesture) {
|
||||
if (user_gesture && target_disposition == WOD_NEW_BACKGROUND_TAB) {
|
||||
// Handle middle-click and ctrl + left-click by opening the URL in a new
|
||||
// browser window.
|
||||
MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
|
||||
true, is_osr(), CefRect(), target_url);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Open the URL in the current browser window.
|
||||
return false;
|
||||
}
|
||||
|
||||
CefRefPtr<CefResourceHandler> ClientHandler::GetResourceHandler(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
|
|
|
@ -166,17 +166,18 @@ class ClientHandler : public CefClient,
|
|||
bool* is_keyboard_shortcut) OVERRIDE;
|
||||
|
||||
// CefLifeSpanHandler methods
|
||||
bool OnBeforePopup(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
const CefString& target_frame_name,
|
||||
WindowOpenDisposition target_disposition,
|
||||
bool user_gesture,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings,
|
||||
bool* no_javascript_access) OVERRIDE;
|
||||
bool OnBeforePopup(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
const CefString& target_frame_name,
|
||||
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
|
||||
bool user_gesture,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings,
|
||||
bool* no_javascript_access) OVERRIDE;
|
||||
void OnAfterCreated(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
bool DoClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
void OnBeforeClose(CefRefPtr<CefBrowser> browser) OVERRIDE;
|
||||
|
@ -197,6 +198,12 @@ class ClientHandler : public CefClient,
|
|||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
bool is_redirect) OVERRIDE;
|
||||
bool OnOpenURLFromTab(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
CefRequestHandler::WindowOpenDisposition target_disposition,
|
||||
bool user_gesture) OVERRIDE;
|
||||
CefRefPtr<CefResourceHandler> GetResourceHandler(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
|
|
|
@ -1438,50 +1438,53 @@ TEST(NavigationTest, Order) {
|
|||
|
||||
namespace {
|
||||
|
||||
const char kCrossOriginNav1[] = "http://tests-conav1/nav1.html";
|
||||
const char kCrossOriginNav2[] = "http://tests-conav2/nav2.html";
|
||||
const char kCrossOriginNavMsg[] = "NavigationTest.CrossOriginNav";
|
||||
const char kLoadNav1[] = "http://tests-conav1.com/nav1.html";
|
||||
const char kLoadNavSameOrigin2[] = "http://tests-conav1.com/nav2.html";
|
||||
const char kLoadNavCrossOrigin2[] = "http://tests-conav2.com/nav2.html";
|
||||
const char kLoadNavMsg[] = "NavigationTest.LoadNav";
|
||||
|
||||
bool g_cross_origin_nav_test = false;
|
||||
bool g_load_nav_test = false;
|
||||
|
||||
// Browser side.
|
||||
class CrossOriginNavBrowserTest : public ClientAppBrowser::Delegate {
|
||||
class LoadNavBrowserTest : public ClientAppBrowser::Delegate {
|
||||
public:
|
||||
CrossOriginNavBrowserTest() {}
|
||||
LoadNavBrowserTest() {}
|
||||
|
||||
void OnBeforeChildProcessLaunch(
|
||||
CefRefPtr<ClientAppBrowser> app,
|
||||
CefRefPtr<CefCommandLine> command_line) override {
|
||||
if (!g_cross_origin_nav_test)
|
||||
if (!g_load_nav_test)
|
||||
return;
|
||||
|
||||
// Indicate to the render process that the test should be run.
|
||||
command_line->AppendSwitchWithValue("test", kCrossOriginNavMsg);
|
||||
command_line->AppendSwitchWithValue("test", kLoadNavMsg);
|
||||
}
|
||||
|
||||
protected:
|
||||
IMPLEMENT_REFCOUNTING(CrossOriginNavBrowserTest);
|
||||
IMPLEMENT_REFCOUNTING(LoadNavBrowserTest);
|
||||
};
|
||||
|
||||
// Renderer side.
|
||||
class CrossOriginNavRendererTest : public ClientAppRenderer::Delegate,
|
||||
public CefLoadHandler {
|
||||
class LoadNavRendererTest : public ClientAppRenderer::Delegate,
|
||||
public CefLoadHandler {
|
||||
public:
|
||||
CrossOriginNavRendererTest()
|
||||
: run_test_(false) {}
|
||||
~CrossOriginNavRendererTest() override {
|
||||
EXPECT_TRUE(status_list_.empty());
|
||||
LoadNavRendererTest()
|
||||
: run_test_(false),
|
||||
browser_id_(0),
|
||||
load_ct_(0) {}
|
||||
~LoadNavRendererTest() override {
|
||||
EXPECT_EQ(0, browser_id_);
|
||||
}
|
||||
|
||||
void OnRenderThreadCreated(
|
||||
CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefListValue> extra_info) override {
|
||||
if (!g_cross_origin_nav_test) {
|
||||
if (!g_load_nav_test) {
|
||||
// Check that the test should be run.
|
||||
CefRefPtr<CefCommandLine> command_line =
|
||||
CefCommandLine::GetGlobalCommandLine();
|
||||
const std::string& test = command_line->GetSwitchValue("test");
|
||||
if (test != kCrossOriginNavMsg)
|
||||
if (test != kLoadNavMsg)
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1509,9 +1512,10 @@ class CrossOriginNavRendererTest : public ClientAppRenderer::Delegate,
|
|||
EXPECT_TRUE(got_render_thread_created_);
|
||||
EXPECT_TRUE(got_webkit_initialized_);
|
||||
|
||||
EXPECT_FALSE(GetStatus(browser));
|
||||
Status* status = AddStatus(browser);
|
||||
status->got_browser_created.yes();
|
||||
EXPECT_EQ(0, browser_id_);
|
||||
browser_id_ = browser->GetIdentifier();
|
||||
EXPECT_GT(browser_id_, 0);
|
||||
got_browser_created_.yes();
|
||||
}
|
||||
|
||||
void OnBrowserDestroyed(CefRefPtr<ClientAppRenderer> app,
|
||||
|
@ -1522,15 +1526,11 @@ class CrossOriginNavRendererTest : public ClientAppRenderer::Delegate,
|
|||
EXPECT_TRUE(got_render_thread_created_);
|
||||
EXPECT_TRUE(got_webkit_initialized_);
|
||||
|
||||
Status* status = GetStatus(browser);
|
||||
EXPECT_TRUE(status);
|
||||
EXPECT_TRUE(got_browser_created_);
|
||||
EXPECT_TRUE(got_loading_state_end_);
|
||||
|
||||
EXPECT_TRUE(status->got_browser_created);
|
||||
EXPECT_TRUE(status->got_loading_state_end);
|
||||
|
||||
EXPECT_EQ(status->browser_id, browser->GetIdentifier());
|
||||
|
||||
EXPECT_TRUE(RemoveStatus(browser));
|
||||
EXPECT_EQ(browser_id_, browser->GetIdentifier());
|
||||
browser_id_ = 0;
|
||||
}
|
||||
|
||||
CefRefPtr<CefLoadHandler> GetLoadHandler(
|
||||
|
@ -1549,16 +1549,13 @@ class CrossOriginNavRendererTest : public ClientAppRenderer::Delegate,
|
|||
EXPECT_TRUE(got_render_thread_created_);
|
||||
EXPECT_TRUE(got_webkit_initialized_);
|
||||
|
||||
Status* status = GetStatus(browser);
|
||||
EXPECT_TRUE(status);
|
||||
EXPECT_TRUE(got_browser_created_);
|
||||
|
||||
EXPECT_TRUE(status->got_browser_created);
|
||||
EXPECT_FALSE(status->got_loading_state_end);
|
||||
got_loading_state_end_.yes();
|
||||
|
||||
status->got_loading_state_end.yes();
|
||||
|
||||
EXPECT_EQ(status->browser_id, browser->GetIdentifier());
|
||||
EXPECT_EQ(browser_id_, browser->GetIdentifier());
|
||||
|
||||
load_ct_++;
|
||||
SendTestResults(browser);
|
||||
}
|
||||
}
|
||||
|
@ -1571,11 +1568,12 @@ class CrossOriginNavRendererTest : public ClientAppRenderer::Delegate,
|
|||
|
||||
// Return the result to the browser process.
|
||||
CefRefPtr<CefProcessMessage> return_msg =
|
||||
CefProcessMessage::Create(kCrossOriginNavMsg);
|
||||
CefProcessMessage::Create(kLoadNavMsg);
|
||||
CefRefPtr<CefListValue> args = return_msg->GetArgumentList();
|
||||
EXPECT_TRUE(args.get());
|
||||
EXPECT_TRUE(args->SetBool(0, result));
|
||||
EXPECT_TRUE(args->SetInt(1, browser->GetIdentifier()));
|
||||
EXPECT_TRUE(args->SetInt(2, load_ct_));
|
||||
EXPECT_TRUE(browser->SendProcessMessage(PID_BROWSER, return_msg));
|
||||
}
|
||||
|
||||
|
@ -1584,68 +1582,60 @@ class CrossOriginNavRendererTest : public ClientAppRenderer::Delegate,
|
|||
TrackCallback got_render_thread_created_;
|
||||
TrackCallback got_webkit_initialized_;
|
||||
|
||||
struct Status {
|
||||
Status() : browser_id(0) {}
|
||||
int browser_id_;
|
||||
int load_ct_;
|
||||
TrackCallback got_browser_created_;
|
||||
TrackCallback got_loading_state_end_;
|
||||
|
||||
CefRefPtr<CefBrowser> browser;
|
||||
int browser_id;
|
||||
TrackCallback got_browser_created;
|
||||
TrackCallback got_loading_state_end;
|
||||
};
|
||||
typedef std::list<Status> StatusList;
|
||||
StatusList status_list_;
|
||||
|
||||
Status* GetStatus(CefRefPtr<CefBrowser> browser) {
|
||||
StatusList::iterator it = status_list_.begin();
|
||||
for (; it != status_list_.end(); ++it) {
|
||||
Status& status = (*it);
|
||||
if (status.browser->IsSame(browser))
|
||||
return &status;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Status* AddStatus(CefRefPtr<CefBrowser> browser) {
|
||||
Status status;
|
||||
status.browser = browser;
|
||||
status.browser_id = browser->GetIdentifier();
|
||||
EXPECT_GT(status.browser_id, 0);
|
||||
status_list_.push_back(status);
|
||||
return &status_list_.back();
|
||||
}
|
||||
|
||||
bool RemoveStatus(CefRefPtr<CefBrowser> browser) {
|
||||
StatusList::iterator it = status_list_.begin();
|
||||
for (; it != status_list_.end(); ++it) {
|
||||
Status& status = (*it);
|
||||
if (status.browser->IsSame(browser)) {
|
||||
status_list_.erase(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
IMPLEMENT_REFCOUNTING(CrossOriginNavRendererTest);
|
||||
IMPLEMENT_REFCOUNTING(LoadNavRendererTest);
|
||||
};
|
||||
|
||||
// Browser side.
|
||||
class CrossOriginNavTestHandler : public TestHandler {
|
||||
class LoadNavTestHandler : public TestHandler {
|
||||
public:
|
||||
CrossOriginNavTestHandler()
|
||||
: browser_id_current_(0),
|
||||
got_message_(false),
|
||||
got_load_end_(false) {}
|
||||
enum TestMode {
|
||||
LOAD,
|
||||
LEFT_CLICK,
|
||||
MIDDLE_CLICK,
|
||||
CTRL_LEFT_CLICK,
|
||||
};
|
||||
|
||||
LoadNavTestHandler(TestMode mode,
|
||||
bool same_origin,
|
||||
bool cancel_in_open_url = false)
|
||||
: mode_(mode),
|
||||
same_origin_(same_origin),
|
||||
cancel_in_open_url_(cancel_in_open_url),
|
||||
browser_id_current_(0),
|
||||
renderer_load_ct_(0) {
|
||||
g_load_nav_test = true;
|
||||
}
|
||||
|
||||
~LoadNavTestHandler() override {
|
||||
g_load_nav_test = false;
|
||||
}
|
||||
|
||||
std::string GetURL2() const {
|
||||
return same_origin_ ? kLoadNavSameOrigin2 : kLoadNavCrossOrigin2;
|
||||
}
|
||||
|
||||
bool ExpectOpenURL() const {
|
||||
return mode_ == MIDDLE_CLICK || mode_ == CTRL_LEFT_CLICK;
|
||||
}
|
||||
|
||||
void RunTest() override {
|
||||
const std::string& url2 = GetURL2();
|
||||
std::string link;
|
||||
if (mode_ != LOAD)
|
||||
link = "<a href=\"" + url2 + "\">CLICK ME</a>";
|
||||
|
||||
// Add the resources that we will navigate to/from.
|
||||
AddResource(kCrossOriginNav1, "<html>Nav1</html>", "text/html");
|
||||
AddResource(kCrossOriginNav2, "<html>Nav2</html>", "text/html");
|
||||
AddResource(kLoadNav1, "<html><body><h1>" + link +
|
||||
"Nav1</h1></body></html>", "text/html");
|
||||
AddResource(url2, "<html>Nav2</html>", "text/html");
|
||||
|
||||
// Create the browser.
|
||||
CreateBrowser(kCrossOriginNav1);
|
||||
CreateBrowser(kLoadNav1);
|
||||
|
||||
// Time out the test after a reasonable period of time.
|
||||
SetTestTimeout();
|
||||
|
@ -1655,13 +1645,48 @@ class CrossOriginNavTestHandler : public TestHandler {
|
|||
if (!got_message_ || !got_load_end_)
|
||||
return;
|
||||
|
||||
got_message_ = false;
|
||||
got_load_end_ = false;
|
||||
|
||||
std::string url = browser->GetMainFrame()->GetURL();
|
||||
if (url == kCrossOriginNav1) {
|
||||
if (url == kLoadNav1) {
|
||||
// Verify the behavior of the previous load.
|
||||
EXPECT_TRUE(got_before_browse_);
|
||||
EXPECT_TRUE(got_before_resource_load_);
|
||||
EXPECT_TRUE(got_load_start_);
|
||||
EXPECT_TRUE(got_load_end_);
|
||||
EXPECT_FALSE(got_open_url_from_tab_);
|
||||
|
||||
got_before_browse_.reset();
|
||||
got_before_resource_load_.reset();
|
||||
got_load_start_.reset();
|
||||
got_load_end_.reset();
|
||||
got_message_.reset();
|
||||
|
||||
EXPECT_EQ(1, renderer_load_ct_);
|
||||
|
||||
// Load the next url.
|
||||
browser->GetMainFrame()->LoadURL(kCrossOriginNav2);
|
||||
if (mode_ == LOAD) {
|
||||
browser->GetMainFrame()->LoadURL(GetURL2());
|
||||
} else {
|
||||
// Navigate to the URL by clicking a link.
|
||||
CefMouseEvent mouse_event;
|
||||
mouse_event.x = 20;
|
||||
mouse_event.y = 20;
|
||||
mouse_event.modifiers =
|
||||
(mode_ == CTRL_LEFT_CLICK ? EVENTFLAG_CONTROL_DOWN : 0);
|
||||
|
||||
cef_mouse_button_type_t button_type =
|
||||
(mode_ == MIDDLE_CLICK ? MBT_MIDDLE : MBT_LEFT);
|
||||
browser->GetHost()->SendMouseClickEvent(
|
||||
mouse_event, button_type, false, 1);
|
||||
browser->GetHost()->SendMouseClickEvent(
|
||||
mouse_event, button_type, true, 1);
|
||||
}
|
||||
|
||||
if (cancel_in_open_url_) {
|
||||
// The next navigation should not occur. Therefore call DestroyTest()
|
||||
// after a reasonable timeout.
|
||||
CefPostDelayedTask(TID_UI,
|
||||
base::Bind(&LoadNavTestHandler::DestroyTest, this), 500);
|
||||
}
|
||||
} else {
|
||||
// Done with the test.
|
||||
DestroyTest();
|
||||
|
@ -1681,22 +1706,67 @@ class CrossOriginNavTestHandler : public TestHandler {
|
|||
CefRefPtr<CefRequest> request,
|
||||
bool is_redirect) override {
|
||||
EXPECT_EQ(RT_MAIN_FRAME, request->GetResourceType());
|
||||
EXPECT_EQ(TT_EXPLICIT, request->GetTransitionType());
|
||||
if (mode_ == LOAD || request->GetURL() == kLoadNav1)
|
||||
EXPECT_EQ(TT_EXPLICIT, request->GetTransitionType());
|
||||
else
|
||||
EXPECT_EQ(TT_LINK, request->GetTransitionType());
|
||||
|
||||
EXPECT_GT(browser_id_current_, 0);
|
||||
EXPECT_EQ(browser_id_current_, browser->GetIdentifier());
|
||||
|
||||
if (ExpectOpenURL() && request->GetURL() == GetURL2()) {
|
||||
// OnOpenURLFromTab should be called first for the file URL navigation.
|
||||
EXPECT_TRUE(got_open_url_from_tab_);
|
||||
} else {
|
||||
EXPECT_FALSE(got_open_url_from_tab_);
|
||||
}
|
||||
|
||||
got_before_browse_.yes();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OnOpenURLFromTab(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
cef_window_open_disposition_t target_disposition,
|
||||
bool user_gesture) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||
|
||||
EXPECT_GT(browser_id_current_, 0);
|
||||
EXPECT_EQ(browser_id_current_, browser->GetIdentifier());
|
||||
|
||||
// OnOpenURLFromTab should only be called for the file URL.
|
||||
EXPECT_STREQ(GetURL2().c_str(), target_url.ToString().c_str());
|
||||
|
||||
if (mode_ == LOAD)
|
||||
EXPECT_FALSE(user_gesture);
|
||||
else
|
||||
EXPECT_TRUE(user_gesture);
|
||||
|
||||
EXPECT_EQ(WOD_NEW_BACKGROUND_TAB, target_disposition);
|
||||
|
||||
// OnOpenURLFromTab should be called before OnBeforeBrowse for the file URL.
|
||||
EXPECT_FALSE(got_before_browse_);
|
||||
|
||||
got_open_url_from_tab_.yes();
|
||||
|
||||
return cancel_in_open_url_;
|
||||
}
|
||||
|
||||
bool OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) override {
|
||||
EXPECT_EQ(RT_MAIN_FRAME, request->GetResourceType());
|
||||
EXPECT_EQ(TT_EXPLICIT, request->GetTransitionType());
|
||||
if (mode_ == LOAD || request->GetURL() == kLoadNav1)
|
||||
EXPECT_EQ(TT_EXPLICIT, request->GetTransitionType());
|
||||
else
|
||||
EXPECT_EQ(TT_LINK, request->GetTransitionType());
|
||||
|
||||
EXPECT_GT(browser_id_current_, 0);
|
||||
EXPECT_EQ(browser_id_current_, browser->GetIdentifier());
|
||||
|
||||
got_before_resource_load_.yes();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1705,6 +1775,8 @@ class CrossOriginNavTestHandler : public TestHandler {
|
|||
CefRefPtr<CefFrame> frame) override {
|
||||
EXPECT_GT(browser_id_current_, 0);
|
||||
EXPECT_EQ(browser_id_current_, browser->GetIdentifier());
|
||||
|
||||
got_load_start_.yes();
|
||||
}
|
||||
|
||||
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
||||
|
@ -1713,7 +1785,7 @@ class CrossOriginNavTestHandler : public TestHandler {
|
|||
EXPECT_GT(browser_id_current_, 0);
|
||||
EXPECT_EQ(browser_id_current_, browser->GetIdentifier());
|
||||
|
||||
got_load_end_ = true;
|
||||
got_load_end_.yes();
|
||||
ContinueIfReady(browser);
|
||||
}
|
||||
|
||||
|
@ -1725,7 +1797,7 @@ class CrossOriginNavTestHandler : public TestHandler {
|
|||
EXPECT_EQ(browser_id_current_, browser->GetIdentifier());
|
||||
|
||||
const std::string& msg_name = message->GetName();
|
||||
if (msg_name == kCrossOriginNavMsg) {
|
||||
if (msg_name == kLoadNavMsg) {
|
||||
// Test that the renderer side succeeded.
|
||||
CefRefPtr<CefListValue> args = message->GetArgumentList();
|
||||
EXPECT_TRUE(args.get());
|
||||
|
@ -1733,8 +1805,11 @@ class CrossOriginNavTestHandler : public TestHandler {
|
|||
|
||||
EXPECT_EQ(browser_id_current_, args->GetInt(1));
|
||||
|
||||
renderer_load_ct_ = args->GetInt(2);
|
||||
EXPECT_GE(renderer_load_ct_, 1);
|
||||
|
||||
// Continue with the test.
|
||||
got_message_ = true;
|
||||
got_message_.yes();
|
||||
ContinueIfReady(browser);
|
||||
|
||||
return true;
|
||||
|
@ -1744,22 +1819,161 @@ class CrossOriginNavTestHandler : public TestHandler {
|
|||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
int browser_id_current_;
|
||||
void DestroyTest() override {
|
||||
if (cancel_in_open_url_) {
|
||||
EXPECT_FALSE(got_before_browse_);
|
||||
EXPECT_FALSE(got_before_resource_load_);
|
||||
EXPECT_FALSE(got_load_start_);
|
||||
EXPECT_FALSE(got_load_end_);
|
||||
EXPECT_FALSE(got_message_);
|
||||
|
||||
bool got_message_;
|
||||
bool got_load_end_;
|
||||
// We should only navigate a single time if the 2nd load is canceled.
|
||||
EXPECT_EQ(1, renderer_load_ct_);
|
||||
} else {
|
||||
EXPECT_TRUE(got_before_browse_);
|
||||
EXPECT_TRUE(got_before_resource_load_);
|
||||
EXPECT_TRUE(got_load_start_);
|
||||
EXPECT_TRUE(got_load_end_);
|
||||
EXPECT_TRUE(got_message_);
|
||||
|
||||
if (same_origin_) {
|
||||
// The renderer process should always be reused.
|
||||
EXPECT_EQ(2, renderer_load_ct_);
|
||||
} else {
|
||||
if (mode_ == LEFT_CLICK) {
|
||||
// For left click on link the renderer process will be reused.
|
||||
EXPECT_EQ(2, renderer_load_ct_);
|
||||
} else {
|
||||
// Each renderer process is only used for a single navigation.
|
||||
EXPECT_EQ(1, renderer_load_ct_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ExpectOpenURL())
|
||||
EXPECT_TRUE(got_open_url_from_tab_);
|
||||
else
|
||||
EXPECT_FALSE(got_open_url_from_tab_);
|
||||
|
||||
TestHandler::DestroyTest();
|
||||
}
|
||||
|
||||
protected:
|
||||
const TestMode mode_;
|
||||
const bool same_origin_;
|
||||
const bool cancel_in_open_url_;
|
||||
|
||||
int browser_id_current_;
|
||||
int renderer_load_ct_;
|
||||
|
||||
TrackCallback got_before_browse_;
|
||||
TrackCallback got_open_url_from_tab_;
|
||||
TrackCallback got_before_resource_load_;
|
||||
TrackCallback got_load_start_;
|
||||
TrackCallback got_load_end_;
|
||||
TrackCallback got_message_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Verify navigation-related callbacks when browsing cross-origin.
|
||||
TEST(NavigationTest, CrossOrigin) {
|
||||
g_cross_origin_nav_test = true;
|
||||
CefRefPtr<CrossOriginNavTestHandler> handler =
|
||||
new CrossOriginNavTestHandler();
|
||||
// Verify navigation-related callbacks when browsing same-origin via LoadURL().
|
||||
TEST(NavigationTest, SameOriginLoadURL) {
|
||||
CefRefPtr<LoadNavTestHandler> handler =
|
||||
new LoadNavTestHandler(LoadNavTestHandler::LOAD, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Verify navigation-related callbacks when browsing same-origin via left-click.
|
||||
TEST(NavigationTest, SameOriginLeftClick) {
|
||||
CefRefPtr<LoadNavTestHandler> handler =
|
||||
new LoadNavTestHandler(LoadNavTestHandler::LEFT_CLICK, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Verify navigation-related callbacks when browsing same-origin via middle-
|
||||
// click.
|
||||
TEST(NavigationTest, SameOriginMiddleClick) {
|
||||
CefRefPtr<LoadNavTestHandler> handler =
|
||||
new LoadNavTestHandler(LoadNavTestHandler::MIDDLE_CLICK, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Same as above but cancel the 2nd navigation in OnOpenURLFromTab.
|
||||
TEST(NavigationTest, SameOriginMiddleClickCancel) {
|
||||
CefRefPtr<LoadNavTestHandler> handler =
|
||||
new LoadNavTestHandler(LoadNavTestHandler::MIDDLE_CLICK, true, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Verify navigation-related callbacks when browsing same-origin via ctrl+left-
|
||||
// click.
|
||||
TEST(NavigationTest, SameOriginCtrlLeftClick) {
|
||||
CefRefPtr<LoadNavTestHandler> handler =
|
||||
new LoadNavTestHandler(LoadNavTestHandler::CTRL_LEFT_CLICK, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Same as above but cancel the 2nd navigation in OnOpenURLFromTab.
|
||||
TEST(NavigationTest, SameOriginCtrlLeftClickCancel) {
|
||||
CefRefPtr<LoadNavTestHandler> handler =
|
||||
new LoadNavTestHandler(LoadNavTestHandler::CTRL_LEFT_CLICK, true, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Verify navigation-related callbacks when browsing cross-origin via LoadURL().
|
||||
TEST(NavigationTest, CrossOriginLoadURL) {
|
||||
CefRefPtr<LoadNavTestHandler> handler =
|
||||
new LoadNavTestHandler(LoadNavTestHandler::LOAD, false);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Verify navigation-related callbacks when browsing cross-origin via left-
|
||||
// click.
|
||||
TEST(NavigationTest, CrossOriginLeftClick) {
|
||||
CefRefPtr<LoadNavTestHandler> handler =
|
||||
new LoadNavTestHandler(LoadNavTestHandler::LEFT_CLICK, false);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Verify navigation-related callbacks when browsing cross-origin via middle-
|
||||
// click.
|
||||
TEST(NavigationTest, CrossOriginMiddleClick) {
|
||||
CefRefPtr<LoadNavTestHandler> handler =
|
||||
new LoadNavTestHandler(LoadNavTestHandler::MIDDLE_CLICK, false);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Same as above but cancel the 2nd navigation in OnOpenURLFromTab.
|
||||
TEST(NavigationTest, CrossOriginMiddleClickCancel) {
|
||||
CefRefPtr<LoadNavTestHandler> handler =
|
||||
new LoadNavTestHandler(LoadNavTestHandler::MIDDLE_CLICK, false, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Verify navigation-related callbacks when browsing cross-origin via ctrl+left-
|
||||
// click.
|
||||
TEST(NavigationTest, CrossOriginCtrlLeftClick) {
|
||||
CefRefPtr<LoadNavTestHandler> handler =
|
||||
new LoadNavTestHandler(LoadNavTestHandler::CTRL_LEFT_CLICK, false);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Same as above but cancel the 2nd navigation in OnOpenURLFromTab.
|
||||
TEST(NavigationTest, CrossOriginCtrlLeftClickCancel) {
|
||||
CefRefPtr<LoadNavTestHandler> handler =
|
||||
new LoadNavTestHandler(LoadNavTestHandler::CTRL_LEFT_CLICK, false, true);
|
||||
handler->ExecuteTest();
|
||||
g_cross_origin_nav_test = false;
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
|
@ -1805,7 +2019,7 @@ class PopupNavTestHandler : public TestHandler {
|
|||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
const CefString& target_frame_name,
|
||||
WindowOpenDisposition target_disposition,
|
||||
cef_window_open_disposition_t target_disposition,
|
||||
bool user_gesture,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
|
@ -2079,7 +2293,7 @@ TEST(NavigationTest, BrowseDeny) {
|
|||
void CreateNavigationBrowserTests(ClientAppBrowser::DelegateSet& delegates) {
|
||||
delegates.insert(new HistoryNavBrowserTest);
|
||||
delegates.insert(new OrderNavBrowserTest);
|
||||
delegates.insert(new CrossOriginNavBrowserTest);
|
||||
delegates.insert(new LoadNavBrowserTest);
|
||||
}
|
||||
|
||||
// Entry point for creating navigation renderer test objects.
|
||||
|
@ -2087,5 +2301,5 @@ void CreateNavigationBrowserTests(ClientAppBrowser::DelegateSet& delegates) {
|
|||
void CreateNavigationRendererTests(ClientAppRenderer::DelegateSet& delegates) {
|
||||
delegates.insert(new HistoryNavRendererTest);
|
||||
delegates.insert(new OrderNavRendererTest);
|
||||
delegates.insert(new CrossOriginNavRendererTest);
|
||||
delegates.insert(new LoadNavRendererTest);
|
||||
}
|
||||
|
|
|
@ -475,7 +475,7 @@ class PopupTestHandler : public TestHandler {
|
|||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
const CefString& target_frame_name,
|
||||
WindowOpenDisposition target_disposition,
|
||||
cef_window_open_disposition_t target_disposition,
|
||||
bool user_gesture,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
|
|
Loading…
Reference in New Issue