summaryrefslogtreecommitdiff
path: root/chromium/chrome/common/apps/platform_apps
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/chrome/common/apps/platform_apps')
-rw-r--r--chromium/chrome/common/apps/platform_apps/OWNERS2
-rw-r--r--chromium/chrome/common/apps/platform_apps/api/arc_apps_private.idl33
-rw-r--r--chromium/chrome/common/apps/platform_apps/api/browser.idl26
-rw-r--r--chromium/chrome/common/apps/platform_apps/api/media_galleries.idl255
-rw-r--r--chromium/chrome/common/apps/platform_apps/api/music_manager_private.idl16
-rw-r--r--chromium/chrome/common/apps/platform_apps/api/sync_file_system.idl199
-rw-r--r--chromium/chrome/common/apps/platform_apps/api/webstore_widget_private.idl24
-rw-r--r--chromium/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc45
-rw-r--r--chromium/chrome/common/apps/platform_apps/chrome_apps_api_permissions.h19
-rw-r--r--chromium/chrome/common/apps/platform_apps/chrome_apps_api_provider.cc65
-rw-r--r--chromium/chrome/common/apps/platform_apps/chrome_apps_api_provider.h36
-rw-r--r--chromium/chrome/common/apps/platform_apps/chrome_apps_message_generator.cc30
-rw-r--r--chromium/chrome/common/apps/platform_apps/chrome_apps_message_generator.h11
-rw-r--r--chromium/chrome/common/apps/platform_apps/chrome_apps_messages.h15
-rw-r--r--chromium/chrome/common/apps/platform_apps/media_galleries_permission.cc157
-rw-r--r--chromium/chrome/common/apps/platform_apps/media_galleries_permission.h63
-rw-r--r--chromium/chrome/common/apps/platform_apps/media_galleries_permission_data.cc60
-rw-r--r--chromium/chrome/common/apps/platform_apps/media_galleries_permission_data.h50
-rw-r--r--chromium/chrome/common/apps/platform_apps/media_galleries_permission_unittest.cc304
19 files changed, 1410 insertions, 0 deletions
diff --git a/chromium/chrome/common/apps/platform_apps/OWNERS b/chromium/chrome/common/apps/platform_apps/OWNERS
new file mode 100644
index 00000000000..42444bcd16d
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/OWNERS
@@ -0,0 +1,2 @@
+per-file *_messages*.h=set noparent
+per-file *_messages*.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/chrome/common/apps/platform_apps/api/arc_apps_private.idl b/chromium/chrome/common/apps/platform_apps/api/arc_apps_private.idl
new file mode 100644
index 00000000000..1a3dd23237c
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/api/arc_apps_private.idl
@@ -0,0 +1,33 @@
+// Copyright 2018 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.
+
+// Use the <code>chrome.arcAppsPrivate</code> API to manage ARC apps.
+[platforms=("chromeos"), nodoc]
+namespace arcAppsPrivate {
+
+ dictionary AppInfo {
+ // The app package name.
+ DOMString packageName;
+ };
+
+ callback VoidCallback = void ();
+ callback GetLaunchableAppsCallback = void (AppInfo[] appsInfo);
+
+ interface Functions {
+ // Returns info of the installed ARC apps that are launchable, including
+ // ready and non-ready apps.
+ static void getLaunchableApps(GetLaunchableAppsCallback callback);
+
+ // Launches the ARC app with its package name. The app is launched
+ // immediately if it's ready, otherwise it will be launched when it becomes
+ // ready. The callback is called as soon as the launch is scheduled.
+ static void launchApp(DOMString packageName,
+ optional VoidCallback callback);
+ };
+
+ interface Events {
+ // Fires when a new app can be launched via $(ref:launchApp).
+ static void onInstalled(AppInfo app_info);
+ };
+};
diff --git a/chromium/chrome/common/apps/platform_apps/api/browser.idl b/chromium/chrome/common/apps/platform_apps/api/browser.idl
new file mode 100644
index 00000000000..971164bd068
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/api/browser.idl
@@ -0,0 +1,26 @@
+// Copyright 2014 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.
+
+// Use the <code>chrome.browser</code> API to interact with the Chrome browser
+// associated with the current application and Chrome profile.
+namespace browser {
+ // Options for the $(ref:openTab) function.
+ dictionary OpenTabOptions {
+ // The URL to navigate to when the new tab is initially opened.
+ DOMString url;
+ };
+
+ callback Callback = void();
+
+ interface Functions {
+ // Opens a new tab in a browser window associated with the current
+ // application and Chrome profile. If no browser window for the Chrome
+ // profile is opened, a new one is opened prior to creating the new tab.
+ // |options|: Configures how the tab should be opened.
+ // |callback|: Called when the tab was successfully created, or failed to
+ // be created. If failed, $(ref:runtime.lastError) will be set.
+ static void openTab(OpenTabOptions options,
+ optional Callback callback);
+ };
+};
diff --git a/chromium/chrome/common/apps/platform_apps/api/media_galleries.idl b/chromium/chrome/common/apps/platform_apps/api/media_galleries.idl
new file mode 100644
index 00000000000..ebbb1f35db3
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/api/media_galleries.idl
@@ -0,0 +1,255 @@
+// 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.
+
+
+// Use the <code>chrome.mediaGalleries</code> API to access media files (audio,
+// images, video) from the user's local disks (with the user's consent).
+namespace mediaGalleries {
+
+ [inline_doc] enum GalleryChangeType {
+ // The contents of the gallery have changed.
+ contents_changed,
+ // The watch has been dropped because the device has been detached,
+ // the gallery permission has been removed, or any other reason.
+ watch_dropped
+ };
+
+ [inline_doc] enum GetMediaFileSystemsInteractivity {
+ // Do not act interactively.
+ no,
+ // Ask the user to manage permitted media galleries.
+ yes,
+ // Ask the user to manage permitted galleries only if the return set would
+ // otherwise be empty.
+ if_needed
+ };
+
+ [inline_doc] enum GetMetadataType {
+ // Retrieve the mime type, metadata tags, and attached images.
+ all,
+ // Retrieve only the mime type and the metadata tags.
+ mimeTypeAndTags,
+ // Retrieve only the mime type.
+ mimeTypeOnly
+ };
+
+ [nodefine, inline_doc] enum ScanProgressType {
+ // The scan started.
+ start,
+ // The scan was cancelled.
+ cancel,
+ // The scan finished but none of the result have been added,
+ // addScanResults() has to be called to ask the user for permission.
+ finish,
+ // The scan encountered an error and could not proceed.
+ error
+ };
+
+ [inline_doc] dictionary GalleryChangeDetails {
+ // Type of change event.
+ GalleryChangeType type;
+
+ // Identifies the modified gallery.
+ DOMString galleryId;
+ };
+
+ [inline_doc] dictionary MediaFileSystemsDetails {
+ // Whether to prompt the user for permission to additional media galleries
+ // before returning the permitted set. Default is silent. If the value
+ // 'yes' is passed, or if the application has not been granted access to
+ // any media galleries and the value 'if_needed' is passed, then the
+ // media gallery configuration dialog will be displayed.
+ GetMediaFileSystemsInteractivity? interactive;
+ };
+
+ [inline_doc] dictionary MediaMetadataOptions {
+ // Specifies which subset of the metadata to retrieve. Defaults to 'all'
+ // if the option is omitted.
+ GetMetadataType? metadataType;
+ };
+
+ callback MediaFileSystemsCallback =
+ void ([instanceOf=DOMFileSystem] object[] mediaFileSystems);
+
+ callback AddUserFolderCallback =
+ void ([instanceOf=DOMFileSystem] object[] mediaFileSystems,
+ DOMString selectedFileSystemName);
+
+ [nodefine] callback DropPermissionForMediaFileSystemCallback = void ();
+
+ [inline_doc] dictionary MediaFileSystemMetadata {
+ // The name of the file system.
+ DOMString name;
+
+ // A unique and persistent id for the media gallery.
+ DOMString galleryId;
+
+ // If the media gallery is on a removable device, a unique id for the
+ // device while the device is online.
+ DOMString? deviceId;
+
+ // True if the media gallery is on a removable device.
+ boolean isRemovable;
+
+ // True if the device the media gallery is on was detected as a media
+ // device. i.e. a PTP or MTP device, or a DCIM directory is present.
+ boolean isMediaDevice;
+
+ // True if the device is currently available.
+ boolean isAvailable;
+ };
+
+ [nodefine, inline_doc] dictionary ScanProgressDetails {
+ // The type of progress event, i.e. start, finish, etc.
+ ScanProgressType type;
+
+ // The number of Galleries found.
+ long? galleryCount;
+
+ // Appoximate number of media files found; some file types can be either
+ // audio or video and are included in both counts.
+ long? audioCount;
+ long? imageCount;
+ long? videoCount;
+ };
+
+ callback MediaFileSystemsMetadataCallback =
+ void (MediaFileSystemMetadata[] metadata);
+
+ dictionary StreamInfo {
+ // Describes format of container or codec of stream, i.e. "mp3", "h264".
+ DOMString type;
+
+ // An unfiltered string->string dictionary of tags for the stream.
+ object tags;
+ };
+
+ dictionary MediaMetadata {
+ // The browser sniffed mime type.
+ DOMString mimeType;
+
+ // Defined for video. In pixels.
+ long? height;
+ long? width;
+
+ // Defined for audio and video. In seconds.
+ double? duration;
+
+ // Defined for video. In degrees.
+ long? rotation;
+
+ // Defined for audio and video.
+ DOMString? album;
+ DOMString? artist;
+ DOMString? comment;
+ DOMString? copyright;
+ long? disc;
+ DOMString? genre;
+ DOMString? language;
+ DOMString? title;
+ long? track;
+
+ // All the metadata in the media file. For formats with multiple streams,
+ // stream order will be preserved. Container metadata is the first element.
+ StreamInfo[] rawTags;
+
+ // The images embedded in the media file's metadata. This is most often
+ // used for album art or video thumbnails.
+ [instanceOf=Blob] object[] attachedImages;
+ };
+
+ callback MediaMetadataCallback = void (MediaMetadata metadata);
+
+ // A dictionary that describes the add gallery watch request results.
+ dictionary AddGalleryWatchResult {
+ DOMString galleryId;
+ boolean success;
+ };
+
+ callback AddGalleryWatchCallback = void (AddGalleryWatchResult result);
+ [nodefine] callback GetAllGalleryWatchCallback =
+ void (DOMString[] galleryIds);
+
+ interface Functions {
+ // Get the media galleries configured in this user agent. If none are
+ // configured or available, the callback will receive an empty array.
+ static void getMediaFileSystems(optional MediaFileSystemsDetails details,
+ MediaFileSystemsCallback callback);
+
+ // Present a directory picker to the user and add the selected directory
+ // as a gallery. If the user cancels the picker, selectedFileSystemName
+ // will be empty.
+ // A user gesture is required for the dialog to display. Without a user
+ // gesture, the callback will run as though the user canceled.
+ static void addUserSelectedFolder(AddUserFolderCallback callback);
+
+ // Give up access to a given media gallery.
+ [nodefine, deprecated="The user can manually drop access to galleries
+ via the permissions dialog."]
+ static void dropPermissionForMediaFileSystem(
+ DOMString galleryId,
+ optional DropPermissionForMediaFileSystemCallback callback);
+
+ // Start a scan of the user's hard disks for directories containing media.
+ // The scan may take a long time so progress and completion is communicated
+ // by events. No permission is granted as a result of the scan, see
+ // addScanResults.
+ [nodefine, deprecated="The mediaGalleries API no longer supports scanning."]
+ static void startMediaScan();
+
+ // Cancel any pending media scan. Well behaved apps should provide a way
+ // for the user to cancel scans they start.
+ [nodefine, deprecated="The mediaGalleries API no longer supports scanning."]
+ static void cancelMediaScan();
+
+ // Show the user the scan results and let them add any or all of them as
+ // galleries. This should be used after the 'finish' onScanProgress()
+ // event has happened. All galleries the app has access to are returned, not
+ // just the newly added galleries.
+ [nodefine, deprecated="The mediaGalleries API no longer supports scanning."]
+ static void addScanResults(MediaFileSystemsCallback callback);
+
+ // Get metadata about a specific media file system.
+ [nocompile] static MediaFileSystemMetadata getMediaFileSystemMetadata(
+ [instanceOf=DOMFileSystem] object mediaFileSystem);
+
+ // Get metadata for all available media galleries.
+ [nodefine, deprecated="Use getMediaFileSystemMetadata instead."]
+ static void getAllMediaFileSystemMetadata(
+ MediaFileSystemsMetadataCallback callback);
+
+ // Gets the media-specific metadata for a media file. This should work
+ // for files in media galleries as well as other DOM filesystems.
+ static void getMetadata([instanceOf=Blob] object mediaFile,
+ optional MediaMetadataOptions options,
+ MediaMetadataCallback callback);
+
+ // Adds a gallery watch for the gallery with the specified gallery ID.
+ // The given callback is then fired with a success or failure result.
+ static void addGalleryWatch(DOMString galleryId,
+ AddGalleryWatchCallback callback);
+
+ // Removes a gallery watch for the gallery with the specified gallery ID.
+ static void removeGalleryWatch(DOMString galleryId);
+
+ // Notifies which galleries are being watched via the given callback.
+ [nodefine, deprecated="Applications should store their own gallery watches
+ as they are added."]
+ static void getAllGalleryWatch(GetAllGalleryWatchCallback callback);
+
+ // Removes all gallery watches.
+ [nodefine, deprecated="Use removeGalleryWatch instead."]
+ static void removeAllGalleryWatch();
+ };
+
+ interface Events {
+ // Fired when a media gallery is changed or a gallery watch is dropped.
+ static void onGalleryChanged(GalleryChangeDetails details);
+
+ // The pending media scan has changed state. See details for more
+ // information.
+ [nodefine, deprecated="The mediaGalleries API no longer supports scanning."]
+ static void onScanProgress(ScanProgressDetails details);
+ };
+};
diff --git a/chromium/chrome/common/apps/platform_apps/api/music_manager_private.idl b/chromium/chrome/common/apps/platform_apps/api/music_manager_private.idl
new file mode 100644
index 00000000000..b6d13fba921
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/api/music_manager_private.idl
@@ -0,0 +1,16 @@
+// Copyright 2013 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.
+
+// musicManagerPrivate.
+namespace musicManagerPrivate {
+
+ callback GetDeviceIdCallback = void (DOMString device_id);
+
+ interface Functions {
+ // Returns an identifier stable across users and reboots.
+ //
+ // |callback| : Called with the stable identifier value.
+ static void getDeviceId(GetDeviceIdCallback callback);
+ };
+};
diff --git a/chromium/chrome/common/apps/platform_apps/api/sync_file_system.idl b/chromium/chrome/common/apps/platform_apps/api/sync_file_system.idl
new file mode 100644
index 00000000000..711625661e9
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/api/sync_file_system.idl
@@ -0,0 +1,199 @@
+// 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.
+
+// Use the <code>chrome.syncFileSystem</code> API to save and synchronize data
+// on Google Drive. This API is NOT for accessing arbitrary user docs stored in
+// Google Drive. It provides app-specific syncable storage for offline and
+// caching usage so that the same data can be available across different
+// clients. Read <a href="app_storage.html">Manage Data</a> for more on using
+// this API.
+namespace syncFileSystem {
+ enum SyncAction {
+ added, updated, deleted
+ };
+
+ enum ServiceStatus {
+ // The sync service is being initialized (e.g. restoring data from the
+ // database, checking connectivity and authenticating to the service etc).
+ initializing,
+
+ // The sync service is up and running.
+ running,
+
+ // The sync service is not synchronizing files because the remote service
+ // needs to be authenticated by the user to proceed.
+ authentication_required,
+
+ // The sync service is not synchronizing files because the remote service
+ // is (temporarily) unavailable due to some recoverable errors, e.g.
+ // network is offline, the remote service is down or not
+ // reachable etc. More details should be given by |description| parameter
+ // in OnServiceInfoUpdated (which could contain service-specific details).
+ temporary_unavailable,
+
+ // The sync service is disabled and the content will never sync.
+ // (E.g. this could happen when the user has no account on
+ // the remote service or the sync service has had an unrecoverable
+ // error.)
+ disabled
+ };
+
+ enum FileStatus {
+ // Not conflicting and has no pending local changes.
+ synced,
+
+ // Has one or more pending local changes that haven't been synchronized.
+ pending,
+
+ // File conflicts with remote version and must be resolved manually.
+ conflicting
+ };
+
+ enum SyncDirection {
+ local_to_remote, remote_to_local
+ };
+
+ enum ConflictResolutionPolicy {
+ last_write_win, manual
+ };
+
+ dictionary FileInfo {
+ // <code>fileEntry</code> for the target file whose status has changed.
+ // Contains name and path information of synchronized file.
+ // On file deletion,
+ // <code>fileEntry</code> information will still be available
+ // but file will no longer exist.
+ [instanceOf=Entry] object fileEntry;
+
+ // Resulting file status after $(ref:onFileStatusChanged) event.
+ // The status value can be <code>'synced'</code>,
+ // <code>'pending'</code> or <code>'conflicting'</code>.
+ FileStatus status;
+
+ // Sync action taken to fire $(ref:onFileStatusChanged) event.
+ // The action value can be
+ // <code>'added'</code>, <code>'updated'</code> or <code>'deleted'</code>.
+ // Only applies if status is <code>'synced'</code>.
+ SyncAction? action;
+
+ // Sync direction for the $(ref:onFileStatusChanged) event.
+ // Sync direction value can be
+ // <code>'local_to_remote'</code> or <code>'remote_to_local'</code>.
+ // Only applies if status is <code>'synced'</code>.
+ SyncDirection? direction;
+ };
+
+ dictionary FileStatusInfo {
+ // One of the Entry's originally given to getFileStatuses.
+ [instanceOf=Entry] object fileEntry;
+
+ // The status value can be <code>'synced'</code>,
+ // <code>'pending'</code> or <code>'conflicting'</code>.
+ FileStatus status;
+
+ // Optional error that is only returned if there was a problem retrieving
+ // the FileStatus for the given file.
+ DOMString? error;
+ };
+
+ dictionary StorageInfo {
+ long usageBytes;
+ long quotaBytes;
+ };
+
+ dictionary ServiceInfo {
+ ServiceStatus state;
+ DOMString description;
+ };
+
+ // A callback type for requestFileSystem.
+ callback GetFileSystemCallback =
+ void ([instanceOf=DOMFileSystem] object fileSystem);
+
+ // A callback type for getUsageAndQuota.
+ callback QuotaAndUsageCallback = void (StorageInfo info);
+
+ // Returns true if operation was successful.
+ callback DeleteFileSystemCallback = void (boolean result);
+
+ // A callback type for getFileStatus.
+ callback GetFileStatusCallback = void (FileStatus status);
+
+ // A callback type for getFileStatuses.
+ callback GetFileStatusesCallback = void (FileStatusInfo[] status);
+
+ // A callback type for getServiceStatus.
+ callback GetServiceStatusCallback = void (ServiceStatus status);
+
+ // A callback type for getConflictResolutionPolicy.
+ callback GetConflictResolutionPolicyCallback =
+ void (ConflictResolutionPolicy policy);
+
+ // A generic result callback to indicate success or failure.
+ callback ResultCallback = void ();
+
+ interface Functions {
+ // Returns a syncable filesystem backed by Google Drive.
+ // The returned <code>DOMFileSystem</code> instance can be operated on
+ // in the same way as the Temporary and Persistant file systems (see
+ // <a href="http://dev.w3.org/2009/dap/file-system/file-dir-sys.html">
+ // http://dev.w3.org/2009/dap/file-system/file-dir-sys.html</a>).
+ //
+ // Calling this multiple times from
+ // the same app will return the same handle to the same file system.
+ //
+ // Note this call can fail. For example, if the user is not signed in to
+ // Chrome or if there is no network operation. To handle these errors it is
+ // important chrome.runtime.lastError is checked in the callback.
+ static void requestFileSystem(GetFileSystemCallback callback);
+
+ // Sets the default conflict resolution policy
+ // for the <code>'syncable'</code> file storage for the app.
+ // By default it is set to <code>'last_write_win'</code>.
+ // When conflict resolution policy is set to <code>'last_write_win'</code>
+ // conflicts for existing files are automatically resolved next time
+ // the file is updated.
+ // |callback| can be optionally given to know if the request has
+ // succeeded or not.
+ static void setConflictResolutionPolicy(
+ ConflictResolutionPolicy policy,
+ optional ResultCallback callback);
+
+ // Gets the current conflict resolution policy.
+ static void getConflictResolutionPolicy(
+ GetConflictResolutionPolicyCallback callback);
+
+ // Returns the current usage and quota in bytes
+ // for the <code>'syncable'</code> file storage for the app.
+ static void getUsageAndQuota([instanceOf=DOMFileSystem] object fileSystem,
+ QuotaAndUsageCallback callback);
+
+ // Returns the $(ref:FileStatus) for the given <code>fileEntry</code>.
+ // The status value can be <code>'synced'</code>,
+ // <code>'pending'</code> or <code>'conflicting'</code>.
+ // Note that <code>'conflicting'</code> state only happens when
+ // the service's conflict resolution policy is set to <code>'manual'</code>.
+ static void getFileStatus([instanceOf=Entry] object fileEntry,
+ GetFileStatusCallback callback);
+
+ // Returns each $(ref:FileStatus) for the given <code>fileEntry</code> array.
+ // Typically called with the result from dirReader.readEntries().
+ static void getFileStatuses(object[] fileEntries,
+ GetFileStatusesCallback callback);
+
+ // Returns the current sync backend status.
+ static void getServiceStatus(GetServiceStatusCallback callback);
+ };
+
+ interface Events {
+ // Fired when an error or other status change has happened in the
+ // sync backend (for example, when the sync is temporarily disabled due to
+ // network or authentication error).
+ static void onServiceStatusChanged(ServiceInfo detail);
+
+ // Fired when a file has been updated by the background sync service.
+ static void onFileStatusChanged(FileInfo detail);
+ };
+
+};
diff --git a/chromium/chrome/common/apps/platform_apps/api/webstore_widget_private.idl b/chromium/chrome/common/apps/platform_apps/api/webstore_widget_private.idl
new file mode 100644
index 00000000000..ea0d07a6778
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/api/webstore_widget_private.idl
@@ -0,0 +1,24 @@
+// Copyright 2015 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.
+
+// webstoreWidgetPrivate API.
+// This is a private API used to install apps via Chrome Web Store widget - for
+// example in Files app to install file system provider services.
+[platforms=("chromeos")]
+namespace webstoreWidgetPrivate {
+
+// Callback that does not take arguments.
+callback SimpleCallback = void();
+
+interface Functions {
+ // Requests to install a webstore item.
+ // |item_id| The id of the item to install.
+ // |silentInstallation| False to show installation prompt. True not to show.
+ // Can be set to true only for a subset of installation requests.
+ static void installWebstoreItem(DOMString itemId,
+ boolean silentInstallation,
+ SimpleCallback callback);
+};
+
+};
diff --git a/chromium/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc b/chromium/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc
new file mode 100644
index 00000000000..99e1f557bb7
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/chrome_apps_api_permissions.cc
@@ -0,0 +1,45 @@
+// Copyright 2018 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/common/apps/platform_apps/chrome_apps_api_permissions.h"
+
+#include <memory>
+
+#include "chrome/common/apps/platform_apps/media_galleries_permission.h"
+
+namespace chrome_apps_api_permissions {
+namespace {
+
+template <typename T>
+std::unique_ptr<extensions::APIPermission> CreateAPIPermission(
+ const extensions::APIPermissionInfo* permission) {
+ return std::make_unique<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.
+constexpr extensions::APIPermissionInfo::InitInfo permissions_to_register[] = {
+ {extensions::APIPermission::kArcAppsPrivate, "arcAppsPrivate"},
+ {extensions::APIPermission::kBrowser, "browser"},
+ {extensions::APIPermission::kFirstRunPrivate, "firstRunPrivate",
+ extensions::APIPermissionInfo::kFlagCannotBeOptional},
+ {extensions::APIPermission::kMusicManagerPrivate, "musicManagerPrivate",
+ extensions::APIPermissionInfo::kFlagCannotBeOptional},
+ {extensions::APIPermission::kMediaGalleries, "mediaGalleries",
+ extensions::APIPermissionInfo::kFlagNone,
+ &CreateAPIPermission<chrome_apps::MediaGalleriesPermission>},
+ {extensions::APIPermission::kPointerLock, "pointerLock"},
+ {extensions::APIPermission::kSyncFileSystem, "syncFileSystem"},
+ {extensions::APIPermission::kWebstoreWidgetPrivate, "webstoreWidgetPrivate",
+ extensions::APIPermissionInfo::kFlagCannotBeOptional},
+};
+
+} // namespace
+
+base::span<const extensions::APIPermissionInfo::InitInfo> GetPermissionInfos() {
+ return base::make_span(permissions_to_register);
+}
+
+} // namespace chrome_apps_api_permissions
diff --git a/chromium/chrome/common/apps/platform_apps/chrome_apps_api_permissions.h b/chromium/chrome/common/apps/platform_apps/chrome_apps_api_permissions.h
new file mode 100644
index 00000000000..eec3cad6d55
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/chrome_apps_api_permissions.h
@@ -0,0 +1,19 @@
+// Copyright 2018 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.
+
+#ifndef CHROME_COMMON_APPS_PLATFORM_APPS_CHROME_APPS_API_PERMISSIONS_H_
+#define CHROME_COMMON_APPS_PLATFORM_APPS_CHROME_APPS_API_PERMISSIONS_H_
+
+#include "base/containers/span.h"
+#include "extensions/common/permissions/api_permission.h"
+
+namespace chrome_apps_api_permissions {
+
+// Returns the information necessary to construct Chrome app-specific
+// APIPermissions.
+base::span<const extensions::APIPermissionInfo::InitInfo> GetPermissionInfos();
+
+} // namespace chrome_apps_api_permissions
+
+#endif // CHROME_COMMON_APPS_PLATFORM_APPS_CHROME_APPS_API_PERMISSIONS_H_
diff --git a/chromium/chrome/common/apps/platform_apps/chrome_apps_api_provider.cc b/chromium/chrome/common/apps/platform_apps/chrome_apps_api_provider.cc
new file mode 100644
index 00000000000..1f7de94c949
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/chrome_apps_api_provider.cc
@@ -0,0 +1,65 @@
+// Copyright 2018 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/common/apps/platform_apps/chrome_apps_api_provider.h"
+
+#include "chrome/common/apps/platform_apps/api/api_features.h"
+#include "chrome/common/apps/platform_apps/api/generated_schemas.h"
+#include "chrome/common/apps/platform_apps/api/permission_features.h"
+#include "chrome/common/apps/platform_apps/chrome_apps_api_permissions.h"
+#include "chrome/grit/common_resources.h"
+#include "extensions/common/alias.h"
+#include "extensions/common/features/json_feature_provider_source.h"
+#include "extensions/common/permissions/permissions_info.h"
+
+namespace chrome_apps {
+
+ChromeAppsAPIProvider::ChromeAppsAPIProvider() {}
+ChromeAppsAPIProvider::~ChromeAppsAPIProvider() = default;
+
+void ChromeAppsAPIProvider::AddAPIFeatures(
+ extensions::FeatureProvider* provider) {
+ AddChromeAppsAPIFeatures(provider);
+}
+
+void ChromeAppsAPIProvider::AddManifestFeatures(
+ extensions::FeatureProvider* provider) {
+ // No Chrome-apps-specific manifest features (yet).
+}
+
+void ChromeAppsAPIProvider::AddPermissionFeatures(
+ extensions::FeatureProvider* provider) {
+ AddChromeAppsPermissionFeatures(provider);
+}
+
+void ChromeAppsAPIProvider::AddBehaviorFeatures(
+ extensions::FeatureProvider* provider) {
+ // No Chrome-apps-specific manifest features.
+}
+
+void ChromeAppsAPIProvider::AddAPIJSONSources(
+ extensions::JSONFeatureProviderSource* json_source) {
+ json_source->LoadJSON(IDR_CHROME_APP_API_FEATURES);
+}
+
+bool ChromeAppsAPIProvider::IsAPISchemaGenerated(const std::string& name) {
+ return api::ChromeAppsGeneratedSchemas::IsGenerated(name);
+}
+
+base::StringPiece ChromeAppsAPIProvider::GetAPISchema(const std::string& name) {
+ return api::ChromeAppsGeneratedSchemas::Get(name);
+}
+
+void ChromeAppsAPIProvider::RegisterPermissions(
+ extensions::PermissionsInfo* permissions_info) {
+ permissions_info->RegisterPermissions(
+ chrome_apps_api_permissions::GetPermissionInfos(),
+ base::span<const extensions::Alias>());
+}
+
+void ChromeAppsAPIProvider::RegisterManifestHandlers() {
+ // No apps-specific manifest handlers (yet).
+}
+
+} // namespace chrome_apps
diff --git a/chromium/chrome/common/apps/platform_apps/chrome_apps_api_provider.h b/chromium/chrome/common/apps/platform_apps/chrome_apps_api_provider.h
new file mode 100644
index 00000000000..b5312b85422
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/chrome_apps_api_provider.h
@@ -0,0 +1,36 @@
+// Copyright 2018 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.
+
+#ifndef CHROME_COMMON_APPS_PLATFORM_APPS_CHROME_APPS_API_PROVIDER_H_
+#define CHROME_COMMON_APPS_PLATFORM_APPS_CHROME_APPS_API_PROVIDER_H_
+
+#include "extensions/common/extensions_api_provider.h"
+
+namespace chrome_apps {
+
+class ChromeAppsAPIProvider : public extensions::ExtensionsAPIProvider {
+ public:
+ ChromeAppsAPIProvider();
+ ~ChromeAppsAPIProvider() override;
+
+ // ExtensionsAPIProvider:
+ void AddAPIFeatures(extensions::FeatureProvider* provider) override;
+ void AddManifestFeatures(extensions::FeatureProvider* provider) override;
+ void AddPermissionFeatures(extensions::FeatureProvider* provider) override;
+ void AddBehaviorFeatures(extensions::FeatureProvider* provider) override;
+ void AddAPIJSONSources(
+ extensions::JSONFeatureProviderSource* json_source) override;
+ bool IsAPISchemaGenerated(const std::string& name) override;
+ base::StringPiece GetAPISchema(const std::string& name) override;
+ void RegisterPermissions(
+ extensions::PermissionsInfo* permissions_info) override;
+ void RegisterManifestHandlers() override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ChromeAppsAPIProvider);
+};
+
+} // namespace chrome_apps
+
+#endif // CHROME_COMMON_APPS_PLATFORM_APPS_CHROME_APPS_API_PROVIDER_H_
diff --git a/chromium/chrome/common/apps/platform_apps/chrome_apps_message_generator.cc b/chromium/chrome/common/apps/platform_apps/chrome_apps_message_generator.cc
new file mode 100644
index 00000000000..e22ff4b8edd
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/chrome_apps_message_generator.cc
@@ -0,0 +1,30 @@
+// Copyright 2018 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.
+
+// Get basic type definitions.
+#define IPC_MESSAGE_IMPL
+#include "chrome/common/apps/platform_apps/chrome_apps_message_generator.h"
+
+// Generate constructors.
+#include "ipc/struct_constructor_macros.h"
+#include "chrome/common/apps/platform_apps/chrome_apps_message_generator.h"
+
+// Generate param traits write methods.
+#include "ipc/param_traits_write_macros.h"
+namespace IPC {
+#include "chrome/common/apps/platform_apps/chrome_apps_message_generator.h"
+} // namespace IPC
+
+// Generate param traits read methods.
+#include "ipc/param_traits_read_macros.h"
+namespace IPC {
+#include "chrome/common/apps/platform_apps/chrome_apps_message_generator.h"
+} // namespace IPC
+
+// Generate param traits log methods.
+#include "ipc/param_traits_log_macros.h"
+namespace IPC {
+#include "chrome/common/apps/platform_apps/chrome_apps_message_generator.h"
+} // namespace IPC
+
diff --git a/chromium/chrome/common/apps/platform_apps/chrome_apps_message_generator.h b/chromium/chrome/common/apps/platform_apps/chrome_apps_message_generator.h
new file mode 100644
index 00000000000..1903b73d9b5
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/chrome_apps_message_generator.h
@@ -0,0 +1,11 @@
+// Copyright 2018 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.
+
+// Multiply-included file, hence no include guard.
+
+#undef CHROME_COMMON_APPS_PLATFORM_APPS_CHROME_APPS_MESSAGES_H_
+#include "chrome/common/apps/platform_apps/chrome_apps_messages.h"
+#ifndef CHROME_COMMON_APPS_PLATFORM_APPS_CHROME_APPS_MESSAGES_H_
+#error "Failed to include header chrome/common/apps/platform_apps/chrome_apps_messages.h"
+#endif
diff --git a/chromium/chrome/common/apps/platform_apps/chrome_apps_messages.h b/chromium/chrome/common/apps/platform_apps/chrome_apps_messages.h
new file mode 100644
index 00000000000..f8138b4fc56
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/chrome_apps_messages.h
@@ -0,0 +1,15 @@
+// Copyright 2018 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.
+
+#ifndef CHROME_COMMON_APPS_PLATFORM_APPS_CHROME_APPS_MESSAGES_H_
+#define CHROME_COMMON_APPS_PLATFORM_APPS_CHROME_APPS_MESSAGES_H_
+
+#include "chrome/common/apps/platform_apps/media_galleries_permission_data.h"
+#include "ipc/ipc_message_macros.h"
+
+IPC_STRUCT_TRAITS_BEGIN(chrome_apps::MediaGalleriesPermissionData)
+ IPC_STRUCT_TRAITS_MEMBER(permission())
+IPC_STRUCT_TRAITS_END()
+
+#endif // CHROME_COMMON_APPS_PLATFORM_APPS_CHROME_APPS_MESSAGES_H_
diff --git a/chromium/chrome/common/apps/platform_apps/media_galleries_permission.cc b/chromium/chrome/common/apps/platform_apps/media_galleries_permission.cc
new file mode 100644
index 00000000000..372145687f4
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/media_galleries_permission.cc
@@ -0,0 +1,157 @@
+// Copyright 2014 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/common/apps/platform_apps/media_galleries_permission.h"
+
+#include <stddef.h>
+
+#include <set>
+#include <string>
+
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "extensions/common/permissions/permissions_info.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace chrome_apps {
+
+namespace {
+
+// copyTo permission requires delete permission as a prerequisite.
+// delete permission requires read permission as a prerequisite.
+bool IsValidPermissionSet(bool has_read,
+ bool has_copy_to,
+ bool has_delete,
+ std::string* error) {
+ if (has_copy_to) {
+ if (has_read && has_delete)
+ return true;
+ if (error)
+ *error = "copyTo permission requires read and delete permissions";
+ return false;
+ }
+ if (has_delete) {
+ if (has_read)
+ return true;
+ if (error)
+ *error = "delete permission requires read permission";
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
+const char MediaGalleriesPermission::kAllAutoDetectedPermission[] =
+ "allAutoDetected";
+const char MediaGalleriesPermission::kReadPermission[] = "read";
+const char MediaGalleriesPermission::kCopyToPermission[] = "copyTo";
+const char MediaGalleriesPermission::kDeletePermission[] = "delete";
+
+MediaGalleriesPermission::MediaGalleriesPermission(
+ const extensions::APIPermissionInfo* info)
+ : SetDisjunctionPermission<MediaGalleriesPermissionData,
+ MediaGalleriesPermission>(info) {}
+
+MediaGalleriesPermission::~MediaGalleriesPermission() {}
+
+bool MediaGalleriesPermission::FromValue(
+ const base::Value* value,
+ std::string* error,
+ std::vector<std::string>* unhandled_permissions) {
+ size_t unhandled_permissions_count = 0;
+ if (unhandled_permissions)
+ unhandled_permissions_count = unhandled_permissions->size();
+ bool parsed_ok = SetDisjunctionPermission<
+ MediaGalleriesPermissionData,
+ MediaGalleriesPermission>::FromValue(value, error, unhandled_permissions);
+ if (unhandled_permissions) {
+ for (size_t i = unhandled_permissions_count;
+ i < unhandled_permissions->size(); i++) {
+ (*unhandled_permissions)[i] =
+ "{\"mediaGalleries\": [" + (*unhandled_permissions)[i] + "]}";
+ }
+ }
+ if (!parsed_ok)
+ return false;
+
+ bool has_read = false;
+ bool has_copy_to = false;
+ bool has_delete = false;
+ for (auto it = data_set_.cbegin(); it != data_set_.cend(); ++it) {
+ if (it->permission() == kAllAutoDetectedPermission) {
+ continue;
+ }
+ if (it->permission() == kReadPermission) {
+ has_read = true;
+ continue;
+ }
+ if (it->permission() == kCopyToPermission) {
+ has_copy_to = true;
+ continue;
+ }
+ if (it->permission() == kDeletePermission) {
+ has_delete = true;
+ continue;
+ }
+
+ // No other permissions, so reaching this means
+ // MediaGalleriesPermissionData is probably out of sync in some way.
+ // Fail so developers notice this.
+ NOTREACHED();
+ return false;
+ }
+
+ return IsValidPermissionSet(has_read, has_copy_to, has_delete, error);
+}
+
+extensions::PermissionIDSet MediaGalleriesPermission::GetPermissions() const {
+ extensions::PermissionIDSet result;
+
+ bool has_all_auto_detected = false;
+ bool has_read = false;
+ bool has_copy_to = false;
+ bool has_delete = false;
+
+ for (const MediaGalleriesPermissionData& data : data_set_) {
+ if (data.permission() == kAllAutoDetectedPermission)
+ has_all_auto_detected = true;
+ else if (data.permission() == kReadPermission)
+ has_read = true;
+ else if (data.permission() == kCopyToPermission)
+ has_copy_to = true;
+ else if (data.permission() == kDeletePermission)
+ has_delete = true;
+ }
+
+ if (!IsValidPermissionSet(has_read, has_copy_to, has_delete, nullptr)) {
+ NOTREACHED();
+ return result;
+ }
+
+ // If |has_all_auto_detected| is false, then Chrome will prompt the user at
+ // runtime when the extension calls the getMediaGalleries API.
+ if (!has_all_auto_detected)
+ return result;
+ // No access permission case.
+ if (!has_read)
+ return result;
+
+ // Separate PermissionMessage IDs for read, copyTo, and delete. Otherwise an
+ // extension can silently gain new access capabilities.
+ result.insert(extensions::APIPermission::kMediaGalleriesAllGalleriesRead);
+
+ // For copyTo and delete, the proper combined permission message will be
+ // derived in ChromePermissionMessageProvider::GetWarningMessages(), such
+ // that the user get 1 entry for all media galleries access permissions,
+ // rather than several separate entries.
+ if (has_copy_to)
+ result.insert(extensions::APIPermission::kMediaGalleriesAllGalleriesCopyTo);
+ if (has_delete)
+ result.insert(extensions::APIPermission::kMediaGalleriesAllGalleriesDelete);
+
+ return result;
+}
+
+} // namespace chrome_apps
diff --git a/chromium/chrome/common/apps/platform_apps/media_galleries_permission.h b/chromium/chrome/common/apps/platform_apps/media_galleries_permission.h
new file mode 100644
index 00000000000..c5792fdab85
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/media_galleries_permission.h
@@ -0,0 +1,63 @@
+// Copyright 2014 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.
+
+#ifndef CHROME_COMMON_APPS_PLATFORM_APPS_MEDIA_GALLERIES_PERMISSION_H_
+#define CHROME_COMMON_APPS_PLATFORM_APPS_MEDIA_GALLERIES_PERMISSION_H_
+
+#include "chrome/common/apps/platform_apps/chrome_apps_messages.h"
+#include "chrome/common/apps/platform_apps/media_galleries_permission_data.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/set_disjunction_permission.h"
+
+namespace chrome_apps {
+
+// Media Galleries permissions are as follows:
+// <media-galleries-permission-pattern>
+// := <access> | <access> 'allAutoDetected' | 'allAutoDetected' |
+// <access> 'scan' | 'scan'
+// <access> := 'read' | 'read' <access> | 'read' <secondary-access>
+// <secondary-access>
+// := 'delete' | 'delete' <secondary-access> |
+// 'delete' <tertiary-access>
+// <tertiary-access>
+// := 'copyTo' | 'copyTo' <tertiary-access>
+// An example of a line for mediaGalleries permissions in a manifest file:
+// {"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 extensions::SetDisjunctionPermission<MediaGalleriesPermissionData,
+ MediaGalleriesPermission> {
+ public:
+ struct CheckParam : public extensions::APIPermission::CheckParam {
+ explicit CheckParam(const std::string& permission)
+ : permission(permission) {}
+ const std::string permission;
+ };
+
+ explicit MediaGalleriesPermission(const extensions::APIPermissionInfo* info);
+ ~MediaGalleriesPermission() override;
+
+ // SetDisjunctionPermission overrides.
+ // MediaGalleriesPermission does additional checks to make sure the
+ // permissions do not contain unknown values.
+ bool FromValue(const base::Value* value,
+ std::string* error,
+ std::vector<std::string>* unhandled_permissions) override;
+
+ // extensions::APIPermission overrides.
+ extensions::PermissionIDSet GetPermissions() const override;
+
+ // Permission strings.
+ static const char kAllAutoDetectedPermission[];
+ static const char kScanPermission[];
+ static const char kReadPermission[];
+ static const char kCopyToPermission[];
+ static const char kDeletePermission[];
+};
+
+} // namespace chrome_apps
+
+#endif // CHROME_COMMON_APPS_PLATFORM_APPS_MEDIA_GALLERIES_PERMISSION_H_
diff --git a/chromium/chrome/common/apps/platform_apps/media_galleries_permission_data.cc b/chromium/chrome/common/apps/platform_apps/media_galleries_permission_data.cc
new file mode 100644
index 00000000000..148abbac461
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/media_galleries_permission_data.cc
@@ -0,0 +1,60 @@
+// Copyright 2014 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/common/apps/platform_apps/media_galleries_permission_data.h"
+
+#include "base/strings/string_util.h"
+#include "base/values.h"
+#include "chrome/common/apps/platform_apps/media_galleries_permission.h"
+
+namespace chrome_apps {
+
+MediaGalleriesPermissionData::MediaGalleriesPermissionData() {}
+
+bool MediaGalleriesPermissionData::Check(
+ const extensions::APIPermission::CheckParam* param) const {
+ if (!param)
+ return false;
+
+ const MediaGalleriesPermission::CheckParam& specific_param =
+ *static_cast<const MediaGalleriesPermission::CheckParam*>(param);
+ return permission_ == specific_param.permission;
+}
+
+std::unique_ptr<base::Value> MediaGalleriesPermissionData::ToValue() const {
+ return std::make_unique<base::Value>(permission_);
+}
+
+bool MediaGalleriesPermissionData::FromValue(const base::Value* value) {
+ if (!value)
+ return false;
+
+ std::string raw_permission;
+ if (!value->GetAsString(&raw_permission))
+ return false;
+
+ std::string permission;
+ base::TrimWhitespaceASCII(raw_permission, base::TRIM_ALL, &permission);
+
+ if (permission == MediaGalleriesPermission::kAllAutoDetectedPermission ||
+ permission == MediaGalleriesPermission::kReadPermission ||
+ permission == MediaGalleriesPermission::kCopyToPermission ||
+ permission == MediaGalleriesPermission::kDeletePermission) {
+ permission_ = permission;
+ return true;
+ }
+ return false;
+}
+
+bool MediaGalleriesPermissionData::operator<(
+ const MediaGalleriesPermissionData& rhs) const {
+ return permission_ < rhs.permission_;
+}
+
+bool MediaGalleriesPermissionData::operator==(
+ const MediaGalleriesPermissionData& rhs) const {
+ return permission_ == rhs.permission_;
+}
+
+} // namespace chrome_apps
diff --git a/chromium/chrome/common/apps/platform_apps/media_galleries_permission_data.h b/chromium/chrome/common/apps/platform_apps/media_galleries_permission_data.h
new file mode 100644
index 00000000000..495cb48d4be
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/media_galleries_permission_data.h
@@ -0,0 +1,50 @@
+// Copyright 2014 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.
+
+#ifndef CHROME_COMMON_APPS_PLATFORM_APPS_MEDIA_GALLERIES_PERMISSION_DATA_H_
+#define CHROME_COMMON_APPS_PLATFORM_APPS_MEDIA_GALLERIES_PERMISSION_DATA_H_
+
+#include <memory>
+#include <string>
+
+#include "extensions/common/permissions/api_permission.h"
+
+namespace base {
+class Value;
+}
+
+namespace chrome_apps {
+
+// A MediaGalleriesPermissionData instance represents a single part of the
+// MediaGalleriesPermission. e.g. "read" or "allAutoDetected".
+class MediaGalleriesPermissionData {
+ public:
+ MediaGalleriesPermissionData();
+
+ // Check if |param| (which must be a MediaGalleriesPermission::CheckParam)
+ // matches the encapsulated attribute.
+ bool Check(const extensions::APIPermission::CheckParam* param) const;
+
+ // Convert |this| into a base::Value.
+ std::unique_ptr<base::Value> ToValue() const;
+
+ // Populate |this| from a base::Value.
+ bool FromValue(const base::Value* value);
+
+ bool operator<(const MediaGalleriesPermissionData& rhs) const;
+ bool operator==(const MediaGalleriesPermissionData& rhs) const;
+
+ std::string permission() const { return permission_; }
+
+ // This accessor is provided for IPC_STRUCT_TRAITS_MEMBER. Please think
+ // twice before using it for anything else.
+ std::string& permission() { return permission_; }
+
+ private:
+ std::string permission_;
+};
+
+} // namespace chrome_apps
+
+#endif // CHROME_COMMON_APPS_PLATFORM_APPS_MEDIA_GALLERIES_PERMISSION_DATA_H_
diff --git a/chromium/chrome/common/apps/platform_apps/media_galleries_permission_unittest.cc b/chromium/chrome/common/apps/platform_apps/media_galleries_permission_unittest.cc
new file mode 100644
index 00000000000..d8fbc24b8be
--- /dev/null
+++ b/chromium/chrome/common/apps/platform_apps/media_galleries_permission_unittest.cc
@@ -0,0 +1,304 @@
+// Copyright (c) 2013 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.
+
+// These tests make sure MediaGalleriesPermission values are parsed correctly.
+
+#include <memory>
+
+#include "base/values.h"
+#include "chrome/common/apps/platform_apps/media_galleries_permission.h"
+#include "chrome/common/apps/platform_apps/media_galleries_permission_data.h"
+#include "extensions/common/permissions/api_permission.h"
+#include "extensions/common/permissions/permissions_info.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using content::SocketPermissionRequest;
+using extensions::SocketPermissionData;
+
+namespace chrome_apps {
+
+namespace {
+
+void CheckFromValue(extensions::APIPermission* permission,
+ base::ListValue* value,
+ bool success_expected) {
+ std::string error;
+ std::vector<std::string> unhandled;
+ EXPECT_EQ(success_expected, permission->FromValue(value, &error, &unhandled));
+ EXPECT_EQ(success_expected, error.empty());
+ EXPECT_TRUE(unhandled.empty());
+}
+
+TEST(MediaGalleriesPermissionTest, GoodValues) {
+ const extensions::APIPermissionInfo* permission_info =
+ extensions::PermissionsInfo::GetInstance()->GetByID(
+ extensions::APIPermission::kMediaGalleries);
+
+ std::unique_ptr<extensions::APIPermission> permission(
+ permission_info->CreateAPIPermission());
+
+ // access_type + all_detected
+ std::unique_ptr<base::ListValue> value(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ CheckFromValue(permission.get(), value.get(), true);
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ value->AppendString(MediaGalleriesPermission::kCopyToPermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ CheckFromValue(permission.get(), value.get(), true);
+
+ // all_detected
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ CheckFromValue(permission.get(), value.get(), true);
+
+ // access_type
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ CheckFromValue(permission.get(), value.get(), true);
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ CheckFromValue(permission.get(), value.get(), true);
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kCopyToPermission);
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ CheckFromValue(permission.get(), value.get(), true);
+
+ // Repeats do not make a difference.
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ CheckFromValue(permission.get(), value.get(), true);
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ CheckFromValue(permission.get(), value.get(), true);
+}
+
+TEST(MediaGalleriesPermissionTest, BadValues) {
+ const extensions::APIPermissionInfo* permission_info =
+ extensions::PermissionsInfo::GetInstance()->GetByID(
+ extensions::APIPermission::kMediaGalleries);
+
+ std::unique_ptr<extensions::APIPermission> permission(
+ permission_info->CreateAPIPermission());
+
+ // copyTo and delete without read
+ std::unique_ptr<base::ListValue> value(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kCopyToPermission);
+ CheckFromValue(permission.get(), value.get(), false);
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ CheckFromValue(permission.get(), value.get(), false);
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ value->AppendString(MediaGalleriesPermission::kCopyToPermission);
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ CheckFromValue(permission.get(), value.get(), false);
+
+ // copyTo without delete
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ value->AppendString(MediaGalleriesPermission::kCopyToPermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ CheckFromValue(permission.get(), value.get(), false);
+
+ // Repeats do not make a difference.
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kCopyToPermission);
+ value->AppendString(MediaGalleriesPermission::kCopyToPermission);
+ CheckFromValue(permission.get(), value.get(), false);
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ value->AppendString(MediaGalleriesPermission::kCopyToPermission);
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ CheckFromValue(permission.get(), value.get(), false);
+}
+
+TEST(MediaGalleriesPermissionTest, UnknownValues) {
+ std::string error;
+ std::vector<std::string> unhandled;
+ const extensions::APIPermissionInfo* permission_info =
+ extensions::PermissionsInfo::GetInstance()->GetByID(
+ extensions::APIPermission::kMediaGalleries);
+
+ std::unique_ptr<extensions::APIPermission> permission(
+ permission_info->CreateAPIPermission());
+
+ // A good one and an unknown one.
+ std::unique_ptr<base::ListValue> value(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ value->AppendString("Unknown");
+ EXPECT_TRUE(permission->FromValue(value.get(), &error, &unhandled));
+ EXPECT_TRUE(error.empty());
+ EXPECT_EQ(1U, unhandled.size());
+ error.clear();
+ unhandled.clear();
+
+ // Multiple unknown permissions.
+ value.reset(new base::ListValue());
+ value->AppendString("Unknown1");
+ value->AppendString("Unknown2");
+ EXPECT_TRUE(permission->FromValue(value.get(), &error, &unhandled));
+ EXPECT_TRUE(error.empty());
+ EXPECT_EQ(2U, unhandled.size());
+ error.clear();
+ unhandled.clear();
+
+ // Unnknown with a NULL argument.
+ value.reset(new base::ListValue());
+ value->AppendString("Unknown1");
+ EXPECT_FALSE(permission->FromValue(value.get(), &error, NULL));
+ EXPECT_FALSE(error.empty());
+ error.clear();
+}
+
+TEST(MediaGalleriesPermissionTest, Equal) {
+ const extensions::APIPermissionInfo* permission_info =
+ extensions::PermissionsInfo::GetInstance()->GetByID(
+ extensions::APIPermission::kMediaGalleries);
+
+ std::unique_ptr<extensions::APIPermission> permission1(
+ permission_info->CreateAPIPermission());
+ std::unique_ptr<extensions::APIPermission> permission2(
+ permission_info->CreateAPIPermission());
+
+ std::unique_ptr<base::ListValue> value(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ ASSERT_TRUE(permission1->FromValue(value.get(), NULL, NULL));
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ ASSERT_TRUE(permission2->FromValue(value.get(), NULL, NULL));
+ EXPECT_TRUE(permission1->Equal(permission2.get()));
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ ASSERT_TRUE(permission2->FromValue(value.get(), NULL, NULL));
+ EXPECT_TRUE(permission1->Equal(permission2.get()));
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ ASSERT_TRUE(permission1->FromValue(value.get(), NULL, NULL));
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ ASSERT_TRUE(permission2->FromValue(value.get(), NULL, NULL));
+ EXPECT_TRUE(permission1->Equal(permission2.get()));
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ value->AppendString(MediaGalleriesPermission::kCopyToPermission);
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ ASSERT_TRUE(permission1->FromValue(value.get(), NULL, NULL));
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ value->AppendString(MediaGalleriesPermission::kCopyToPermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ ASSERT_TRUE(permission2->FromValue(value.get(), NULL, NULL));
+ EXPECT_TRUE(permission1->Equal(permission2.get()));
+}
+
+TEST(MediaGalleriesPermissionTest, NotEqual) {
+ const extensions::APIPermissionInfo* permission_info =
+ extensions::PermissionsInfo::GetInstance()->GetByID(
+ extensions::APIPermission::kMediaGalleries);
+
+ std::unique_ptr<extensions::APIPermission> permission1(
+ permission_info->CreateAPIPermission());
+ std::unique_ptr<extensions::APIPermission> permission2(
+ permission_info->CreateAPIPermission());
+
+ std::unique_ptr<base::ListValue> value(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ ASSERT_TRUE(permission1->FromValue(value.get(), NULL, NULL));
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ value->AppendString(MediaGalleriesPermission::kCopyToPermission);
+ ASSERT_TRUE(permission2->FromValue(value.get(), NULL, NULL));
+ EXPECT_FALSE(permission1->Equal(permission2.get()));
+}
+
+TEST(MediaGalleriesPermissionTest, ToFromValue) {
+ const extensions::APIPermissionInfo* permission_info =
+ extensions::PermissionsInfo::GetInstance()->GetByID(
+ extensions::APIPermission::kMediaGalleries);
+
+ std::unique_ptr<extensions::APIPermission> permission1(
+ permission_info->CreateAPIPermission());
+ std::unique_ptr<extensions::APIPermission> permission2(
+ permission_info->CreateAPIPermission());
+
+ std::unique_ptr<base::ListValue> value(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kAllAutoDetectedPermission);
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ ASSERT_TRUE(permission1->FromValue(value.get(), NULL, NULL));
+
+ std::unique_ptr<base::Value> vtmp(permission1->ToValue());
+ ASSERT_TRUE(vtmp);
+ ASSERT_TRUE(permission2->FromValue(vtmp.get(), NULL, NULL));
+ EXPECT_TRUE(permission1->Equal(permission2.get()));
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ value->AppendString(MediaGalleriesPermission::kCopyToPermission);
+ ASSERT_TRUE(permission1->FromValue(value.get(), NULL, NULL));
+
+ vtmp = permission1->ToValue();
+ ASSERT_TRUE(vtmp);
+ ASSERT_TRUE(permission2->FromValue(vtmp.get(), NULL, NULL));
+ EXPECT_TRUE(permission1->Equal(permission2.get()));
+
+ value.reset(new base::ListValue());
+ value->AppendString(MediaGalleriesPermission::kReadPermission);
+ value->AppendString(MediaGalleriesPermission::kDeletePermission);
+ ASSERT_TRUE(permission1->FromValue(value.get(), NULL, NULL));
+
+ vtmp = permission1->ToValue();
+ ASSERT_TRUE(vtmp);
+ ASSERT_TRUE(permission2->FromValue(vtmp.get(), NULL, NULL));
+ EXPECT_TRUE(permission1->Equal(permission2.get()));
+
+ value.reset(new base::ListValue());
+ // without sub-permission
+ ASSERT_TRUE(permission1->FromValue(NULL, NULL, NULL));
+
+ vtmp = permission1->ToValue();
+ ASSERT_TRUE(vtmp);
+ ASSERT_TRUE(permission2->FromValue(vtmp.get(), NULL, NULL));
+ EXPECT_TRUE(permission1->Equal(permission2.get()));
+}
+
+} // namespace
+
+} // namespace chrome_apps