mirror of
				https://bitbucket.org/chromiumembedded/cef
				synced 2025-06-05 21:39:12 +02:00 
			
		
		
		
	Add chrome.tabs.create API support (issue #1947)
This commit is contained in:
		| @@ -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. | ||||
| // | ||||
|   | ||||
		Reference in New Issue
	
	Block a user