Commit 14ab0224 authored by Wei Lee's avatar Wei Lee Committed by Commit Bot

[CCA] Change the default folder to MyFiles/Camera

Design Doc: go/cros-camera:dd:cca-default-saved-folder

Bug: 1127587
Test: Take a photo and Camera folder is created and the photo is saved
there.

Change-Id: I2701ee5ed82df3df3a0ff2e65ad33f6e6145c3bd
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2407732
Commit-Queue: Wei Lee <wtlee@chromium.org>
Reviewed-by: default avatarInker Kuo <inker@chromium.org>
Cr-Commit-Position: refs/heads/master@{#809023}
parent 0a0bec54
......@@ -89,11 +89,11 @@ void ChromeCameraAppUIDelegate::SetLaunchDirectory() {
// path in it.
base::FilePath empty_file_path("/dev/null");
auto downloads_folder_path =
file_manager::util::GetDownloadsFolderForProfile(profile);
auto my_files_folder_path =
file_manager::util::GetMyFilesFolderForProfile(profile);
web_launch::WebLaunchFilesHelper::SetLaunchDirectoryAndLaunchPaths(
web_contents, web_contents->GetURL(), downloads_folder_path,
web_contents, web_contents->GetURL(), my_files_folder_path,
std::vector<base::FilePath>{empty_file_path});
web_app::WebAppTabHelper::CreateForWebContents(web_contents);
}
......@@ -119,9 +119,9 @@ void ChromeCameraAppUIDelegate::OpenFileInGallery(const std::string& name) {
Profile* profile = Profile::FromWebUI(web_ui_);
base::FilePath path =
file_manager::util::GetDownloadsFolderForProfile(profile).Append(
name_component);
base::FilePath path = file_manager::util::GetMyFilesFolderForProfile(profile)
.Append("Camera")
.Append(name_component);
auto&& file_paths = std::vector<base::FilePath>({path});
apps::mojom::FilePathsPtr launch_files =
apps::mojom::FilePaths::New(file_paths);
......
......@@ -158,6 +158,7 @@ copy("chrome_camera_app_js_models") {
"src/js/models/file_system.js",
"src/js/models/file_system_entry.js",
"src/js/models/file_util.js",
"src/js/models/lazy_directory_entry.js",
"src/js/models/mp4_video_processor.js",
"src/js/models/nop_video_processor.js",
"src/js/models/result_saver.js",
......
......@@ -40,6 +40,7 @@
<structure name="IDR_CAMERA_INIT_JS" file="src/js/init.js" type="chrome_html" />
<structure name="IDR_CAMERA_INTENT_JS" file="src/js/intent.js" type="chrome_html" />
<structure name="IDR_CAMERA_LAYOUT_JS" file="src/js/views/camera/layout.js" type="chrome_html" />
<structure name="IDR_CAMERA_LAZY_DIRECTORY_ENTRY_JS" file="src/js/models/lazy_directory_entry.js" type="chrome_html" />
<structure name="IDR_CAMERA_MAIN_CSS" file="src/css/main.css" type="chrome_html" />
<structure name="IDR_CAMERA_MAIN_HTML" file="src/views/main.html" type="chrome_html" />
<structure name="IDR_CAMERA_MAIN_JS" file="src/js/main.js" type="chrome_html" />
......
......@@ -47,6 +47,7 @@ js_library("compile_resources") {
"models/file_system.js",
"models/file_system_entry.js",
"models/file_util.js",
"models/lazy_directory_entry.js",
"models/mp4_video_processor.js",
"models/native_file_system_entry.js",
"models/nop_video_processor.js",
......
......@@ -4,7 +4,9 @@
import {assert, promisify} from '../chrome_util.js';
import {ChromeDirectoryEntry} from '../models/chrome_file_system_entry.js';
import {getMaybeLazyDirectory} from '../models/lazy_directory_entry.js';
import {Resolution} from '../type.js';
// eslint-disable-next-line no-unused-vars
import {BrowserProxy} from './browser_proxy_interface.js';
......@@ -39,7 +41,7 @@ class ChromeAppBrowserProxy {
}
/** @override */
async getExternalDir() {
async getCameraDirectory() {
let volumes;
try {
volumes = await promisify(chrome.fileSystem.getVolumeList)();
......@@ -67,9 +69,8 @@ class ChromeAppBrowserProxy {
continue;
}
const rootEntry = new ChromeDirectoryEntry(root);
const entries = await rootEntry.getDirectories();
return entries.find((entry) => entry.name === 'Downloads') || null;
const myFilesDir = new ChromeDirectoryEntry(root);
return getMaybeLazyDirectory(myFilesDir, 'Camera');
}
return null;
}
......
......@@ -25,7 +25,7 @@ export class BrowserProxy {
* @return {!Promise<?AbstractDirectoryEntry>}
* @abstract
*/
async getExternalDir() {}
async getCameraDirectory() {}
/**
* @param {(string|!Array<string>|!Object)} keys
......
......@@ -16,6 +16,7 @@ import {BackgroundOps} from '../background_ops.js';
import {assert} from '../chrome_util.js';
import {NotImplementedError} from '../error.js';
import {Intent} from '../intent.js';
import {getMaybeLazyDirectory} from '../models/lazy_directory_entry.js';
import {NativeDirectoryEntry} from '../models/native_file_system_entry.js';
import {ChromeHelper} from '../mojo/chrome_helper.js';
import {PerfLogger} from '../perf.js';
......@@ -36,7 +37,7 @@ class WebUIBrowserProxy {
}
/** @override */
async getExternalDir() {
async getCameraDirectory() {
return new Promise((resolve) => {
const launchQueue = window.launchQueue;
assert(launchQueue !== undefined);
......@@ -45,7 +46,9 @@ class WebUIBrowserProxy {
const dir =
/** @type {!FileSystemDirectoryHandle} */ (launchParams.files[0]);
assert(dir.kind === 'directory');
resolve(new NativeDirectoryEntry(dir));
const myFilesDir = new NativeDirectoryEntry(dir);
resolve(getMaybeLazyDirectory(myFilesDir, 'Camera'));
});
});
}
......
......@@ -209,9 +209,9 @@ export class App {
metrics.sendLaunchEvent({ackMigrate});
});
const externalDir = filesystem.getExternalDirectory();
assert(externalDir !== null);
this.galleryButton_.initialize(externalDir);
const cameraDir = filesystem.getCameraDirectory();
assert(cameraDir !== null);
this.galleryButton_.initialize(cameraDir);
} catch (error) {
console.error(error);
if (error && error.message === 'no-migrate') {
......
......@@ -48,17 +48,17 @@ let internalDir = null;
let internalTempDir = null;
/**
* Directory in the external file system.
* Camera directory in the external file system.
* @type {?AbstractDirectoryEntry}
*/
let externalDir = null;
let cameraDir = null;
/**
* Gets global external directory used by CCA.
* Gets camera directory used by CCA.
* @return {?AbstractDirectoryEntry}
*/
export function getExternalDirectory() {
return externalDir;
export function getCameraDirectory() {
return cameraDir;
}
/**
......@@ -86,11 +86,11 @@ function initInternalTempDir() {
}
/**
* Initializes the directory in the external file system.
* Initializes the camera directory in the external file system.
* @return {!Promise<?AbstractDirectoryEntry>} Promise for the directory result.
*/
async function initExternalDir() {
return browserProxy.getExternalDir();
async function initCameraDirectory() {
return browserProxy.getCameraDirectory();
}
/**
......@@ -122,6 +122,7 @@ function regulatePictureName(entry) {
* @return {!Promise} Promise for the operation.
*/
async function migratePictures() {
assert(cameraDir !== null);
const internalEntries = await internalDir.getFiles();
for (const entry of internalEntries) {
if (entry.name.startsWith(THUMBNAIL_PREFIX)) {
......@@ -129,8 +130,7 @@ async function migratePictures() {
continue;
}
const name = regulatePictureName(entry);
assert(externalDir !== null);
await entry.moveTo(externalDir, name);
await entry.moveTo(cameraDir, name);
}
}
......@@ -146,8 +146,8 @@ export async function initialize() {
internalTempDir = await initInternalTempDir();
assert(internalTempDir !== null);
externalDir = await initExternalDir();
assert(externalDir !== null);
cameraDir = await initCameraDirectory();
assert(cameraDir !== null);
}
/**
......@@ -198,9 +198,7 @@ export async function checkMigration(promptMigrate) {
* @return {!Promise<?AbstractFileEntry>} Promise for the result.
*/
export async function saveBlob(blob, name) {
assert(externalDir !== null);
const file = await externalDir.createFile(name);
const file = await cameraDir.createFile(name);
assert(file !== null);
await file.write(blob);
......@@ -213,9 +211,8 @@ export async function saveBlob(blob, name) {
* @throws {!Error} If failed to create video file.
*/
export async function createVideoFile() {
assert(externalDir !== null);
const name = new Filenamer().newVideoName();
const file = await externalDir.createFile(name);
const file = await cameraDir.createFile(name);
if (file === null) {
throw new Error('Failed to create video temp file.');
}
......@@ -248,7 +245,7 @@ export async function createPrivateTempVideoFile() {
* entries.
*/
export async function getEntries() {
const entries = await externalDir.getFiles();
const entries = await cameraDir.getFiles();
return entries.filter((entry) => {
if (!hasVideoPrefix(entry) && !hasImagePrefix(entry)) {
return false;
......
......@@ -125,6 +125,8 @@ export class AbstractDirectoryEntry extends AbstractFileSystemEntry {
/**
* Gets the directory given by its |name|. If the directory is not found,
* create one if |createIfNotExist| is true.
* TODO(crbug.com/1127587): Split this method to getDirectory() and
* createDirectory().
* @param {{name: string, createIfNotExist: boolean}} params
* @return {!Promise<?AbstractDirectoryEntry>} The entry of the found/created
* directory.
......
// Copyright 2020 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.
import {
AbstractDirectoryEntry, // eslint-disable-line no-unused-vars
} from './file_system_entry.js';
/**
* Gets directory entry by given |name| under |parentDir| directory. If the
* directory does not exist, returns a lazy directory which will only be created
* once there is any file written in it.
* @param {!AbstractDirectoryEntry} parentDir Parent directory.
* @param {string} name Name of the target directory.
* @return {!Promise<!AbstractDirectoryEntry>}
*/
export async function getMaybeLazyDirectory(parentDir, name) {
const targetDir =
await parentDir.getDirectory({name, createIfNotExist: false});
return targetDir !== null ? targetDir :
new LazyDirectoryEntry(parentDir, name);
}
/**
* A directory entry which will only create itself if there is any
* file/directory created under it.
* @implements {AbstractDirectoryEntry}
*/
class LazyDirectoryEntry {
/**
* @param {!AbstractDirectoryEntry} parentDirectory
* @param {string} name
*/
constructor(parentDirectory, name) {
/**
* @type {!AbstractDirectoryEntry}
* @private
*/
this.parent_ = parentDirectory;
/**
* @type {string}
* @private
*/
this.name_ = name;
/**
* @type {?AbstractDirectoryEntry}
* @private
*/
this.directory_ = null;
/**
* @type {?Promise<!AbstractDirectoryEntry>}
* @private
*/
this.creatingDirectory_ = null;
}
/**
* The name of the directory that will lazily created.
* @return {string}
*/
get name() {
return this.name_;
}
/**
* @override
*/
async getFiles() {
if (this.directory_ === null) {
return [];
}
return this.directory_.getFiles();
}
/**
* @override
*/
async getDirectories() {
if (this.directory_ === null) {
return [];
}
return this.directory_.getDirectories();
}
/**
* @override
*/
async getFile(name) {
if (this.directory_ === null) {
return null;
}
return this.directory_.getFile(name);
}
/**
* @override
*/
async createFile(name) {
const dir = await this.getRealDirectory_();
return dir.createFile(name);
}
/**
* @override
*/
async getDirectory({name, createIfNotExist}) {
if (this.directory_ === null && !createIfNotExist) {
return null;
}
const dir = await this.getRealDirectory_();
return dir.getDirectory({name, createIfNotExist});
}
/**
* Gets the directory which this entry points to. Create it if it does not
* exist.
* @return {!Promise<!AbstractDirectoryEntry>}
* @private
*/
async getRealDirectory_() {
if (this.creatingDirectory_ === null) {
this.creatingDirectory_ =
(async () => /** @type {!AbstractDirectoryEntry} */ (
await this.parent_.getDirectory(
{name: this.name_, createIfNotExist: true})))();
}
this.directory_ =
/** @type {!AbstractDirectoryEntry} */ (await this.creatingDirectory_);
return this.directory_;
}
}
......@@ -166,11 +166,18 @@ export class NativeDirectoryEntry extends NativeFileSystemEntry {
* @override
*/
async getDirectory({name, createIfNotExist}) {
const handle =
await this.handle_.getDirectoryHandle(name, {create: createIfNotExist});
assert(handle !== null);
return new NativeDirectoryEntry(
/** @type {!FileSystemDirectoryHandle} */ (handle));
try {
const handle = await this.handle_.getDirectoryHandle(
name, {create: createIfNotExist});
assert(handle !== null);
return new NativeDirectoryEntry(
/** @type {!FileSystemDirectoryHandle} */ (handle));
} catch (error) {
if (!createIfNotExist && error.name === 'NotFoundError') {
return null;
}
throw error;
}
}
/**
......
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