mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Add support for loading extensions (issue #1947)
- Add CefRequestContext::LoadExtension, CefExtension, CefExtensionHandler and related methods/interfaces. - Add chrome://extensions-support that lists supported Chrome APIs. - Add CefBrowserHost::SetAutoResizeEnabled and CefDisplayHandler::OnAutoResize to support browser resize based on preferred web contents size. - views: Add support for custom CefMenuButton popups. - cefclient: Run with `--load-extension=set_page_color` command-line flag for an extension loading example. Add `--use-views` on Windows and Linux for an even better example.
This commit is contained in:
291
tests/ceftests/extensions/background_unittest.cc
Normal file
291
tests/ceftests/extensions/background_unittest.cc
Normal file
@@ -0,0 +1,291 @@
|
||||
// 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.
|
||||
|
||||
#include "tests/ceftests/extensions/extension_test_handler.h"
|
||||
|
||||
#include "tests/ceftests/test_util.h"
|
||||
#include "tests/shared/browser/client_app_browser.h"
|
||||
#include "tests/shared/browser/extension_util.h"
|
||||
|
||||
using client::ClientAppBrowser;
|
||||
|
||||
namespace {
|
||||
|
||||
const char kExtensionPath[] = "background-extension";
|
||||
const char kBackgroundScript[] = "background.js";
|
||||
// HTML file created internally to load the background script.
|
||||
const char kGeneratedBackgroundPage[] = "_generated_background_page.html";
|
||||
|
||||
// Test load/unload of an extension with a background script.
|
||||
class BackgroundLoadUnloadTestHandler : public ExtensionTestHandler {
|
||||
public:
|
||||
explicit BackgroundLoadUnloadTestHandler(
|
||||
RequestContextType request_context_type)
|
||||
: ExtensionTestHandler(request_context_type) {
|
||||
// Only creating the extension browser.
|
||||
set_create_main_browser(false);
|
||||
}
|
||||
|
||||
// CefExtensionHandler methods:
|
||||
void OnExtensionLoaded(CefRefPtr<CefExtension> extension) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||
EXPECT_TRUE(extension);
|
||||
EXPECT_TRUE(extension->IsLoaded());
|
||||
EXPECT_TRUE(extension->GetLoaderContext());
|
||||
EXPECT_TRUE(
|
||||
loader_request_context()->IsSame(extension->GetLoaderContext()));
|
||||
VerifyExtension(extension);
|
||||
|
||||
EXPECT_FALSE(got_loaded_);
|
||||
got_loaded_.yes();
|
||||
|
||||
EXPECT_FALSE(extension_);
|
||||
extension_ = extension;
|
||||
|
||||
background_page_url_ = GetExtensionURL(extension, kGeneratedBackgroundPage);
|
||||
|
||||
// Add extension resources.
|
||||
script_url_ = GetExtensionURL(extension, kBackgroundScript);
|
||||
AddResource(script_url_, GetMessageJS("extension_onload"),
|
||||
"text/javascript");
|
||||
}
|
||||
|
||||
void OnExtensionUnloaded(CefRefPtr<CefExtension> extension) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||
EXPECT_TRUE(extension);
|
||||
EXPECT_FALSE(extension->IsLoaded());
|
||||
EXPECT_FALSE(extension->GetLoaderContext());
|
||||
|
||||
EXPECT_FALSE(got_unloaded_);
|
||||
got_unloaded_.yes();
|
||||
|
||||
EXPECT_TRUE(extension_);
|
||||
EXPECT_TRUE(extension_->IsSame(extension));
|
||||
|
||||
// The extension should no longer be registered with the context.
|
||||
if (loader_request_context())
|
||||
VerifyExtensionInContext(extension, loader_request_context(), false,
|
||||
true);
|
||||
if (request_context() && !request_context_same_loader())
|
||||
VerifyExtensionInContext(extension, request_context(), false, false);
|
||||
|
||||
extension_ = NULL;
|
||||
|
||||
// Execute asynchronously so call stacks have a chance to unwind.
|
||||
// Will close the browser windows.
|
||||
CefPostTask(
|
||||
TID_UI,
|
||||
base::Bind(&BackgroundLoadUnloadTestHandler::DestroyTest, this));
|
||||
}
|
||||
|
||||
bool OnBeforeBackgroundBrowser(CefRefPtr<CefExtension> extension,
|
||||
const CefString& url,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||
EXPECT_TRUE(extension);
|
||||
EXPECT_TRUE(extension->IsLoaded());
|
||||
EXPECT_TRUE(extension->GetLoaderContext());
|
||||
EXPECT_TRUE(
|
||||
loader_request_context()->IsSame(extension->GetLoaderContext()));
|
||||
VerifyExtension(extension);
|
||||
|
||||
const std::string& background_page_url =
|
||||
GetExtensionURL(extension, kGeneratedBackgroundPage);
|
||||
EXPECT_STREQ(background_page_url.c_str(), url.ToString().c_str());
|
||||
|
||||
EXPECT_FALSE(client);
|
||||
client = this;
|
||||
|
||||
// Allow the browser creation.
|
||||
return false;
|
||||
}
|
||||
|
||||
// CefLoadHandler methods:
|
||||
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
|
||||
bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) override {
|
||||
EXPECT_TRUE(browser->GetHost()->IsBackgroundHost());
|
||||
|
||||
CefRefPtr<CefExtension> extension = browser->GetHost()->GetExtension();
|
||||
EXPECT_TRUE(extension);
|
||||
EXPECT_TRUE(extension_->IsSame(extension));
|
||||
|
||||
if (isLoading) {
|
||||
EXPECT_FALSE(extension_browser_);
|
||||
extension_browser_ = browser;
|
||||
} else {
|
||||
EXPECT_TRUE(browser->IsSame(extension_browser_));
|
||||
|
||||
const std::string& url = browser->GetMainFrame()->GetURL();
|
||||
EXPECT_STREQ(background_page_url_.c_str(), url.c_str());
|
||||
|
||||
EXPECT_FALSE(got_load_done_);
|
||||
got_load_done_.yes();
|
||||
|
||||
TriggerDestroyTestIfDone();
|
||||
}
|
||||
}
|
||||
|
||||
// CefRequestHandler methods:
|
||||
CefRefPtr<CefResourceHandler> GetResourceHandler(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) override {
|
||||
EXPECT_TRUE(browser->GetHost()->IsBackgroundHost());
|
||||
EXPECT_TRUE(browser->IsSame(extension_browser_));
|
||||
|
||||
CefRefPtr<CefExtension> extension = browser->GetHost()->GetExtension();
|
||||
EXPECT_TRUE(extension);
|
||||
EXPECT_TRUE(extension_->IsSame(extension));
|
||||
|
||||
const std::string& url = request->GetURL();
|
||||
if (url == background_page_url_) {
|
||||
EXPECT_FALSE(got_background_page_url_request_);
|
||||
got_background_page_url_request_.yes();
|
||||
} else if (url == script_url_) {
|
||||
EXPECT_FALSE(got_script_url_request_);
|
||||
got_script_url_request_.yes();
|
||||
} else {
|
||||
EXPECT_TRUE(false); // Not reached.
|
||||
}
|
||||
|
||||
// Handle the resource request.
|
||||
return RoutingTestHandler::GetResourceHandler(browser, frame, request);
|
||||
}
|
||||
|
||||
CefRefPtr<CefExtension> extension() const { return extension_; }
|
||||
|
||||
// Verify |extension| contents.
|
||||
void VerifyExtension(CefRefPtr<CefExtension> extension) const {
|
||||
EXPECT_STREQ(("extensions/" + std::string(kExtensionPath)).c_str(),
|
||||
client::extension_util::GetInternalExtensionResourcePath(
|
||||
extension->GetPath())
|
||||
.c_str());
|
||||
|
||||
CefRefPtr<CefDictionaryValue> expected_manifest = CreateManifest();
|
||||
TestDictionaryEqual(expected_manifest, extension->GetManifest());
|
||||
|
||||
VerifyExtensionInContext(extension, loader_request_context(), true, true);
|
||||
if (!request_context_same_loader())
|
||||
VerifyExtensionInContext(extension, request_context(), true, false);
|
||||
}
|
||||
|
||||
std::string GetExtensionURL(CefRefPtr<CefExtension> extension,
|
||||
const std::string& resource_path) const {
|
||||
const std::string& identifier = extension->GetIdentifier();
|
||||
const std::string& origin =
|
||||
client::extension_util::GetExtensionOrigin(identifier);
|
||||
EXPECT_FALSE(origin.empty());
|
||||
return origin + resource_path;
|
||||
}
|
||||
|
||||
protected:
|
||||
void OnLoadExtensions() override {
|
||||
LoadExtension(kExtensionPath, CreateManifest());
|
||||
}
|
||||
|
||||
bool OnMessage(CefRefPtr<CefBrowser> browser,
|
||||
const std::string& message) override {
|
||||
EXPECT_STREQ("extension_onload", message.c_str());
|
||||
EXPECT_TRUE(browser->GetHost()->IsBackgroundHost());
|
||||
|
||||
CefRefPtr<CefExtension> extension = browser->GetHost()->GetExtension();
|
||||
EXPECT_TRUE(extension);
|
||||
EXPECT_TRUE(extension_->IsSame(extension));
|
||||
|
||||
EXPECT_TRUE(browser->IsSame(extension_browser_));
|
||||
EXPECT_TRUE(browser->GetHost()->IsBackgroundHost());
|
||||
|
||||
EXPECT_FALSE(got_body_onload_);
|
||||
got_body_onload_.yes();
|
||||
|
||||
TriggerDestroyTestIfDone();
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnDestroyTest() override {
|
||||
extension_browser_ = NULL;
|
||||
|
||||
EXPECT_TRUE(got_loaded_);
|
||||
EXPECT_TRUE(got_background_page_url_request_);
|
||||
EXPECT_TRUE(got_script_url_request_);
|
||||
EXPECT_TRUE(got_body_onload_);
|
||||
EXPECT_TRUE(got_load_done_);
|
||||
EXPECT_TRUE(got_unloaded_);
|
||||
}
|
||||
|
||||
// Create a manifest with background script.
|
||||
CefRefPtr<CefDictionaryValue> CreateManifest() const {
|
||||
CefRefPtr<CefDictionaryValue> manifest =
|
||||
CreateDefaultManifest(ApiPermissionsList());
|
||||
|
||||
CefRefPtr<CefDictionaryValue> background = CefDictionaryValue::Create();
|
||||
CefRefPtr<CefListValue> scripts = CefListValue::Create();
|
||||
scripts->SetString(0, kBackgroundScript);
|
||||
background->SetList("scripts", scripts);
|
||||
manifest->SetDictionary("background", background);
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
||||
void TriggerDestroyTestIfDone() {
|
||||
if (got_body_onload_ && got_load_done_) {
|
||||
TriggerDestroyTest();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TriggerDestroyTest() {
|
||||
// Execute asynchronously so call stacks have a chance to unwind.
|
||||
CefPostTask(TID_UI,
|
||||
base::Bind(&BackgroundLoadUnloadTestHandler::UnloadExtension,
|
||||
this, extension_));
|
||||
}
|
||||
|
||||
CefRefPtr<CefExtension> extension_;
|
||||
std::string script_url_;
|
||||
std::string background_page_url_;
|
||||
CefRefPtr<CefBrowser> extension_browser_;
|
||||
|
||||
TrackCallback got_loaded_;
|
||||
TrackCallback got_background_page_url_request_;
|
||||
TrackCallback got_script_url_request_;
|
||||
TrackCallback got_body_onload_;
|
||||
TrackCallback got_load_done_;
|
||||
TrackCallback got_unloaded_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(BackgroundLoadUnloadTestHandler);
|
||||
DISALLOW_COPY_AND_ASSIGN(BackgroundLoadUnloadTestHandler);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
EXTENSION_TEST_GROUP_ALL(BackgroundLoadUnload, BackgroundLoadUnloadTestHandler);
|
||||
|
||||
namespace {
|
||||
|
||||
// Same as above but without the unload. Only do this with a custom context to
|
||||
// avoid poluting the global context.
|
||||
class BackgroundLoadNoUnloadTestHandler
|
||||
: public BackgroundLoadUnloadTestHandler {
|
||||
public:
|
||||
explicit BackgroundLoadNoUnloadTestHandler(
|
||||
RequestContextType request_context_type)
|
||||
: BackgroundLoadUnloadTestHandler(request_context_type) {}
|
||||
|
||||
protected:
|
||||
void TriggerDestroyTest() override {
|
||||
// Release everything that references the request context. This should
|
||||
// trigger unload of the extension.
|
||||
CloseBrowser(extension_browser_, false);
|
||||
extension_browser_ = NULL;
|
||||
ReleaseRequestContexts();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
EXTENSION_TEST_GROUP_MINIMAL_CUSTOM(BackgroundLoadNoUnload,
|
||||
BackgroundLoadNoUnloadTestHandler);
|
1048
tests/ceftests/extensions/chrome_tabs_unittest.cc
Normal file
1048
tests/ceftests/extensions/chrome_tabs_unittest.cc
Normal file
File diff suppressed because it is too large
Load Diff
240
tests/ceftests/extensions/extension_test_handler.cc
Normal file
240
tests/ceftests/extensions/extension_test_handler.cc
Normal file
@@ -0,0 +1,240 @@
|
||||
// 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.
|
||||
|
||||
#include "tests/ceftests/extensions/extension_test_handler.h"
|
||||
|
||||
#include "tests/ceftests/test_suite.h"
|
||||
#include "tests/ceftests/test_util.h"
|
||||
|
||||
ExtensionTestHandler::ExtensionTestHandler(
|
||||
RequestContextType request_context_type)
|
||||
: request_context_type_(request_context_type), create_main_browser_(true) {
|
||||
// Verify supported flag combinations.
|
||||
if (request_context_on_disk()) {
|
||||
EXPECT_TRUE(request_context_is_custom());
|
||||
}
|
||||
if (request_context_load_with_handler()) {
|
||||
EXPECT_FALSE(request_context_load_without_handler());
|
||||
}
|
||||
if (request_context_load_without_handler()) {
|
||||
EXPECT_TRUE(request_context_with_handler());
|
||||
EXPECT_FALSE(request_context_load_with_handler());
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionTestHandler::~ExtensionTestHandler() {
|
||||
if (!request_context_temp_dir_.IsEmpty()) {
|
||||
// Delete temporary directories on shutdown.
|
||||
CefTestSuite::GetInstance()->RegisterTempDirectory(
|
||||
request_context_temp_dir_.Take());
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionTestHandler::RunTest() {
|
||||
if (create_main_browser_)
|
||||
OnAddMainBrowserResources();
|
||||
|
||||
CefRefPtr<CefRequestContextHandler> rc_handler;
|
||||
if (request_context_with_handler()) {
|
||||
class Handler : public CefRequestContextHandler {
|
||||
public:
|
||||
explicit Handler(ExtensionTestHandler* test_handler)
|
||||
: test_handler_(test_handler) {}
|
||||
|
||||
void OnRequestContextInitialized(
|
||||
CefRefPtr<CefRequestContext> request_context) override {
|
||||
if (test_handler_->create_main_browser()) {
|
||||
// Load extensions after the RequestContext has been initialized by
|
||||
// creation of the main browser.
|
||||
test_handler_->OnLoadExtensions();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ExtensionTestHandler* test_handler_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(Handler);
|
||||
};
|
||||
rc_handler = new Handler(this);
|
||||
}
|
||||
|
||||
if (request_context_is_custom()) {
|
||||
CefRequestContextSettings settings;
|
||||
|
||||
if (request_context_on_disk()) {
|
||||
// Create a new temporary directory.
|
||||
EXPECT_TRUE(request_context_temp_dir_.CreateUniqueTempDir());
|
||||
CefString(&settings.cache_path) = request_context_temp_dir_.GetPath();
|
||||
}
|
||||
|
||||
request_context_ = CefRequestContext::CreateContext(settings, rc_handler);
|
||||
} else {
|
||||
request_context_ = CefRequestContext::CreateContext(
|
||||
CefRequestContext::GetGlobalContext(), rc_handler);
|
||||
}
|
||||
|
||||
if (request_context_load_with_handler()) {
|
||||
class Handler : public CefRequestContextHandler {
|
||||
public:
|
||||
Handler() {}
|
||||
|
||||
private:
|
||||
IMPLEMENT_REFCOUNTING(Handler);
|
||||
};
|
||||
loader_request_context_ =
|
||||
CefRequestContext::CreateContext(request_context_, new Handler());
|
||||
} else if (request_context_load_without_handler()) {
|
||||
loader_request_context_ =
|
||||
CefRequestContext::CreateContext(request_context_, NULL);
|
||||
} else {
|
||||
loader_request_context_ = request_context_;
|
||||
}
|
||||
|
||||
if (create_main_browser_) {
|
||||
OnCreateMainBrowser();
|
||||
} else {
|
||||
// Creation of the extension browser will trigger initialization of the
|
||||
// RequestContext, so just load the extensions now.
|
||||
OnLoadExtensions();
|
||||
}
|
||||
|
||||
// Time out the test after a reasonable period of time.
|
||||
SetTestTimeout();
|
||||
}
|
||||
|
||||
void ExtensionTestHandler::DestroyTest() {
|
||||
OnDestroyTest();
|
||||
ReleaseRequestContexts();
|
||||
RoutingTestHandler::DestroyTest();
|
||||
}
|
||||
|
||||
void ExtensionTestHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
|
||||
RoutingTestHandler::OnAfterCreated(browser);
|
||||
|
||||
if (create_main_browser() && !request_context_with_handler() &&
|
||||
GetBrowserId() == browser->GetIdentifier()) {
|
||||
// When the RequestContext doesn't have a handler we won't get a
|
||||
// notification for RequestContext initialization. Instead use main browser
|
||||
// creation to indicate that the RequestContext has been initialized.
|
||||
OnLoadExtensions();
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionTestHandler::OnExtensionLoadFailed(cef_errorcode_t result) {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||
EXPECT_TRUE(false); // Not reached.
|
||||
}
|
||||
|
||||
// CefMessageRouterBrowserSide::Handler methods:
|
||||
bool ExtensionTestHandler::OnQuery(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id,
|
||||
const CefString& request,
|
||||
bool persistent,
|
||||
CefRefPtr<Callback> callback) {
|
||||
if (OnMessage(browser, request))
|
||||
return true;
|
||||
|
||||
EXPECT_FALSE(true) << "Unexpected message: " << request.ToString();
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
CefRefPtr<CefDictionaryValue> ExtensionTestHandler::CreateDefaultManifest(
|
||||
const std::vector<std::string>& api_permissions) {
|
||||
CefRefPtr<CefDictionaryValue> manifest = CefDictionaryValue::Create();
|
||||
manifest->SetString("name", "An extension");
|
||||
manifest->SetString("description", "An extension description");
|
||||
manifest->SetString("version", "1.0");
|
||||
manifest->SetInt("manifest_version", 2);
|
||||
|
||||
CefRefPtr<CefListValue> permissions = CefListValue::Create();
|
||||
permissions->SetSize(api_permissions.size() + 2);
|
||||
size_t idx = 0;
|
||||
for (; idx < api_permissions.size(); ++idx)
|
||||
permissions->SetString(idx, api_permissions[idx]);
|
||||
|
||||
// Allow access to all http/https origins.
|
||||
permissions->SetString(idx++, "http://*/*");
|
||||
permissions->SetString(idx++, "https://*/*");
|
||||
|
||||
manifest->SetList("permissions", permissions);
|
||||
|
||||
return manifest;
|
||||
}
|
||||
|
||||
// static
|
||||
std::string ExtensionTestHandler::GetMessageJS(const std::string& message) {
|
||||
EXPECT_TRUE(!message.empty());
|
||||
return "window.testQuery({request:'" + message + "'});";
|
||||
}
|
||||
|
||||
// static
|
||||
void ExtensionTestHandler::VerifyExtensionInContext(
|
||||
CefRefPtr<CefExtension> extension,
|
||||
CefRefPtr<CefRequestContext> context,
|
||||
bool has_access,
|
||||
bool is_loader) {
|
||||
const CefString& extension_id = extension->GetIdentifier();
|
||||
EXPECT_FALSE(extension_id.empty());
|
||||
|
||||
if (has_access) {
|
||||
if (is_loader) {
|
||||
EXPECT_TRUE(context->DidLoadExtension(extension_id));
|
||||
} else {
|
||||
EXPECT_FALSE(context->DidLoadExtension(extension_id));
|
||||
}
|
||||
EXPECT_TRUE(context->HasExtension(extension_id));
|
||||
} else {
|
||||
EXPECT_FALSE(context->DidLoadExtension(extension_id));
|
||||
EXPECT_FALSE(context->HasExtension(extension_id));
|
||||
}
|
||||
|
||||
CefRefPtr<CefExtension> extension2 = context->GetExtension(extension_id);
|
||||
if (has_access) {
|
||||
EXPECT_TRUE(extension2);
|
||||
EXPECT_TRUE(extension->IsSame(extension2));
|
||||
TestDictionaryEqual(extension->GetManifest(), extension2->GetManifest());
|
||||
} else {
|
||||
EXPECT_FALSE(extension2);
|
||||
}
|
||||
|
||||
std::vector<CefString> extension_ids;
|
||||
EXPECT_TRUE(context->GetExtensions(extension_ids));
|
||||
|
||||
// Should be our test extension and possibly the builtin PDF extension if it
|
||||
// has finished loading (our extension may load first if the call to
|
||||
// LoadExtension initializes the request context).
|
||||
bool has_extension = false;
|
||||
for (size_t i = 0; i < extension_ids.size(); ++i) {
|
||||
if (extension_ids[i] == extension_id) {
|
||||
has_extension = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (has_access) {
|
||||
EXPECT_TRUE(has_extension);
|
||||
} else {
|
||||
EXPECT_FALSE(has_extension);
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionTestHandler::LoadExtension(
|
||||
const std::string& extension_path,
|
||||
CefRefPtr<CefDictionaryValue> manifest) {
|
||||
EXPECT_TRUE(!extension_path.empty());
|
||||
loader_request_context_->LoadExtension(extension_path, manifest, this);
|
||||
}
|
||||
|
||||
void ExtensionTestHandler::UnloadExtension(CefRefPtr<CefExtension> extension) {
|
||||
EXPECT_TRUE(extension);
|
||||
extension->Unload();
|
||||
EXPECT_FALSE(extension->IsLoaded());
|
||||
EXPECT_FALSE(extension->GetLoaderContext());
|
||||
}
|
||||
|
||||
void ExtensionTestHandler::ReleaseRequestContexts() {
|
||||
request_context_ = NULL;
|
||||
loader_request_context_ = NULL;
|
||||
}
|
238
tests/ceftests/extensions/extension_test_handler.h
Normal file
238
tests/ceftests/extensions/extension_test_handler.h
Normal file
@@ -0,0 +1,238 @@
|
||||
// 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_UNITTESTS_EXTENSIONS_EXTENSION_TEST_HANDLER_H_
|
||||
#define CEF_TESTS_UNITTESTS_EXTENSIONS_EXTENSION_TEST_HANDLER_H_
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#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<CefBrowser> browser) override;
|
||||
|
||||
// CefExtensionHandler methods:
|
||||
void OnExtensionLoadFailed(cef_errorcode_t result) override;
|
||||
|
||||
// CefMessageRouterBrowserSide::Handler methods:
|
||||
bool OnQuery(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id,
|
||||
const CefString& request,
|
||||
bool persistent,
|
||||
CefRefPtr<Callback> callback) override;
|
||||
|
||||
CefRefPtr<CefRequestContext> request_context() const {
|
||||
return request_context_;
|
||||
}
|
||||
CefRefPtr<CefRequestContext> 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<std::string> ApiPermissionsList;
|
||||
static CefRefPtr<CefDictionaryValue> 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<CefExtension> extension,
|
||||
CefRefPtr<CefRequestContext> context,
|
||||
bool has_access,
|
||||
bool is_loader);
|
||||
|
||||
// Helper for loading/unloading an extension.
|
||||
void LoadExtension(const std::string& extension_path,
|
||||
CefRefPtr<CefDictionaryValue> manifest);
|
||||
void UnloadExtension(CefRefPtr<CefExtension> 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<CefBrowser> 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<CefRequestContext> request_context_;
|
||||
|
||||
// Context used when loading extensions.
|
||||
CefRefPtr<CefRequestContext> 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<test_class> handler = new test_class( \
|
||||
static_cast<ExtensionTestHandler::RequestContextType>(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_UNITTESTS_EXTENSIONS_EXTENSION_TEST_HANDLER_H_
|
241
tests/ceftests/extensions/view_unittest.cc
Normal file
241
tests/ceftests/extensions/view_unittest.cc
Normal file
@@ -0,0 +1,241 @@
|
||||
// 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.
|
||||
|
||||
#include "tests/ceftests/extensions/extension_test_handler.h"
|
||||
|
||||
#include "tests/ceftests/test_util.h"
|
||||
#include "tests/shared/browser/extension_util.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const char kExtensionPath[] = "view-extension";
|
||||
|
||||
// Test extension load/unload.
|
||||
class ViewLoadUnloadTestHandler : public ExtensionTestHandler {
|
||||
public:
|
||||
explicit ViewLoadUnloadTestHandler(RequestContextType request_context_type)
|
||||
: ExtensionTestHandler(request_context_type) {
|
||||
// Only creating the extension browser.
|
||||
set_create_main_browser(false);
|
||||
}
|
||||
|
||||
// CefExtensionHandler methods:
|
||||
void OnExtensionLoaded(CefRefPtr<CefExtension> extension) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||
EXPECT_TRUE(extension);
|
||||
EXPECT_TRUE(extension->IsLoaded());
|
||||
EXPECT_TRUE(extension->GetLoaderContext());
|
||||
EXPECT_TRUE(
|
||||
loader_request_context()->IsSame(extension->GetLoaderContext()));
|
||||
VerifyExtension(extension);
|
||||
|
||||
EXPECT_FALSE(got_loaded_);
|
||||
got_loaded_.yes();
|
||||
|
||||
EXPECT_FALSE(extension_);
|
||||
extension_ = extension;
|
||||
|
||||
CreateBrowserForExtension();
|
||||
}
|
||||
|
||||
void OnExtensionUnloaded(CefRefPtr<CefExtension> extension) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||
EXPECT_TRUE(extension);
|
||||
EXPECT_FALSE(extension->IsLoaded());
|
||||
EXPECT_FALSE(extension->GetLoaderContext());
|
||||
|
||||
EXPECT_FALSE(got_unloaded_);
|
||||
got_unloaded_.yes();
|
||||
|
||||
EXPECT_TRUE(extension_);
|
||||
EXPECT_TRUE(extension_->IsSame(extension));
|
||||
|
||||
// The extension should no longer be registered with the context.
|
||||
if (loader_request_context())
|
||||
VerifyExtensionInContext(extension, loader_request_context(), false,
|
||||
true);
|
||||
if (request_context() && !request_context_same_loader())
|
||||
VerifyExtensionInContext(extension, request_context(), false, false);
|
||||
|
||||
extension_ = NULL;
|
||||
|
||||
// Execute asynchronously so call stacks have a chance to unwind.
|
||||
// Will close the browser windows.
|
||||
CefPostTask(TID_UI,
|
||||
base::Bind(&ViewLoadUnloadTestHandler::DestroyTest, this));
|
||||
}
|
||||
|
||||
// CefLoadHandler methods:
|
||||
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
|
||||
bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) override {
|
||||
EXPECT_FALSE(browser->GetHost()->IsBackgroundHost());
|
||||
|
||||
CefRefPtr<CefExtension> extension = browser->GetHost()->GetExtension();
|
||||
EXPECT_TRUE(extension);
|
||||
EXPECT_TRUE(extension_->IsSame(extension));
|
||||
|
||||
if (isLoading) {
|
||||
EXPECT_FALSE(extension_browser_);
|
||||
extension_browser_ = browser;
|
||||
} else {
|
||||
EXPECT_TRUE(browser->IsSame(extension_browser_));
|
||||
|
||||
const std::string& url = browser->GetMainFrame()->GetURL();
|
||||
EXPECT_STREQ(extension_url_.c_str(), url.c_str());
|
||||
|
||||
EXPECT_FALSE(got_load_done_);
|
||||
got_load_done_.yes();
|
||||
|
||||
TriggerDestroyTestIfDone();
|
||||
}
|
||||
}
|
||||
|
||||
// CefRequestHandler methods:
|
||||
CefRefPtr<CefResourceHandler> GetResourceHandler(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) override {
|
||||
EXPECT_FALSE(browser->GetHost()->IsBackgroundHost());
|
||||
EXPECT_TRUE(browser->IsSame(extension_browser_));
|
||||
|
||||
CefRefPtr<CefExtension> extension = browser->GetHost()->GetExtension();
|
||||
EXPECT_TRUE(extension);
|
||||
EXPECT_TRUE(extension_->IsSame(extension));
|
||||
|
||||
const std::string& url = request->GetURL();
|
||||
EXPECT_STREQ(extension_url_.c_str(), url.c_str());
|
||||
|
||||
EXPECT_FALSE(got_url_request_);
|
||||
got_url_request_.yes();
|
||||
|
||||
// Handle the resource request.
|
||||
return RoutingTestHandler::GetResourceHandler(browser, frame, request);
|
||||
}
|
||||
|
||||
protected:
|
||||
void OnLoadExtensions() override {
|
||||
LoadExtension(kExtensionPath, CreateManifest());
|
||||
}
|
||||
|
||||
bool OnMessage(CefRefPtr<CefBrowser> browser,
|
||||
const std::string& message) override {
|
||||
EXPECT_FALSE(browser->GetHost()->IsBackgroundHost());
|
||||
EXPECT_STREQ("extension_onload", message.c_str());
|
||||
|
||||
CefRefPtr<CefExtension> extension = browser->GetHost()->GetExtension();
|
||||
EXPECT_TRUE(extension);
|
||||
EXPECT_TRUE(extension_->IsSame(extension));
|
||||
|
||||
EXPECT_TRUE(browser->IsSame(extension_browser_));
|
||||
|
||||
EXPECT_FALSE(got_body_onload_);
|
||||
got_body_onload_.yes();
|
||||
|
||||
TriggerDestroyTestIfDone();
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnDestroyTest() override {
|
||||
extension_browser_ = NULL;
|
||||
|
||||
EXPECT_TRUE(got_loaded_);
|
||||
EXPECT_TRUE(got_url_request_);
|
||||
EXPECT_TRUE(got_body_onload_);
|
||||
EXPECT_TRUE(got_load_done_);
|
||||
EXPECT_TRUE(got_unloaded_);
|
||||
}
|
||||
|
||||
// Create the default manifest.
|
||||
CefRefPtr<CefDictionaryValue> CreateManifest() const {
|
||||
return CreateDefaultManifest(ApiPermissionsList());
|
||||
}
|
||||
|
||||
// Verify |extension| contents.
|
||||
void VerifyExtension(CefRefPtr<CefExtension> extension) const {
|
||||
EXPECT_STREQ(("extensions/" + std::string(kExtensionPath)).c_str(),
|
||||
client::extension_util::GetInternalExtensionResourcePath(
|
||||
extension->GetPath())
|
||||
.c_str());
|
||||
|
||||
CefRefPtr<CefDictionaryValue> expected_manifest = CreateManifest();
|
||||
TestDictionaryEqual(expected_manifest, extension->GetManifest());
|
||||
|
||||
VerifyExtensionInContext(extension, loader_request_context(), true, true);
|
||||
if (!request_context_same_loader())
|
||||
VerifyExtensionInContext(extension, request_context(), true, false);
|
||||
}
|
||||
|
||||
void CreateBrowserForExtension() {
|
||||
const std::string& identifier = extension_->GetIdentifier();
|
||||
EXPECT_FALSE(identifier.empty());
|
||||
const std::string& origin =
|
||||
client::extension_util::GetExtensionOrigin(identifier);
|
||||
EXPECT_FALSE(origin.empty());
|
||||
|
||||
// Add extension resources.
|
||||
extension_url_ = origin + "extension.html";
|
||||
AddResource(extension_url_,
|
||||
"<html><body onLoad=" + GetMessageJS("extension_onload") +
|
||||
">Extension</body></html>",
|
||||
"text/html");
|
||||
|
||||
// Create a browser to host the extension.
|
||||
CreateBrowser(extension_url_, request_context());
|
||||
}
|
||||
|
||||
void TriggerDestroyTestIfDone() {
|
||||
if (got_body_onload_ && got_load_done_) {
|
||||
TriggerDestroyTest();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TriggerDestroyTest() {
|
||||
// Execute asynchronously so call stacks have a chance to unwind.
|
||||
CefPostTask(TID_UI, base::Bind(&ViewLoadUnloadTestHandler::UnloadExtension,
|
||||
this, extension_));
|
||||
}
|
||||
|
||||
CefRefPtr<CefExtension> extension_;
|
||||
std::string extension_url_;
|
||||
CefRefPtr<CefBrowser> extension_browser_;
|
||||
|
||||
TrackCallback got_loaded_;
|
||||
TrackCallback got_url_request_;
|
||||
TrackCallback got_body_onload_;
|
||||
TrackCallback got_load_done_;
|
||||
TrackCallback got_unloaded_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ViewLoadUnloadTestHandler);
|
||||
DISALLOW_COPY_AND_ASSIGN(ViewLoadUnloadTestHandler);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
EXTENSION_TEST_GROUP_ALL(ViewLoadUnload, ViewLoadUnloadTestHandler);
|
||||
|
||||
namespace {
|
||||
|
||||
// Same as above but without the unload. Only do this with a custom context to
|
||||
// avoid poluting the global context.
|
||||
class ViewLoadNoUnloadTestHandler : public ViewLoadUnloadTestHandler {
|
||||
public:
|
||||
explicit ViewLoadNoUnloadTestHandler(RequestContextType request_context_type)
|
||||
: ViewLoadUnloadTestHandler(request_context_type) {}
|
||||
|
||||
protected:
|
||||
void TriggerDestroyTest() override {
|
||||
// Release everything that references the request context. This should
|
||||
// trigger unload of the extension.
|
||||
CloseBrowser(extension_browser_, false);
|
||||
extension_browser_ = NULL;
|
||||
ReleaseRequestContexts();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
EXTENSION_TEST_GROUP_MINIMAL_CUSTOM(ViewLoadNoUnload,
|
||||
ViewLoadNoUnloadTestHandler);
|
Reference in New Issue
Block a user