mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-16 20:20:51 +01:00
Add chrome.tabs.create API support (issue #1947)
This commit is contained in:
parent
3006329678
commit
607a1d9f49
@ -33,7 +33,7 @@
|
||||
// by hand. See the translator.README.txt file in the tools directory for
|
||||
// more information.
|
||||
//
|
||||
// $hash=b49f4c91db8eccdfe9ded503d8bb32ee0e433f60$
|
||||
// $hash=b6311a69fc01fa19d3c49230f412a5963633ce27$
|
||||
//
|
||||
|
||||
#ifndef CEF_INCLUDE_CAPI_CEF_EXTENSION_HANDLER_CAPI_H_
|
||||
@ -129,6 +129,33 @@ typedef struct _cef_extension_handler_t {
|
||||
struct _cef_client_t** client,
|
||||
struct _cef_browser_settings_t* settings);
|
||||
|
||||
///
|
||||
// Called when an extension API (e.g. chrome.tabs.create) requests creation of
|
||||
// a new browser. |extension| and |browser| are the source of the API call.
|
||||
// |active_browser| may optionally be specified via the windowId property or
|
||||
// returned via the get_active_browser() callback and provides the default
|
||||
// |client| and |settings| values for the new browser. |index| is the position
|
||||
// value optionally specified via the index property. |url| is the URL that
|
||||
// will be loaded in the browser. |active| is true (1) if the new browser
|
||||
// should be active when opened. To allow creation of the browser optionally
|
||||
// modify |windowInfo|, |client| and |settings| and return false (0). To
|
||||
// cancel creation of the browser return true (1). Successful creation will be
|
||||
// indicated by a call to cef_life_span_handler_t::OnAfterCreated. Any
|
||||
// modifications to |windowInfo| will be ignored if |active_browser| is
|
||||
// wrapped in a cef_browser_view_t.
|
||||
///
|
||||
int(CEF_CALLBACK* on_before_browser)(
|
||||
struct _cef_extension_handler_t* self,
|
||||
struct _cef_extension_t* extension,
|
||||
struct _cef_browser_t* browser,
|
||||
struct _cef_browser_t* active_browser,
|
||||
int index,
|
||||
const cef_string_t* url,
|
||||
int active,
|
||||
struct _cef_window_info_t* windowInfo,
|
||||
struct _cef_client_t** client,
|
||||
struct _cef_browser_settings_t* settings);
|
||||
|
||||
///
|
||||
// Called when no tabId is specified to an extension API call that accepts a
|
||||
// tabId parameter (e.g. chrome.tabs.*). |extension| and |browser| are the
|
||||
|
@ -116,6 +116,33 @@ class CefExtensionHandler : public virtual CefBaseRefCounted {
|
||||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
// Called when an extension API (e.g. chrome.tabs.create) requests creation of
|
||||
// a new browser. |extension| and |browser| are the source of the API call.
|
||||
// |active_browser| may optionally be specified via the windowId property or
|
||||
// returned via the GetActiveBrowser() callback and provides the default
|
||||
// |client| and |settings| values for the new browser. |index| is the position
|
||||
// value optionally specified via the index property. |url| is the URL that
|
||||
// will be loaded in the browser. |active| is true if the new browser should
|
||||
// be active when opened. To allow creation of the browser optionally modify
|
||||
// |windowInfo|, |client| and |settings| and return false. To cancel creation
|
||||
// of the browser return true. Successful creation will be indicated by a call
|
||||
// to CefLifeSpanHandler::OnAfterCreated. Any modifications to |windowInfo|
|
||||
// will be ignored if |active_browser| is wrapped in a CefBrowserView.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual bool OnBeforeBrowser(CefRefPtr<CefExtension> extension,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefBrowser> active_browser,
|
||||
int index,
|
||||
const CefString& url,
|
||||
bool active,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) {
|
||||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
// Called when no tabId is specified to an extension API call that accepts a
|
||||
// tabId parameter (e.g. chrome.tabs.*). |extension| and |browser| are the
|
||||
|
@ -52,12 +52,49 @@ void ZoomModeToZoomSettings(zoom::ZoomController::ZoomMode zoom_mode,
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void AssignOptionalValue(const std::unique_ptr<T>& source,
|
||||
std::unique_ptr<T>& destination) {
|
||||
if (source.get()) {
|
||||
destination.reset(new T(*source));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ExtensionFunction::ResponseAction TabsGetFunction::Run() {
|
||||
return RespondNow(Error(kNotImplementedError));
|
||||
}
|
||||
|
||||
TabsCreateFunction::TabsCreateFunction() : cef_details_(this) {}
|
||||
|
||||
ExtensionFunction::ResponseAction TabsCreateFunction::Run() {
|
||||
std::unique_ptr<tabs::Create::Params> params(
|
||||
tabs::Create::Params::Create(*args_));
|
||||
EXTENSION_FUNCTION_VALIDATE(params.get());
|
||||
|
||||
CefExtensionFunctionDetails::OpenTabParams options;
|
||||
AssignOptionalValue(params->create_properties.window_id, options.window_id);
|
||||
AssignOptionalValue(params->create_properties.opener_tab_id,
|
||||
options.opener_tab_id);
|
||||
AssignOptionalValue(params->create_properties.selected, options.active);
|
||||
// The 'active' property has replaced the 'selected' property.
|
||||
AssignOptionalValue(params->create_properties.active, options.active);
|
||||
AssignOptionalValue(params->create_properties.pinned, options.pinned);
|
||||
AssignOptionalValue(params->create_properties.index, options.index);
|
||||
AssignOptionalValue(params->create_properties.url, options.url);
|
||||
|
||||
std::string error;
|
||||
std::unique_ptr<base::DictionaryValue> result(
|
||||
cef_details_.OpenTab(options, user_gesture(), &error));
|
||||
if (!result)
|
||||
return RespondNow(Error(error));
|
||||
|
||||
// Return data about the newly created tab.
|
||||
return RespondNow(has_callback() ? OneArgument(std::move(result))
|
||||
: NoArguments());
|
||||
}
|
||||
|
||||
ExecuteCodeInTabFunction::ExecuteCodeInTabFunction()
|
||||
: cef_details_(this), execute_tab_id_(-1) {}
|
||||
|
||||
|
@ -29,6 +29,19 @@ class TabsGetFunction : public UIThreadExtensionFunction {
|
||||
DECLARE_EXTENSION_FUNCTION("tabs.get", TABS_GET)
|
||||
};
|
||||
|
||||
class TabsCreateFunction : public UIThreadExtensionFunction {
|
||||
public:
|
||||
TabsCreateFunction();
|
||||
~TabsCreateFunction() override {}
|
||||
|
||||
ResponseAction Run() override;
|
||||
|
||||
DECLARE_EXTENSION_FUNCTION("tabs.create", TABS_CREATE)
|
||||
|
||||
private:
|
||||
const CefExtensionFunctionDetails cef_details_;
|
||||
};
|
||||
|
||||
// Implement API call tabs.executeScript and tabs.insertCSS.
|
||||
class ExecuteCodeInTabFunction : public ExecuteCodeFunction {
|
||||
public:
|
||||
|
@ -137,7 +137,7 @@ CefRefPtr<CefBrowserHostImpl> GetBrowserForTabId(
|
||||
content::BrowserContext* browser_context) {
|
||||
CEF_REQUIRE_UIT();
|
||||
DCHECK(browser_context);
|
||||
if (tab_id == -1 || !browser_context)
|
||||
if (tab_id < 0 || !browser_context)
|
||||
return nullptr;
|
||||
|
||||
CefBrowserContextImpl* browser_context_impl =
|
||||
|
@ -53,7 +53,7 @@ CefRefPtr<CefBrowserHostImpl> GetOwnerBrowserForHost(
|
||||
bool* is_guest_view);
|
||||
|
||||
// Returns the browser matching |tab_id| and |browser_context|. Returns false if
|
||||
// |tab_id| is -1 or a matching browser cannot be found within
|
||||
// |tab_id| is < 0 or a matching browser cannot be found within
|
||||
// |browser_context|. Similar in concept to ExtensionTabUtil::GetTabById.
|
||||
CefRefPtr<CefBrowserHostImpl> GetBrowserForTabId(
|
||||
int tab_id,
|
||||
|
@ -45,6 +45,7 @@ const char* const kSupportedAPIs[] = {
|
||||
EXTENSION_FUNCTION_NAME(StorageStorageAreaGetBytesInUseFunction),
|
||||
"tabs",
|
||||
EXTENSION_FUNCTION_NAME(cefimpl::TabsGetFunction),
|
||||
EXTENSION_FUNCTION_NAME(cefimpl::TabsCreateFunction),
|
||||
EXTENSION_FUNCTION_NAME(cefimpl::TabsExecuteScriptFunction),
|
||||
EXTENSION_FUNCTION_NAME(cefimpl::TabsInsertCSSFunction),
|
||||
EXTENSION_FUNCTION_NAME(cefimpl::TabsSetZoomFunction),
|
||||
@ -82,6 +83,7 @@ void ChromeFunctionRegistry::RegisterAll(ExtensionFunctionRegistry* registry) {
|
||||
registry->RegisterFunction<cefimpl::TabsExecuteScriptFunction>();
|
||||
registry->RegisterFunction<cefimpl::TabsInsertCSSFunction>();
|
||||
registry->RegisterFunction<cefimpl::TabsGetFunction>();
|
||||
registry->RegisterFunction<cefimpl::TabsCreateFunction>();
|
||||
registry->RegisterFunction<cefimpl::TabsSetZoomFunction>();
|
||||
registry->RegisterFunction<cefimpl::TabsGetZoomFunction>();
|
||||
registry->RegisterFunction<cefimpl::TabsSetZoomSettingsFunction>();
|
||||
|
@ -7,11 +7,16 @@
|
||||
#include "libcef/browser/browser_context_impl.h"
|
||||
#include "libcef/browser/extensions/browser_extensions_util.h"
|
||||
#include "libcef/browser/extensions/extension_system.h"
|
||||
#include "libcef/browser/navigate_params.h"
|
||||
#include "libcef/browser/thread_util.h"
|
||||
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/task_scheduler/post_task.h"
|
||||
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
|
||||
#include "chrome/browser/extensions/extension_tab_util.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "content/public/browser/favicon_status.h"
|
||||
#include "content/public/browser/navigation_entry.h"
|
||||
#include "extensions/browser/extension_function.h"
|
||||
#include "extensions/browser/extension_function_dispatcher.h"
|
||||
#include "extensions/common/error_utils.h"
|
||||
@ -208,13 +213,12 @@ CefRefPtr<CefBrowserHostImpl>
|
||||
CefExtensionFunctionDetails::GetBrowserForTabIdFirstTime(
|
||||
int tab_id,
|
||||
std::string* error_message) const {
|
||||
DCHECK_GE(tab_id, -1);
|
||||
DCHECK(!get_browser_called_first_time_);
|
||||
get_browser_called_first_time_ = true;
|
||||
|
||||
CefRefPtr<CefBrowserHostImpl> browser;
|
||||
|
||||
if (tab_id != -1) {
|
||||
if (tab_id >= 0) {
|
||||
// May be an invalid tabId or in the wrong BrowserContext.
|
||||
browser = GetBrowserForTabId(tab_id, function_->browser_context());
|
||||
if (!browser || !browser->web_contents() || !CanAccessBrowser(browser)) {
|
||||
@ -277,6 +281,184 @@ bool CefExtensionFunctionDetails::LoadFile(const std::string& file,
|
||||
return false;
|
||||
}
|
||||
|
||||
CefExtensionFunctionDetails::OpenTabParams::OpenTabParams() {}
|
||||
|
||||
CefExtensionFunctionDetails::OpenTabParams::~OpenTabParams() {}
|
||||
|
||||
base::DictionaryValue* CefExtensionFunctionDetails::OpenTab(
|
||||
const OpenTabParams& params,
|
||||
bool user_gesture,
|
||||
std::string* error_message) const {
|
||||
CefRefPtr<CefBrowserHostImpl> sender_browser = GetSenderBrowser();
|
||||
if (!sender_browser)
|
||||
return nullptr;
|
||||
|
||||
// windowId defaults to "current" window.
|
||||
int window_id = extension_misc::kCurrentWindowId;
|
||||
if (params.window_id.get())
|
||||
window_id = *params.window_id;
|
||||
|
||||
// CEF doesn't have the concept of windows containing tab strips so we'll
|
||||
// select an "active browser" for BrowserContext sharing instead.
|
||||
CefRefPtr<CefBrowserHostImpl> active_browser =
|
||||
GetBrowserForTabIdFirstTime(window_id, error_message);
|
||||
if (!active_browser)
|
||||
return nullptr;
|
||||
|
||||
// If an opener browser was specified then we expect it to exist.
|
||||
int opener_browser_id = -1;
|
||||
if (params.opener_tab_id.get() && *params.opener_tab_id >= 0) {
|
||||
if (GetBrowserForTabIdAgain(*params.opener_tab_id, error_message)) {
|
||||
opener_browser_id = *params.opener_tab_id;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
GURL url;
|
||||
if (params.url.get()) {
|
||||
std::string url_string = *params.url;
|
||||
url = ExtensionTabUtil::ResolvePossiblyRelativeURL(url_string,
|
||||
function()->extension());
|
||||
if (!url.is_valid()) {
|
||||
if (error_message) {
|
||||
*error_message =
|
||||
ErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, url_string);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't let extensions crash the browser or renderers.
|
||||
if (ExtensionTabUtil::IsKillURL(url)) {
|
||||
if (error_message)
|
||||
*error_message = keys::kNoCrashBrowserError;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Default to foreground for the new tab. The presence of 'active' property
|
||||
// will override this default.
|
||||
bool active = true;
|
||||
if (params.active.get())
|
||||
active = *params.active;
|
||||
|
||||
// CEF doesn't use the index value but we let the client see/modify it.
|
||||
int index = 0;
|
||||
if (params.index.get())
|
||||
index = *params.index;
|
||||
|
||||
CefBrowserContextImpl* browser_context_impl =
|
||||
CefBrowserContextImpl::GetForContext(active_browser->GetBrowserContext());
|
||||
|
||||
// A CEF representation should always exist.
|
||||
CefRefPtr<CefExtension> cef_extension =
|
||||
browser_context_impl->extension_system()->GetExtension(
|
||||
function()->extension()->id());
|
||||
DCHECK(cef_extension);
|
||||
if (!cef_extension)
|
||||
return nullptr;
|
||||
|
||||
// Always use the same request context that the extension was registered with.
|
||||
// May represent an *Impl or *Proxy BrowserContext.
|
||||
// GetLoaderContext() will return NULL for internal extensions.
|
||||
CefRefPtr<CefRequestContext> request_context =
|
||||
cef_extension->GetLoaderContext();
|
||||
if (!request_context)
|
||||
return nullptr;
|
||||
|
||||
CefBrowserHostImpl::CreateParams create_params;
|
||||
create_params.url = url;
|
||||
create_params.request_context = request_context;
|
||||
create_params.window_info.reset(new CefWindowInfo);
|
||||
|
||||
#if defined(OS_WIN)
|
||||
create_params.window_info->SetAsPopup(NULL, CefString());
|
||||
#endif
|
||||
|
||||
// Start with the active browser's settings.
|
||||
create_params.client = active_browser->GetClient();
|
||||
create_params.settings = active_browser->settings();
|
||||
|
||||
CefRefPtr<CefExtensionHandler> handler = cef_extension->GetHandler();
|
||||
if (handler.get() &&
|
||||
handler->OnBeforeBrowser(cef_extension, sender_browser.get(),
|
||||
active_browser.get(), index, url.spec(), active,
|
||||
*create_params.window_info, create_params.client,
|
||||
create_params.settings)) {
|
||||
// Cancel the browser creation.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (active_browser->IsViewsHosted()) {
|
||||
// The new browser will also be Views hosted.
|
||||
create_params.window_info.reset();
|
||||
}
|
||||
|
||||
// Browser creation may fail under certain rare circumstances.
|
||||
CefRefPtr<CefBrowserHostImpl> new_browser =
|
||||
CefBrowserHostImpl::Create(create_params);
|
||||
if (!new_browser)
|
||||
return nullptr;
|
||||
|
||||
// Return data about the newly created tab.
|
||||
auto result = CreateTabObject(new_browser, opener_browser_id, active, index);
|
||||
ExtensionTabUtil::ScrubTabForExtension(
|
||||
function()->extension(), new_browser->web_contents(), result.get());
|
||||
return result->ToValue().release();
|
||||
}
|
||||
|
||||
std::unique_ptr<api::tabs::Tab> CefExtensionFunctionDetails::CreateTabObject(
|
||||
CefRefPtr<CefBrowserHostImpl> new_browser,
|
||||
int opener_browser_id,
|
||||
bool active,
|
||||
int index) const {
|
||||
content::WebContents* contents = new_browser->web_contents();
|
||||
|
||||
bool is_loading = contents->IsLoading();
|
||||
auto tab_object = base::MakeUnique<api::tabs::Tab>();
|
||||
tab_object->id = base::MakeUnique<int>(new_browser->GetIdentifier());
|
||||
tab_object->index = index;
|
||||
tab_object->window_id = *tab_object->id;
|
||||
tab_object->status = base::MakeUnique<std::string>(
|
||||
is_loading ? keys::kStatusValueLoading : keys::kStatusValueComplete);
|
||||
tab_object->active = active;
|
||||
tab_object->selected = true;
|
||||
tab_object->highlighted = true;
|
||||
tab_object->pinned = false;
|
||||
tab_object->audible = base::MakeUnique<bool>(contents->WasRecentlyAudible());
|
||||
tab_object->discarded = false;
|
||||
tab_object->auto_discardable = false;
|
||||
tab_object->muted_info = CreateMutedInfo(contents);
|
||||
tab_object->incognito = false;
|
||||
gfx::Size contents_size = contents->GetContainerBounds().size();
|
||||
tab_object->width = base::MakeUnique<int>(contents_size.width());
|
||||
tab_object->height = base::MakeUnique<int>(contents_size.height());
|
||||
tab_object->url = base::MakeUnique<std::string>(contents->GetURL().spec());
|
||||
tab_object->title =
|
||||
base::MakeUnique<std::string>(base::UTF16ToUTF8(contents->GetTitle()));
|
||||
|
||||
content::NavigationEntry* entry = contents->GetController().GetVisibleEntry();
|
||||
if (entry && entry->GetFavicon().valid) {
|
||||
tab_object->fav_icon_url =
|
||||
base::MakeUnique<std::string>(entry->GetFavicon().url.spec());
|
||||
}
|
||||
|
||||
if (opener_browser_id >= 0)
|
||||
tab_object->opener_tab_id = base::MakeUnique<int>(opener_browser_id);
|
||||
|
||||
return tab_object;
|
||||
}
|
||||
|
||||
// static
|
||||
std::unique_ptr<api::tabs::MutedInfo>
|
||||
CefExtensionFunctionDetails::CreateMutedInfo(content::WebContents* contents) {
|
||||
DCHECK(contents);
|
||||
std::unique_ptr<api::tabs::MutedInfo> info(new api::tabs::MutedInfo);
|
||||
info->muted = contents->IsAudioMuted();
|
||||
// TODO(cef): Maybe populate |info->reason|.
|
||||
return info;
|
||||
}
|
||||
|
||||
CefRefPtr<CefExtension> CefExtensionFunctionDetails::GetCefExtension() const {
|
||||
if (!cef_extension_) {
|
||||
cef_extension_ =
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "base/callback_forward.h"
|
||||
#include "base/macros.h"
|
||||
#include "chrome/common/extensions/api/tabs.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
|
||||
class Profile;
|
||||
@ -64,7 +65,7 @@ class CefExtensionFunctionDetails {
|
||||
bool CanAccessBrowser(CefRefPtr<CefBrowserHostImpl> target) const;
|
||||
|
||||
// Returns the browser matching |tab_id| or NULL if the browser cannot be
|
||||
// found or does not have a WebContents. If |tab_id| is -1 the "current"
|
||||
// found or does not have a WebContents. If |tab_id| is < 0 the "current"
|
||||
// browser will be returned. |error_message| can optionally be passed in and
|
||||
// will be set with an appropriate message on error. This method should only
|
||||
// be called one time per extension function and will check all necessary
|
||||
@ -89,6 +90,40 @@ class CefExtensionFunctionDetails {
|
||||
base::OnceCallback<void(std::unique_ptr<std::string>)>;
|
||||
bool LoadFile(const std::string& file, LoadFileCallback callback) const;
|
||||
|
||||
struct OpenTabParams {
|
||||
OpenTabParams();
|
||||
~OpenTabParams();
|
||||
|
||||
std::unique_ptr<int> window_id;
|
||||
std::unique_ptr<int> opener_tab_id;
|
||||
std::unique_ptr<std::string> url;
|
||||
std::unique_ptr<bool> active;
|
||||
std::unique_ptr<bool> pinned;
|
||||
std::unique_ptr<int> index;
|
||||
};
|
||||
|
||||
// Opens a new tab given creation parameters |params|. Returns a Tab object
|
||||
// if successful, or NULL and optionally sets |error_message| if an error
|
||||
// occurs.
|
||||
base::DictionaryValue* OpenTab(const OpenTabParams& params,
|
||||
bool user_gesture,
|
||||
std::string* error_message) const;
|
||||
|
||||
// Creates a Tab object (see chrome/common/extensions/api/tabs.json) with
|
||||
// information about the state of a browser tab. Depending on the
|
||||
// permissions of the extension, the object may or may not include sensitive
|
||||
// data such as the tab's URL.
|
||||
std::unique_ptr<api::tabs::Tab> CreateTabObject(
|
||||
CefRefPtr<CefBrowserHostImpl> new_browser,
|
||||
int opener_browser_id,
|
||||
bool active,
|
||||
int index) const;
|
||||
|
||||
// Creates a tab MutedInfo object (see chrome/common/extensions/api/tabs.json)
|
||||
// with information about the mute state of a browser tab.
|
||||
static std::unique_ptr<api::tabs::MutedInfo> CreateMutedInfo(
|
||||
content::WebContents* contents);
|
||||
|
||||
// Returns a pointer to the associated UIThreadExtensionFunction
|
||||
UIThreadExtensionFunction* function() { return function_; }
|
||||
const UIThreadExtensionFunction* function() const { return function_; }
|
||||
|
@ -9,7 +9,7 @@
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=a4c5733b13d0513946314faf2ac0745c86419df7$
|
||||
// $hash=05b6fa7134b9e58dcef8262b0b726e4afd6e3512$
|
||||
//
|
||||
|
||||
#include "libcef_dll/cpptoc/extension_handler_cpptoc.h"
|
||||
@ -133,6 +133,92 @@ int CEF_CALLBACK extension_handler_on_before_background_browser(
|
||||
return _retval;
|
||||
}
|
||||
|
||||
int CEF_CALLBACK
|
||||
extension_handler_on_before_browser(struct _cef_extension_handler_t* self,
|
||||
cef_extension_t* extension,
|
||||
cef_browser_t* browser,
|
||||
cef_browser_t* active_browser,
|
||||
int index,
|
||||
const cef_string_t* url,
|
||||
int active,
|
||||
cef_window_info_t* windowInfo,
|
||||
cef_client_t** client,
|
||||
struct _cef_browser_settings_t* settings) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return 0;
|
||||
// Verify param: extension; type: refptr_diff
|
||||
DCHECK(extension);
|
||||
if (!extension)
|
||||
return 0;
|
||||
// Verify param: browser; type: refptr_diff
|
||||
DCHECK(browser);
|
||||
if (!browser)
|
||||
return 0;
|
||||
// Verify param: active_browser; type: refptr_diff
|
||||
DCHECK(active_browser);
|
||||
if (!active_browser)
|
||||
return 0;
|
||||
// Verify param: url; type: string_byref_const
|
||||
DCHECK(url);
|
||||
if (!url)
|
||||
return 0;
|
||||
// Verify param: windowInfo; type: struct_byref
|
||||
DCHECK(windowInfo);
|
||||
if (!windowInfo)
|
||||
return 0;
|
||||
// Verify param: client; type: refptr_same_byref
|
||||
DCHECK(client);
|
||||
if (!client)
|
||||
return 0;
|
||||
// Verify param: settings; type: struct_byref
|
||||
DCHECK(settings);
|
||||
if (!settings)
|
||||
return 0;
|
||||
|
||||
// Translate param: windowInfo; type: struct_byref
|
||||
CefWindowInfo windowInfoObj;
|
||||
if (windowInfo)
|
||||
windowInfoObj.AttachTo(*windowInfo);
|
||||
// Translate param: client; type: refptr_same_byref
|
||||
CefRefPtr<CefClient> clientPtr;
|
||||
if (client && *client)
|
||||
clientPtr = CefClientCppToC::Unwrap(*client);
|
||||
CefClient* clientOrig = clientPtr.get();
|
||||
// Translate param: settings; type: struct_byref
|
||||
CefBrowserSettings settingsObj;
|
||||
if (settings)
|
||||
settingsObj.AttachTo(*settings);
|
||||
|
||||
// Execute
|
||||
bool _retval = CefExtensionHandlerCppToC::Get(self)->OnBeforeBrowser(
|
||||
CefExtensionCToCpp::Wrap(extension), CefBrowserCToCpp::Wrap(browser),
|
||||
CefBrowserCToCpp::Wrap(active_browser), index, CefString(url),
|
||||
active ? true : false, windowInfoObj, clientPtr, settingsObj);
|
||||
|
||||
// Restore param: windowInfo; type: struct_byref
|
||||
if (windowInfo)
|
||||
windowInfoObj.DetachTo(*windowInfo);
|
||||
// Restore param: client; type: refptr_same_byref
|
||||
if (client) {
|
||||
if (clientPtr.get()) {
|
||||
if (clientPtr.get() != clientOrig) {
|
||||
*client = CefClientCppToC::Wrap(clientPtr);
|
||||
}
|
||||
} else {
|
||||
*client = NULL;
|
||||
}
|
||||
}
|
||||
// Restore param: settings; type: struct_byref
|
||||
if (settings)
|
||||
settingsObj.DetachTo(*settings);
|
||||
|
||||
// Return type: bool
|
||||
return _retval;
|
||||
}
|
||||
|
||||
cef_browser_t* CEF_CALLBACK
|
||||
extension_handler_get_active_browser(struct _cef_extension_handler_t* self,
|
||||
cef_extension_t* extension,
|
||||
@ -243,6 +329,7 @@ CefExtensionHandlerCppToC::CefExtensionHandlerCppToC() {
|
||||
GetStruct()->on_extension_unloaded = extension_handler_on_extension_unloaded;
|
||||
GetStruct()->on_before_background_browser =
|
||||
extension_handler_on_before_background_browser;
|
||||
GetStruct()->on_before_browser = extension_handler_on_before_browser;
|
||||
GetStruct()->get_active_browser = extension_handler_get_active_browser;
|
||||
GetStruct()->can_access_browser = extension_handler_can_access_browser;
|
||||
GetStruct()->get_extension_resource =
|
||||
|
@ -9,7 +9,7 @@
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=b8f2ada19624a72741d86b5d6ff5214a4b711dd6$
|
||||
// $hash=0166cbfe3039f90a07fd2d9267178ad1fdb0d4f7$
|
||||
//
|
||||
|
||||
#include "libcef_dll/ctocpp/extension_handler_ctocpp.h"
|
||||
@ -109,6 +109,64 @@ bool CefExtensionHandlerCToCpp::OnBeforeBackgroundBrowser(
|
||||
return _retval ? true : false;
|
||||
}
|
||||
|
||||
bool CefExtensionHandlerCToCpp::OnBeforeBrowser(
|
||||
CefRefPtr<CefExtension> extension,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefBrowser> active_browser,
|
||||
int index,
|
||||
const CefString& url,
|
||||
bool active,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) {
|
||||
cef_extension_handler_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, on_before_browser))
|
||||
return false;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: extension; type: refptr_diff
|
||||
DCHECK(extension.get());
|
||||
if (!extension.get())
|
||||
return false;
|
||||
// Verify param: browser; type: refptr_diff
|
||||
DCHECK(browser.get());
|
||||
if (!browser.get())
|
||||
return false;
|
||||
// Verify param: active_browser; type: refptr_diff
|
||||
DCHECK(active_browser.get());
|
||||
if (!active_browser.get())
|
||||
return false;
|
||||
// Verify param: url; type: string_byref_const
|
||||
DCHECK(!url.empty());
|
||||
if (url.empty())
|
||||
return false;
|
||||
|
||||
// Translate param: client; type: refptr_same_byref
|
||||
cef_client_t* clientStruct = NULL;
|
||||
if (client.get())
|
||||
clientStruct = CefClientCToCpp::Unwrap(client);
|
||||
cef_client_t* clientOrig = clientStruct;
|
||||
|
||||
// Execute
|
||||
int _retval = _struct->on_before_browser(
|
||||
_struct, CefExtensionCppToC::Wrap(extension),
|
||||
CefBrowserCppToC::Wrap(browser), CefBrowserCppToC::Wrap(active_browser),
|
||||
index, url.GetStruct(), active, &windowInfo, &clientStruct, &settings);
|
||||
|
||||
// Restore param:client; type: refptr_same_byref
|
||||
if (clientStruct) {
|
||||
if (clientStruct != clientOrig) {
|
||||
client = CefClientCToCpp::Wrap(clientStruct);
|
||||
}
|
||||
} else {
|
||||
client = NULL;
|
||||
}
|
||||
|
||||
// Return type: bool
|
||||
return _retval ? true : false;
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> CefExtensionHandlerCToCpp::GetActiveBrowser(
|
||||
CefRefPtr<CefExtension> extension,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
|
@ -9,7 +9,7 @@
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=369179037f2f6abc4d30e25099b52acf2f71e1e2$
|
||||
// $hash=0d7d8e2694c5828bb5506fbb5737819b60094428$
|
||||
//
|
||||
|
||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_EXTENSION_HANDLER_CTOCPP_H_
|
||||
@ -43,6 +43,15 @@ class CefExtensionHandlerCToCpp
|
||||
const CefString& url,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) override;
|
||||
bool OnBeforeBrowser(CefRefPtr<CefExtension> extension,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefBrowser> active_browser,
|
||||
int index,
|
||||
const CefString& url,
|
||||
bool active,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) override;
|
||||
CefRefPtr<CefBrowser> GetActiveBrowser(CefRefPtr<CefExtension> extension,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
bool include_incognito) override;
|
||||
|
@ -6,6 +6,8 @@
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "include/cef_parser.h"
|
||||
|
||||
#include "tests/ceftests/test_util.h"
|
||||
#include "tests/shared/browser/extension_util.h"
|
||||
|
||||
@ -291,6 +293,7 @@ class TabsTestHandler : public ExtensionTestHandler {
|
||||
void set_expected_api_call_count(int val) { expected_api_call_count_ = val; }
|
||||
|
||||
bool got_success_message() const { return got_success_message_; }
|
||||
void set_got_success_message() { got_success_message_.yes(); }
|
||||
|
||||
private:
|
||||
void CreateBrowserForExtensionIfReady() {
|
||||
@ -361,6 +364,175 @@ class TabsTestHandler : public ExtensionTestHandler {
|
||||
int got_can_access_browser_count_;
|
||||
};
|
||||
|
||||
//
|
||||
// chrome.tabs.create tests.
|
||||
//
|
||||
|
||||
const char kCreateBrowserURL[] =
|
||||
"https://test-extensions.com/chrome-tabs-create";
|
||||
const char kTabCallbackMessage[] = "tab-callback";
|
||||
const int kCreateTabIndex = 2;
|
||||
|
||||
// Class for chrome.tabs.create tests.
|
||||
class CreateTestHandler : public TabsTestHandler {
|
||||
public:
|
||||
explicit CreateTestHandler(RequestContextType request_context_type)
|
||||
: TabsTestHandler(request_context_type) {}
|
||||
|
||||
bool OnBeforeBrowser(CefRefPtr<CefExtension> extension,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefBrowser> active_browser,
|
||||
int index,
|
||||
const CefString& url,
|
||||
bool foreground,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings) override {
|
||||
EXPECT_TRUE(extension->IsSame(this->extension()));
|
||||
EXPECT_TRUE(browser->IsSame(extension_browser()));
|
||||
EXPECT_TRUE(active_browser->IsSame(main_browser()));
|
||||
EXPECT_EQ(kCreateTabIndex, index);
|
||||
EXPECT_STREQ(kCreateBrowserURL, url.ToString().c_str());
|
||||
EXPECT_TRUE(foreground);
|
||||
EXPECT_TRUE(client);
|
||||
|
||||
EXPECT_FALSE(got_on_before_browser_);
|
||||
got_on_before_browser_.yes();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void OnAddMainBrowserResources() override {
|
||||
AddResource(kCreateBrowserURL, GetCreatedBrowserHTML(), "text/html");
|
||||
|
||||
TabsTestHandler::OnAddMainBrowserResources();
|
||||
}
|
||||
|
||||
void OnLoadingStateChange(CefRefPtr<CefBrowser> browser,
|
||||
bool isLoading,
|
||||
bool canGoBack,
|
||||
bool canGoForward) override {
|
||||
if (extension_browser() && main_browser()) {
|
||||
if (isLoading) {
|
||||
// Keep a reference to the newly created browser.
|
||||
EXPECT_FALSE(created_browser_);
|
||||
created_browser_ = browser;
|
||||
return;
|
||||
} else {
|
||||
const std::string& url = browser->GetMainFrame()->GetURL();
|
||||
if (url == kCreateBrowserURL) {
|
||||
EXPECT_TRUE(browser->IsSame(created_browser_));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TabsTestHandler::OnLoadingStateChange(browser, isLoading, canGoBack,
|
||||
canGoForward);
|
||||
}
|
||||
|
||||
CefRefPtr<CefResourceHandler> GetResourceHandler(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) override {
|
||||
const std::string& url = request->GetURL();
|
||||
if (url == kCreateBrowserURL) {
|
||||
EXPECT_TRUE(browser->IsSame(created_browser_));
|
||||
EXPECT_FALSE(got_create_browser_url_request_);
|
||||
got_create_browser_url_request_.yes();
|
||||
}
|
||||
|
||||
return TabsTestHandler::GetResourceHandler(browser, frame, request);
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string GetTabsApiJS() const override {
|
||||
std::stringstream ss;
|
||||
ss << kCreateTabIndex;
|
||||
|
||||
return "chrome.tabs.create({url: \"" + std::string(kCreateBrowserURL) +
|
||||
"\", index: " + ss.str() +
|
||||
"}, function(tab) { window.testQuery({request:'" +
|
||||
kTabCallbackMessage + ":' + JSON.stringify(tab)}); });";
|
||||
}
|
||||
|
||||
bool OnMessage(CefRefPtr<CefBrowser> browser,
|
||||
const std::string& message) override {
|
||||
if (message.find(kTabCallbackMessage) != std::string::npos) {
|
||||
EXPECT_TRUE(browser->IsSame(extension_browser()));
|
||||
EXPECT_FALSE(got_tab_callback_message_);
|
||||
got_tab_callback_message_.yes();
|
||||
|
||||
// Verify the contents of the Tab object.
|
||||
const std::string& json_str =
|
||||
message.substr(strlen(kTabCallbackMessage) + 1);
|
||||
CefRefPtr<CefValue> obj = CefParseJSON(json_str, JSON_PARSER_RFC);
|
||||
EXPECT_TRUE(obj);
|
||||
EXPECT_EQ(VTYPE_DICTIONARY, obj->GetType());
|
||||
CefRefPtr<CefDictionaryValue> dict = obj->GetDictionary();
|
||||
|
||||
int index = dict->GetInt("index");
|
||||
EXPECT_EQ(kCreateTabIndex, index);
|
||||
|
||||
int id = dict->GetInt("id");
|
||||
int windowId = dict->GetInt("windowId");
|
||||
EXPECT_EQ(created_browser_->GetIdentifier(), id);
|
||||
EXPECT_EQ(created_browser_->GetIdentifier(), windowId);
|
||||
|
||||
const std::string& url = dict->GetString("url");
|
||||
EXPECT_STREQ(kCreateBrowserURL, url.c_str());
|
||||
|
||||
TriggerDestroyTestIfReady();
|
||||
return true;
|
||||
} else if (message == kSuccessMessage) {
|
||||
// Overriding default kSuccessMessage handling.
|
||||
EXPECT_TRUE(browser->IsSame(created_browser_));
|
||||
EXPECT_FALSE(got_success_message());
|
||||
set_got_success_message();
|
||||
TriggerDestroyTestIfReady();
|
||||
return true;
|
||||
}
|
||||
|
||||
return TabsTestHandler::OnMessage(browser, message);
|
||||
}
|
||||
|
||||
void OnDestroyTest() override {
|
||||
created_browser_ = NULL;
|
||||
|
||||
EXPECT_TRUE(got_on_before_browser_);
|
||||
EXPECT_TRUE(got_create_browser_url_request_);
|
||||
EXPECT_TRUE(got_tab_callback_message_);
|
||||
|
||||
TabsTestHandler::OnDestroyTest();
|
||||
}
|
||||
|
||||
private:
|
||||
std::string GetCreatedBrowserHTML() {
|
||||
return "<html><body onLoad=" + GetMessageJS(kSuccessMessage) +
|
||||
">Created</body></html>";
|
||||
}
|
||||
|
||||
void TriggerDestroyTestIfReady() {
|
||||
if (got_tab_callback_message_ && got_success_message())
|
||||
TriggerDestroyTest();
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowser> created_browser_;
|
||||
|
||||
TrackCallback got_on_before_browser_;
|
||||
TrackCallback got_create_browser_url_request_;
|
||||
TrackCallback got_tab_callback_message_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(CreateTestHandler);
|
||||
DISALLOW_COPY_AND_ASSIGN(CreateTestHandler);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TABS_TEST_GROUP_ALL(Create, CreateTestHandler);
|
||||
|
||||
namespace {
|
||||
|
||||
//
|
||||
// chrome.tabs.executeScript tests.
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user