summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/extensions/api/browser/browser_api.cc36
-rw-r--r--chrome/browser/extensions/api/browser/browser_api.h27
-rw-r--r--chrome/browser/extensions/api/browser/browser_apitest.cc41
-rw-r--r--chrome/browser/extensions/api/tabs/tabs_api.cc203
-rw-r--r--chrome/browser/extensions/extension_tab_util.cc219
-rw-r--r--chrome/browser/extensions/extension_tab_util.h24
-rw-r--r--chrome/chrome_browser_extensions.gypi2
-rw-r--r--chrome/chrome_tests.gypi1
-rw-r--r--chrome/common/extensions/api/_api_features.json4
-rw-r--r--chrome/common/extensions/api/_permission_features.json4
-rw-r--r--chrome/common/extensions/api/api.gyp1
-rw-r--r--chrome/common/extensions/api/browser.idl26
-rw-r--r--chrome/common/extensions/permissions/chrome_api_permissions.cc1
-rw-r--r--chrome/common/extensions/permissions/permission_set_unittest.cc1
-rw-r--r--extensions/browser/extension_function_histogram_value.h1
-rw-r--r--extensions/common/permissions/api_permission.h1
-rw-r--r--tools/metrics/histograms/histograms.xml1
17 files changed, 424 insertions, 169 deletions
diff --git a/chrome/browser/extensions/api/browser/browser_api.cc b/chrome/browser/extensions/api/browser/browser_api.cc
new file mode 100644
index 0000000..7e1a64b
--- /dev/null
+++ b/chrome/browser/extensions/api/browser/browser_api.cc
@@ -0,0 +1,36 @@
+// Copyright 2014 The Chromium 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 "chrome/browser/extensions/api/browser/browser_api.h"
+
+#include "chrome/browser/extensions/extension_tab_util.h"
+
+namespace extensions {
+namespace api {
+
+BrowserOpenTabFunction::~BrowserOpenTabFunction() {
+}
+
+bool BrowserOpenTabFunction::RunSync() {
+ scoped_ptr<browser::OpenTab::Params> params(
+ browser::OpenTab::Params::Create(*args_));
+ EXTENSION_FUNCTION_VALIDATE(params.get());
+
+ ExtensionTabUtil::OpenTabParams options;
+ options.create_browser_if_needed = true;
+ options.url.reset(new std::string(params->options.url));
+
+ std::string error;
+ scoped_ptr<base::DictionaryValue> result(
+ ExtensionTabUtil::OpenTab(this, options, &error));
+ if (!result) {
+ SetError(error);
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace api
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/browser/browser_api.h b/chrome/browser/extensions/api/browser/browser_api.h
new file mode 100644
index 0000000..5707857
--- /dev/null
+++ b/chrome/browser/extensions/api/browser/browser_api.h
@@ -0,0 +1,27 @@
+// Copyright 2014 The Chromium 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 CHROME_BROWSER_EXTENSIONS_API_BROWSER_BROWSER_API_H_
+#define CHROME_BROWSER_EXTENSIONS_API_BROWSER_BROWSER_API_H_
+
+#include "chrome/browser/extensions/chrome_extension_function.h"
+#include "chrome/common/extensions/api/browser.h"
+
+namespace extensions {
+namespace api {
+
+class BrowserOpenTabFunction : public ChromeSyncExtensionFunction {
+ public:
+ DECLARE_EXTENSION_FUNCTION("browser.openTab", BROWSER_OPENTAB)
+
+ protected:
+ virtual ~BrowserOpenTabFunction();
+
+ virtual bool RunSync() OVERRIDE;
+};
+
+} // namespace api
+} // namespace extensions
+
+#endif // CHROME_BROWSER_EXTENSIONS_API_BROWSER_BROWSER_API_H_
diff --git a/chrome/browser/extensions/api/browser/browser_apitest.cc b/chrome/browser/extensions/api/browser/browser_apitest.cc
new file mode 100644
index 0000000..88754b8
--- /dev/null
+++ b/chrome/browser/extensions/api/browser/browser_apitest.cc
@@ -0,0 +1,41 @@
+// Copyright 2014 The Chromium 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 <string>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "chrome/browser/extensions/api/browser/browser_api.h"
+#include "chrome/browser/extensions/extension_function_test_utils.h"
+#include "chrome/test/base/in_process_browser_test.h"
+
+namespace extensions {
+
+namespace utils = extension_function_test_utils;
+
+namespace {
+
+class BrowserApiTest : public InProcessBrowserTest {
+};
+
+}
+
+IN_PROC_BROWSER_TEST_F(BrowserApiTest, OpenTab) {
+ std::string url = "about:blank";
+
+ scoped_refptr<api::BrowserOpenTabFunction> function =
+ new api::BrowserOpenTabFunction();
+ scoped_refptr<Extension> extension(utils::CreateEmptyExtension());
+ function->set_extension(extension.get());
+ base::Value* result = utils::RunFunctionAndReturnSingleResult(
+ function.get(),
+ base::StringPrintf("[{\"url\":\"%s\"}]", url.c_str()),
+ browser());
+
+ // result is currently NULL on success.
+ EXPECT_FALSE(result);
+}
+
+} // namespace extensions
diff --git a/chrome/browser/extensions/api/tabs/tabs_api.cc b/chrome/browser/extensions/api/tabs/tabs_api.cc
index e30904d..e551852 100644
--- a/chrome/browser/extensions/api/tabs/tabs_api.cc
+++ b/chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -68,13 +68,11 @@
#include "extensions/browser/extension_function_util.h"
#include "extensions/browser/extension_host.h"
#include "extensions/browser/file_reader.h"
-#include "extensions/common/constants.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_l10n_util.h"
#include "extensions/common/extension_messages.h"
#include "extensions/common/manifest_constants.h"
-#include "extensions/common/manifest_handlers/incognito_info.h"
#include "extensions/common/message_bundle.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/user_script.h"
@@ -108,52 +106,19 @@ using api::tabs::InjectDetails;
namespace {
-// |error_message| can optionally be passed in a will be set with an appropriate
-// message if the window cannot be found by id.
-Browser* GetBrowserInProfileWithId(Profile* profile,
- const int window_id,
- bool include_incognito,
- std::string* error_message) {
- Profile* incognito_profile =
- include_incognito && profile->HasOffTheRecordProfile() ?
- profile->GetOffTheRecordProfile() : NULL;
- for (chrome::BrowserIterator it; !it.done(); it.Next()) {
- Browser* browser = *it;
- if ((browser->profile() == profile ||
- browser->profile() == incognito_profile) &&
- ExtensionTabUtil::GetWindowId(browser) == window_id &&
- browser->window()) {
- return browser;
- }
- }
-
- if (error_message)
- *error_message = ErrorUtils::FormatErrorMessage(
- keys::kWindowNotFoundError, base::IntToString(window_id));
-
- return NULL;
-}
-
bool GetBrowserFromWindowID(ChromeAsyncExtensionFunction* function,
int window_id,
Browser** browser) {
- if (window_id == extension_misc::kCurrentWindowId) {
- *browser = function->GetCurrentBrowser();
- if (!(*browser) || !(*browser)->window()) {
- function->SetError(keys::kNoCurrentWindowError);
- return false;
- }
- } else {
- std::string error;
- *browser = GetBrowserInProfileWithId(function->GetProfile(),
- window_id,
- function->include_incognito(),
- &error);
- if (!*browser) {
- function->SetError(error);
- return false;
- }
+ std::string error;
+ Browser* result;
+ result =
+ ExtensionTabUtil::GetBrowserFromWindowID(function, window_id, &error);
+ if (!result) {
+ function->SetError(error);
+ return false;
}
+
+ *browser = result;
return true;
}
@@ -185,6 +150,14 @@ bool MatchesBool(bool* boolean, bool value) {
return !boolean || *boolean == value;
}
+template <typename T>
+void AssignOptionalValue(const scoped_ptr<T>& source,
+ scoped_ptr<T>& destination) {
+ if (source.get()) {
+ destination.reset(new T(*source.get()));
+ }
+}
+
} // namespace
// Windows ---------------------------------------------------------------------
@@ -904,137 +877,29 @@ bool TabsCreateFunction::RunSync() {
scoped_ptr<tabs::Create::Params> params(tabs::Create::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
- // windowId defaults to "current" window.
- int window_id = extension_misc::kCurrentWindowId;
- if (params->create_properties.window_id.get())
- window_id = *params->create_properties.window_id;
-
- Browser* browser = NULL;
- if (!GetBrowserFromWindowID(this, window_id, &browser))
- return false;
-
- // Ensure the selected browser is tabbed.
- if (!browser->is_type_tabbed() && browser->IsAttemptingToCloseBrowser())
- browser = chrome::FindTabbedBrowser(
- GetProfile(), include_incognito(), browser->host_desktop_type());
-
- if (!browser || !browser->window())
- return false;
-
- // TODO(jstritar): Add a constant, chrome.tabs.TAB_ID_ACTIVE, that
- // represents the active tab.
- WebContents* opener = NULL;
- if (params->create_properties.opener_tab_id.get()) {
- int opener_id = *params->create_properties.opener_tab_id;
-
- if (!ExtensionTabUtil::GetTabById(opener_id,
- GetProfile(),
- include_incognito(),
- NULL,
- NULL,
- &opener,
- NULL)) {
- return false;
- }
- }
-
- // TODO(rafaelw): handle setting remaining tab properties:
- // -title
- // -favIconUrl
-
- std::string url_string;
- GURL url;
- if (params->create_properties.url.get()) {
- url_string = *params->create_properties.url;
- url = ExtensionTabUtil::ResolvePossiblyRelativeURL(url_string,
- GetExtension());
- if (!url.is_valid()) {
- error_ = ErrorUtils::FormatErrorMessage(keys::kInvalidUrlError,
- url_string);
- return false;
- }
- }
-
- // Don't let extensions crash the browser or renderers.
- if (ExtensionTabUtil::IsCrashURL(url)) {
- error_ = keys::kNoCrashBrowserError;
- return false;
- }
-
- // Default to foreground for the new tab. The presence of 'selected' property
- // will override this default. This property is deprecated ('active' should
- // be used instead).
- bool active = true;
- if (params->create_properties.selected.get())
- active = *params->create_properties.selected;
-
+ ExtensionTabUtil::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.
- if (params->create_properties.active.get())
- active = *params->create_properties.active;
-
- // Default to not pinning the tab. Setting the 'pinned' property to true
- // will override this default.
- bool pinned = false;
- if (params->create_properties.pinned.get())
- pinned = *params->create_properties.pinned;
-
- // We can't load extension URLs into incognito windows unless the extension
- // uses split mode. Special case to fall back to a tabbed window.
- if (url.SchemeIs(kExtensionScheme) &&
- !IncognitoInfo::IsSplitMode(GetExtension()) &&
- browser->profile()->IsOffTheRecord()) {
- Profile* profile = browser->profile()->GetOriginalProfile();
- chrome::HostDesktopType desktop_type = browser->host_desktop_type();
-
- browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
- if (!browser) {
- browser = new Browser(Browser::CreateParams(Browser::TYPE_TABBED,
- profile, desktop_type));
- browser->window()->Show();
- }
+ 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;
+ scoped_ptr<base::DictionaryValue> result(
+ ExtensionTabUtil::OpenTab(this, options, &error));
+ if (!result) {
+ SetError(error);
+ return false;
}
- // If index is specified, honor the value, but keep it bound to
- // -1 <= index <= tab_strip->count() where -1 invokes the default behavior.
- int index = -1;
- if (params->create_properties.index.get())
- index = *params->create_properties.index;
-
- TabStripModel* tab_strip = browser->tab_strip_model();
-
- index = std::min(std::max(index, -1), tab_strip->count());
-
- int add_types = active ? TabStripModel::ADD_ACTIVE :
- TabStripModel::ADD_NONE;
- add_types |= TabStripModel::ADD_FORCE_INDEX;
- if (pinned)
- add_types |= TabStripModel::ADD_PINNED;
- chrome::NavigateParams navigate_params(
- browser, url, content::PAGE_TRANSITION_LINK);
- navigate_params.disposition =
- active ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
- navigate_params.tabstrip_index = index;
- navigate_params.tabstrip_add_types = add_types;
- chrome::Navigate(&navigate_params);
-
- // The tab may have been created in a different window, so make sure we look
- // at the right tab strip.
- tab_strip = navigate_params.browser->tab_strip_model();
- int new_index = tab_strip->GetIndexOfWebContents(
- navigate_params.target_contents);
- if (opener)
- tab_strip->SetOpenerOfWebContentsAt(new_index, opener);
-
- if (active)
- navigate_params.target_contents->GetView()->SetInitialFocus();
-
// Return data about the newly created tab.
if (has_callback()) {
- SetResult(ExtensionTabUtil::CreateTabValue(
- navigate_params.target_contents,
- tab_strip, new_index, GetExtension()));
+ SetResult(result.release());
}
-
return true;
}
diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc
index be7f4c9..1537a33 100644
--- a/chrome/browser/extensions/extension_tab_util.cc
+++ b/chrome/browser/extensions/extension_tab_util.cc
@@ -6,7 +6,9 @@
#include "apps/app_window.h"
#include "apps/app_window_registry.h"
+#include "base/strings/string_number_conversions.h"
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
+#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/extensions/window_controller.h"
#include "chrome/browser/extensions/window_controller_list.h"
@@ -26,8 +28,11 @@
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
+#include "extensions/common/constants.h"
+#include "extensions/common/error_utils.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_constants.h"
+#include "extensions/common/manifest_handlers/incognito_info.h"
#include "extensions/common/permissions/api_permission.h"
#include "extensions/common/permissions/permissions_data.h"
#include "url/gurl.h"
@@ -55,8 +60,222 @@ WindowController* GetAppWindowController(const WebContents* contents) {
app_window->session_id().id());
}
+// |error_message| can optionally be passed in and will be set with an
+// appropriate message if the window cannot be found by id.
+Browser* GetBrowserInProfileWithId(Profile* profile,
+ const int window_id,
+ bool include_incognito,
+ std::string* error_message) {
+ Profile* incognito_profile =
+ include_incognito && profile->HasOffTheRecordProfile()
+ ? profile->GetOffTheRecordProfile()
+ : NULL;
+ for (chrome::BrowserIterator it; !it.done(); it.Next()) {
+ Browser* browser = *it;
+ if ((browser->profile() == profile ||
+ browser->profile() == incognito_profile) &&
+ ExtensionTabUtil::GetWindowId(browser) == window_id &&
+ browser->window()) {
+ return browser;
+ }
+ }
+
+ if (error_message)
+ *error_message = ErrorUtils::FormatErrorMessage(
+ keys::kWindowNotFoundError, base::IntToString(window_id));
+
+ return NULL;
+}
+
+Browser* CreateBrowser(ChromeAsyncExtensionFunction* function,
+ int window_id,
+ std::string* error) {
+ content::WebContents* web_contents = function->GetAssociatedWebContents();
+ DCHECK(web_contents);
+ DCHECK(web_contents->GetView());
+ DCHECK(web_contents->GetView()->GetNativeView());
+ DCHECK(!chrome::FindBrowserWithWebContents(web_contents));
+
+ chrome::HostDesktopType desktop_type =
+ chrome::GetHostDesktopTypeForNativeView(
+ web_contents->GetView()->GetNativeView());
+ Browser::CreateParams params(
+ Browser::TYPE_TABBED, function->GetProfile(), desktop_type);
+ Browser* browser = new Browser(params);
+ browser->window()->Show();
+ return browser;
+}
+
} // namespace
+ExtensionTabUtil::OpenTabParams::OpenTabParams()
+ : create_browser_if_needed(false) {
+}
+
+ExtensionTabUtil::OpenTabParams::~OpenTabParams() {
+}
+
+// Opens a new tab for a given extension. Returns NULL and sets |error| if an
+// error occurs.
+base::DictionaryValue* ExtensionTabUtil::OpenTab(
+ ChromeAsyncExtensionFunction* function,
+ const OpenTabParams& params,
+ std::string* error) {
+ // windowId defaults to "current" window.
+ int window_id = extension_misc::kCurrentWindowId;
+ if (params.window_id.get())
+ window_id = *params.window_id;
+
+ Browser* browser = GetBrowserFromWindowID(function, window_id, error);
+ if (!browser) {
+ if (!params.create_browser_if_needed) {
+ return NULL;
+ }
+ browser = CreateBrowser(function, window_id, error);
+ if (!browser)
+ return NULL;
+ }
+
+ // Ensure the selected browser is tabbed.
+ if (!browser->is_type_tabbed() && browser->IsAttemptingToCloseBrowser())
+ browser = chrome::FindTabbedBrowser(function->GetProfile(),
+ function->include_incognito(),
+ browser->host_desktop_type());
+
+ if (!browser || !browser->window()) {
+ // TODO(rpaquay): Error message?
+ return NULL;
+ }
+
+ // TODO(jstritar): Add a constant, chrome.tabs.TAB_ID_ACTIVE, that
+ // represents the active tab.
+ WebContents* opener = NULL;
+ if (params.opener_tab_id.get()) {
+ int opener_id = *params.opener_tab_id;
+
+ if (!ExtensionTabUtil::GetTabById(opener_id,
+ function->GetProfile(),
+ function->include_incognito(),
+ NULL,
+ NULL,
+ &opener,
+ NULL)) {
+ // TODO(rpaquay): Error message?
+ return NULL;
+ }
+ }
+
+ // TODO(rafaelw): handle setting remaining tab properties:
+ // -title
+ // -favIconUrl
+
+ std::string url_string;
+ GURL url;
+ if (params.url.get()) {
+ url_string = *params.url;
+ url = ExtensionTabUtil::ResolvePossiblyRelativeURL(
+ url_string, function->GetExtension());
+ if (!url.is_valid()) {
+ *error =
+ ErrorUtils::FormatErrorMessage(keys::kInvalidUrlError, url_string);
+ return NULL;
+ }
+ }
+
+ // Don't let extensions crash the browser or renderers.
+ if (ExtensionTabUtil::IsCrashURL(url)) {
+ *error = keys::kNoCrashBrowserError;
+ return NULL;
+ }
+
+ // 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;
+
+ // Default to not pinning the tab. Setting the 'pinned' property to true
+ // will override this default.
+ bool pinned = false;
+ if (params.pinned.get())
+ pinned = *params.pinned;
+
+ // We can't load extension URLs into incognito windows unless the extension
+ // uses split mode. Special case to fall back to a tabbed window.
+ if (url.SchemeIs(kExtensionScheme) &&
+ !IncognitoInfo::IsSplitMode(function->GetExtension()) &&
+ browser->profile()->IsOffTheRecord()) {
+ Profile* profile = browser->profile()->GetOriginalProfile();
+ chrome::HostDesktopType desktop_type = browser->host_desktop_type();
+
+ browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
+ if (!browser) {
+ browser = new Browser(
+ Browser::CreateParams(Browser::TYPE_TABBED, profile, desktop_type));
+ browser->window()->Show();
+ }
+ }
+
+ // If index is specified, honor the value, but keep it bound to
+ // -1 <= index <= tab_strip->count() where -1 invokes the default behavior.
+ int index = -1;
+ if (params.index.get())
+ index = *params.index;
+
+ TabStripModel* tab_strip = browser->tab_strip_model();
+
+ index = std::min(std::max(index, -1), tab_strip->count());
+
+ int add_types = active ? TabStripModel::ADD_ACTIVE : TabStripModel::ADD_NONE;
+ add_types |= TabStripModel::ADD_FORCE_INDEX;
+ if (pinned)
+ add_types |= TabStripModel::ADD_PINNED;
+ chrome::NavigateParams navigate_params(
+ browser, url, content::PAGE_TRANSITION_LINK);
+ navigate_params.disposition =
+ active ? NEW_FOREGROUND_TAB : NEW_BACKGROUND_TAB;
+ navigate_params.tabstrip_index = index;
+ navigate_params.tabstrip_add_types = add_types;
+ chrome::Navigate(&navigate_params);
+
+ // The tab may have been created in a different window, so make sure we look
+ // at the right tab strip.
+ tab_strip = navigate_params.browser->tab_strip_model();
+ int new_index =
+ tab_strip->GetIndexOfWebContents(navigate_params.target_contents);
+ if (opener)
+ tab_strip->SetOpenerOfWebContentsAt(new_index, opener);
+
+ if (active)
+ navigate_params.target_contents->GetView()->SetInitialFocus();
+
+ // Return data about the newly created tab.
+ return ExtensionTabUtil::CreateTabValue(navigate_params.target_contents,
+ tab_strip,
+ new_index,
+ function->GetExtension());
+}
+
+Browser* ExtensionTabUtil::GetBrowserFromWindowID(
+ ChromeAsyncExtensionFunction* function,
+ int window_id,
+ std::string* error) {
+ if (window_id == extension_misc::kCurrentWindowId) {
+ Browser* result = function->GetCurrentBrowser();
+ if (!result || !result->window()) {
+ if (error)
+ *error = keys::kNoCurrentWindowError;
+ return NULL;
+ }
+ return result;
+ } else {
+ return GetBrowserInProfileWithId(function->GetProfile(),
+ window_id,
+ function->include_incognito(),
+ error);
+ }
+}
+
int ExtensionTabUtil::GetWindowId(const Browser* browser) {
return browser->session_id().id();
}
diff --git a/chrome/browser/extensions/extension_tab_util.h b/chrome/browser/extensions/extension_tab_util.h
index 0b3092a..bbf042b 100644
--- a/chrome/browser/extensions/extension_tab_util.h
+++ b/chrome/browser/extensions/extension_tab_util.h
@@ -12,6 +12,7 @@
#include "ui/base/window_open_disposition.h"
class Browser;
+class ChromeAsyncExtensionFunction;
class GURL;
class Profile;
class TabStripModel;
@@ -36,6 +37,26 @@ class WindowController;
// Provides various utility functions that help manipulate tabs.
class ExtensionTabUtil {
public:
+ struct OpenTabParams {
+ OpenTabParams();
+ ~OpenTabParams();
+
+ bool create_browser_if_needed;
+ scoped_ptr<int> window_id;
+ scoped_ptr<int> opener_tab_id;
+ scoped_ptr<std::string> url;
+ scoped_ptr<bool> active;
+ scoped_ptr<bool> pinned;
+ scoped_ptr<int> index;
+ };
+
+ // Opens a new tab given an extension function |function| and creation
+ // parameters |params|. Returns a Tab object if successful, or NULL and
+ // optionally sets |error| if an error occurs.
+ static base::DictionaryValue* OpenTab(ChromeAsyncExtensionFunction* function,
+ const OpenTabParams& params,
+ std::string* error);
+
static int GetWindowId(const Browser* browser);
static int GetWindowIdOfTabStripModel(const TabStripModel* tab_strip_model);
static int GetTabId(const content::WebContents* web_contents);
@@ -43,6 +64,9 @@ class ExtensionTabUtil {
static int GetWindowIdOfTab(const content::WebContents* web_contents);
static base::ListValue* CreateTabList(const Browser* browser,
const Extension* extension);
+ static Browser* GetBrowserFromWindowID(ChromeAsyncExtensionFunction* function,
+ int window_id,
+ std::string* error_message);
// Creates a Tab object (see chrome/common/extensions/api/tabs.json) with
// information about the state of a browser tab. Depending on the
diff --git a/chrome/chrome_browser_extensions.gypi b/chrome/chrome_browser_extensions.gypi
index 779f594..c740c77 100644
--- a/chrome/chrome_browser_extensions.gypi
+++ b/chrome/chrome_browser_extensions.gypi
@@ -184,6 +184,8 @@
'browser/extensions/api/braille_display_private/brlapi_connection.h',
'browser/extensions/api/braille_display_private/stub_braille_controller.cc',
'browser/extensions/api/braille_display_private/stub_braille_controller.h',
+ 'browser/extensions/api/browser/browser_api.cc',
+ 'browser/extensions/api/browser/browser_api.h',
'browser/extensions/api/browsing_data/browsing_data_api.cc',
'browser/extensions/api/browsing_data/browsing_data_api.h',
'browser/extensions/api/capture_web_contents_function.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 15e8b08..8fd2444 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1001,6 +1001,7 @@
'browser/extensions/api/braille_display_private/braille_display_private_apitest.cc',
'browser/extensions/api/braille_display_private/mock_braille_controller.cc',
'browser/extensions/api/braille_display_private/mock_braille_controller.h',
+ 'browser/extensions/api/browser/browser_apitest.cc',
'browser/extensions/api/bookmarks/bookmark_apitest.cc',
'browser/extensions/api/browsing_data/browsing_data_test.cc',
'browser/extensions/api/cast_channel/cast_channel_apitest.cc',
diff --git a/chrome/common/extensions/api/_api_features.json b/chrome/common/extensions/api/_api_features.json
index e1775c4..ba3a54f 100644
--- a/chrome/common/extensions/api/_api_features.json
+++ b/chrome/common/extensions/api/_api_features.json
@@ -140,6 +140,10 @@
"dependencies": ["permission:brailleDisplayPrivate"],
"contexts": ["blessed_extension"]
},
+ "browser": {
+ "dependencies": ["permission:browser"],
+ "contexts": ["blessed_extension"]
+ },
"browserAction": {
"dependencies": ["manifest:browser_action"],
"contexts": ["blessed_extension"]
diff --git a/chrome/common/extensions/api/_permission_features.json b/chrome/common/extensions/api/_permission_features.json
index fb979c4..8b63d30 100644
--- a/chrome/common/extensions/api/_permission_features.json
+++ b/chrome/common/extensions/api/_permission_features.json
@@ -152,6 +152,10 @@
"extension_types": ["extension", "legacy_packaged_app", "platform_app"],
"location": "component"
},
+ "browser": {
+ "channel": "dev",
+ "extension_types": ["platform_app"]
+ },
"browsingData": {
"channel": "stable",
"extension_types": ["extension", "legacy_packaged_app"]
diff --git a/chrome/common/extensions/api/api.gyp b/chrome/common/extensions/api/api.gyp
index 7ba5fa1..6a20fa5 100644
--- a/chrome/common/extensions/api/api.gyp
+++ b/chrome/common/extensions/api/api.gyp
@@ -50,6 +50,7 @@
'bluetooth_socket.idl',
'bookmark_manager_private.json',
'bookmarks.json',
+ 'browser.idl',
'braille_display_private.idl',
'cast_channel.idl',
'cloud_print_private.json',
diff --git a/chrome/common/extensions/api/browser.idl b/chrome/common/extensions/api/browser.idl
new file mode 100644
index 0000000..99515dc
--- /dev/null
+++ b/chrome/common/extensions/api/browser.idl
@@ -0,0 +1,26 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Use the <code>chrome.browser</code> API to interact with the Chrome browser
+// associated with the current application and Chrome profile.
+[nodoc] namespace browser {
+ // Options for the $(ref:openTab) function.
+ dictionary OpenTabOptions {
+ // The URL to navigate to when the new tab is initially opened.
+ DOMString url;
+ };
+
+ callback Callback = void();
+
+ interface Functions {
+ // Opens a new tab in a browser window associated with the current
+ // application and Chrome profile. If no browser window for the Chrome
+ // profile is opened, a new one is opened prior to creating the new tab. The
+ // initial URL of the new tab is specified in |options|.
+ // |options| : The $(ref:OpenTabOptions) for this function.
+ // |callback| : Called to indicate success or failure.
+ static void openTab(OpenTabOptions options,
+ Callback callback);
+ };
+};
diff --git a/chrome/common/extensions/permissions/chrome_api_permissions.cc b/chrome/common/extensions/permissions/chrome_api_permissions.cc
index f999969..b815ffd 100644
--- a/chrome/common/extensions/permissions/chrome_api_permissions.cc
+++ b/chrome/common/extensions/permissions/chrome_api_permissions.cc
@@ -368,6 +368,7 @@ std::vector<APIPermissionInfo*> ChromeAPIPermissions::GetAllPermissions()
{APIPermission::kOverrideEscFullscreen,
"app.window.fullscreen.overrideEsc"},
{APIPermission::kWindowShape, "app.window.shape"},
+ {APIPermission::kBrowser, "browser"},
// Settings override permissions.
{APIPermission::kHomepage, "homepage",
diff --git a/chrome/common/extensions/permissions/permission_set_unittest.cc b/chrome/common/extensions/permissions/permission_set_unittest.cc
index 7884a2c..967de7b 100644
--- a/chrome/common/extensions/permissions/permission_set_unittest.cc
+++ b/chrome/common/extensions/permissions/permission_set_unittest.cc
@@ -751,6 +751,7 @@ TEST(PermissionsTest, PermissionMessages) {
skip.insert(APIPermission::kDevtools);
// Platform apps.
+ skip.insert(APIPermission::kBrowser);
skip.insert(APIPermission::kFileSystem);
skip.insert(APIPermission::kFileSystemProvider);
skip.insert(APIPermission::kFileSystemRetainEntries);
diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h
index 90f8d7f..10665898 100644
--- a/extensions/browser/extension_function_histogram_value.h
+++ b/extensions/browser/extension_function_histogram_value.h
@@ -810,6 +810,7 @@ enum HistogramValue {
SHELL_CREATEWINDOW,
FILESYSTEMPROVIDERINTERNAL_GETMETADATAREQUESTEDSUCCESS,
FILESYSTEMPROVIDERINTERNAL_GETMETADATAREQUESTEDERROR,
+ BROWSER_OPENTAB,
// Last entry: Add new entries above and ensure to update
// tools/metrics/histograms/histograms/histograms.xml.
ENUM_BOUNDARY
diff --git a/extensions/common/permissions/api_permission.h b/extensions/common/permissions/api_permission.h
index a660f79..487cb2c 100644
--- a/extensions/common/permissions/api_permission.h
+++ b/extensions/common/permissions/api_permission.h
@@ -174,6 +174,7 @@ class APIPermission {
kSystemInfoCpu,
kSystemInfoMemory,
kFirstRunPrivate,
+ kBrowser,
kEnumBoundary
};
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml
index e51d519..53995d0 100644
--- a/tools/metrics/histograms/histograms.xml
+++ b/tools/metrics/histograms/histograms.xml
@@ -33790,6 +33790,7 @@ Therefore, the affected-histogram name has to have at least one dot in it.
label="FILESYSTEMPROVIDERINTERNAL_GETMETADATAREQUESTEDSUCCESS"/>
<int value="751"
label="FILESYSTEMPROVIDERINTERNAL_GETMETADATAREQUESTEDERROR"/>
+ <int value="752" label="BROWSER_OPENTAB"/>
</enum>
<enum name="ExtensionInstallCause" type="int">