// Copyright (c) 2012 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/extension_tab_util.h"

#include <stddef.h>
#include <algorithm>
#include <utility>

#include "base/no_destructor.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/tabs/tabs_constants.h"
#include "chrome/browser/extensions/browser_extension_window_controller.h"
#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/extensions/chrome_extension_function_details.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/resource_coordinator/tab_lifecycle_unit_external.h"
#include "chrome/browser/sessions/session_tab_helper.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/recently_audible_helper.h"
#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
#include "chrome/browser/ui/singleton_tabs.h"
#include "chrome/browser/ui/tab_contents/tab_contents_iterator.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/tabs/tab_utils.h"
#include "chrome/common/extensions/api/tabs.h"
#include "chrome/common/url_constants.h"
#include "components/url_formatter/url_fixer.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "extensions/common/constants.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/extension.h"
#include "extensions/common/feature_switch.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_handlers/incognito_info.h"
#include "extensions/common/manifest_handlers/options_page_info.h"
#include "extensions/common/permissions/api_permission.h"
#include "extensions/common/permissions/permissions_data.h"
#include "url/gurl.h"

#if defined(OS_CHROMEOS)
#include "ash/public/cpp/window_pin_type.h"
#endif

using content::NavigationEntry;
using content::WebContents;

namespace extensions {

namespace {

// |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 match_incognito_profile,
                                   std::string* error_message) {
  Profile* incognito_profile =
      match_incognito_profile && profile->HasOffTheRecordProfile()
          ? profile->GetOffTheRecordProfile()
          : nullptr;
  for (auto* browser : *BrowserList::GetInstance()) {
    if ((browser->profile() == profile ||
         browser->profile() == incognito_profile) &&
        ExtensionTabUtil::GetWindowId(browser) == window_id &&
        browser->window()) {
      return browser;
    }
  }

  if (error_message)
    *error_message = ErrorUtils::FormatErrorMessage(
        tabs_constants::kWindowNotFoundError, base::NumberToString(window_id));

  return nullptr;
}

Browser* CreateBrowser(Profile* profile,
                       int window_id,
                       bool user_gesture,
                       std::string* error) {
  Browser::CreateParams params(Browser::TYPE_TABBED, profile, user_gesture);
  Browser* browser = new Browser(params);
  browser->window()->Show();
  return browser;
}

// Use this function for reporting a tab id to an extension. It will
// take care of setting the id to TAB_ID_NONE if necessary (for
// example with devtools).
int GetTabIdForExtensions(const WebContents* web_contents) {
  Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
  if (browser && !ExtensionTabUtil::BrowserSupportsTabs(browser))
    return -1;
  return SessionTabHelper::IdForTab(web_contents).id();
}

std::unique_ptr<ExtensionTabUtil::Delegate>&
GetExtensionTabUtilDelegateWrapper() {
  static base::NoDestructor<std::unique_ptr<ExtensionTabUtil::Delegate>>
      delegate_wrapper;
  return *delegate_wrapper;
}

ExtensionTabUtil::Delegate* GetExtensionTabUtilDelegate() {
  return GetExtensionTabUtilDelegateWrapper().get();
}

}  // namespace

ExtensionTabUtil::OpenTabParams::OpenTabParams()
    : create_browser_if_needed(false) {
}

ExtensionTabUtil::OpenTabParams::~OpenTabParams() {
}

