// 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_web_ui.h"

#include <stddef.h>

#include <set>
#include <utility>
#include <vector>

#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chrome/browser/extensions/api/bookmark_manager_private/bookmark_manager_private_api.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/extensions/extension_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_registry.h"
#include "extensions/browser/image_loader.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_icon_set.h"
#include "extensions/common/extension_resource.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/gfx/codec/png_codec.h"
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/image/image_skia.h"

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::ListValue* list) {
  base::ListValue migrated;
  std::set<std::string> seen_entries;
  for (const auto& val : *list) {
    std::unique_ptr<base::DictionaryValue> new_dict(
        new base::DictionaryValue());
    std::string entry_name;
    base::DictionaryValue* existing_dict = nullptr;
    if (val->GetAsDictionary(&existing_dict)) {
      bool success = existing_dict->GetString(kEntry, &entry_name);
      if (!success)  // See comment about CHECK(success) in ForEachOverrideList.
        continue;
      new_dict->Swap(existing_dict);
    } else if (val->GetAsString(&entry_name)) {
      new_dict->SetString(kEntry, entry_name);
      new_dict->SetBoolean(kActive, true);
    } else {
      NOTREACHED();
      continue;
    }

    if (seen_entries.count(entry_name) == 0) {
      seen_entries.insert(entry_name);
      migrated.Append(std::move(new_dict));
    }
  }

  list->Swap(&migrated);
}

// Adds |override| to |list|, or, if there's already an entry for the override,
// marks it as active.
void AddOverridesToList(base::ListValue* list,
                        const std::string& override) {
  for (const auto& val : *list) {
    base::DictionaryValue* dict = nullptr;
    std::string entry;
    if (!val->GetAsDictionary(&dict) || !dict->GetString(kEntry, &entry)) {
      NOTREACHED();
      continue;
    }
    if (entry == override) {
      dict->SetBoolean(kActive, true);
      return;  // All done!
    }
  }

  auto dict = base::MakeUnique<base::DictionaryValue>();
  dict->SetString(kEntry, override);
  dict->SetBoolean(kActive, true);
  // Add the entry to the front of the list.
  list->Insert(0, 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::ListValue* list) {
  base::ListValue migrated;
  for (const auto& val : *list) {
    base::DictionaryValue* dict = nullptr;
    std::string entry;
    if (!val->GetAsDictionary(&dict) || !dict->GetString(kEntry, &entry)) {
      NOTREACHED();
      continue;
    }
    std::unique_ptr<base::DictionaryValue> new_dict(
        new base::DictionaryValue());
    new_dict->Swap(dict);
    GURL override_url(entry);
    if (!override_url.is_valid())
      continue;

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

    migrated.Append(std::move(new_dict));
  }

  list->Swap(&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;

  GURL url = web_contents->GetURL();
  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, blink::WebReferrerPolicyDefault)),
      ui::PAGE_TRANSITION_RELOAD, std::string());
}

enum UpdateBehavior {
  UPDATE_DEACTIVATE,  // Mark 'active' as false.
  UPDATE_REMOVE,      // 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::ListValue* overrides_list,
                         const std::string& override_url,
                         UpdateBehavior behavior) {
  base::ListValue::iterator iter =
      std::find_if(overrides_list->begin(), overrides_list->end(),
                   [&override_url](const std::unique_ptr<base::Value>& value) {
                     std::string entry;
                     const base::DictionaryValue* dict = nullptr;
                     return value->GetAsDictionary(&dict) &&
                            dict->GetString(kEntry, &entry) &&
                            entry == override_url;
                   });
  if (iter != overrides_list->end()) {
    switch (behavior) {
      case UPDATE_DEACTIVATE: {
        base::DictionaryValue* dict = nullptr;
        bool success = (*iter)->GetAsDictionary(&dict);
        // See comment about CHECK(success) in ForEachOverrideList.
        if (success) {
          dict->SetBoolean(kActive, false);
          break;
        }
        // Else fall through and erase the broken pref.
      }
      case UPDATE_REMOVE:
        overrides_list->Erase(iter, nullptr);
        break;
    }
    return true;
  }
  return false;
}

