Commit d1282794 authored by Devlin Cronin's avatar Devlin Cronin Committed by Commit Bot

[Extensions + Apps] Move the mediaGalleries API

Move the mediaGalleries API out of extensions code and into apps
code. This includes the API implementation, schema definition, features
entries, and API permission info.

Bug: 877240

Change-Id: I8b750143cdcd36700f36d9da088ebaec4abd4cfe
Reviewed-on: https://chromium-review.googlesource.com/1255584Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Reviewed-by: default avatarTommy Li <tommycli@chromium.org>
Commit-Queue: Devlin <rdevlin.cronin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#595866}
parent 3401067a
......@@ -27,15 +27,28 @@ source_set("api") {
"browser/browser_api.h",
"browser_context_keyed_service_factories.cc",
"browser_context_keyed_service_factories.h",
"media_galleries/blob_data_source_factory.cc",
"media_galleries/blob_data_source_factory.h",
"media_galleries/media_galleries_api.cc",
"media_galleries/media_galleries_api.h",
"media_galleries/media_galleries_api_util.cc",
"media_galleries/media_galleries_api_util.h",
]
deps = [
"//chrome/app:generated_resources_grit",
# TODO(https://crbug.com/883570): It'd be nice to have more APIs here
# extracted into their own BUILD files (so they are easy to audit, add, or
# remove), but any that depend on //chrome/browser:browser can't.
"//chrome/browser/apps/platform_apps/api/music_manager_private",
"//chrome/browser/extensions",
"//chrome/browser/ui",
"//chrome/common",
"//chrome/common/apps/platform_apps/api",
"//chrome/services/media_gallery_util/public/cpp",
"//components/storage_monitor",
"//components/web_modal",
"//extensions/browser",
]
......@@ -52,7 +65,6 @@ source_set("api") {
deps += [
"//chrome:strings",
"//chrome/browser/chromeos",
"//chrome/browser/ui",
"//chromeos/components/proximity_auth",
"//chromeos/components/proximity_auth/logging",
"//components/account_id",
......
......@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/api/media_galleries/blob_data_source_factory.h"
#include "chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.h"
#include "content/public/browser/browser_context.h"
#include "extensions/browser/blob_reader.h"
#include "mojo/public/cpp/bindings/binding.h"
namespace extensions {
namespace chrome_apps {
namespace api {
namespace {
// Media data source that reads data from a blob in browser process.
......@@ -80,4 +81,5 @@ BlobDataSourceFactory::CreateMediaDataSource(
blob_uuid_, media_data_callback);
}
} // namespace extensions
} // namespace api
} // namespace chrome_apps
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_
#define CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_
#ifndef CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_
#define CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_
#include <memory>
#include <string>
......@@ -16,7 +16,8 @@ namespace content {
class BrowserContext;
} // namespace content
namespace extensions {
namespace chrome_apps {
namespace api {
// Factory to provide media data source for extension media gallery API.
// Internally it will read media data from a blob in browser process.
......@@ -40,6 +41,7 @@ class BlobDataSourceFactory
DISALLOW_COPY_AND_ASSIGN(BlobDataSourceFactory);
};
} // namespace extensions
} // namespace api
} // namespace chrome_apps
#endif // CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_
#endif // CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_BLOB_DATA_SOURCE_FACTORY_H_
......@@ -4,7 +4,7 @@
// Implements the Chrome Extensions Media Galleries API.
#include "chrome/browser/extensions/api/media_galleries/media_galleries_api.h"
#include "chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.h"
#include <stddef.h>
......@@ -23,9 +23,9 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/apps/platform_apps/api/media_galleries/blob_data_source_factory.h"
#include "chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/media_galleries/blob_data_source_factory.h"
#include "chrome/browser/extensions/api/media_galleries/media_galleries_api_util.h"
#include "chrome/browser/extensions/chrome_extension_function_details.h"
#include "chrome/browser/extensions/extension_tab_util.h"
#include "chrome/browser/media_galleries/gallery_watch_manager.h"
......@@ -36,7 +36,7 @@
#include "chrome/browser/platform_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/chrome_select_file_policy.h"
#include "chrome/common/extensions/api/media_galleries.h"
#include "chrome/common/apps/platform_apps/api/media_galleries.h"
#include "chrome/common/pref_names.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/services/media_gallery_util/public/cpp/safe_media_metadata_parser.h"
......@@ -70,9 +70,10 @@ using content::WebContents;
using storage_monitor::MediaStorageUtil;
using storage_monitor::StorageInfo;
namespace extensions {
namespace chrome_apps {
namespace api {
namespace MediaGalleries = api::media_galleries;
namespace MediaGalleries = media_galleries;
namespace GetMediaFileSystems = MediaGalleries::GetMediaFileSystems;
namespace AddGalleryWatch = MediaGalleries::AddGalleryWatch;
namespace RemoveGalleryWatch = MediaGalleries::RemoveGalleryWatch;
......@@ -112,8 +113,8 @@ GalleryWatchManager* gallery_watch_manager() {
// initializes the MediaGalleriesPreferences
bool Setup(Profile* profile, std::string* error, base::Closure callback) {
if (!ChromeSelectFilePolicy::FileSelectDialogsAllowed()) {
*error = std::string(kDisallowedByPolicy) +
prefs::kAllowFileSelectionDialogs;
*error =
std::string(kDisallowedByPolicy) + prefs::kAllowFileSelectionDialogs;
return false;
}
......@@ -127,7 +128,7 @@ bool Setup(Profile* profile, std::string* error, base::Closure callback) {
// |gallery_id| is valid and returns false otherwise.
bool GetGalleryFilePathAndId(const std::string& gallery_id,
Profile* profile,
const Extension* extension,
const extensions::Extension* extension,
base::FilePath* gallery_file_path,
MediaGalleryPrefId* gallery_pref_id) {
MediaGalleryPrefId pref_id;
......@@ -146,24 +147,25 @@ bool GetGalleryFilePathAndId(const std::string& gallery_id,
base::ListValue* ConstructFileSystemList(
content::RenderFrameHost* rfh,
const Extension* extension,
const extensions::Extension* extension,
const std::vector<MediaFileSystemInfo>& filesystems) {
if (!rfh)
return NULL;
MediaGalleriesPermission::CheckParam read_param(
MediaGalleriesPermission::kReadPermission);
const PermissionsData* permissions_data = extension->permissions_data();
extensions::MediaGalleriesPermission::CheckParam read_param(
extensions::MediaGalleriesPermission::kReadPermission);
const extensions::PermissionsData* permissions_data =
extension->permissions_data();
bool has_read_permission = permissions_data->CheckAPIPermissionWithParam(
APIPermission::kMediaGalleries, &read_param);
MediaGalleriesPermission::CheckParam copy_to_param(
MediaGalleriesPermission::kCopyToPermission);
extensions::APIPermission::kMediaGalleries, &read_param);
extensions::MediaGalleriesPermission::CheckParam copy_to_param(
extensions::MediaGalleriesPermission::kCopyToPermission);
bool has_copy_to_permission = permissions_data->CheckAPIPermissionWithParam(
APIPermission::kMediaGalleries, &copy_to_param);
MediaGalleriesPermission::CheckParam delete_param(
MediaGalleriesPermission::kDeletePermission);
extensions::APIPermission::kMediaGalleries, &copy_to_param);
extensions::MediaGalleriesPermission::CheckParam delete_param(
extensions::MediaGalleriesPermission::kDeletePermission);
bool has_delete_permission = permissions_data->CheckAPIPermissionWithParam(
APIPermission::kMediaGalleries, &delete_param);
extensions::APIPermission::kMediaGalleries, &delete_param);
const int child_id = rfh->GetProcess()->GetID();
std::unique_ptr<base::ListValue> list(new base::ListValue());
......@@ -217,8 +219,7 @@ class SelectDirectoryDialog : public ui::SelectFileDialog::Listener,
typedef base::Callback<void(const base::FilePath&)> Callback;
SelectDirectoryDialog(WebContents* web_contents, const Callback& callback)
: web_contents_(web_contents),
callback_(callback) {
: web_contents_(web_contents), callback_(callback) {
select_file_dialog_ = ui::SelectFileDialog::Create(
this, std::make_unique<ChromeSelectFilePolicy>(web_contents));
}
......@@ -226,14 +227,10 @@ class SelectDirectoryDialog : public ui::SelectFileDialog::Listener,
void Show(const base::FilePath& default_path) {
AddRef(); // Balanced in the two reachable listener outcomes.
select_file_dialog_->SelectFile(
ui::SelectFileDialog::SELECT_FOLDER,
l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY_TITLE),
default_path,
NULL,
0,
base::FilePath::StringType(),
platform_util::GetTopLevel(web_contents_->GetNativeView()),
NULL);
ui::SelectFileDialog::SELECT_FOLDER,
l10n_util::GetStringUTF16(IDS_MEDIA_GALLERIES_DIALOG_ADD_GALLERY_TITLE),
default_path, NULL, 0, base::FilePath::StringType(),
platform_util::GetTopLevel(web_contents_->GetNativeView()), NULL);
}
// ui::SelectFileDialog::Listener implementation.
......@@ -281,8 +278,9 @@ content::WebContents* GetWebContentsForPrompt(
// Otherwise, check for the current app window for the app (app windows
// support modal dialogs).
if (!app_id.empty()) {
AppWindow* window = AppWindowRegistry::Get(browser_context)
->GetCurrentAppWindowForApp(app_id);
extensions::AppWindow* window =
extensions::AppWindowRegistry::Get(browser_context)
->GetCurrentAppWindowForApp(app_id);
if (window)
return window->web_contents();
}
......@@ -297,30 +295,29 @@ MediaGalleriesEventRouter::MediaGalleriesEventRouter(
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(profile_);
EventRouter::Get(profile_)->RegisterObserver(
extensions::EventRouter::Get(profile_)->RegisterObserver(
this, MediaGalleries::OnGalleryChanged::kEventName);
gallery_watch_manager()->AddObserver(profile_, this);
}
MediaGalleriesEventRouter::~MediaGalleriesEventRouter() {
}
MediaGalleriesEventRouter::~MediaGalleriesEventRouter() {}
void MediaGalleriesEventRouter::Shutdown() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
weak_ptr_factory_.InvalidateWeakPtrs();
EventRouter::Get(profile_)->UnregisterObserver(this);
extensions::EventRouter::Get(profile_)->UnregisterObserver(this);
gallery_watch_manager()->RemoveObserver(profile_);
}
static base::LazyInstance<
BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>>::DestructorAtExit
static base::LazyInstance<extensions::BrowserContextKeyedAPIFactory<
MediaGalleriesEventRouter>>::DestructorAtExit
g_media_galleries_api_factory = LAZY_INSTANCE_INITIALIZER;
// static
BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>*
extensions::BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>*
MediaGalleriesEventRouter::GetFactoryInstance() {
return g_media_galleries_api_factory.Pointer();
}
......@@ -331,23 +328,24 @@ MediaGalleriesEventRouter* MediaGalleriesEventRouter::Get(
DCHECK(media_file_system_registry()
->GetPreferences(Profile::FromBrowserContext(context))
->IsInitialized());
return BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>::Get(context);
return extensions::BrowserContextKeyedAPIFactory<
MediaGalleriesEventRouter>::Get(context);
}
bool MediaGalleriesEventRouter::ExtensionHasGalleryChangeListener(
const std::string& extension_id) const {
return EventRouter::Get(profile_)->ExtensionHasEventListener(
return extensions::EventRouter::Get(profile_)->ExtensionHasEventListener(
extension_id, MediaGalleries::OnGalleryChanged::kEventName);
}
void MediaGalleriesEventRouter::DispatchEventToExtension(
const std::string& extension_id,
events::HistogramValue histogram_value,
extensions::events::HistogramValue histogram_value,
const std::string& event_name,
std::unique_ptr<base::ListValue> event_args) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
EventRouter* router = EventRouter::Get(profile_);
extensions::EventRouter* router = extensions::EventRouter::Get(profile_);
if (!router->ExtensionHasEventListener(extension_id, event_name))
return;
......@@ -357,29 +355,31 @@ void MediaGalleriesEventRouter::DispatchEventToExtension(
}
void MediaGalleriesEventRouter::OnGalleryChanged(
const std::string& extension_id, MediaGalleryPrefId gallery_id) {
const std::string& extension_id,
MediaGalleryPrefId gallery_id) {
MediaGalleries::GalleryChangeDetails details;
details.type = MediaGalleries::GALLERY_CHANGE_TYPE_CONTENTS_CHANGED;
details.gallery_id = base::NumberToString(gallery_id);
DispatchEventToExtension(extension_id,
events::MEDIA_GALLERIES_ON_GALLERY_CHANGED,
MediaGalleries::OnGalleryChanged::kEventName,
MediaGalleries::OnGalleryChanged::Create(details));
DispatchEventToExtension(
extension_id, extensions::events::MEDIA_GALLERIES_ON_GALLERY_CHANGED,
MediaGalleries::OnGalleryChanged::kEventName,
MediaGalleries::OnGalleryChanged::Create(details));
}
void MediaGalleriesEventRouter::OnGalleryWatchDropped(
const std::string& extension_id, MediaGalleryPrefId gallery_id) {
const std::string& extension_id,
MediaGalleryPrefId gallery_id) {
MediaGalleries::GalleryChangeDetails details;
details.type = MediaGalleries::GALLERY_CHANGE_TYPE_WATCH_DROPPED;
details.gallery_id = gallery_id;
DispatchEventToExtension(extension_id,
events::MEDIA_GALLERIES_ON_GALLERY_CHANGED,
MediaGalleries::OnGalleryChanged::kEventName,
MediaGalleries::OnGalleryChanged::Create(details));
DispatchEventToExtension(
extension_id, extensions::events::MEDIA_GALLERIES_ON_GALLERY_CHANGED,
MediaGalleries::OnGalleryChanged::kEventName,
MediaGalleries::OnGalleryChanged::Create(details));
}
void MediaGalleriesEventRouter::OnListenerRemoved(
const EventListenerInfo& details) {
const extensions::EventListenerInfo& details) {
if (details.event_name == MediaGalleries::OnGalleryChanged::kEventName &&
!ExtensionHasGalleryChangeListener(details.extension_id)) {
gallery_watch_manager()->RemoveAllWatches(profile_, details.extension_id);
......@@ -393,20 +393,22 @@ MediaGalleriesGetMediaFileSystemsFunction::
~MediaGalleriesGetMediaFileSystemsFunction() {}
bool MediaGalleriesGetMediaFileSystemsFunction::RunAsync() {
media_galleries::UsageCount(media_galleries::GET_MEDIA_FILE_SYSTEMS);
::media_galleries::UsageCount(::media_galleries::GET_MEDIA_FILE_SYSTEMS);
std::unique_ptr<GetMediaFileSystems::Params> params(
GetMediaFileSystems::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
MediaGalleries::GetMediaFileSystemsInteractivity interactive =
MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO;
if (params->details.get() && params->details->interactive != MediaGalleries::
GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE) {
if (params->details.get() &&
params->details->interactive !=
MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE) {
interactive = params->details->interactive;
}
return Setup(GetProfile(), &error_, base::Bind(
&MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit, this,
interactive));
return Setup(
GetProfile(), &error_,
base::Bind(&MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit,
this, interactive));
}
void MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit(
......@@ -470,11 +472,9 @@ void MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries(
}
void MediaGalleriesGetMediaFileSystemsFunction::ShowDialog() {
media_galleries::UsageCount(media_galleries::SHOW_DIALOG);
WebContents* contents =
GetWebContentsForPrompt(GetSenderWebContents(),
browser_context(),
extension()->id());
::media_galleries::UsageCount(::media_galleries::SHOW_DIALOG);
WebContents* contents = GetWebContentsForPrompt(
GetSenderWebContents(), browser_context(), extension()->id());
if (!contents) {
SendResponse(false);
return;
......@@ -505,17 +505,18 @@ MediaGalleriesAddUserSelectedFolderFunction::
~MediaGalleriesAddUserSelectedFolderFunction() {}
bool MediaGalleriesAddUserSelectedFolderFunction::RunAsync() {
media_galleries::UsageCount(media_galleries::ADD_USER_SELECTED_FOLDER);
return Setup(GetProfile(), &error_, base::Bind(
&MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit, this));
::media_galleries::UsageCount(::media_galleries::ADD_USER_SELECTED_FOLDER);
return Setup(
GetProfile(), &error_,
base::Bind(
&MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit,
this));
}
void MediaGalleriesAddUserSelectedFolderFunction::OnPreferencesInit() {
const std::string& app_id = extension()->id();
WebContents* contents =
GetWebContentsForPrompt(GetSenderWebContents(),
browser_context(),
app_id);
WebContents* contents = GetWebContentsForPrompt(GetSenderWebContents(),
browser_context(), app_id);
if (!contents) {
SendResponse(false);
return;
......@@ -542,26 +543,22 @@ void MediaGalleriesAddUserSelectedFolderFunction::OnDirectorySelected(
// User cancelled case.
GetMediaFileSystemsForExtension(base::Bind(
&MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId,
this,
kInvalidMediaGalleryPrefId));
this, kInvalidMediaGalleryPrefId));
return;
}
extensions::file_system_api::SetLastChooseEntryDirectory(
extensions::ExtensionPrefs::Get(GetProfile()),
extension()->id(),
extensions::ExtensionPrefs::Get(GetProfile()), extension()->id(),
selected_directory);
MediaGalleriesPreferences* preferences =
media_file_system_registry()->GetPreferences(GetProfile());
MediaGalleryPrefId pref_id =
preferences->AddGalleryByPath(selected_directory,
MediaGalleryPrefInfo::kUserAdded);
MediaGalleryPrefId pref_id = preferences->AddGalleryByPath(
selected_directory, MediaGalleryPrefInfo::kUserAdded);
preferences->SetGalleryPermissionForExtension(*extension(), pref_id, true);
GetMediaFileSystemsForExtension(base::Bind(
&MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId,
this,
&MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId, this,
pref_id));
}
......@@ -591,9 +588,8 @@ void MediaGalleriesAddUserSelectedFolderFunction::ReturnGalleriesAndId(
SendResponse(true);
}
void
MediaGalleriesAddUserSelectedFolderFunction::GetMediaFileSystemsForExtension(
const MediaFileSystemsCallback& cb) {
void MediaGalleriesAddUserSelectedFolderFunction::
GetMediaFileSystemsForExtension(const MediaFileSystemsCallback& cb) {
if (!render_frame_host()) {
cb.Run(std::vector<MediaFileSystemInfo>());
return;
......@@ -610,7 +606,7 @@ MediaGalleriesAddUserSelectedFolderFunction::GetMediaFileSystemsForExtension(
MediaGalleriesGetMetadataFunction::~MediaGalleriesGetMetadataFunction() {}
bool MediaGalleriesGetMetadataFunction::RunAsync() {
media_galleries::UsageCount(media_galleries::GET_METADATA);
::media_galleries::UsageCount(::media_galleries::GET_METADATA);
std::string blob_uuid;
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &blob_uuid));
......@@ -622,9 +618,9 @@ bool MediaGalleriesGetMetadataFunction::RunAsync() {
if (!options)
return false;
return Setup(GetProfile(), &error_, base::Bind(
&MediaGalleriesGetMetadataFunction::OnPreferencesInit, this,
options->metadata_type, blob_uuid));
return Setup(GetProfile(), &error_,
base::Bind(&MediaGalleriesGetMetadataFunction::OnPreferencesInit,
this, options->metadata_type, blob_uuid));
}
void MediaGalleriesGetMetadataFunction::OnPreferencesInit(
......@@ -633,11 +629,10 @@ void MediaGalleriesGetMetadataFunction::OnPreferencesInit(
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
// BlobReader is self-deleting.
BlobReader* reader = new BlobReader(
GetProfile(),
blob_uuid,
base::Bind(&MediaGalleriesGetMetadataFunction::GetMetadata, this,
metadata_type, blob_uuid));
BlobReader* reader =
new BlobReader(GetProfile(), blob_uuid,
base::Bind(&MediaGalleriesGetMetadataFunction::GetMetadata,
this, metadata_type, blob_uuid));
reader->SetByteRange(0, net::kMaxBytesToSniff);
reader->Start();
}
......@@ -791,8 +786,7 @@ void MediaGalleriesGetMetadataFunction::ConstructNextBlob(
// MediaGalleriesAddGalleryWatchFunction //
///////////////////////////////////////////////////////////////////////////////
MediaGalleriesAddGalleryWatchFunction::
~MediaGalleriesAddGalleryWatchFunction() {
}
~MediaGalleriesAddGalleryWatchFunction() {}
bool MediaGalleriesAddGalleryWatchFunction::RunAsync() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
......@@ -809,8 +803,7 @@ bool MediaGalleriesAddGalleryWatchFunction::RunAsync() {
GetProfile());
preferences->EnsureInitialized(
base::Bind(&MediaGalleriesAddGalleryWatchFunction::OnPreferencesInit,
this,
params->gallery_id));
this, params->gallery_id));
return true;
}
......@@ -819,11 +812,8 @@ void MediaGalleriesAddGalleryWatchFunction::OnPreferencesInit(
const std::string& pref_id) {
base::FilePath gallery_file_path;
MediaGalleryPrefId gallery_pref_id = kInvalidMediaGalleryPrefId;
if (!GetGalleryFilePathAndId(pref_id,
GetProfile(),
extension(),
&gallery_file_path,
&gallery_pref_id)) {
if (!GetGalleryFilePathAndId(pref_id, GetProfile(), extension(),
&gallery_file_path, &gallery_pref_id)) {
api::media_galleries::AddGalleryWatchResult result;
error_ = kInvalidGalleryIdMsg;
result.gallery_id = kInvalidGalleryId;
......@@ -834,11 +824,8 @@ void MediaGalleriesAddGalleryWatchFunction::OnPreferencesInit(
}
gallery_watch_manager()->AddWatch(
GetProfile(),
extension(),
gallery_pref_id,
base::Bind(&MediaGalleriesAddGalleryWatchFunction::HandleResponse,
this,
GetProfile(), extension(), gallery_pref_id,
base::Bind(&MediaGalleriesAddGalleryWatchFunction::HandleResponse, this,
gallery_pref_id));
}
......@@ -876,8 +863,7 @@ void MediaGalleriesAddGalleryWatchFunction::HandleResponse(
///////////////////////////////////////////////////////////////////////////////
MediaGalleriesRemoveGalleryWatchFunction::
~MediaGalleriesRemoveGalleryWatchFunction() {
}
~MediaGalleriesRemoveGalleryWatchFunction() {}
bool MediaGalleriesRemoveGalleryWatchFunction::RunAsync() {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
......@@ -893,8 +879,7 @@ bool MediaGalleriesRemoveGalleryWatchFunction::RunAsync() {
GetProfile());
preferences->EnsureInitialized(
base::Bind(&MediaGalleriesRemoveGalleryWatchFunction::OnPreferencesInit,
this,
params->gallery_id));
this, params->gallery_id));
return true;
}
......@@ -902,19 +887,17 @@ void MediaGalleriesRemoveGalleryWatchFunction::OnPreferencesInit(
const std::string& pref_id) {
base::FilePath gallery_file_path;
MediaGalleryPrefId gallery_pref_id = 0;
if (!GetGalleryFilePathAndId(pref_id,
GetProfile(),
extension(),
&gallery_file_path,
&gallery_pref_id)) {
if (!GetGalleryFilePathAndId(pref_id, GetProfile(), extension(),
&gallery_file_path, &gallery_pref_id)) {
error_ = kInvalidGalleryIdMsg;
SendResponse(false);
return;
}
gallery_watch_manager()->RemoveWatch(
GetProfile(), extension_id(), gallery_pref_id);
gallery_watch_manager()->RemoveWatch(GetProfile(), extension_id(),
gallery_pref_id);
SendResponse(true);
}
} // namespace extensions
} // namespace api
} // namespace chrome_apps
......@@ -5,8 +5,8 @@
// Defines the Chrome Extensions Media Galleries API functions for accessing
// user's media files, as specified in the extension API IDL.
#ifndef CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_H_
#define CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_H_
#ifndef CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_H_
#define CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_H_
#include <stdint.h>
......@@ -20,7 +20,7 @@
#include "chrome/browser/extensions/chrome_extension_function.h"
#include "chrome/browser/media_galleries/gallery_watch_manager_observer.h"
#include "chrome/browser/media_galleries/media_file_system_registry.h"
#include "chrome/common/extensions/api/media_galleries.h"
#include "chrome/common/apps/platform_apps/api/media_galleries.h"
#include "chrome/common/media_galleries/metadata_types.h"
#include "chrome/services/media_gallery_util/public/mojom/media_parser.mojom.h"
#include "components/storage_monitor/media_storage_util.h"
......@@ -28,19 +28,18 @@
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_event_histogram_value.h"
namespace MediaGalleries = extensions::api::media_galleries;
namespace content {
class BlobHandle;
}
class SafeMediaMetadataParser;
namespace extensions {
namespace chrome_apps {
namespace api {
// The profile-keyed service that manages the media galleries extension API.
// Created at the same time as the Profile. This is also the event router.
class MediaGalleriesEventRouter : public BrowserContextKeyedAPI,
class MediaGalleriesEventRouter : public extensions::BrowserContextKeyedAPI,
public GalleryWatchManagerObserver,
public extensions::EventRouter::Observer {
public:
......@@ -48,8 +47,8 @@ class MediaGalleriesEventRouter : public BrowserContextKeyedAPI,
void Shutdown() override;
// BrowserContextKeyedAPI implementation.
static BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>*
GetFactoryInstance();
static extensions::BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>*
GetFactoryInstance();
// Convenience method to get the MediaGalleriesAPI for a profile.
static MediaGalleriesEventRouter* Get(content::BrowserContext* context);
......@@ -57,20 +56,20 @@ class MediaGalleriesEventRouter : public BrowserContextKeyedAPI,
bool ExtensionHasGalleryChangeListener(const std::string& extension_id) const;
private:
friend class BrowserContextKeyedAPIFactory<MediaGalleriesEventRouter>;
friend class extensions::BrowserContextKeyedAPIFactory<
MediaGalleriesEventRouter>;
void DispatchEventToExtension(const std::string& extension_id,
events::HistogramValue histogram_value,
const std::string& event_name,
std::unique_ptr<base::ListValue> event_args);
void DispatchEventToExtension(
const std::string& extension_id,
extensions::events::HistogramValue histogram_value,
const std::string& event_name,
std::unique_ptr<base::ListValue> event_args);
explicit MediaGalleriesEventRouter(content::BrowserContext* context);
~MediaGalleriesEventRouter() override;
// BrowserContextKeyedAPI implementation.
static const char* service_name() {
return "MediaGalleriesAPI";
}
static const char* service_name() { return "MediaGalleriesAPI"; }
static const bool kServiceIsNULLWhileTesting = true;
// GalleryWatchManagerObserver
......@@ -80,7 +79,7 @@ class MediaGalleriesEventRouter : public BrowserContextKeyedAPI,
MediaGalleryPrefId gallery_id) override;
// extensions::EventRouter::Observer implementation.
void OnListenerRemoved(const EventListenerInfo& details) override;
void OnListenerRemoved(const extensions::EventListenerInfo& details) override;
// Current profile.
Profile* profile_;
......@@ -103,7 +102,7 @@ class MediaGalleriesGetMediaFileSystemsFunction
private:
// Bottom half for RunAsync, invoked after the preferences is initialized.
void OnPreferencesInit(
MediaGalleries::GetMediaFileSystemsInteractivity interactive);
media_galleries::GetMediaFileSystemsInteractivity interactive);
// Always show the dialog.
void AlwaysShowDialog(const std::vector<MediaFileSystemInfo>& filesystems);
......@@ -171,10 +170,10 @@ class MediaGalleriesGetMetadataFunction : public ChromeAsyncExtensionFunction {
private:
// Bottom half for RunAsync, invoked after the preferences is initialized.
void OnPreferencesInit(MediaGalleries::GetMetadataType metadata_type,
void OnPreferencesInit(media_galleries::GetMetadataType metadata_type,
const std::string& blob_uuid);
void GetMetadata(MediaGalleries::GetMetadataType metadata_type,
void GetMetadata(media_galleries::GetMetadataType metadata_type,
const std::string& blob_uuid,
std::unique_ptr<std::string> blob_header,
int64_t total_blob_length);
......@@ -223,6 +222,7 @@ class MediaGalleriesRemoveGalleryWatchFunction
void OnPreferencesInit(const std::string& pref_id);
};
} // namespace extensions
} // namespace api
} // namespace chrome_apps
#endif // CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_H_
#endif // CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_H_
......@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/api/media_galleries/media_galleries_api_util.h"
#include "chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api_util.h"
#include "base/logging.h"
#include "chrome/common/extensions/api/media_galleries.h"
#include "chrome/common/apps/platform_apps/api/media_galleries.h"
namespace extensions {
namespace chrome_apps {
namespace api {
template <class T>
void SetValueScopedPtr(T value, std::unique_ptr<T>* destination) {
......@@ -27,7 +28,7 @@ void SetValueScopedPtr(std::string value,
std::unique_ptr<base::DictionaryValue> SerializeMediaMetadata(
chrome::mojom::MediaMetadataPtr metadata) {
DCHECK(metadata);
extensions::api::media_galleries::MediaMetadata extension_metadata;
media_galleries::MediaMetadata extension_metadata;
extension_metadata.mime_type = std::move(metadata->mime_type);
if (metadata->height >= 0 && metadata->width >= 0) {
extension_metadata.height.reset(new int(metadata->height));
......@@ -49,7 +50,7 @@ std::unique_ptr<base::DictionaryValue> SerializeMediaMetadata(
SetValueScopedPtr(metadata->track, &extension_metadata.track);
for (const chrome::mojom::MediaStreamInfoPtr& info : metadata->raw_tags) {
extensions::api::media_galleries::StreamInfo stream_info;
media_galleries::StreamInfo stream_info;
stream_info.type = std::move(info->type);
base::DictionaryValue* dict_value;
info->additional_properties.GetAsDictionary(&dict_value);
......@@ -60,4 +61,5 @@ std::unique_ptr<base::DictionaryValue> SerializeMediaMetadata(
return extension_metadata.ToValue();
}
} // namespace extensions
} // namespace api
} // namespace chrome_apps
......@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_
#define CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_
#ifndef CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_
#define CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_
#include <memory>
......@@ -13,13 +13,15 @@ namespace base {
class DictionaryValue;
} // namespace base
namespace extensions {
namespace chrome_apps {
namespace api {
// Converts a mojo media metadata struct into a dictionary. Internally uses
// extension's auto generated serializer.
std::unique_ptr<base::DictionaryValue> SerializeMediaMetadata(
chrome::mojom::MediaMetadataPtr metadata);
} // namespace extensions
} // namespace api
} // namespace chrome_apps
#endif // CHROME_BROWSER_EXTENSIONS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_
#endif // CHROME_BROWSER_APPS_PLATFORM_APPS_API_MEDIA_GALLERIES_MEDIA_GALLERIES_API_UTIL_H_
......@@ -18,9 +18,9 @@
#include "base/threading/thread_restrictions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/apps/platform_apps/api/media_galleries/media_galleries_api.h"
#include "chrome/browser/apps/platform_apps/app_browsertest_util.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/api/media_galleries/media_galleries_api.h"
#include "chrome/browser/media_galleries/media_file_system_registry.h"
#include "chrome/browser/media_galleries/media_galleries_preferences.h"
#include "chrome/browser/media_galleries/media_galleries_test_util.h"
......@@ -156,8 +156,7 @@ class MediaGalleriesPlatformAppBrowserTest : public PlatformAppBrowserTest {
MediaGalleriesPreferences* preferences = GetAndInitializePreferences();
// Make a copy, as the iterator would be invalidated otherwise.
const MediaGalleriesPrefInfoMap galleries =
preferences->known_galleries();
const MediaGalleriesPrefInfoMap galleries = preferences->known_galleries();
for (MediaGalleriesPrefInfoMap::const_iterator it = galleries.begin();
it != galleries.end(); ++it) {
preferences->ForgetGalleryById(it->first);
......@@ -178,15 +177,11 @@ class MediaGalleriesPlatformAppBrowserTest : public PlatformAppBrowserTest {
ASSERT_FALSE(preferences->LookUpGalleryByPath(
fake_gallery_temp_dir_.GetPath(), &gallery_info));
MediaGalleryPrefId id = preferences->AddGallery(
gallery_info.device_id,
gallery_info.path,
MediaGalleryPrefInfo::kAutoDetected,
gallery_info.volume_label,
gallery_info.vendor_name,
gallery_info.model_name,
gallery_info.total_size_in_bytes,
gallery_info.last_attach_time,
0, 0, 0);
gallery_info.device_id, gallery_info.path,
MediaGalleryPrefInfo::kAutoDetected, gallery_info.volume_label,
gallery_info.vendor_name, gallery_info.model_name,
gallery_info.total_size_in_bytes, gallery_info.last_attach_time, 0, 0,
0);
if (pref_id)
*pref_id = id;
......@@ -210,8 +205,8 @@ class MediaGalleriesPlatformAppBrowserTest : public PlatformAppBrowserTest {
base::FilePath GetCommonDataDir() const {
return test_data_dir_.AppendASCII("api_test")
.AppendASCII("media_galleries")
.AppendASCII("common");
.AppendASCII("media_galleries")
.AppendASCII("common");
}
int num_galleries() const {
......@@ -256,15 +251,13 @@ class MediaGalleriesPlatformAppPpapiTest
ASSERT_TRUE(base::PathService::Get(chrome::DIR_GEN_TEST_DATA, &app_dir_));
app_dir_ = app_dir_.AppendASCII("ppapi")
.AppendASCII("tests")
.AppendASCII("extensions")
.AppendASCII("media_galleries")
.AppendASCII("newlib");
.AppendASCII("tests")
.AppendASCII("extensions")
.AppendASCII("media_galleries")
.AppendASCII("newlib");
}
const base::FilePath& app_dir() const {
return app_dir_;
}
const base::FilePath& app_dir() const { return app_dir_; }
private:
base::FilePath app_dir_;
......
......@@ -151,18 +151,12 @@ class MediaGalleriesGalleryWatchApiTest : public extensions::ExtensionApiTest {
MediaGalleryPrefInfo gallery_info;
ASSERT_FALSE(preferences->LookUpGalleryByPath(test_gallery_.GetPath(),
&gallery_info));
MediaGalleryPrefId id =
preferences->AddGallery(gallery_info.device_id,
gallery_info.path,
MediaGalleryPrefInfo::kAutoDetected,
gallery_info.volume_label,
gallery_info.vendor_name,
gallery_info.model_name,
gallery_info.total_size_in_bytes,
gallery_info.last_attach_time,
0,
0,
0);
MediaGalleryPrefId id = preferences->AddGallery(
gallery_info.device_id, gallery_info.path,
MediaGalleryPrefInfo::kAutoDetected, gallery_info.volume_label,
gallery_info.vendor_name, gallery_info.model_name,
gallery_info.total_size_in_bytes, gallery_info.last_attach_time, 0, 0,
0);
preferences->SetGalleryPermissionForExtension(*extension_, id, true);
}
......@@ -220,10 +214,9 @@ IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest,
kAddGalleryChangedListenerOK);
SetupGalleryWatches();
// Modify gallery contents; expect correct details.
ExtensionTestMessageListener got_correct_details(
kOnGalleryChangedCheckingOK, false);
ExtensionTestMessageListener got_correct_details(kOnGalleryChangedCheckingOK,
false);
ASSERT_TRUE(AddNewFileInTestGallery());
EXPECT_TRUE(got_correct_details.WaitUntilSatisfied());
}
......@@ -287,6 +280,6 @@ IN_PROC_BROWSER_TEST_F(MediaGalleriesGalleryWatchApiTest,
ExecuteCmdAndCheckReply(kAddGalleryChangedListenerCmd,
kAddGalleryChangedListenerOK);
// Set up a invalid gallery watch.
ExecuteCmdAndCheckReply(
kSetupWatchOnInvalidGalleryCmd, kAddGalleryWatchRequestFailed);
ExecuteCmdAndCheckReply(kSetupWatchOnInvalidGalleryCmd,
kAddGalleryWatchRequestFailed);
}
......@@ -238,12 +238,6 @@ jumbo_static_library("extensions") {
"api/language_settings_private/language_settings_private_delegate_factory.h",
"api/management/chrome_management_api_delegate.cc",
"api/management/chrome_management_api_delegate.h",
"api/media_galleries/blob_data_source_factory.cc",
"api/media_galleries/blob_data_source_factory.h",
"api/media_galleries/media_galleries_api.cc",
"api/media_galleries/media_galleries_api.h",
"api/media_galleries/media_galleries_api_util.cc",
"api/media_galleries/media_galleries_api_util.h",
"api/messaging/chrome_messaging_delegate.cc",
"api/messaging/chrome_messaging_delegate.h",
"api/messaging/incognito_connectability.cc",
......@@ -803,7 +797,6 @@ jumbo_static_library("extensions") {
"//chrome/common/extensions:mojo_bindings",
"//chrome/common/extensions/api:extensions_features",
"//chrome/common/safe_browsing:proto",
"//chrome/services/media_gallery_util/public/cpp",
"//chrome/services/removable_storage_writer/public/mojom",
"//components/app_modal",
"//components/autofill/content/browser",
......
......@@ -15,6 +15,10 @@
"dependencies": ["permission:easyUnlockPrivate"],
"contexts": ["blessed_extension"]
},
"mediaGalleries": {
"dependencies": ["permission:mediaGalleries"],
"contexts": ["blessed_extension"]
},
"musicManagerPrivate": {
"dependencies": ["permission:musicManagerPrivate"],
"contexts": ["blessed_extension"]
......
......@@ -17,6 +17,32 @@
"location": "component",
"platforms": ["chromeos"]
},
"mediaGalleries": {
"channel": "stable",
"extension_types": [ "platform_app" ]
},
// TODO(devlin): These all specify the same permissions. There's no need for
// child features.
"mediaGalleries.allAutoDetected": {
"channel": "stable",
"extension_types": [ "platform_app" ]
},
"mediaGalleries.scan": {
"channel": "dev",
"extension_types": [ "platform_app" ]
},
"mediaGalleries.read": {
"channel": "stable",
"extension_types": [ "platform_app" ]
},
"mediaGalleries.copyTo": {
"channel": "stable",
"extension_types": [ "platform_app" ]
},
"mediaGalleries.delete": {
"channel": "stable",
"extension_types": [ "platform_app" ]
},
"musicManagerPrivate": {
"channel": "stable",
"extension_types": ["platform_app"],
......
......@@ -7,7 +7,10 @@ import("//chrome/common/features.gni")
assert(enable_extensions)
chrome_apps_api_schema_files_ = [ "browser.idl" ]
chrome_apps_api_schema_files_ = [
"browser.idl",
"media_galleries.idl",
]
if (is_chromeos) {
chrome_apps_api_schema_files_ += [ "easy_unlock_private.idl" ]
......
......@@ -4,9 +4,17 @@
#include "chrome/common/apps/platform_apps/chrome_apps_api_permissions.h"
#include "extensions/common/permissions/media_galleries_permission.h"
namespace chrome_apps_api_permissions {
namespace {
template <typename T>
extensions::APIPermission* CreateAPIPermission(
const extensions::APIPermissionInfo* permission) {
return new T(permission);
}
// WARNING: If you are modifying a permission message in this list, be sure to
// add the corresponding permission message rule to
// ChromePermissionMessageProvider::GetPermissionMessages as well.
......@@ -15,6 +23,9 @@ constexpr extensions::APIPermissionInfo::InitInfo permissions_to_register[] = {
{extensions::APIPermission::kEasyUnlockPrivate, "easyUnlockPrivate"},
{extensions::APIPermission::kMusicManagerPrivate, "musicManagerPrivate",
extensions::APIPermissionInfo::kFlagCannotBeOptional},
{extensions::APIPermission::kMediaGalleries, "mediaGalleries",
extensions::APIPermissionInfo::kFlagNone,
&CreateAPIPermission<extensions::MediaGalleriesPermission>},
};
} // namespace
......
......@@ -570,10 +570,6 @@
"channel": "stable",
"contexts": ["blessed_extension"]
},
"mediaGalleries": {
"dependencies": ["permission:mediaGalleries"],
"contexts": ["blessed_extension"]
},
"mediaPlayerPrivate": {
"dependencies": ["permission:mediaPlayerPrivate"],
"contexts": ["blessed_extension"]
......
......@@ -515,30 +515,6 @@
"session_types": ["kiosk"]
}
],
"mediaGalleries": {
"channel": "stable",
"extension_types": [ "platform_app" ]
},
"mediaGalleries.allAutoDetected": {
"channel": "stable",
"extension_types": [ "platform_app" ]
},
"mediaGalleries.scan": {
"channel": "dev",
"extension_types": [ "platform_app" ]
},
"mediaGalleries.read": {
"channel": "stable",
"extension_types": [ "platform_app" ]
},
"mediaGalleries.copyTo": {
"channel": "stable",
"extension_types": [ "platform_app" ]
},
"mediaGalleries.delete": {
"channel": "stable",
"extension_types": [ "platform_app" ]
},
"mediaPlayerPrivate": {
"channel": "stable",
"extension_types": ["extension", "legacy_packaged_app", "platform_app"],
......
......@@ -48,7 +48,6 @@ schema_sources_ = [
"instance_id.json",
"language_settings_private.idl",
"manifest_types.json",
"media_galleries.idl",
"notifications.idl",
"omnibox.json",
"page_capture.json",
......
......@@ -12,7 +12,6 @@
#include "base/memory/ptr_util.h"
#include "extensions/common/permissions/api_permission.h"
#include "extensions/common/permissions/api_permission_set.h"
#include "extensions/common/permissions/media_galleries_permission.h"
#include "extensions/common/permissions/permissions_info.h"
#include "extensions/common/permissions/settings_override_permission.h"
......@@ -205,9 +204,6 @@ constexpr APIPermissionInfo::InitInfo permissions_to_register[] = {
// Platform-app permissions.
{APIPermission::kFileSystemProvider, "fileSystemProvider"},
{APIPermission::kMediaGalleries, "mediaGalleries",
APIPermissionInfo::kFlagNone,
&CreateAPIPermission<MediaGalleriesPermission>},
{APIPermission::kPointerLock, "pointerLock"},
{APIPermission::kCastStreaming, "cast.streaming"},
{APIPermission::kLauncherSearchProvider, "launcherSearchProvider"},
......
......@@ -1203,6 +1203,8 @@ test("browser_tests") {
sources += [
"../browser/accessibility/accessibility_extension_api_browsertest.cc",
"../browser/apps/platform_apps/api/browser/browser_apitest.cc",
"../browser/apps/platform_apps/api/media_galleries/media_galleries_apitest.cc",
"../browser/apps/platform_apps/api/media_galleries/media_galleries_watch_apitest.cc",
"../browser/apps/platform_apps/api/music_manager_private/music_manager_private_browsertest.cc",
"../browser/apps/platform_apps/app_browsertest_util.cc",
"../browser/apps/platform_apps/app_browsertest_util.h",
......@@ -1261,8 +1263,6 @@ test("browser_tests") {
"../browser/extensions/api/management/management_api_browsertest.cc",
"../browser/extensions/api/management/management_apitest.cc",
"../browser/extensions/api/management/management_browsertest.cc",
"../browser/extensions/api/media_galleries/media_galleries_apitest.cc",
"../browser/extensions/api/media_galleries/media_galleries_watch_apitest.cc",
"../browser/extensions/api/messaging/native_messaging_apitest.cc",
"../browser/extensions/api/metrics_private/metrics_apitest.cc",
"../browser/extensions/api/module/module_apitest.cc",
......
......@@ -25,6 +25,7 @@ namespace extensions {
// {"mediaGalleries": "read delete"},
// We also allow a permission without any sub-permissions:
// "mediaGalleries",
// TODO(devlin): Move this class to chrome/common/apps/platform_apps.
class MediaGalleriesPermission
: public SetDisjunctionPermission<MediaGalleriesPermissionData,
MediaGalleriesPermission> {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment