// Copyright 2012 The Chromium Authors
// 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_web_ui.h"

#include <stddef.h>

#include <algorithm>
#include <iterator>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/command_line.h"
#include "base/functional/bind.h"
#include "base/memory/scoped_refptr.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/single_thread_task_runner.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/url_constants.h"
#include "components/favicon/core/favicon_service.h"
#include "components/favicon_base/favicon_util.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_service.h"
#include "components/prefs/scoped_user_pref_update.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/bindings_policy.h"
#include "extensions/browser/extension_icon_placeholder.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_util.h"
#include "extensions/browser/image_loader.h"
#include "extensions/buildflags/buildflags.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_resource.h"
#include "extensions/common/icons/extension_icon_set.h"
#include "extensions/common/manifest_handlers/icons_handler.h"
#include "extensions/common/manifest_handlers/incognito_info.h"
#include "net/base/file_stream.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/page_transition_types.h"
#include "ui/base/resource/resource_scale_factor.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_rep.h"

static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE));

using content::WebContents;
using extensions::Extension;
using extensions::URLOverrides;

namespace {

// The key to the override value for a page.
const char kEntry[] = "entry";
// The key to whether or not the override is active (i.e., can be used).
// Overrides may be inactive e.g. when an extension is disabled.
const char kActive[] = "active";

// Iterates over |list| and:
// - Converts any entries of the form <entry> to
//   { 'entry': <entry>, 'active': true }.
// - Removes any duplicate entries.
// We do the conversion because we previously stored these values as strings
// rather than objects.
// TODO(devlin): Remove the conversion once everyone's updated.
void InitializeOverridesList(base::Value::List& list) {
  base::Value::List migrated;
  std::set<std::string> seen_entries;
  for (auto& val : list) {
    base::Value::Dict new_dict;
    std::string entry_name;
    if (val.is_dict()) {
      const std::string* tmp = val.GetDict().FindString(kEntry);
      if (!tmp)  // See comment about CHECK(success) in
                 // ForEachOverrideList.
        continue;
      entry_name = *tmp;
      new_dict = val.GetDict().Clone();
    } else if (val.is_string()) {
      entry_name = val.GetString();
      new_dict.Set(kEntry, entry_name);
      new_dict.Set(kActive, true);
    } else {
      NOTREACHED();
    }

    // |entry_name| will be set by this point.
    if (seen_entries.count(entry_name) == 0) {
      seen_entries.insert(entry_name);
      migrated.Append(std::move(new_dict));
    }
  }

  list = std::move(migrated);
}

// Adds |override| to |list|, or, if there's already an entry for the override,
// marks it as active.
void AddOverridesToList(base::Value::List& list, const GURL& override_url) {
  const std::string& spec = override_url.spec();
  for (auto& val : list) {
    std::string* entry = nullptr;
    base::Value::Dict* dict = val.GetIfDict();
    if (dict) {
      entry = dict->FindString(kEntry);
    }
    if (!entry) {
      NOTREACHED();
    }
    if (*entry == spec) {
      dict->Set(kActive, true);
      return;  // All done!
    }
    GURL entry_url(*entry);
    if (!entry_url.is_valid()) {
      NOTREACHED();
    }
    if (entry_url.host() == override_url.host()) {
      dict->Set(kActive, true);
      dict->Set(kEntry, spec);
      return;
    }
  }

  base::Value::Dict dict;
  dict.Set(kEntry, spec);
  dict.Set(kActive, true);
  // Add the entry to the front of the list.
  list.Insert(list.begin(), base::Value(std::move(dict)));
}

// Validates that each entry in |list| contains a valid url and points to an
// extension contained in |all_extensions| (and, if not, removes it).
void ValidateOverridesList(const extensions::ExtensionSet* all_extensions,
                           base::Value::List& list) {
  base::Value::List migrated;
  std::set<std::string> seen_hosts;
  for (auto& val : list) {
    std::string* entry = nullptr;
    if (val.is_dict()) {
      entry = val.GetDict().FindString(kEntry);
    }
    if (!entry) {
      NOTREACHED();
    }
    GURL override_url(*entry);
    if (!override_url.is_valid())
      continue;

    if (!all_extensions->GetByID(override_url.host()))
      continue;

    // If we've already seen this extension, remove the entry. Only retain the
    // most recent entry for each extension.
    if (!seen_hosts.insert(override_url.host()).second)
      continue;

    migrated.Append(val.Clone());
  }

  list = std::move(migrated);
}

// Reloads the page in |web_contents| if it uses the same profile as |profile|
// and if the current URL is a chrome URL.
void UnregisterAndReplaceOverrideForWebContents(const std::string& page,
                                                Profile* profile,
                                                WebContents* web_contents) {
  if (Profile::FromBrowserContext(web_contents->GetBrowserContext()) != profile)
    return;

  const GURL& url = web_contents->GetLastCommittedURL();
  if (!url.SchemeIs(content::kChromeUIScheme) || url.host_piece() != page)
    return;

  // Don't use Reload() since |url| isn't the same as the internal URL that
  // NavigationController has.
  web_contents->GetController().LoadURL(
      url,
      content::Referrer::SanitizeForRequest(
          url,
          content::Referrer(url, network::mojom::ReferrerPolicy::kDefault)),
      ui::PAGE_TRANSITION_RELOAD, std::string());
}

enum class UpdateBehavior {
  kDeactivate,  // Mark 'active' as false.
  kRemove,      // Remove the entry from the list.
};

// Updates the entry (if any) for |override_url| in |overrides_list| according
// to |behavior|. Returns true if anything changed.
bool UpdateOverridesList(base::Value::List& overrides_list,
                         const std::string& override_url,
                         UpdateBehavior behavior) {
  auto iter = std::ranges::find_if(
      overrides_list, [&override_url](const base::Value& value) {
        if (!value.is_dict())
          return false;
        const std::string* entry = value.GetDict().FindString(kEntry);
        return entry && *entry == override_url;
      });
  if (iter == overrides_list.end())
    return false;

  switch (behavior) {
    case UpdateBehavior::kDeactivate: {
      // See comment about CHECK(success) in ForEachOverrideList.
      if (iter->is_dict()) {
        iter->GetDict().Set(kActive, false);
        break;
      }
      // Else fall through and erase the broken pref.
      [[fallthrough]];
    }
    case UpdateBehavior::kRemove:
      overrides_list.erase(iter);
      break;
  }
  return true;
}

// Updates each list referenced in |overrides| according to |behavior|.
void UpdateOverridesLists(Profile* profile,
                          const URLOverrides::URLOverrideMap& overrides,
                          UpdateBehavior behavior) {
  if (overrides.empty())
    return;
  PrefService* prefs = profile->GetPrefs();
  ScopedDictPrefUpdate update(prefs, ExtensionWebUI::kExtensionURLOverrides);
  base::Value::Dict& all_overrides = update.Get();
  for (const auto& page_override_pair : overrides) {
    base::Value::List* page_overrides =
        all_overrides.FindList(page_override_pair.first);
    if (!page_overrides) {
      // If it's being unregistered it may or may not be in the list. Eg: On
      // uninstalling an externally loaded extension, which has not been enabled
      // once.
      // But if it's being deactivated, it should already be in the list.
      DCHECK_NE(behavior, UpdateBehavior::kDeactivate);
      continue;
    }
    if (UpdateOverridesList(*page_overrides, page_override_pair.second.spec(),
                            behavior)) {
      // This is the active override, so we need to find all existing
      // tabs for this override and get them to reload the original URL.
      base::RepeatingCallback<void(WebContents*)> callback =
          base::BindRepeating(&UnregisterAndReplaceOverrideForWebContents,
                              page_override_pair.first, profile);
      // Apply to all existing tabs.
      extensions::ExtensionTabUtil::ForEachTab(callback);
    }
  }
}

// Run favicon callback with image result. If no favicon was available then
// |image| will be empty.
void RunFaviconCallbackAsync(favicon_base::FaviconResultsCallback callback,
                             const gfx::Image& image) {
  std::vector<favicon_base::FaviconRawBitmapResult> favicon_bitmap_results;

  const std::vector<gfx::ImageSkiaRep>& image_reps =
      image.AsImageSkia().image_reps();
  for (const gfx::ImageSkiaRep& image_rep : image_reps) {
    std::optional<std::vector<uint8_t>> png_data =
        gfx::PNGCodec::EncodeBGRASkBitmap(image_rep.GetBitmap(),
                                          /*discard_transparency=*/false);
    if (png_data) {
      favicon_base::FaviconRawBitmapResult bitmap_result;
      bitmap_result.bitmap_data = base::MakeRefCounted<base::RefCountedBytes>(
          std::move(png_data.value()));
      bitmap_result.pixel_size =
          gfx::Size(image_rep.pixel_width(), image_rep.pixel_height());
      // Leave |bitmap_result|'s icon URL as the default of GURL().
      bitmap_result.icon_type = favicon_base::IconType::kFavicon;

      favicon_bitmap_results.push_back(bitmap_result);
    } else {
      NOTREACHED() << "Could not encode extension favicon";
    }
  }

  base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
      FROM_HERE,
      base::BindOnce(std::move(callback), std::move(favicon_bitmap_results)));
}