// 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();
  DictionaryPrefUpdate update(prefs, ExtensionWebUI::kExtensionURLOverrides);
  base::DictionaryValue* all_overrides = update.Get();
  for (const auto& page_override_pair : overrides) {
    base::ListValue* page_overrides = nullptr;
    // If it's being unregistered, it should already be in the list.
    if (!all_overrides->GetList(page_override_pair.first, &page_overrides)) {
      NOTREACHED();
      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::Callback<void(WebContents*)> callback =
          base::Bind(&UnregisterAndReplaceOverrideForWebContents,
                     page_override_pair.first, profile);
      extensions::ExtensionTabUtil::ForEachTab(callback);
    }
  }
}

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

  const std::vector<gfx::ImageSkiaRep>& image_reps =
      image.AsImageSkia().image_reps();
  for (size_t i = 0; i < image_reps.size(); ++i) {
    const gfx::ImageSkiaRep& image_rep = image_reps[i];
    scoped_refptr<base::RefCountedBytes> bitmap_data(
        new base::RefCountedBytes());
    if (gfx::PNGCodec::EncodeBGRASkBitmap(image_rep.sk_bitmap(),
                                          false,
                                          &bitmap_data->data())) {
      favicon_base::FaviconRawBitmapResult bitmap_result;
      bitmap_result.bitmap_data = bitmap_data;
      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::FAVICON;

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

  base::ThreadTaskRunnerHandle::Get()->PostTask(
      FROM_HERE,
      base::Bind(&favicon::FaviconService::FaviconResultsCallbackRunner,
                 callback, base::Owned(favicon_bitmap_results)));
}

bool ValidateOverrideURL(const base::Value* override_url_value,
                         const GURL& source_url,
                         const extensions::ExtensionSet& extensions,
                         GURL* override_url,
                         const Extension** extension) {
  const base::DictionaryValue* dict = nullptr;
  std::string override;
  bool is_active = false;
  if (!override_url_value || !override_url_value->GetAsDictionary(&dict) ||
      !dict->GetBoolean(kActive, &is_active) || !is_active ||
      !dict->GetString(kEntry, &override)) {
    return false;
  }
  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 false;
  }
  *extension = extensions.GetByID(override_url->host());
  if (!*extension) {
    return false;
  }
  return true;
}

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

  // DictionaryValue::Iterator cannot be used to modify the list. Generate the
  // set of keys instead.
  std::vector<std::string> keys;
  for (base::DictionaryValue::Iterator iter(*all_overrides);
       !iter.IsAtEnd(); iter.Advance()) {
    keys.push_back(iter.key());
  }
  for (const std::string& key : keys) {
    base::ListValue* list = nullptr;
    bool success = all_overrides->GetList(key, &list);
    // In a perfect world, we could CHECK(success) 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 (!success) {
      all_overrides->Remove(key, nullptr);
      continue;
    }
    callback.Run(list);
  }
}

}  // namespace

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

ExtensionWebUI::ExtensionWebUI(content::WebUI* web_ui, const GURL& url)
    : WebUIController(web_ui) {
  Profile* profile = Profile::FromWebUI(web_ui);
  const Extension* extension = extensions::ExtensionRegistry::Get(
      profile)->enabled_extensions().GetExtensionOrAppByURL(url);
  DCHECK(extension);
  DCHECK_EQ(extension_misc::kBookmarkManagerId, extension->id());

  // The base class defaults to enabling WebUI bindings, but we don't need
  // those (this is also reflected in ChromeWebUIControllerFactory::
  // UseWebUIBindingsForURL).
  int bindings = 0;
  web_ui->SetBindings(bindings);

  // Hack: A few things we specialize just for the bookmark manager.
  bookmark_manager_private_drag_event_router_.reset(
      new extensions::BookmarkManagerPrivateDragEventRouter(
          profile, web_ui->GetWebContents()));

  web_ui->SetLinkTransitionType(ui::PAGE_TRANSITION_AUTO_BOOKMARK);
}

ExtensionWebUI::~ExtensionWebUI() {}

// static
bool ExtensionWebUI::NeedsExtensionWebUI(
    content::BrowserContext* browser_context,
    const GURL& url) {
  CHECK(browser_context);
  const Extension* extension =
      extensions::ExtensionRegistry::Get(browser_context)->enabled_extensions().
          GetExtensionOrAppByURL(url);
  // Only use bindings for the Bookmark Manager extension, which needs it as a
  // hack (see ExtensionWebUI's constructor below).
  return extension && extension->id() == extension_misc::kBookmarkManagerId;
}