// Opens a new tab for a given extension. Returns nullptr and sets |error| if an
// error occurs.
base::DictionaryValue* ExtensionTabUtil::OpenTab(
    UIThreadExtensionFunction* function,
    const OpenTabParams& params,
    bool user_gesture,
    std::string* error) {
  ChromeExtensionFunctionDetails chrome_details(function);
  Profile* profile = chrome_details.GetProfile();
  // windowId defaults to "current" window.
  int window_id = extension_misc::kCurrentWindowId;
  if (params.window_id.get())
    window_id = *params.window_id;

  Browser* browser = GetBrowserFromWindowID(chrome_details, window_id, error);
  if (!browser) {
    if (!params.create_browser_if_needed) {
      return nullptr;
    }
    browser = CreateBrowser(profile, window_id, user_gesture, error);
    if (!browser)
      return nullptr;
  }

  // Ensure the selected browser is tabbed.
  if (!browser->is_type_tabbed() && browser->IsAttemptingToCloseBrowser())
    browser = chrome::FindTabbedBrowser(
        profile, function->include_incognito_information());
  if (!browser || !browser->window()) {
    if (error)
      *error = tabs_constants::kNoCurrentWindowError;
    return nullptr;
  }

  // TODO(jstritar): Add a constant, chrome.tabs.TAB_ID_ACTIVE, that
  // represents the active tab.
  WebContents* opener = nullptr;
  Browser* opener_browser = nullptr;
  if (params.opener_tab_id.get()) {
    int opener_id = *params.opener_tab_id;

    if (!ExtensionTabUtil::GetTabById(
            opener_id, profile, function->include_incognito_information(),
            &opener_browser, nullptr, &opener, nullptr)) {
      if (error) {
        *error = ErrorUtils::FormatErrorMessage(
            tabs_constants::kTabNotFoundError, base::NumberToString(opener_id));
      }
      return nullptr;
    }
  }

  // TODO(rafaelw): handle setting remaining tab properties:
  // -title
  // -favIconUrl

  GURL url;
  if (params.url.get()) {
    std::string url_string = *params.url;
    url = ExtensionTabUtil::ResolvePossiblyRelativeURL(url_string,
                                                       function->extension());
    if (!url.is_valid()) {
      *error = ErrorUtils::FormatErrorMessage(tabs_constants::kInvalidUrlError,
                                              url_string);
      return nullptr;
    }
  } else {
    url = GURL(chrome::kChromeUINewTabURL);
  }

  // Don't let extensions crash the browser or renderers.
  if (ExtensionTabUtil::IsKillURL(url)) {
    *error = tabs_constants::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;

  // 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) &&
      (!function->extension() ||
       !IncognitoInfo::IsSplitMode(function->extension())) &&
      browser->profile()->IsOffTheRecord()) {
    Profile* profile = browser->profile()->GetOriginalProfile();

    browser = chrome::FindTabbedBrowser(profile, false);
    if (!browser) {
      Browser::CreateParams params =
          Browser::CreateParams(Browser::TYPE_TABBED, profile, user_gesture);
      browser = new Browser(params);
      browser->window()->Show();
    }
  }

  if (opener_browser && browser != opener_browser) {
    if (error) {
      *error = "Tab opener must be in the same window as the updated tab.";
    }
    return nullptr;
  }

  // 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;
  NavigateParams navigate_params(browser, url, ui::PAGE_TRANSITION_LINK);
  navigate_params.disposition = active
                                    ? WindowOpenDisposition::NEW_FOREGROUND_TAB
                                    : WindowOpenDisposition::NEW_BACKGROUND_TAB;
  navigate_params.tabstrip_index = index;
  navigate_params.tabstrip_add_types = add_types;
  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.navigated_or_inserted_contents);
  if (opener) {
    // Only set the opener if the opener tab is in the same tab strip as the
    // new tab.
    if (tab_strip->GetIndexOfWebContents(opener) != TabStripModel::kNoTab)
      tab_strip->SetOpenerOfWebContentsAt(new_index, opener);
  }

  if (active)
    navigate_params.navigated_or_inserted_contents->SetInitialFocus();

  // Return data about the newly created tab.
  return ExtensionTabUtil::CreateTabObject(
             navigate_params.navigated_or_inserted_contents, kScrubTab,
             function->extension(), tab_strip, new_index)
      ->ToValue()
      .release();
}

Browser* ExtensionTabUtil::GetBrowserFromWindowID(
    const ChromeExtensionFunctionDetails& details,
    int window_id,
    std::string* error) {
  if (window_id == extension_misc::kCurrentWindowId) {
    Browser* result = details.GetCurrentBrowser();
    if (!result || !result->window()) {
      if (error)
        *error = tabs_constants::kNoCurrentWindowError;
      return nullptr;
    }
    return result;
  } else {
    return GetBrowserInProfileWithId(
        details.GetProfile(), window_id,
        details.function()->include_incognito_information(), error);
  }
}

int ExtensionTabUtil::GetWindowId(const Browser* browser) {
  return browser->session_id().id();
}

int ExtensionTabUtil::GetWindowIdOfTabStripModel(
    const TabStripModel* tab_strip_model) {
  for (auto* browser : *BrowserList::GetInstance()) {
    if (browser->tab_strip_model() == tab_strip_model)
      return GetWindowId(browser);
  }
  return -1;
}

int ExtensionTabUtil::GetTabId(const WebContents* web_contents) {
  return SessionTabHelper::IdForTab(web_contents).id();
}

std::string ExtensionTabUtil::GetTabStatusText(bool is_loading) {
  return is_loading ? tabs_constants::kStatusValueLoading
                    : tabs_constants::kStatusValueComplete;
}

