<commit_before>// Copyright (c) 2011 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/ui/webui/options/extension_settings_handler.h"

#include "base/base64.h"
#include "base/file_util.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/debugger/devtools_window.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_disabled_infobar_delegate.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_updater.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/background_contents.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/tab_contents/tab_contents_view.h"
#include "content/common/content_notification_types.h"
#include "content/common/notification_service.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/skbitmap_operations.h"
#include "webkit/glue/image_decoder.h"

namespace {

bool ShouldShowExtension(const Extension* extension) {
  // Don't show themes since this page's UI isn't really useful for themes.
  if (extension->is_theme())
    return false;

  // Don't show component extensions because they are only extensions as an
  // implementation detail of Chrome.
  if (extension->location() == Extension::COMPONENT)
    return false;

  // Always show unpacked extensions and apps.
  if (extension->location() == Extension::LOAD)
    return true;

  // Unless they are unpacked, never show hosted apps.
  if (extension->is_hosted_app())
    return false;

  return true;
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
//
// ExtensionSettingsHandler::IconLoader
//
////////////////////////////////////////////////////////////////////////////////

ExtensionSettingsHandler::IconLoader::IconLoader(
    ExtensionSettingsHandler* handler)
    : handler_(handler) {
}

void ExtensionSettingsHandler::IconLoader::LoadIcons(
    std::vector<ExtensionResource>* icons, DictionaryValue* json) {
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      NewRunnableMethod(this,
          &IconLoader::LoadIconsOnFileThread, icons, json));
}

void ExtensionSettingsHandler::IconLoader::Cancel() {
  handler_ = NULL;
}

void ExtensionSettingsHandler::IconLoader::LoadIconsOnFileThread(
    std::vector<ExtensionResource>* icons, DictionaryValue* json) {
  scoped_ptr<std::vector<ExtensionResource> > icons_deleter(icons);
  scoped_ptr<DictionaryValue> json_deleter(json);

  ListValue* extensions = NULL;
  CHECK(json->GetList("extensions", &extensions));

  for (size_t i = 0; i < icons->size(); ++i) {
    DictionaryValue* extension = NULL;
    CHECK(extensions->GetDictionary(static_cast<int>(i), &extension));

    // Read the file.
    std::string file_contents;
    if (icons->at(i).relative_path().empty() ||
        !file_util::ReadFileToString(icons->at(i).GetFilePath(),
                                     &file_contents)) {
      // If there's no icon, use the default icon. This is safe to do from
      // the file thread.
      // TODO(erikkay) Assuming we're going to keep showing apps in this list,
      // then we need to figure out when we should use the app default icon.
      file_contents = ResourceBundle::GetSharedInstance().GetRawDataResource(
          IDR_EXTENSION_DEFAULT_ICON).as_string();
    }

    // If the extension is disabled, we desaturate the icon to add to the
    // disabledness effect.
    bool enabled = false;
    CHECK(extension->GetBoolean("enabled", &enabled));
    if (!enabled) {
      const unsigned char* data =
          reinterpret_cast<const unsigned char*>(file_contents.data());
      webkit_glue::ImageDecoder decoder;
      scoped_ptr<SkBitmap> decoded(new SkBitmap());
      *decoded = decoder.Decode(data, file_contents.length());

      // Desaturate the icon and lighten it a bit.
      color_utils::HSL shift = {-1, 0, 0.6};
      *decoded = SkBitmapOperations::CreateHSLShiftedBitmap(*decoded, shift);

      std::vector<unsigned char> output;
      gfx::PNGCodec::EncodeBGRASkBitmap(*decoded, false, &output);

      // Lame, but we must make a copy of this now, because base64 doesn't take
      // the same input type.
      file_contents.assign(reinterpret_cast<char*>(&output.front()),
                           output.size());
    }

    // Create a data URL (all icons are converted to PNGs during unpacking).
    std::string base64_encoded;
    base::Base64Encode(file_contents, &base64_encoded);
    GURL icon_url("data:image/png;base64," + base64_encoded);

    extension->SetString("icon", icon_url.spec());
  }

  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      NewRunnableMethod(this, &IconLoader::ReportResultOnUIThread,
                        json_deleter.release()));
}

void ExtensionSettingsHandler::IconLoader::ReportResultOnUIThread(
    DictionaryValue* json) {
  if (handler_)
    handler_->OnIconsLoaded(json);
}


///////////////////////////////////////////////////////////////////////////////
//
// ExtensionSettingsHandler
//
///////////////////////////////////////////////////////////////////////////////

ExtensionSettingsHandler::ExtensionSettingsHandler()
    : extension_service_(NULL),
      ignore_notifications_(false),
      deleting_rvh_(NULL) {
}

ExtensionSettingsHandler::~ExtensionSettingsHandler() {
  // There may be pending file dialogs, we need to tell them that we've gone
  // away so they don't try and call back to us.
  if (load_extension_dialog_.get())
    load_extension_dialog_->ListenerDestroyed();

  if (icon_loader_.get())
    icon_loader_->Cancel();
}

