<commit_before>// 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.

// Implements the Chrome Extensions Media Galleries API.

#include "chrome/browser/extensions/api/media_galleries/media_galleries_api.h"

#include <set>
#include <string>
#include <vector>

#include "base/platform_file.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/media_gallery/media_file_system_registry.h"
#include "chrome/browser/media_gallery/media_galleries_dialog_controller.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/browser/ui/extensions/shell_window.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/common/extensions/api/experimental_media_galleries.h"
#include "chrome/common/extensions/api/media_galleries.h"
#include "chrome/common/extensions/permissions/media_galleries_permission.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"

#if defined(OS_WIN)
#include "base/sys_string_conversions.h"
#endif

using chrome::MediaFileSystemInfo;
using chrome::MediaFileSystemRegistry;
using content::ChildProcessSecurityPolicy;
using content::WebContents;

namespace MediaGalleries = extensions::api::media_galleries;
namespace GetMediaFileSystems = MediaGalleries::GetMediaFileSystems;

namespace extensions {

namespace {

const char kDisallowedByPolicy[] =
    "Media Galleries API is disallowed by policy: ";
const char kInvalidInteractive[] = "Unknown value for interactive.";

// Checks whether the MediaGalleries API is currently accessible (it may be
// disallowed even if an extension has the requisite permission).
bool ApiIsAccessible(std::string* error) {
  if (!ChromeSelectFilePolicy::FileSelectDialogsAllowed()) {
    *error = std::string(kDisallowedByPolicy) +
        prefs::kAllowFileSelectionDialogs;
    return false;
  }

  return true;
}

}  // namespace

MediaGalleriesGetMediaFileSystemsFunction::
    ~MediaGalleriesGetMediaFileSystemsFunction() {}

bool MediaGalleriesGetMediaFileSystemsFunction::RunImpl() {
  if (!ApiIsAccessible(&error_))
    return false;

  scoped_ptr<GetMediaFileSystems::Params> params(
      GetMediaFileSystems::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());
  MediaGalleries::GetMediaFileSystemsInteractivity interactive = "no";
  if (params->details.get() && params->details->interactive.get())
    interactive = *params->details->interactive;

  if (interactive == "yes") {
    ShowDialog();
    return true;
  } else if (interactive == "if_needed") {
    MediaFileSystemRegistry::GetInstance()->GetMediaFileSystemsForExtension(
        render_view_host(), GetExtension(), base::Bind(
            &MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries,
            this));
    return true;
  } else if (interactive == "no") {
    GetAndReturnGalleries();
    return true;
  }

  error_ = kInvalidInteractive;
  return false;
}

void MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries(
    const std::vector<MediaFileSystemInfo>& filesystems) {
  if (filesystems.empty())
    ShowDialog();
  else
    ReturnGalleries(filesystems);
}

void MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries() {
  MediaFileSystemRegistry::GetInstance()->GetMediaFileSystemsForExtension(
      render_view_host(), GetExtension(), base::Bind(
          &MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries, this));
}

void MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries(
    const std::vector<MediaFileSystemInfo>& filesystems) {
  const int child_id = render_view_host()->GetProcess()->GetID();
  std::set<std::string> file_system_names;
  base::ListValue* list = new base::ListValue();
  for (size_t i = 0; i < filesystems.size(); i++) {
    base::DictionaryValue* file_system_dict_value = new base::DictionaryValue();

    // Send the file system id so the renderer can create a valid FileSystem
    // object.
    file_system_dict_value->SetWithoutPathExpansion(
        "fsid", Value::CreateStringValue(filesystems[i].fsid));

    // The name must be unique according to the HTML5 File System API spec.
    if (ContainsKey(file_system_names, filesystems[i].name)) {
      NOTREACHED() << "Duplicate file system name: " << filesystems[i].name;
      continue;
    }
    file_system_names.insert(filesystems[i].name);
    file_system_dict_value->SetWithoutPathExpansion(
        "name", Value::CreateStringValue(filesystems[i].name));

    list->Append(file_system_dict_value);

    if (!filesystems[i].path.empty() &&
        MediaGalleriesPermission::HasReadAccess(*GetExtension())) {
      content::ChildProcessSecurityPolicy* policy =
          ChildProcessSecurityPolicy::GetInstance();
      if (!policy->CanReadFile(child_id, filesystems[i].path))
        policy->GrantReadFile(child_id, filesystems[i].path);
      policy->GrantReadFileSystem(child_id, filesystems[i].fsid);
    }
    // TODO(vandebo) Handle write permission.
  }

  SetResult(list);
  SendResponse(true);
}

void MediaGalleriesGetMediaFileSystemsFunction::ShowDialog() {
  WebContents* contents = WebContents::FromRenderViewHost(render_view_host());
  TabContents* tab_contents =
      contents ? TabContents::FromWebContents(contents) : NULL;
  if (!tab_contents) {
    ShellWindow* window = ShellWindowRegistry::Get(profile())->
        GetCurrentShellWindowForApp(GetExtension()->id());
    if (window) {
      tab_contents = window->tab_contents();
    } else {
      // Abort showing the dialog. TODO(estade) Perhaps return an error instead.
      GetAndReturnGalleries();
      return;
    }
  }

  // Controller will delete itself.
  base::Closure cb = base::Bind(
      &MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries, this);
  new chrome::MediaGalleriesDialogController(tab_contents, *GetExtension(), cb);
}

// MediaGalleriesAssembleMediaFileFunction -------------------------------------

MediaGalleriesAssembleMediaFileFunction::
    ~MediaGalleriesAssembleMediaFileFunction() {}

bool MediaGalleriesAssembleMediaFileFunction::RunImpl() {
  if (!ApiIsAccessible(&error_))
    return false;

  // TODO(vandebo) Update the metadata and return the new file.
  SetResult(Value::CreateNullValue());
  return true;
}

}  // namespace extensions
<commit_msg>Fix drive-by memory leak in media_galleries_api.cc.<commit_after>// 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.