const Extension* ValidateOverrideURL(const base::Value* override_url_value,
                                     const GURL& source_url,
                                     const extensions::ExtensionSet& extensions,
                                     GURL* override_url) {
  if (!override_url_value || !override_url_value->is_dict() ||
      !override_url_value->GetDict().FindBool(kActive).value_or(false) ||
      !override_url_value->GetDict().FindString(kEntry)) {
    return nullptr;
  }
  const std::string* const_override =
      override_url_value->GetDict().FindString(kEntry);
  std::string override = *const_override;
  if (!source_url.query().empty())
    override += "?" + source_url.query();
  if (!source_url.ref().empty())
    override += "#" + source_url.ref();
  *override_url = GURL(override);
  if (!override_url->is_valid())
    return nullptr;
  return extensions.GetByID(override_url->host());
}

// Fetches each list in the overrides dictionary and runs |callback| on it.
void ForEachOverrideList(
    Profile* profile,
    base::RepeatingCallback<void(base::Value::List&)> callback) {
  PrefService* prefs = profile->GetPrefs();
  ScopedDictPrefUpdate update(prefs, ExtensionWebUI::kExtensionURLOverrides);
  base::Value::Dict& all_overrides = update.Get();

  // We shouldn't modify the list during iteration. Generate the set of keys
  // instead.
  std::vector<std::string> keys;
  for (const auto entry : all_overrides) {
    keys.push_back(entry.first);
  }
  for (const std::string& key : keys) {
    base::Value::List* list = all_overrides.FindList(key);
    // In a perfect world, we could CHECK(list) here. Unfortunately, if a
    // user's prefs are mangled (by malware, user modification, hard drive
    // corruption, evil robots, etc), this will fail. Instead, delete the pref.
    if (!list) {
      all_overrides.Remove(key);
      continue;
    }
    callback.Run(*list);
  }
}

