mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-21 22:47:42 +01:00
See the new cef_frame_handler.h for complete usage documentation. This change includes the following related enhancements: - The newly added CefBrowser::IsValid method will return false (in the browser process) after CefLifeSpanHandler::OnBeforeClose is called. - CefBrowser::GetMainFrame will return a valid object (in the browser process) until after CefLifeSpanHandler::OnBeforeClose is called. - The main frame object will change during cross-origin navigation or re-navigation after renderer process termination. During that time, GetMainFrame will return the new/pending frame (in the browser process) and any messages that arrive for the new/pending frame will be correctly attributed in OnProcessMessageReceived. - Commands to be executed in the renderer process that may fail during early frame initialization (ExecuteJavaScript, LoadRequest, etc.) will now be queued until after the JavaScript context for the frame has been created. - Logging has been added for any commands that are dropped because they arrived after frame detachment.
356 lines
13 KiB
C++
356 lines
13 KiB
C++
// Copyright (c) 2013 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_CEFTESTS_TEST_HANDLER_H_
|
|
#define CEF_TESTS_CEFTESTS_TEST_HANDLER_H_
|
|
#pragma once
|
|
|
|
#include <list>
|
|
#include <map>
|
|
#include <string>
|
|
#include <utility>
|
|
|
|
#include "include/base/cef_bind.h"
|
|
#include "include/base/cef_scoped_ptr.h"
|
|
#include "include/cef_browser.h"
|
|
#include "include/cef_client.h"
|
|
#include "include/cef_frame.h"
|
|
#include "include/cef_task.h"
|
|
#include "include/cef_waitable_event.h"
|
|
#include "tests/ceftests/thread_helper.h"
|
|
#include "tests/ceftests/track_callback.h"
|
|
#include "tests/gtest/include/gtest/gtest.h"
|
|
|
|
class ResourceContent {
|
|
public:
|
|
typedef std::multimap<std::string, std::string> HeaderMap;
|
|
|
|
ResourceContent(const std::string& content,
|
|
const std::string& mime_type,
|
|
const HeaderMap& header_map)
|
|
: content_(content), mime_type_(mime_type), header_map_(header_map) {}
|
|
|
|
const std::string& content() const { return content_; }
|
|
const std::string& mimeType() const { return mime_type_; }
|
|
const HeaderMap& headerMap() const { return header_map_; }
|
|
|
|
private:
|
|
std::string content_;
|
|
std::string mime_type_;
|
|
HeaderMap header_map_;
|
|
};
|
|
|
|
// Base implementation of CefClient for unit tests. Add new interfaces as needed
|
|
// by test cases.
|
|
class TestHandler : public CefClient,
|
|
public CefDialogHandler,
|
|
public CefDisplayHandler,
|
|
public CefDownloadHandler,
|
|
public CefJSDialogHandler,
|
|
public CefLifeSpanHandler,
|
|
public CefLoadHandler,
|
|
public CefRequestHandler,
|
|
public CefResourceRequestHandler {
|
|
public:
|
|
// Tracks the completion state of related test runs.
|
|
class CompletionState {
|
|
public:
|
|
// |total| is the number of times that TestComplete() must be called before
|
|
// WaitForTests() will return.
|
|
explicit CompletionState(int total);
|
|
|
|
// Call this method to indicate that a test has completed.
|
|
void TestComplete();
|
|
|
|
// This method blocks until TestComplete() has been called the required
|
|
// number of times.
|
|
void WaitForTests();
|
|
|
|
int total() const { return total_; }
|
|
int count() const { return count_; }
|
|
|
|
private:
|
|
int total_;
|
|
int count_;
|
|
|
|
// Handle used to notify when the test is complete
|
|
CefRefPtr<CefWaitableEvent> event_;
|
|
};
|
|
|
|
// Represents a collection of related tests that need to be run
|
|
// simultaniously.
|
|
class Collection {
|
|
public:
|
|
// The |completion_state| object must outlive this class.
|
|
explicit Collection(CompletionState* completion_state);
|
|
|
|
// The |test_handler| object must outlive this class and it must share the
|
|
// same CompletionState object passed to the constructor.
|
|
void AddTestHandler(TestHandler* test_handler);
|
|
|
|
// Manages the test run.
|
|
// 1. Calls TestHandler::SetupTest() for all of the test objects.
|
|
// 2. Waits for all TestHandler objects to report that initial setup is
|
|
// complete by calling TestHandler::SetupComplete().
|
|
// 3. Calls TestHandler::RunTest() for all of the test objects.
|
|
// 4. Waits for all TestHandler objects to report that the test is
|
|
// complete by calling TestHandler::DestroyTest().
|
|
void ExecuteTests();
|
|
|
|
private:
|
|
CompletionState* completion_state_;
|
|
|
|
typedef std::list<TestHandler*> TestHandlerList;
|
|
TestHandlerList handler_list_;
|
|
};
|
|
|
|
typedef std::map<int, CefRefPtr<CefBrowser>> BrowserMap;
|
|
|
|
// Helper for executing methods using WeakPtr references to TestHandler.
|
|
class UIThreadHelper {
|
|
public:
|
|
UIThreadHelper();
|
|
|
|
// Pass in a |task| with an unretained reference to TestHandler. |task| will
|
|
// be executed only if TestHandler::DestroyTest has not yet been called.
|
|
// For example:
|
|
// GetUIThreadHelper()->PostTask(
|
|
// base::Bind(&TestHandler::DoSomething, base::Unretained(this)));
|
|
void PostTask(const base::Closure& task);
|
|
void PostDelayedTask(const base::Closure& task, int delay_ms);
|
|
|
|
private:
|
|
void TaskHelper(const base::Closure& task);
|
|
|
|
// Must be the last member.
|
|
base::WeakPtrFactory<UIThreadHelper> weak_ptr_factory_;
|
|
};
|
|
|
|
// The |completion_state| object if specified must outlive this class.
|
|
explicit TestHandler(CompletionState* completion_state = nullptr);
|
|
~TestHandler() override;
|
|
|
|
// Implement this method to set up the test. Only used in combination with a
|
|
// Collection. Call SetupComplete() once the setup is complete.
|
|
virtual void SetupTest() {}
|
|
|
|
// Implement this method to run the test. Call DestroyTest() once the test is
|
|
// complete.
|
|
virtual void RunTest() = 0;
|
|
|
|
// CefClient methods. Add new methods as needed by test cases.
|
|
CefRefPtr<CefDialogHandler> GetDialogHandler() override { return this; }
|
|
CefRefPtr<CefDisplayHandler> GetDisplayHandler() override { return this; }
|
|
CefRefPtr<CefDownloadHandler> GetDownloadHandler() override { return this; }
|
|
CefRefPtr<CefJSDialogHandler> GetJSDialogHandler() override { return this; }
|
|
CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }
|
|
CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }
|
|
CefRefPtr<CefRequestHandler> GetRequestHandler() override { return this; }
|
|
|
|
// CefDownloadHandler methods
|
|
void OnBeforeDownload(
|
|
CefRefPtr<CefBrowser> browser,
|
|
CefRefPtr<CefDownloadItem> download_item,
|
|
const CefString& suggested_name,
|
|
CefRefPtr<CefBeforeDownloadCallback> callback) override {}
|
|
|
|
// CefLifeSpanHandler methods
|
|
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
|
|
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
|
|
|
|
// CefRequestHandler methods
|
|
CefRefPtr<CefResourceRequestHandler> GetResourceRequestHandler(
|
|
CefRefPtr<CefBrowser> browser,
|
|
CefRefPtr<CefFrame> frame,
|
|
CefRefPtr<CefRequest> request,
|
|
bool is_navigation,
|
|
bool is_download,
|
|
const CefString& request_initiator,
|
|
bool& disable_default_handling) override {
|
|
return this;
|
|
}
|
|
|
|
// CefResourceRequestHandler methods
|
|
CefRefPtr<CefResourceHandler> GetResourceHandler(
|
|
CefRefPtr<CefBrowser> browser,
|
|
CefRefPtr<CefFrame> frame,
|
|
CefRefPtr<CefRequest> request) override;
|
|
|
|
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
|
|
TerminationStatus status) override;
|
|
|
|
// These methods should only be used if at most one non-popup browser exists.
|
|
CefRefPtr<CefBrowser> GetBrowser() const;
|
|
int GetBrowserId() const;
|
|
|
|
// Copies the map of all the currently existing browsers into |map|. Must be
|
|
// called on the UI thread.
|
|
void GetAllBrowsers(BrowserMap* map);
|
|
|
|
// Called by the test function to execute the test. This method blocks until
|
|
// the test is complete. Do not reference the object after this method
|
|
// returns. Do not use this method if the CompletionState object is shared by
|
|
// multiple handlers or when using a Collection object.
|
|
void ExecuteTest();
|
|
|
|
// Event that will be signaled from the TestHandler destructor.
|
|
// Used by ReleaseAndWaitForDestructor.
|
|
void SetDestroyEvent(CefRefPtr<CefWaitableEvent> event) {
|
|
destroy_event_ = event;
|
|
}
|
|
|
|
// If a test will not call DestroyTest() indicate so using this method.
|
|
void SetDestroyTestExpected(bool expected) {
|
|
destroy_test_expected_ = expected;
|
|
}
|
|
|
|
// Returns true if a browser currently exists.
|
|
static bool HasBrowser() { return browser_count_ > 0; }
|
|
|
|
protected:
|
|
// Indicate that test setup is complete. Only used in combination with a
|
|
// Collection.
|
|
virtual void SetupComplete();
|
|
|
|
// Close any existing non-popup browsers. Test completion will be signaled
|
|
// once all the browsers have closed if
|
|
// |signal_completion_when_all_browsers_close_| is true (default value).
|
|
// If no browsers exist then this method will do nothing and
|
|
// TestComplete() must be called manually.
|
|
virtual void DestroyTest();
|
|
|
|
// Called on the UI thread if the test times out as a result of calling
|
|
// SetTestTimeout(). Calls DestroyTest() by default.
|
|
virtual void OnTestTimeout(int timeout_ms, bool treat_as_error);
|
|
|
|
// Called from CreateBrowser() to optionally set per-browser settings.
|
|
virtual void PopulateBrowserSettings(CefBrowserSettings* settings) {}
|
|
|
|
void CreateBrowser(const CefString& url,
|
|
CefRefPtr<CefRequestContext> request_context = nullptr,
|
|
CefRefPtr<CefDictionaryValue> extra_info = nullptr);
|
|
static void CloseBrowser(CefRefPtr<CefBrowser> browser, bool force_close);
|
|
|
|
void AddResource(const std::string& url,
|
|
const std::string& content,
|
|
const std::string& mime_type);
|
|
|
|
void AddResource(const std::string& url,
|
|
const std::string& content,
|
|
const std::string& mime_type,
|
|
const ResourceContent::HeaderMap& header_map);
|
|
|
|
void AddResourceEx(const std::string& url, const ResourceContent& content);
|
|
|
|
void ClearResources();
|
|
|
|
void SetSignalCompletionWhenAllBrowsersClose(bool val) {
|
|
signal_completion_when_all_browsers_close_ = val;
|
|
}
|
|
bool SignalCompletionWhenAllBrowsersClose() const {
|
|
return signal_completion_when_all_browsers_close_;
|
|
}
|
|
|
|
// Call OnTestTimeout() after the specified amount of time.
|
|
void SetTestTimeout(int timeout_ms = 5000, bool treat_as_error = true);
|
|
|
|
// Signal that the test is complete. This will be called automatically when
|
|
// all existing non-popup browsers are closed if
|
|
// |signal_completion_when_all_browsers_close_| is true (default value). It
|
|
// is an error to call this method before all browsers have closed.
|
|
void TestComplete();
|
|
|
|
// Returns the single UIThreadHelper instance, creating it if necessary. Must
|
|
// be called on the UI thread.
|
|
UIThreadHelper* GetUIThreadHelper();
|
|
|
|
private:
|
|
// Used to notify when the test is complete. Can be accessed on any thread.
|
|
CompletionState* completion_state_;
|
|
bool completion_state_owned_;
|
|
|
|
// Map browser ID to browser object for non-popup browsers. Only accessed on
|
|
// the UI thread.
|
|
BrowserMap browser_map_;
|
|
|
|
// Values for the first created browser. Modified on the UI thread but can be
|
|
// accessed on any thread.
|
|
int first_browser_id_;
|
|
CefRefPtr<CefBrowser> first_browser_;
|
|
|
|
// Map of resources that can be automatically loaded. Only accessed on the
|
|
// IO thread.
|
|
typedef std::map<std::string, ResourceContent> ResourceMap;
|
|
ResourceMap resource_map_;
|
|
|
|
// If true test completion will be signaled when all browsers have closed.
|
|
bool signal_completion_when_all_browsers_close_;
|
|
|
|
CefRefPtr<CefWaitableEvent> destroy_event_;
|
|
|
|
// Tracks whether DestroyTest() is expected or has been called.
|
|
bool destroy_test_expected_;
|
|
bool destroy_test_called_;
|
|
|
|
scoped_ptr<UIThreadHelper> ui_thread_helper_;
|
|
|
|
// Used to track the number of currently existing browser windows.
|
|
static int browser_count_;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(TestHandler);
|
|
};
|
|
|
|
// Release |handler| and wait for the destructor to be called.
|
|
// This function is used to avoid test state leakage and to verify that
|
|
// all Handler references have been released on test completion.
|
|
template <typename T>
|
|
void ReleaseAndWaitForDestructor(CefRefPtr<T>& handler, int delay_ms = 2000) {
|
|
CefRefPtr<CefWaitableEvent> event =
|
|
CefWaitableEvent::CreateWaitableEvent(true, false);
|
|
handler->SetDestroyEvent(event);
|
|
T* _handler_ptr = handler.get();
|
|
handler = nullptr;
|
|
bool handler_destructed = event->TimedWait(delay_ms);
|
|
EXPECT_TRUE(handler_destructed);
|
|
if (!handler_destructed) {
|
|
// |event| is a stack variable so clear the reference before returning.
|
|
_handler_ptr->SetDestroyEvent(nullptr);
|
|
}
|
|
}
|
|
|
|
// Returns true if the currently running test has failed.
|
|
bool TestFailed();
|
|
|
|
// Helper macros for executing checks in a method with a boolean return value.
|
|
// For example:
|
|
//
|
|
// bool VerifyVals(bool a, bool b) {
|
|
// V_DECLARE();
|
|
// V_EXPECT_TRUE(a);
|
|
// V_EXPECT_FALSE(b);
|
|
// V_RETURN();
|
|
// }
|
|
//
|
|
// EXPECT_TRUE(VerifyVals(true, false));
|
|
|
|
#define V_DECLARE() \
|
|
bool __verify = true; \
|
|
bool __result
|
|
|
|
#define V_RETURN() return __verify
|
|
|
|
#define V_EXPECT_TRUE(condition) \
|
|
__result = !!(condition); \
|
|
__verify &= __result; \
|
|
GTEST_TEST_BOOLEAN_(__result, #condition, false, true, \
|
|
GTEST_NONFATAL_FAILURE_)
|
|
|
|
#define V_EXPECT_FALSE(condition) \
|
|
__result = !!(condition); \
|
|
__verify &= !__result; \
|
|
GTEST_TEST_BOOLEAN_(!(__result), #condition, true, false, \
|
|
GTEST_NONFATAL_FAILURE_)
|
|
|
|
#endif // CEF_TESTS_CEFTESTS_TEST_HANDLER_H_
|