// Implements the Chrome Extensions Media Galleries API.

#include "chrome/browser/extensions/api/media_galleries/media_galleries_api.h"

#include <set>
#include <string>
#include <vector>

#include "base/memory/scoped_ptr.h"
#include "base/platform_file.h"
#include "base/stl_util.h"
#include "base/values.h"
#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/media_gallery/media_file_system_registry.h"
#include "chrome/browser/media_gallery/media_galleries_dialog_controller.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/browser/ui/extensions/shell_window.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/common/extensions/api/experimental_media_galleries.h"
#include "chrome/common/extensions/api/media_galleries.h"
#include "chrome/common/extensions/permissions/media_galleries_permission.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"

#if defined(OS_WIN)
#include "base/sys_string_conversions.h"
#endif

using chrome::MediaFileSystemInfo;
using chrome::MediaFileSystemRegistry;
using content::ChildProcessSecurityPolicy;
using content::WebContents;

namespace MediaGalleries = extensions::api::media_galleries;
namespace GetMediaFileSystems = MediaGalleries::GetMediaFileSystems;

namespace extensions {

namespace {

const char kDisallowedByPolicy[] =
    "Media Galleries API is disallowed by policy: ";
const char kInvalidInteractive[] = "Unknown value for interactive.";

// Checks whether the MediaGalleries API is currently accessible (it may be
// disallowed even if an extension has the requisite permission).
bool ApiIsAccessible(std::string* error) {
  if (!ChromeSelectFilePolicy::FileSelectDialogsAllowed()) {
    *error = std::string(kDisallowedByPolicy) +
        prefs::kAllowFileSelectionDialogs;
    return false;
  }

  return true;
}

}  // namespace

MediaGalleriesGetMediaFileSystemsFunction::
    ~MediaGalleriesGetMediaFileSystemsFunction() {}

bool MediaGalleriesGetMediaFileSystemsFunction::RunImpl() {
  if (!ApiIsAccessible(&error_))
    return false;

  scoped_ptr<GetMediaFileSystems::Params> params(
      GetMediaFileSystems::Params::Create(*args_));
  EXTENSION_FUNCTION_VALIDATE(params.get());
  MediaGalleries::GetMediaFileSystemsInteractivity interactive = "no";
  if (params->details.get() && params->details->interactive.get())
    interactive = *params->details->interactive;

  if (interactive == "yes") {
    ShowDialog();
    return true;
  } else if (interactive == "if_needed") {
    MediaFileSystemRegistry::GetInstance()->GetMediaFileSystemsForExtension(
        render_view_host(), GetExtension(), base::Bind(
            &MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries,
            this));
    return true;
  } else if (interactive == "no") {
    GetAndReturnGalleries();
    return true;
  }

  error_ = kInvalidInteractive;
  return false;
}

void MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries(
    const std::vector<MediaFileSystemInfo>& filesystems) {
  if (filesystems.empty())
    ShowDialog();
  else
    ReturnGalleries(filesystems);
}

void MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries() {
  MediaFileSystemRegistry::GetInstance()->GetMediaFileSystemsForExtension(
      render_view_host(), GetExtension(), base::Bind(
          &MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries, this));
}

void MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries(
    const std::vector<MediaFileSystemInfo>& filesystems) {
  const int child_id = render_view_host()->GetProcess()->GetID();
  std::set<std::string> file_system_names;
  base::ListValue* list = new base::ListValue();
  for (size_t i = 0; i < filesystems.size(); i++) {
    scoped_ptr<base::DictionaryValue> file_system_dict_value(
        new base::DictionaryValue());

    // Send the file system id so the renderer can create a valid FileSystem
    // object.
    file_system_dict_value->SetWithoutPathExpansion(
        "fsid", Value::CreateStringValue(filesystems[i].fsid));

    // The name must be unique according to the HTML5 File System API spec.
    if (ContainsKey(file_system_names, filesystems[i].name)) {
      NOTREACHED() << "Duplicate file system name: " << filesystems[i].name;
      continue;
    }
    file_system_names.insert(filesystems[i].name);
    file_system_dict_value->SetWithoutPathExpansion(
        "name", Value::CreateStringValue(filesystems[i].name));

    list->Append(file_system_dict_value.release());

    if (!filesystems[i].path.empty() &&
        MediaGalleriesPermission::HasReadAccess(*GetExtension())) {
      content::ChildProcessSecurityPolicy* policy =
          ChildProcessSecurityPolicy::GetInstance();
      if (!policy->CanReadFile(child_id, filesystems[i].path))
        policy->GrantReadFile(child_id, filesystems[i].path);
      policy->GrantReadFileSystem(child_id, filesystems[i].fsid);
    }
    // TODO(vandebo) Handle write permission.
  }

  SetResult(list);
  SendResponse(true);
}

void MediaGalleriesGetMediaFileSystemsFunction::ShowDialog() {
  WebContents* contents = WebContents::FromRenderViewHost(render_view_host());
  TabContents* tab_contents =
      contents ? TabContents::FromWebContents(contents) : NULL;
  if (!tab_contents) {
    ShellWindow* window = ShellWindowRegistry::Get(profile())->
        GetCurrentShellWindowForApp(GetExtension()->id());
    if (window) {
      tab_contents = window->tab_contents();
    } else {
      // Abort showing the dialog. TODO(estade) Perhaps return an error instead.
      GetAndReturnGalleries();
      return;
    }
  }

  // Controller will delete itself.
  base::Closure cb = base::Bind(
      &MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries, this);
  new chrome::MediaGalleriesDialogController(tab_contents, *GetExtension(), cb);
}

// MediaGalleriesAssembleMediaFileFunction -------------------------------------

MediaGalleriesAssembleMediaFileFunction::
    ~MediaGalleriesAssembleMediaFileFunction() {}

bool MediaGalleriesAssembleMediaFileFunction::RunImpl() {
  if (!ApiIsAccessible(&error_))
    return false;

  // TODO(vandebo) Update the metadata and return the new file.
  SetResult(Value::CreateNullValue());
  return true;
}

}  // namespace extensions

{'fraction_non_alphanumeric': 0.1192557722483748, 'fraction_numerical': 0.0008966599417171038, 'mean_word_length': 5.150735294117647, 'pattern_counts': {'":': 0, '<': 28, '<?xml version=': 0, '>': 54, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1089091', 'n_tokens_mistral': 4042, 'n_tokens_neox': 3878, 'n_words': 759}