// A helper method to retrieve active overrides for the given |url|, if any. If
// |get_all| is true, this will retrieve all active overrides; otherwise it will
// return the highest-priority one (potentially early-out-ing). The resulting
// vector is ordered by priority.
std::vector<GURL> GetOverridesForChromeURL(
    const GURL& url,
    content::BrowserContext* browser_context,
    bool get_all) {
  // Only chrome: URLs can be overridden like this.
  DCHECK(url.SchemeIs(content::kChromeUIScheme));

  Profile* profile = Profile::FromBrowserContext(browser_context);
  const base::Value::Dict& overrides =
      profile->GetPrefs()->GetDict(ExtensionWebUI::kExtensionURLOverrides);

  const base::Value::List* url_list =
      overrides.FindListByDottedPath(url.host_piece());
  if (!url_list)
    return {};  // No overrides present for this host.

  extensions::ExtensionRegistry* registry =
      extensions::ExtensionRegistry::Get(browser_context);
  const extensions::ExtensionSet& extensions = registry->enabled_extensions();

  // Separate out overrides from non-component extensions (higher priority).
  std::vector<GURL> override_urls;
  std::vector<GURL> component_overrides;

  // Iterate over the URL list looking for suitable overrides.
  for (const auto& value : *url_list) {
    GURL override_url;
    const Extension* extension =
        ValidateOverrideURL(&value, url, extensions, &override_url);
    if (!extension) {
      // Invalid overrides are cleaned up on startup.
      continue;
    }

    // We can't handle chrome-extension URLs in incognito mode unless the
    // extension uses split mode.
    bool incognito_override_allowed =
        extensions::IncognitoInfo::IsSplitMode(extension) &&
        extensions::util::IsIncognitoEnabled(extension->id(), profile);
    if (profile->IsOffTheRecord() && !incognito_override_allowed) {
      continue;
    }

    if (extensions::Manifest::IsComponentLocation(extension->location())) {
      component_overrides.push_back(override_url);
    } else {
      override_urls.push_back(override_url);
      if (!get_all) {  // Early out, since the highest-priority was found.
        DCHECK_EQ(1u, override_urls.size());
        return override_urls;
      }
    }
  }

  if (!get_all) {
    // Since component overrides are lower priority, we should only get here if
    // there are no non-component overrides.
    DCHECK(override_urls.empty());
    // Return the highest-priority component override, if any.
    if (component_overrides.size() > 1)
      component_overrides.resize(1);
    return component_overrides;
  }

  override_urls.insert(override_urls.end(),
                       std::make_move_iterator(component_overrides.begin()),
                       std::make_move_iterator(component_overrides.end()));
  return override_urls;
}

}  // namespace

