#ifndef CEF_TESTS_CEFTESTS_TEST_HANDLER_H_
#define CEF_TESTS_CEFTESTS_TEST_HANDLER_H_
#pragma once
#include <list>
#include <map>
#include <memory>
#include <string>
#include <utility>
#include "include/base/cef_callback.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_;
};
class TestHandler : public CefClient,
public CefDialogHandler,
public CefDisplayHandler,
public CefDownloadHandler,
public CefJSDialogHandler,
public CefLifeSpanHandler,
public CefLoadHandler,
public CefRequestHandler,
public CefResourceRequestHandler {
public:
class CompletionState {
public:
explicit CompletionState(int total);
void TestComplete();
void WaitForTests();
int total() const { return total_; }
int count() const { return count_; }
private:
int total_;
int count_;
CefRefPtr<CefWaitableEvent> event_;
};
class Collection {
public:
explicit Collection(CompletionState* completion_state);
void AddTestHandler(TestHandler* test_handler);
void ExecuteTests();
private:
CompletionState* completion_state_;
typedef std::list<TestHandler*> TestHandlerList;
TestHandlerList handler_list_;
};
typedef std::map<int, CefRefPtr<CefBrowser>> BrowserMap;
class UIThreadHelper {
public:
UIThreadHelper();
void PostTask(base::OnceClosure task);
void PostDelayedTask(base::OnceClosure task, int delay_ms);
private:
void TaskHelper(base::OnceClosure task);
base::WeakPtrFactory<UIThreadHelper> weak_ptr_factory_;
};
explicit TestHandler(CompletionState* completion_state = nullptr);
~TestHandler() override;
virtual void SetupTest() {}
virtual void RunTest() = 0;
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; }
void OnBeforeDownload(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefDownloadItem> download_item,
const CefString& suggested_name,
CefRefPtr<CefBeforeDownloadCallback> callback) override {}
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
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;
}
CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) override;
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) override;
CefRefPtr<CefBrowser> GetBrowser() const;
int GetBrowserId() const;
void GetAllBrowsers(BrowserMap* map);
void ExecuteTest();
void SetDestroyEvent(CefRefPtr<CefWaitableEvent> event) {
destroy_event_ = event;
}
void SetDestroyTestExpected(bool expected) {
destroy_test_expected_ = expected;
}
static bool HasBrowser() { return browser_count_ > 0; }
protected:
virtual void SetupComplete();
virtual void DestroyTest();
virtual void OnTestTimeout(int timeout_ms, bool treat_as_error);
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_;
}
void SetTestTimeout(int timeout_ms = 5000, bool treat_as_error = true);
void TestComplete();
UIThreadHelper* GetUIThreadHelper();
private:
CompletionState* completion_state_;
bool completion_state_owned_;
BrowserMap browser_map_;
int first_browser_id_;
CefRefPtr<CefBrowser> first_browser_;
typedef std::map<std::string, ResourceContent> ResourceMap;
ResourceMap resource_map_;
bool signal_completion_when_all_browsers_close_;
CefRefPtr<CefWaitableEvent> destroy_event_;
bool destroy_test_expected_;
bool destroy_test_called_;
std::unique_ptr<UIThreadHelper> ui_thread_helper_;
static int browser_count_;
DISALLOW_COPY_AND_ASSIGN(TestHandler);
};
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) {
_handler_ptr->SetDestroyEvent(nullptr);
}
}
bool TestFailed();
#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