int ExtensionTabUtil::GetWindowIdOfTab(const WebContents* web_contents) {
  return SessionTabHelper::IdForWindowContainingTab(web_contents).id();
}

// static
std::string ExtensionTabUtil::GetBrowserWindowTypeText(const Browser& browser) {
  if (browser.is_devtools())
    return tabs_constants::kWindowTypeValueDevTools;
  if (browser.is_type_popup())
    return tabs_constants::kWindowTypeValuePopup;
  // TODO(devlin): Browser::is_app() returns true whenever Browser::app_name_
  // is non-empty (and includes instances such as devtools). Platform apps
  // should no longer be returned here; are there any other cases (that aren't
  // captured by is_devtools() or is_type_popup() for an app-type browser?
  if (browser.is_app())
    return tabs_constants::kWindowTypeValueApp;
  return tabs_constants::kWindowTypeValueNormal;
}

// static
std::unique_ptr<api::tabs::Tab> ExtensionTabUtil::CreateTabObject(
    WebContents* contents,
    ScrubTabBehavior scrub_tab_behavior,
    const Extension* extension,
    TabStripModel* tab_strip,
    int tab_index) {
  if (!tab_strip)
    ExtensionTabUtil::GetTabStripModel(contents, &tab_strip, &tab_index);
  bool is_loading = contents->IsLoading();
  auto tab_object = std::make_unique<api::tabs::Tab>();
  tab_object->id = std::make_unique<int>(GetTabIdForExtensions(contents));
  tab_object->index = tab_index;
  tab_object->window_id = GetWindowIdOfTab(contents);
  tab_object->status =
      std::make_unique<std::string>(GetTabStatusText(is_loading));
  tab_object->active = tab_strip && tab_index == tab_strip->active_index();
  tab_object->selected = tab_strip && tab_index == tab_strip->active_index();
  tab_object->highlighted = tab_strip && tab_strip->IsTabSelected(tab_index);
  tab_object->pinned = tab_strip && tab_strip->IsTabPinned(tab_index);
  auto* audible_helper = RecentlyAudibleHelper::FromWebContents(contents);
  bool audible = false;
  if (audible_helper) {
    // WebContents in a tab strip have RecentlyAudible helpers. They endow the
    // tab with a notion of audibility that has a timeout for quiet periods. Use
    // that if available.
    audible = audible_helper->WasRecentlyAudible();
  } else {
    // Otherwise use the instantaneous notion of audibility.
    audible = contents->IsCurrentlyAudible();
  }
  tab_object->audible = std::make_unique<bool>(audible);
  auto* tab_lifeycle_unit_external =
      resource_coordinator::TabLifecycleUnitExternal::FromWebContents(contents);
  tab_object->discarded =
      tab_lifeycle_unit_external && tab_lifeycle_unit_external->IsDiscarded();
  tab_object->auto_discardable =
      !tab_lifeycle_unit_external ||
      tab_lifeycle_unit_external->IsAutoDiscardable();
  tab_object->muted_info = CreateMutedInfo(contents);
  tab_object->incognito = contents->GetBrowserContext()->IsOffTheRecord();
  gfx::Size contents_size = contents->GetContainerBounds().size();
  tab_object->width = std::make_unique<int>(contents_size.width());
  tab_object->height = std::make_unique<int>(contents_size.height());

  tab_object->url = std::make_unique<std::string>(contents->GetURL().spec());
  tab_object->title =
      std::make_unique<std::string>(base::UTF16ToUTF8(contents->GetTitle()));
  NavigationEntry* entry = contents->GetController().GetVisibleEntry();
  if (entry && entry->GetFavicon().valid) {
    tab_object->fav_icon_url =
        std::make_unique<std::string>(entry->GetFavicon().url.spec());
  }
  if (tab_strip) {
    WebContents* opener = tab_strip->GetOpenerOfWebContentsAt(tab_index);
    if (opener) {
      tab_object->opener_tab_id =
          std::make_unique<int>(GetTabIdForExtensions(opener));
    }
  }

  if (scrub_tab_behavior == kScrubTab)
    ScrubTabForExtension(extension, contents, tab_object.get());
  return tab_object;
}