void ExtensionSettingsHandler::RegisterMessages() {
  web_ui_->RegisterMessageCallback("extensionSettingsRequestExtensionsData",
      NewCallback(this,
                  &ExtensionSettingsHandler::HandleRequestExtensionsData));<commit_msg>Plugged potential leak in ExtensionSettingsHandler::IconLoader.<commit_after>// Copyright (c) 2011 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/ui/webui/options/extension_settings_handler.h"

#include "base/base64.h"
#include "base/file_util.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/debugger/devtools_window.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/browser/extensions/extension_disabled_infobar_delegate.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_updater.h"
#include "chrome/browser/google/google_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/tab_contents/background_contents.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/browser/renderer_host/render_process_host.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/browser/tab_contents/tab_contents_view.h"
#include "content/common/content_notification_types.h"
#include "content/common/notification_service.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/skbitmap_operations.h"
#include "webkit/glue/image_decoder.h"

namespace {

bool ShouldShowExtension(const Extension* extension) {
  // Don't show themes since this page's UI isn't really useful for themes.
  if (extension->is_theme())
    return false;

  // Don't show component extensions because they are only extensions as an
  // implementation detail of Chrome.
  if (extension->location() == Extension::COMPONENT)
    return false;

  // Always show unpacked extensions and apps.
  if (extension->location() == Extension::LOAD)
    return true;

  // Unless they are unpacked, never show hosted apps.
  if (extension->is_hosted_app())
    return false;

  return true;
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
//
// ExtensionSettingsHandler::IconLoader
//
////////////////////////////////////////////////////////////////////////////////

ExtensionSettingsHandler::IconLoader::IconLoader(
    ExtensionSettingsHandler* handler)
    : handler_(handler) {
}

void ExtensionSettingsHandler::IconLoader::LoadIcons(
    std::vector<ExtensionResource>* icons, DictionaryValue* json) {
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      NewRunnableMethod(this,
          &IconLoader::LoadIconsOnFileThread, icons, json));
}

void ExtensionSettingsHandler::IconLoader::Cancel() {
  handler_ = NULL;
}

void ExtensionSettingsHandler::IconLoader::LoadIconsOnFileThread(
    std::vector<ExtensionResource>* icons, DictionaryValue* json) {
  scoped_ptr<std::vector<ExtensionResource> > icons_deleter(icons);
  scoped_ptr<DictionaryValue> json_deleter(json);

  ListValue* extensions = NULL;
  CHECK(json->GetList("extensions", &extensions));

  for (size_t i = 0; i < icons->size(); ++i) {
    DictionaryValue* extension = NULL;
    CHECK(extensions->GetDictionary(static_cast<int>(i), &extension));

    // Read the file.
    std::string file_contents;
    if (icons->at(i).relative_path().empty() ||
        !file_util::ReadFileToString(icons->at(i).GetFilePath(),
                                     &file_contents)) {
      // If there's no icon, use the default icon. This is safe to do from
      // the file thread.
      // TODO(erikkay) Assuming we're going to keep showing apps in this list,
      // then we need to figure out when we should use the app default icon.
      file_contents = ResourceBundle::GetSharedInstance().GetRawDataResource(
          IDR_EXTENSION_DEFAULT_ICON).as_string();
    }

    // If the extension is disabled, we desaturate the icon to add to the
    // disabledness effect.
    bool enabled = false;
    CHECK(extension->GetBoolean("enabled", &enabled));
    if (!enabled) {
      const unsigned char* data =
          reinterpret_cast<const unsigned char*>(file_contents.data());
      webkit_glue::ImageDecoder decoder;
      scoped_ptr<SkBitmap> decoded(new SkBitmap());
      *decoded = decoder.Decode(data, file_contents.length());

      // Desaturate the icon and lighten it a bit.
      color_utils::HSL shift = {-1, 0, 0.6};
      *decoded = SkBitmapOperations::CreateHSLShiftedBitmap(*decoded, shift);

      std::vector<unsigned char> output;
      gfx::PNGCodec::EncodeBGRASkBitmap(*decoded, false, &output);

      // Lame, but we must make a copy of this now, because base64 doesn't take
      // the same input type.
      file_contents.assign(reinterpret_cast<char*>(&output.front()),
                           output.size());
    }

    // Create a data URL (all icons are converted to PNGs during unpacking).
    std::string base64_encoded;
    base::Base64Encode(file_contents, &base64_encoded);
    GURL icon_url("data:image/png;base64," + base64_encoded);

    extension->SetString("icon", icon_url.spec());
  }

  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      NewRunnableMethod(this, &IconLoader::ReportResultOnUIThread,
                        json_deleter.release()));
}

void ExtensionSettingsHandler::IconLoader::ReportResultOnUIThread(
    DictionaryValue* json) {
  if (handler_)
    handler_->OnIconsLoaded(json);
  else
    delete json;
}

///////////////////////////////////////////////////////////////////////////////
//
// ExtensionSettingsHandler
//
///////////////////////////////////////////////////////////////////////////////

ExtensionSettingsHandler::ExtensionSettingsHandler()
    : extension_service_(NULL),
      ignore_notifications_(false),
      deleting_rvh_(NULL) {
}

ExtensionSettingsHandler::~ExtensionSettingsHandler() {
  // There may be pending file dialogs, we need to tell them that we've gone
  // away so they don't try and call back to us.
  if (load_extension_dialog_.get())
    load_extension_dialog_->ListenerDestroyed();

  if (icon_loader_.get())
    icon_loader_->Cancel();
}

void ExtensionSettingsHandler::RegisterMessages() {
  web_ui_->RegisterMessageCallback("extensionSettingsRequestExtensionsData",
      NewCallback(this,
                  &ExtensionSettingsHandler::HandleRequestExtensionsData));
{'fraction_non_alphanumeric': 0.16049474703822367, 'fraction_numerical': 0.004023545190373295, 'mean_word_length': 3.3977719528178243, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6985915', 'n_tokens_mistral': 3893, 'n_tokens_neox': 3774, 'n_words': 848}