| Index: chrome/browser/extensions/extension_tab_util.cc
 | 
| diff --git a/chrome/browser/extensions/extension_tab_util.cc b/chrome/browser/extensions/extension_tab_util.cc
 | 
| index be7f4c9640555885503eecd615f2ef1a821322f8..1537a33e8ed4d0b4f06d9a57fcd96724029f4ca0 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();
 | 
|  }
 | 
| 
 |