std::unique_ptr<base::ListValue> ExtensionTabUtil::CreateTabList(
    const Browser* browser,
    const Extension* extension) {
  std::unique_ptr<base::ListValue> tab_list(new base::ListValue());
  TabStripModel* tab_strip = browser->tab_strip_model();
  for (int i = 0; i < tab_strip->count(); ++i) {
    tab_list->Append(CreateTabObject(tab_strip->GetWebContentsAt(i), kScrubTab,
                                     extension, tab_strip, i)
                         ->ToValue());
  }

  return tab_list;
}

// static
std::unique_ptr<base::DictionaryValue>
ExtensionTabUtil::CreateWindowValueForExtension(
    const Browser& browser,
    const Extension* extension,
    PopulateTabBehavior populate_tab_behavior) {
  auto result = std::make_unique<base::DictionaryValue>();

  result->SetInteger(tabs_constants::kIdKey, browser.session_id().id());
  result->SetString(tabs_constants::kWindowTypeKey,
                    GetBrowserWindowTypeText(browser));
  ui::BaseWindow* window = browser.window();
  result->SetBoolean(tabs_constants::kFocusedKey, window->IsActive());
  const Profile* profile = browser.profile();
  result->SetBoolean(tabs_constants::kIncognitoKey, profile->IsOffTheRecord());
  result->SetBoolean(tabs_constants::kAlwaysOnTopKey, window->IsAlwaysOnTop());

  std::string window_state;
  if (window->IsMinimized()) {
    window_state = tabs_constants::kShowStateValueMinimized;
  } else if (window->IsFullscreen()) {
    window_state = tabs_constants::kShowStateValueFullscreen;
#if defined(OS_CHROMEOS)
    if (ash::IsWindowTrustedPinned(window))
      window_state = tabs_constants::kShowStateValueLockedFullscreen;
#endif
  } else if (window->IsMaximized()) {
    window_state = tabs_constants::kShowStateValueMaximized;
  } else {
    window_state = tabs_constants::kShowStateValueNormal;
  }
  result->SetString(tabs_constants::kShowStateKey, window_state);

  gfx::Rect bounds;
  if (window->IsMinimized())
    bounds = window->GetRestoredBounds();
  else
    bounds = window->GetBounds();
  result->SetInteger(tabs_constants::kLeftKey, bounds.x());
  result->SetInteger(tabs_constants::kTopKey, bounds.y());
  result->SetInteger(tabs_constants::kWidthKey, bounds.width());
  result->SetInteger(tabs_constants::kHeightKey, bounds.height());

  if (populate_tab_behavior == kPopulateTabs)
    result->Set(tabs_constants::kTabsKey, CreateTabList(&browser, extension));

  return result;
}

// static
std::unique_ptr<api::tabs::MutedInfo> ExtensionTabUtil::CreateMutedInfo(
    content::WebContents* contents) {
  DCHECK(contents);
  auto info = std::make_unique<api::tabs::MutedInfo>();
  info->muted = contents->IsAudioMuted();
  switch (chrome::GetTabAudioMutedReason(contents)) {
    case TabMutedReason::NONE:
      break;
    case TabMutedReason::CONTENT_SETTING:
    case TabMutedReason::CONTENT_SETTING_CHROME:
    case TabMutedReason::CONTEXT_MENU:
      info->reason = api::tabs::MUTED_INFO_REASON_USER;
      break;
    case TabMutedReason::MEDIA_CAPTURE:
      info->reason = api::tabs::MUTED_INFO_REASON_CAPTURE;
      break;
    case TabMutedReason::EXTENSION:
      info->reason = api::tabs::MUTED_INFO_REASON_EXTENSION;
      info->extension_id = std::make_unique<std::string>(
          LastMuteMetadata::FromWebContents(contents)->extension_id);
      DCHECK(!info->extension_id->empty());
      break;
  }
  return info;
}

// static
void ExtensionTabUtil::SetPlatformDelegate(std::unique_ptr<Delegate> delegate) {
  GetExtensionTabUtilDelegateWrapper() = std::move(delegate);
}

// static
void ExtensionTabUtil::ScrubTabForExtension(const Extension* extension,
                                            content::WebContents* contents,
                                            api::tabs::Tab* tab) {
  bool has_permission = false;
  if (extension) {
    bool api_permission = false;
    std::string url;
    if (contents) {
      api_permission = extension->permissions_data()->HasAPIPermissionForTab(
          GetTabId(contents), APIPermission::kTab);
      url = contents->GetURL().spec();
    } else {
      api_permission =
          extension->permissions_data()->HasAPIPermission(APIPermission::kTab);
      url = *tab->url;
    }
    bool host_permission = extension->permissions_data()
                               ->active_permissions()
                               .HasExplicitAccessToOrigin(GURL(url));
    has_permission = api_permission || host_permission;
  }
  if (!has_permission) {
    tab->url.reset();
    tab->title.reset();
    tab->fav_icon_url.reset();
  }
  if (GetExtensionTabUtilDelegate()) {
    GetExtensionTabUtilDelegate()->ScrubTabForExtension(extension, contents,
                                                        tab);
  }
}