////////////////////////////////////////////////////////////////////////////////
// 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;

  Profile* profile = Profile::FromBrowserContext(browser_context);
  const base::DictionaryValue* overrides =
      profile->GetPrefs()->GetDictionary(kExtensionURLOverrides);

  std::string url_host = url->host();
  const base::ListValue* url_list = NULL;
  if (!overrides || !overrides->GetList(url_host, &url_list))
    return false;

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

  GURL component_url;
  bool found_component_override = false;

  // Iterate over the URL list looking for a suitable override. If a
  // valid non-component override is encountered it is chosen immediately.
  for (size_t i = 0; i < url_list->GetSize(); ++i) {
    const base::Value* val = NULL;
    url_list->Get(i, &val);

    GURL override_url;
    const Extension* extension;
    if (!ValidateOverrideURL(
            val, *url, extensions, &override_url, &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())) {
      *url = override_url;
      return true;
    }

    if (!found_component_override) {
      found_component_override = true;
      component_url = override_url;
    }
  }

  // If no other non-component overrides were found, use the first known
  // component override, if any.
  if (found_component_override) {
    *url = component_url;
    return true;
  }

  return false;
}

// static
bool ExtensionWebUI::HandleChromeURLOverrideReverse(
    GURL* url, content::BrowserContext* browser_context) {
  Profile* profile = Profile::FromBrowserContext(browser_context);
  const base::DictionaryValue* overrides =
      profile->GetPrefs()->GetDictionary(kExtensionURLOverrides);
  if (!overrides)
    return false;

  // 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 (base::DictionaryValue::Iterator dict_iter(*overrides);
       !dict_iter.IsAtEnd(); dict_iter.Advance()) {
    const base::ListValue* url_list = nullptr;
    if (!dict_iter.value().GetAsList(&url_list))
      continue;

    for (base::ListValue::const_iterator list_iter = url_list->begin();
         list_iter != url_list->end(); ++list_iter) {
      const base::DictionaryValue* dict = nullptr;
      if (!(*list_iter)->GetAsDictionary(&dict))
        continue;
      std::string override;
      if (!dict->GetString(kEntry, &override))
        continue;
      if (base::StartsWith(url->spec(), override,
                           base::CompareCase::SENSITIVE)) {
        GURL original_url(content::kChromeUIScheme + std::string("://") +
                          dict_iter.key() +
                          url->spec().substr(override.length()));
        *url = original_url;
        return true;
      }
    }
  }

  return false;
}

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

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

  ForEachOverrideList(profile,
                      base::Bind(&ValidateOverridesList, all_extensions.get()));
}

// static
void ExtensionWebUI::RegisterOrActivateChromeURLOverrides(
    Profile* profile,
    const URLOverrides::URLOverrideMap& overrides) {
  if (overrides.empty())
    return;
  PrefService* prefs = profile->GetPrefs();
  DictionaryPrefUpdate update(prefs, kExtensionURLOverrides);
  base::DictionaryValue* all_overrides = update.Get();
  for (const auto& page_override_pair : overrides) {
    base::ListValue* page_overrides = nullptr;
    if (!all_overrides->GetList(page_override_pair.first, &page_overrides)) {
      page_overrides = new base::ListValue();
      all_overrides->Set(page_override_pair.first, page_overrides);
    }
    AddOverridesToList(page_overrides, page_override_pair.second.spec());
  }
}

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

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

// static
void ExtensionWebUI::GetFaviconForURL(
    Profile* profile,
    const GURL& page_url,
    const favicon_base::FaviconResultsCallback& callback) {
  const Extension* extension = extensions::ExtensionRegistry::Get(
      profile)->enabled_extensions().GetByID(page_url.host());
  if (!extension) {
    RunFaviconCallbackAsync(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 (size_t i = 0; i < favicon_scales.size(); ++i) {
    float scale = favicon_scales[i];
    int pixel_size = static_cast<int>(gfx::kFaviconSize * scale);
    extensions::ExtensionResource icon_resource =
        extensions::IconsInfo::GetIconResource(extension,
                                               pixel_size,
                                               ExtensionIconSet::MATCH_BIGGER);

    ui::ScaleFactor resource_scale_factor = ui::GetSupportedScaleFactor(scale);
    info_list.push_back(extensions::ImageLoader::ImageRepresentation(
        icon_resource,
        extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE,
        gfx::Size(pixel_size, pixel_size),
        resource_scale_factor));
  }

  // LoadImagesAsync actually can run callback synchronously. We want to force
  // async.
  extensions::ImageLoader::Get(profile)->LoadImagesAsync(
      extension, info_list, base::Bind(&RunFaviconCallbackAsync, callback));
}
