// Copyright (c) 2017 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_EXTENSIONS_EXTENSION_TEST_HANDLER_H_ #define CEF_TESTS_CEFTESTS_EXTENSIONS_EXTENSION_TEST_HANDLER_H_ #pragma once #include #include "include/cef_extension_handler.h" #include "include/cef_values.h" #include "include/wrapper/cef_scoped_temp_dir.h" #include "tests/ceftests/routing_test_handler.h" #include "tests/gtest/include/gtest/gtest.h" class ExtensionTestHandler : public RoutingTestHandler, public CefExtensionHandler { public: // All tests must be able to run with all RequestContext combinations. See the // EXTENSION_TEST_GROUP_* macros below. enum RequestContextType { // If set create a custom context. Otherwise, use the global context. RC_TYPE_FLAG_CUSTOM = 1 << 0, // If set store data on disk. Otherwise, store data in memory. // Requires RC_TYPE_FLAG_CUSTOM. RC_TYPE_FLAG_ON_DISK = 1 << 1, // If set use a handler. Otherwise, don't. RC_TYPE_FLAG_WITH_HANDLER = 1 << 2, // If set load extensions with a different context that shares the same // storage but specifies a different handler. // Excludes RC_TYPE_FLAG_LOAD_WITHOUT_HANDLER. RC_TYPE_FLAG_LOAD_WITH_HANDLER = 1 << 3, // If set load extensions with a different context that shares the same // storage but doesn't specify a handler. // Requires RC_TYPE_FLAG_WITH_HANDLER. // Excludes RC_TYPE_FLAG_LOAD_WITH_HANDLER. RC_TYPE_FLAG_LOAD_WITHOUT_HANDLER = 1 << 4, }; explicit ExtensionTestHandler(RequestContextType request_context_type); virtual ~ExtensionTestHandler(); // TestHandler methods: void RunTest() override; void DestroyTest() override; void OnAfterCreated(CefRefPtr browser) override; // CefExtensionHandler methods: void OnExtensionLoadFailed(cef_errorcode_t result) override; // CefMessageRouterBrowserSide::Handler methods: bool OnQuery(CefRefPtr browser, CefRefPtr frame, int64 query_id, const CefString& request, bool persistent, CefRefPtr callback) override; CefRefPtr request_context() const { return request_context_; } CefRefPtr loader_request_context() const { return loader_request_context_; } bool request_context_is_custom() const { return !!(request_context_type_ & RC_TYPE_FLAG_CUSTOM); } bool request_context_on_disk() const { return !!(request_context_type_ & RC_TYPE_FLAG_ON_DISK); } bool request_context_with_handler() const { return !!(request_context_type_ & RC_TYPE_FLAG_WITH_HANDLER); } bool request_context_load_with_handler() const { return !!(request_context_type_ & RC_TYPE_FLAG_LOAD_WITH_HANDLER); } bool request_context_load_without_handler() const { return !!(request_context_type_ & RC_TYPE_FLAG_LOAD_WITHOUT_HANDLER); } bool request_context_same_loader() const { return !(request_context_load_with_handler() || request_context_load_without_handler()); } protected: // Returns the default extension manifest. typedef std::vector ApiPermissionsList; static CefRefPtr CreateDefaultManifest( const ApiPermissionsList& api_permissions); // Returns the JS code that, when executed, will deliver |message| to the // OnMessage callback. static std::string GetMessageJS(const std::string& message); // Run checks on the state of |extension| in |context|. If |has_access| is // true then |context| is expected to have access to |extension|. If // |is_loader| is true then |context| is expected to have loaded |extension|. static void VerifyExtensionInContext(CefRefPtr extension, CefRefPtr context, bool has_access, bool is_loader); // Helper for loading/unloading an extension. void LoadExtension(const std::string& extension_path, CefRefPtr manifest); void UnloadExtension(CefRefPtr extension); // Release request contexts. This is normally called from DestroyTest(). void ReleaseRequestContexts(); void set_create_main_browser(bool val) { create_main_browser_ = val; } bool create_main_browser() const { return create_main_browser_; } // Called when its time to add resources for the main browser if // |create_main_browser_| is true. virtual void OnAddMainBrowserResources() {} // Called when its time to create the main browser if // |create_main_browser_| is true. virtual void OnCreateMainBrowser() {} // Called when its time to load extensions. virtual void OnLoadExtensions() = 0; // Called when |browser| receives |message|. Return true if the message is // handled. The JS code that sends messages is created by GetMessageJS(). virtual bool OnMessage(CefRefPtr browser, const std::string& message) = 0; // Called to perform verification on test destruction. virtual void OnDestroyTest() = 0; private: const RequestContextType request_context_type_; CefScopedTempDir request_context_temp_dir_; // Context used when creating browsers. CefRefPtr request_context_; // Context used when loading extensions. CefRefPtr loader_request_context_; // If true expect creation of a main browser. Default is true. bool create_main_browser_; DISALLOW_COPY_AND_ASSIGN(ExtensionTestHandler); }; // Helper for implementing an extension test. #define EXTENSION_TEST(name, test_class, rc_type) \ TEST(ExtensionTest, name) { \ CefRefPtr handler = new test_class( \ static_cast(rc_type)); \ handler->ExecuteTest(); \ ReleaseAndWaitForDestructor(handler); \ } // Helper for implementing extension tests that include all RequestContext // combinations. When two or more extension tests significantly overlap in // tested functionality the first test should use the ALL macro and the others // should use the MINIMAL macro. #define EXTENSION_TEST_GROUP_ALL(name, test_class) \ EXTENSION_TEST(name##RCGlobal, test_class, 0) \ EXTENSION_TEST(name##RCGlobalLoadWithHandler, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_LOAD_WITH_HANDLER) \ EXTENSION_TEST(name##RCGlobalWithHandler, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_WITH_HANDLER) \ EXTENSION_TEST(name##RCGlobalWithHandlerLoadWithHandler, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_WITH_HANDLER | \ ExtensionTestHandler::RC_TYPE_FLAG_LOAD_WITH_HANDLER) \ EXTENSION_TEST(name##RCGlobalWithHandlerLoadWithoutHandler, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_WITH_HANDLER | \ ExtensionTestHandler::RC_TYPE_FLAG_LOAD_WITHOUT_HANDLER) \ EXTENSION_TEST(name##RCCustomInMemory, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_CUSTOM) \ EXTENSION_TEST(name##RCCustomInMemoryLoadWithHandler, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_CUSTOM | \ ExtensionTestHandler::RC_TYPE_FLAG_LOAD_WITH_HANDLER) \ EXTENSION_TEST(name##RCCustomInMemoryWithHandler, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_CUSTOM | \ ExtensionTestHandler::RC_TYPE_FLAG_WITH_HANDLER) \ EXTENSION_TEST(name##RCCustomInMemoryWithHandlerLoadWithHandler, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_CUSTOM | \ ExtensionTestHandler::RC_TYPE_FLAG_WITH_HANDLER | \ ExtensionTestHandler::RC_TYPE_FLAG_LOAD_WITH_HANDLER) \ EXTENSION_TEST(name##RCCustomInMemoryWithHandlerLoadWithoutHandler, \ test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_CUSTOM | \ ExtensionTestHandler::RC_TYPE_FLAG_WITH_HANDLER | \ ExtensionTestHandler::RC_TYPE_FLAG_LOAD_WITHOUT_HANDLER) \ EXTENSION_TEST(name##RCCustomOnDisk, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_CUSTOM | \ ExtensionTestHandler::RC_TYPE_FLAG_ON_DISK) \ EXTENSION_TEST(name##RCCustomOnDiskLoadWithHandler, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_CUSTOM | \ ExtensionTestHandler::RC_TYPE_FLAG_ON_DISK | \ ExtensionTestHandler::RC_TYPE_FLAG_LOAD_WITH_HANDLER) \ EXTENSION_TEST(name##RCCustomOnDiskWithHandler, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_CUSTOM | \ ExtensionTestHandler::RC_TYPE_FLAG_ON_DISK | \ ExtensionTestHandler::RC_TYPE_FLAG_WITH_HANDLER) \ EXTENSION_TEST(name##RCCustomOnDiskWithHandlerLoadWithHandler, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_CUSTOM | \ ExtensionTestHandler::RC_TYPE_FLAG_ON_DISK | \ ExtensionTestHandler::RC_TYPE_FLAG_WITH_HANDLER | \ ExtensionTestHandler::RC_TYPE_FLAG_LOAD_WITH_HANDLER) \ EXTENSION_TEST(name##RCCustomOnDiskWithHandlerLoadWithoutHandler, \ test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_CUSTOM | \ ExtensionTestHandler::RC_TYPE_FLAG_ON_DISK | \ ExtensionTestHandler::RC_TYPE_FLAG_WITH_HANDLER | \ ExtensionTestHandler::RC_TYPE_FLAG_LOAD_WITHOUT_HANDLER) #define EXTENSION_TEST_GROUP_MINIMAL_GLOBAL(name, test_class) \ EXTENSION_TEST(name##RCGlobal, test_class, 0) \ EXTENSION_TEST(name##RCGlobalWithHandler, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_WITH_HANDLER) #define EXTENSION_TEST_GROUP_MINIMAL_CUSTOM(name, test_class) \ EXTENSION_TEST(name##RCCustomInMemory, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_CUSTOM) \ EXTENSION_TEST(name##RCCustomInMemoryWithHandler, test_class, \ ExtensionTestHandler::RC_TYPE_FLAG_CUSTOM | \ ExtensionTestHandler::RC_TYPE_FLAG_WITH_HANDLER) // Helper for implementing extension tests that include a minimal set of // RequestContext combinations. This mostly just verifies that the test runs // and doesn't leak state information in the context. #define EXTENSION_TEST_GROUP_MINIMAL(name, test_class) \ EXTENSION_TEST_GROUP_MINIMAL_GLOBAL(name, test_class) \ EXTENSION_TEST_GROUP_MINIMAL_CUSTOM(name, test_class) #endif // CEF_TESTS_CEFTESTS_EXTENSIONS_EXTENSION_TEST_HANDLER_H_