bool ExtensionTabUtil::GetTabStripModel(const WebContents* web_contents,
                                        TabStripModel** tab_strip_model,
                                        int* tab_index) {
  DCHECK(web_contents);
  DCHECK(tab_strip_model);
  DCHECK(tab_index);

  for (auto* browser : *BrowserList::GetInstance()) {
    TabStripModel* tab_strip = browser->tab_strip_model();
    int index = tab_strip->GetIndexOfWebContents(web_contents);
    if (index != -1) {
      *tab_strip_model = tab_strip;
      *tab_index = index;
      return true;
    }
  }

  return false;
}

bool ExtensionTabUtil::GetDefaultTab(Browser* browser,
                                     WebContents** contents,
                                     int* tab_id) {
  DCHECK(browser);
  DCHECK(contents);

  *contents = browser->tab_strip_model()->GetActiveWebContents();
  if (*contents) {
    if (tab_id)
      *tab_id = GetTabId(*contents);
    return true;
  }

  return false;
}

bool ExtensionTabUtil::GetTabById(int tab_id,
                                  content::BrowserContext* browser_context,
                                  bool include_incognito,
                                  Browser** browser,
                                  TabStripModel** tab_strip,
                                  WebContents** contents,
                                  int* tab_index) {
  if (tab_id == api::tabs::TAB_ID_NONE)
    return false;
  Profile* profile = Profile::FromBrowserContext(browser_context);
  Profile* incognito_profile =
      include_incognito && profile->HasOffTheRecordProfile()
          ? profile->GetOffTheRecordProfile()
          : nullptr;
  for (auto* target_browser : *BrowserList::GetInstance()) {
    if (target_browser->profile() == profile ||
        target_browser->profile() == incognito_profile) {
      TabStripModel* target_tab_strip = target_browser->tab_strip_model();
      for (int i = 0; i < target_tab_strip->count(); ++i) {
        WebContents* target_contents = target_tab_strip->GetWebContentsAt(i);
        if (SessionTabHelper::IdForTab(target_contents).id() == tab_id) {
          if (browser)
            *browser = target_browser;
          if (tab_strip)
            *tab_strip = target_tab_strip;
          if (contents)
            *contents = target_contents;
          if (tab_index)
            *tab_index = i;
          return true;
        }
      }
    }
  }
  return false;
}

GURL ExtensionTabUtil::ResolvePossiblyRelativeURL(const std::string& url_string,
                                                  const Extension* extension) {
  GURL url = GURL(url_string);
  if (!url.is_valid())
    url = extension->GetResourceURL(url_string);

  return url;
}

bool ExtensionTabUtil::IsKillURL(const GURL& url) {
  static const char* const kill_hosts[] = {
      chrome::kChromeUICrashHost,         chrome::kChromeUIDelayedHangUIHost,
      chrome::kChromeUIHangUIHost,        chrome::kChromeUIKillHost,
      chrome::kChromeUIQuitHost,          chrome::kChromeUIRestartHost,
      content::kChromeUIBrowserCrashHost, content::kChromeUIMemoryExhaustHost,
  };

  // Check a fixed-up URL, to normalize the scheme and parse hosts correctly.
  GURL fixed_url =
      url_formatter::FixupURL(url.possibly_invalid_spec(), std::string());
  if (!fixed_url.SchemeIs(content::kChromeUIScheme))
    return false;

  base::StringPiece fixed_host = fixed_url.host_piece();
  for (size_t i = 0; i < base::size(kill_hosts); ++i) {
    if (fixed_host == kill_hosts[i])
      return true;
  }

  return false;
}