const char ExtensionWebUI::kExtensionURLOverrides[] =
    "extensions.chrome_url_overrides";

// static
void ExtensionWebUI::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterDictionaryPref(kExtensionURLOverrides);
}

// static
bool ExtensionWebUI::HandleChromeURLOverride(
    GURL* url,
    content::BrowserContext* browser_context) {
  if (!url->SchemeIs(content::kChromeUIScheme))
    return false;

  std::vector<GURL> overrides =
      GetOverridesForChromeURL(*url, browser_context, /*get_all=*/false);
  if (overrides.empty())
    return false;

  *url = overrides[0];
  return true;
}

// static
bool ExtensionWebUI::HandleChromeURLOverrideReverse(
    GURL* url, content::BrowserContext* browser_context) {
  Profile* profile = Profile::FromBrowserContext(browser_context);
  const base::Value::Dict& overrides =
      profile->GetPrefs()->GetDict(kExtensionURLOverrides);

  // Find the reverse mapping based on the given URL. For example this maps the
  // internal URL
  // chrome-extension://eemcgdkfndhakfknompkggombfjjjeno/main.html#1 to
  // chrome://bookmarks/#1 for display in the omnibox.
  for (const auto dict_iter : overrides) {
    if (!dict_iter.second.is_list())
      continue;

    for (const auto& list_iter : dict_iter.second.GetList()) {
      const std::string* override = nullptr;
      if (list_iter.is_dict())
        override = list_iter.GetDict().FindString(kEntry);
      if (!override)
        continue;
      if (base::StartsWith(url->spec(), *override,
                           base::CompareCase::SENSITIVE)) {
        GURL original_url(content::kChromeUIScheme + std::string("://") +
                          dict_iter.first +
                          url->spec().substr(override->length()));
        *url = original_url;
        return true;
      }
    }
  }

  return false;
}

// static
const extensions::Extension* ExtensionWebUI::GetExtensionControllingURL(
    const GURL& url,
    content::BrowserContext* browser_context) {
  GURL mutable_url(url);
  if (!HandleChromeURLOverride(&mutable_url, browser_context))
    return nullptr;

  DCHECK_NE(url, mutable_url);
  DCHECK(mutable_url.SchemeIs(extensions::kExtensionScheme));

  const extensions::Extension* extension =
      extensions::ExtensionRegistry::Get(browser_context)
          ->enabled_extensions()
          .GetByID(mutable_url.host());
  DCHECK(extension);

  return extension;
}

// static
size_t ExtensionWebUI::GetNumberOfExtensionsOverridingURL(
    const GURL& url,
    content::BrowserContext* browser_context) {
  if (!url.SchemeIs(content::kChromeUIScheme))
    return 0;

  return GetOverridesForChromeURL(url, browser_context, /*get_all=*/true)
      .size();
}

// static
void ExtensionWebUI::InitializeChromeURLOverrides(Profile* profile) {
  ForEachOverrideList(profile, base::BindRepeating(&InitializeOverridesList));
}