void ExtensionTabUtil::CreateTab(std::unique_ptr<WebContents> web_contents,
                                 const std::string& extension_id,
                                 WindowOpenDisposition disposition,
                                 const gfx::Rect& initial_rect,
                                 bool user_gesture) {
  Profile* profile =
      Profile::FromBrowserContext(web_contents->GetBrowserContext());
  Browser* browser = chrome::FindTabbedBrowser(profile, false);
  const bool browser_created = !browser;
  if (!browser) {
    Browser::CreateParams params = Browser::CreateParams(profile, user_gesture);
    browser = new Browser(params);
  }
  NavigateParams params(browser, std::move(web_contents));

  // The extension_app_id parameter ends up as app_name in the Browser
  // which causes the Browser to return true for is_app().  This affects
  // among other things, whether the location bar gets displayed.
  // TODO(mpcomplete): This seems wrong. What if the extension content is hosted
  // in a tab?
  if (disposition == WindowOpenDisposition::NEW_POPUP)
    params.extension_app_id = extension_id;

  params.disposition = disposition;
  params.window_bounds = initial_rect;
  params.window_action = NavigateParams::SHOW_WINDOW;
  params.user_gesture = user_gesture;
  Navigate(&params);

  // Close the browser if Navigate created a new one.
  if (browser_created && (browser != params.browser))
    browser->window()->Close();
}

// static
void ExtensionTabUtil::ForEachTab(
    const base::Callback<void(WebContents*)>& callback) {
  for (auto* web_contents : AllTabContentses())
    callback.Run(web_contents);
}

// static
WindowController* ExtensionTabUtil::GetWindowControllerOfTab(
    const WebContents* web_contents) {
  Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
  if (browser != nullptr)
    return browser->extension_window_controller();

  return nullptr;
}

bool ExtensionTabUtil::OpenOptionsPageFromAPI(
    const Extension* extension,
    content::BrowserContext* browser_context) {
  if (!OptionsPageInfo::HasOptionsPage(extension))
    return false;
  Profile* profile = Profile::FromBrowserContext(browser_context);
  // This version of OpenOptionsPage() is only called when the extension
  // initiated the command via chrome.runtime.openOptionsPage. For a spanning
  // mode extension, this API could only be called from a regular profile, since
  // that's the only place it's running.
  DCHECK(!profile->IsOffTheRecord() || IncognitoInfo::IsSplitMode(extension));
  Browser* browser = chrome::FindBrowserWithProfile(profile);
  if (!browser)
    browser = new Browser(Browser::CreateParams(profile, true));
  return extensions::ExtensionTabUtil::OpenOptionsPage(extension, browser);
}

bool ExtensionTabUtil::OpenOptionsPage(const Extension* extension,
                                       Browser* browser) {
  if (!OptionsPageInfo::HasOptionsPage(extension))
    return false;

  // Force the options page to open in non-OTR window if the extension is not
  // running in split mode, because it won't be able to save settings from OTR.
  // This version of OpenOptionsPage() can be called from an OTR window via e.g.
  // the action menu, since that's not initiated by the extension.
  std::unique_ptr<chrome::ScopedTabbedBrowserDisplayer> displayer;
  if (browser->profile()->IsOffTheRecord() &&
      !IncognitoInfo::IsSplitMode(extension)) {
    displayer.reset(new chrome::ScopedTabbedBrowserDisplayer(
        browser->profile()->GetOriginalProfile()));
    browser = displayer->browser();
  }

  GURL url_to_navigate;
  bool open_in_tab = OptionsPageInfo::ShouldOpenInTab(extension);
  if (open_in_tab) {
    // Options page tab is simply e.g. chrome-extension://.../options.html.
    url_to_navigate = OptionsPageInfo::GetOptionsPage(extension);
  } else {
    // Options page tab is Extension settings pointed at that Extension's ID,
    // e.g. chrome://extensions?options=...
    url_to_navigate = GURL(chrome::kChromeUIExtensionsURL);
    GURL::Replacements replacements;
    std::string query =
        base::StringPrintf("options=%s", extension->id().c_str());
    replacements.SetQueryStr(query);
    url_to_navigate = url_to_navigate.ReplaceComponents(replacements);
  }

  NavigateParams params(
      GetSingletonTabNavigateParams(browser, url_to_navigate));
  // We need to respect path differences because we don't want opening the
  // options page to close a page that might be open to extension content.
  // However, if the options page opens inside the chrome://extensions page, we
  // can override an existing page.
  // Note: ref behavior is to ignore.
  params.path_behavior = open_in_tab ? NavigateParams::RESPECT
                                     : NavigateParams::IGNORE_AND_NAVIGATE;
  params.url = url_to_navigate;
  ShowSingletonTabOverwritingNTP(browser, std::move(params));
  return true;
}

// static
bool ExtensionTabUtil::BrowserSupportsTabs(Browser* browser) {
  return browser && browser->tab_strip_model() && !browser->is_devtools();
}

}  // namespace extensions