// static
void ExtensionWebUI::ValidateChromeURLOverrides(Profile* profile) {
  extensions::ExtensionSet all_extensions =
      extensions::ExtensionRegistry::Get(profile)
          ->GenerateInstalledExtensionsSet();

  ForEachOverrideList(
      profile, base::BindRepeating(&ValidateOverridesList, &all_extensions));
}

// static
void ExtensionWebUI::RegisterOrActivateChromeURLOverrides(
    Profile* profile,
    const URLOverrides::URLOverrideMap& overrides) {
  if (overrides.empty())
    return;
  PrefService* prefs = profile->GetPrefs();
  ScopedDictPrefUpdate update(prefs, kExtensionURLOverrides);
  base::Value::Dict& all_overrides = update.Get();
  for (const auto& page_override_pair : overrides) {
    base::Value::List* page_overrides_weak =
        all_overrides.FindListByDottedPath(page_override_pair.first);
    if (page_overrides_weak == nullptr) {
      page_overrides_weak =
          &all_overrides
               .SetByDottedPath(page_override_pair.first, base::Value::List())
               ->GetList();
    }
    AddOverridesToList(*page_overrides_weak, page_override_pair.second);
  }
}

// static
void ExtensionWebUI::DeactivateChromeURLOverrides(
    Profile* profile,
    const URLOverrides::URLOverrideMap& overrides) {
  UpdateOverridesLists(profile, overrides, UpdateBehavior::kDeactivate);
}

// static
void ExtensionWebUI::UnregisterChromeURLOverrides(
    Profile* profile,
    const URLOverrides::URLOverrideMap& overrides) {
  UpdateOverridesLists(profile, overrides, UpdateBehavior::kRemove);
}

// static
void ExtensionWebUI::GetFaviconForURL(
    Profile* profile,
    const GURL& page_url,
    favicon_base::FaviconResultsCallback callback) {
  const Extension* extension = extensions::ExtensionRegistry::Get(
      profile)->enabled_extensions().GetByID(page_url.host());
  if (!extension) {
    RunFaviconCallbackAsync(std::move(callback), gfx::Image());
    return;
  }

  // Fetch resources for all supported scale factors for which there are
  // resources. Load image reps for all supported scale factors (in addition to
  // 1x) immediately instead of in an as needed fashion to be consistent with
  // how favicons are requested for chrome:// and page URLs.
  const std::vector<float>& favicon_scales = favicon_base::GetFaviconScales();
  std::vector<extensions::ImageLoader::ImageRepresentation> info_list;
  for (float scale : favicon_scales) {
    int pixel_size = static_cast<int>(gfx::kFaviconSize * scale);
    extensions::ExtensionResource icon_resource =
        extensions::IconsInfo::GetIconResource(
            extension, pixel_size, ExtensionIconSet::Match::kBigger);

    if (!icon_resource.empty()) {
      ui::ResourceScaleFactor resource_scale_factor =
          ui::GetSupportedResourceScaleFactor(scale);
      info_list.emplace_back(
          icon_resource,
          extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE,
          gfx::Size(pixel_size, pixel_size), resource_scale_factor);
    }
  }

  if (info_list.empty()) {
    // Use the placeholder image when no default icon is available.
    gfx::Image placeholder_image =
        extensions::ExtensionIconPlaceholder::CreateImage(
            extension_misc::EXTENSION_ICON_SMALL, extension->name());
    gfx::ImageSkia placeholder_skia(placeholder_image.AsImageSkia());
    // Ensure the ImageSkia has representation at all scales we would use for
    // favicons.
    for (const auto scale_factor : ui::GetSupportedResourceScaleFactors()) {
      placeholder_skia.GetRepresentation(
          ui::GetScaleForResourceScaleFactor(scale_factor));
    }
    RunFaviconCallbackAsync(std::move(callback), gfx::Image(placeholder_skia));
  } else {
    // LoadImagesAsync actually can run callback synchronously. We want to force
    // async.
    extensions::ImageLoader::Get(profile)->LoadImagesAsync(
        extension, info_list,
        base::BindOnce(&RunFaviconCallbackAsync, std::move(callback)));
  }
}
