Commit fd924e72 authored by Noel Gordon's avatar Noel Gordon Committed by Commit Bot

Add fileManagerPrivate getContentMimeType getContentMetadata tests

Test files come from //media/test/data. Change apitest C++ to copy the
files to the 'testing' Volume before starting tests.

  id3_png_test.mp3: audio file with embedded album artwork image
  90rotation.mp4: h264 video, with 90 degree rotation, no images

Add test JS helpers to read the files from the 'testing' volume / file
system and convert them to Blobs before starting the tests.

Add fileManagerPrivate.getContentMimeType mime sniffing tests:

 testGetContentMimeTypeEmpty
   - input is an empty blob, returns undefined mimeType result
 testGetContentMimeTypeImage
   - input is an image file blob, sniff image/gif
 testGetContentMimeTypeAudio
   - input is an audio file blob, sniff audio/mpeg
 testGetContentMimeTypeVideo
   - input is a video file blob, sniff video/mp4
 testGetContentMimeTypeUnknownMimeTypeError
   - net::mime_sniffer fails, sets chrome.runtime.LastError

Add fileManagerPrivate.getContentMetadata metadata extraction tests:

 testGetContentMetadataEmpty
   - input is an empty blob, returns undefined MediaMetadata
 testGetContentMetadataAudioTags
   - extract tags only into the MediaMetadata result
   - vet result with JS verifyExpectedAudioMetadata() helper
 testGetContentMetadataAudioTagsImages
   - extract tags and images into the MediaMetadata result
   - vet result with JS verifyExpectedAudioMetadata() helper
 testGetContentMetadataVideoTagsImages
   - extract tags and images into the MediaMetadata result
   - vet result with verifyExpectedVideoMetadata() helper
 testGetContentMetadataRetainsInputMimeType
   - input mime type is copied through to MediaMetadata.mimeType
 testGetContentMetadataVideoResetsAudioMime
   - audio mime is changed to video if there is width and height
 testGetContentMetadataUnsupportedMimetypeError
   - input mime not video or audio, sets chrome.runtime.LastError

Bug: 1114622
Change-Id: Ic96ce7faa409ae25d6b3c956666bbfd7db362f25
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2345936
Commit-Queue: Noel Gordon <noel@chromium.org>
Reviewed-by: default avatarNaoki Fukino <fukino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797078}
parent e697f4f1
// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include "base/base64.h" #include "base/base64.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/path_service.h"
#include "base/run_loop.h" #include "base/run_loop.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "chrome/browser/chromeos/crostini/crostini_manager.h" #include "chrome/browser/chromeos/crostini/crostini_manager.h"
...@@ -463,6 +464,35 @@ IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, Recent) { ...@@ -463,6 +464,35 @@ IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, Recent) {
ASSERT_TRUE(RunComponentExtensionTest("file_browser/recent_test")); ASSERT_TRUE(RunComponentExtensionTest("file_browser/recent_test"));
} }
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, MediaMetadata) {
const base::FilePath test_dir = temp_dir_.GetPath();
AddLocalFileSystem(browser()->profile(), test_dir);
// Get the source tree media/test/data directory path.
base::FilePath root_dir;
CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &root_dir));
const base::FilePath media_test_data_dir =
root_dir.AppendASCII("media").AppendASCII("test").AppendASCII("data");
// Returns a path to a media/test/data test file.
auto get_media_test_data_file = [&](const std::string& file) {
return media_test_data_dir.Append(base::FilePath::FromUTF8Unsafe(file));
};
// Create test files.
{
base::ScopedAllowBlockingForTesting allow_io;
const base::FilePath video = get_media_test_data_file("90rotation.mp4");
ASSERT_TRUE(base::CopyFile(video, test_dir.Append(video.BaseName())));
const base::FilePath audio = get_media_test_data_file("id3_png_test.mp3");
ASSERT_TRUE(base::CopyFile(audio, test_dir.Append(audio.BaseName())));
}
ASSERT_TRUE(RunComponentExtensionTest("file_browser/media_metadata"));
}
IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, Crostini) { IN_PROC_BROWSER_TEST_F(FileManagerPrivateApiTest, Crostini) {
crostini::FakeCrostiniFeatures crostini_features; crostini::FakeCrostiniFeatures crostini_features;
crostini_features.set_ui_allowed(true); crostini_features.set_ui_allowed(true);
......
{
// chrome-extension://pkplfbidichfdicaijlchgnapepdginl
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtDfX9dHNh948bt00YhZBm3P6E5QLaOt+v8kXVtibQfiPtOD2FTScB/f0wX/EQWVO7BkaSOsRkTPcPIgocyMPYr2FLgqGLFlYT9nQpKJZUFNF5oJ5rG6Nv7ppf4zEB3j6da1IBRTz2yOZ+6O1TMZxol/V62/QcqrJeggsHTEPGLdr9Ua4b1Ka0xKJnJngZljsbw93FI1o+P9dAh5BS6wTPiZI/vmJVjvMTkSTnaZ3n9Go2t7A0XLcSxLcVyuLAd2mAvSN0mIviOukdM66wr7llif71nKuUt+4qvlr/r9HfwzN6pA4jkwhtS1UD+3CmB+wsHwsnohNcuu4FIQ6rgq/7QIDAQAB",
"name": "chrome.fileManagerPrivate tests",
"version": "0.1",
"manifest_version": 2,
"description": "Tests chrome.fileManagerPrivate.getContetMimeType and getContentMetadata",
"app": {
"background": {
"scripts": ["test.js"]
}
},
"permissions": [
"fileManagerPrivate",
{
"fileSystem": ["requestFileSystem"]
}
]
}
// 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.
/**
* Test files should be created before running the tests.
*/
let audioBlob = null;
let videoBlob = null;
/*
* getContentMineType of an empty blob is undefined.
*/
function testGetContentMimeTypeEmpty() {
const blob = new Blob([]);
chrome.fileManagerPrivate.getContentMimeType(blob, (mimeType) => {
chrome.test.assertEq(undefined, mimeType);
chrome.test.assertNoLastError();
chrome.test.succeed();
});
}
/*
* getContentMineType detects content mime types: image.
*/
function testGetContentMimeTypeImage() {
const image = new Uint8Array([
71, 73, 70, 56, 57, 97, 1, 0, 1, 0, 128, 0, 0, 0,
0, 0, 255, 255, 255, 33, 249, 4, 1, 0, 0, 0, 0, 44,
0, 0, 0, 0, 1, 0, 1, 0, 0, 2, 1, 68, 0, 59
]);
const blob = new Blob([image]);
chrome.fileManagerPrivate.getContentMimeType(blob, (mimeType) => {
chrome.test.assertEq('image/gif', mimeType);
chrome.test.assertNoLastError();
chrome.test.succeed();
});
}
/*
* getContentMineType detects content mime types: audio.
*/
function testGetContentMimeTypeAudio() {
const blob = audioBlob;
chrome.fileManagerPrivate.getContentMimeType(blob, (mimeType) => {
chrome.test.assertEq('audio/mpeg', mimeType);
chrome.test.assertNoLastError();
chrome.test.succeed();
});
}
/*
* getContentMineType detects content mime types: video.
*/
function testGetContentMimeTypeVideo() {
const blob = videoBlob;
chrome.fileManagerPrivate.getContentMimeType(blob, (mimeType) => {
chrome.test.assertEq('video/mp4', mimeType);
chrome.test.assertNoLastError();
chrome.test.succeed();
});
}
/*
* getContentMineType can fail to detect the blob content mime type and sets
* chrome.runtime.lastError in that case.
*/
function testGetContentMimeTypeUnknownMimeTypeError() {
const blob = new Blob([42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42]);
chrome.fileManagerPrivate.getContentMimeType(blob, (mimeType) => {
chrome.test.assertEq(undefined, mimeType);
if (!chrome.runtime.lastError) {
chrome.test.fail('chrome.runtime.lastError expected.');
} else {
chrome.test.succeed();
}
});
}
/*
* Helper to verify the audio test file metadata.
*/
function verifyExpectedAudioMetadata(metadata) {
chrome.test.assertEq('Airbag', metadata.title);
chrome.test.assertEq('Radiohead', metadata.artist);
chrome.test.assertEq('OK Computer', metadata.album);
chrome.test.assertEq('Alternative', metadata.genre);
chrome.test.assertEq('Other', metadata.comment);
chrome.test.assertEq(1.018776, metadata.duration);
chrome.test.assertEq(1, metadata.track);
// The file has 3 container streams: mp3 meta, mp3 audio, png image.
chrome.test.assertEq(3, metadata.rawTags.length);
chrome.test.assertEq('mp3', metadata.rawTags[0].type);
chrome.test.assertEq('OK Computer', metadata.rawTags[0].tags['album']);
chrome.test.assertEq('Radiohead', metadata.rawTags[0].tags['artist']);
chrome.test.assertEq('1997', metadata.rawTags[0].tags['date']);
chrome.test.assertEq('Lavf54.4.100', metadata.rawTags[0].tags['encoder']);
chrome.test.assertEq('Alternative', metadata.rawTags[0].tags['genre']);
chrome.test.assertEq('Airbag', metadata.rawTags[0].tags['title']);
chrome.test.assertEq('1', metadata.rawTags[0].tags['track']);
chrome.test.assertEq('mp3', metadata.rawTags[1].type);
// File contains an embedded album artwork thumbnail image.
chrome.test.assertEq('png', metadata.rawTags[2].type);
// Embedded images do not set the video-only width and height fields.
chrome.test.assertEq(undefined, metadata.width);
chrome.test.assertEq(undefined, metadata.height);
}
/*
* getContentMetadata of an empty blob is undefined.
*/
function testGetContentMetadataEmpty() {
const blob = new Blob([]);
chrome.fileManagerPrivate.getContentMetadata(
blob, 'audio/mpeg', 'metadataTags', (metadata) => {
chrome.test.assertEq(undefined, metadata);
chrome.test.assertNoLastError();
chrome.test.succeed();
});
}
/*
* getContentMetadata 'metadataTags' returns tags only.
*/
function testGetContentMetadataAudioTags() {
const blob = audioBlob;
chrome.fileManagerPrivate.getContentMetadata(
blob, 'audio/mpeg', 'metadataTags', (metadata) => {
chrome.test.assertEq('audio/mpeg', metadata.mimeType);
chrome.test.assertNoLastError();
verifyExpectedAudioMetadata(metadata);
chrome.test.assertEq(0, metadata.attachedImages.length);
chrome.test.succeed();
});
}
/*
* getContentMetadata 'metadataTagsImages' returns tags and images.
*/
function testGetContentMetadataAudioTagsImages() {
const blob = audioBlob;
chrome.fileManagerPrivate.getContentMetadata(
blob, 'audio/mpeg', 'metadataTagsImages', (metadata) => {
chrome.test.assertEq('audio/mpeg', metadata.mimeType);
chrome.test.assertNoLastError();
verifyExpectedAudioMetadata(metadata);
chrome.test.assertEq(1, metadata.attachedImages.length);
const data = metadata.attachedImages[0].data;
if (!data || !data.startsWith('data:image/png;base64,')) {
chrome.test.fail('Attached image expected.');
} else {
const type = metadata.attachedImages[0].type;
chrome.test.assertEq('image/png', type);
chrome.test.succeed();
}
});
}
/*
* Helper to verify the video test file metadata.
*/
function verifyExpectedVideoMetadata(metadata) {
chrome.test.assertEq(1920, metadata.width);
chrome.test.assertEq(1080, metadata.height);
chrome.test.assertEq(0.196, metadata.duration);
chrome.test.assertEq(90, metadata.rotation);
chrome.test.assertEq('eng', metadata.language);
// The file has 3 container streams: video meta, h264 video, aac audio.
chrome.test.assertEq(3, metadata.rawTags.length);
chrome.test.assertEq('mov,mp4,m4a,3gp,3g2,mj2', metadata.rawTags[0].type);
chrome.test.assertEq('isom3gp4',
metadata.rawTags[0].tags['compatible_brands']);
chrome.test.assertEq('2014-02-11T00:39:25.000000Z',
metadata.rawTags[0].tags['creation_time']);
chrome.test.assertEq('isom', metadata.rawTags[0].tags['major_brand']);
chrome.test.assertEq('0', metadata.rawTags[0].tags['minor_version']);
chrome.test.assertEq('h264', metadata.rawTags[1].type);
chrome.test.assertEq('2014-02-11T00:39:25.000000Z',
metadata.rawTags[1].tags['creation_time']);
chrome.test.assertEq('VideoHandle',
metadata.rawTags[1].tags['handler_name']);
chrome.test.assertEq('eng', metadata.rawTags[1].tags['language']);
chrome.test.assertEq('90', metadata.rawTags[1].tags['rotate']);
chrome.test.assertEq('aac', metadata.rawTags[2].type);
chrome.test.assertEq('2014-02-11T00:39:25.000000Z',
metadata.rawTags[2].tags['creation_time']);
chrome.test.assertEq('SoundHandle',
metadata.rawTags[2].tags['handler_name']);
chrome.test.assertEq('eng', metadata.rawTags[2].tags['language']);
}
/*
* getContentMetadata returns tags and images of a video file. Note: the test
* video file has no attached images.
*/
function testGetContentMetadataVideoTagsImages() {
const blob = videoBlob;
chrome.fileManagerPrivate.getContentMetadata(
blob, 'video/mp4', 'metadataTagsImages', (metadata) => {
chrome.test.assertEq('video/mp4', metadata.mimeType);
chrome.test.assertNoLastError();
verifyExpectedVideoMetadata(metadata);
chrome.test.assertEq(0, metadata.attachedImages.length);
chrome.test.succeed();
});
}
/*
* getContentMetadata returns the input mime type in the metadata mime type.
*/
function testGetContentMetadataRetainsInputMimeType() {
const blob = audioBlob;
chrome.fileManagerPrivate.getContentMetadata(
blob, 'audio/input-type', 'metadataTags', (metadata) => {
chrome.test.assertEq('audio/input-type', metadata.mimeType);
chrome.test.assertNoLastError();
chrome.test.succeed();
});
}
/*
* getContentMetadata of a video file resets audio/type mime to video/type if
* the video has width and height.
*/
function testGetContentMetadataVideoResetsAudioMime() {
const blob = videoBlob;
chrome.fileManagerPrivate.getContentMetadata(
blob, 'audio/input-type', 'metadataTagsImages', (metadata) => {
chrome.test.assertEq('video/input-type', metadata.mimeType);
chrome.test.assertNoLastError();
chrome.test.assertEq(1920, metadata.width);
chrome.test.assertEq(1080, metadata.height);
chrome.test.succeed();
});
}
/*
* getContentMetadata supports audio and video mime types only, and will set
* chrome.runtime.lastError given other mime types.
*/
function testGetContentMetadataUnsupportedMimetypeError() {
const blob = new Blob([71, 73, 70, 56, 57, 97, 1, 0, 1, 0, 128, 0]);
chrome.fileManagerPrivate.getContentMetadata(
blob, 'image/gif', 'metadataTags', (metadata) => {
chrome.test.assertEq(undefined, metadata);
if (!chrome.runtime.lastError) {
chrome.test.fail('chrome.runtime.lastError expected.');
} else {
chrome.test.succeed();
}
});
}
/*
* Resolves the test fileSystem.
*/
function resolveTestFileSystem() {
return new Promise((resolve) => {
const testVolumeType = 'testing';
chrome.fileManagerPrivate.getVolumeMetadataList(list => {
const volume = list.find(v => v.volumeType === testVolumeType);
if (!volume) {
chrome.test.fail('Failed to find testing volume.');
}
const volumeId = {volumeId: volume.volumeId};
chrome.fileSystem.requestFileSystem(volumeId, (fileSystem) => {
if (!fileSystem) {
chrome.test.fail('Failed to acquire fileSystem.');
}
resolve(fileSystem);
});
});
});
}
/*
* Resolves the content of |fileName| as a Blob.
*/
function resolveFileBlob(fileSystem, fileName) {
return new Promise((resolve) => {
const failure = (error) => {
chrome.test.fail('While reading file system: ' + error);
};
const readEntry = (fileEntry) => {
fileEntry.file((file) => {
const reader = new FileReader();
reader.onerror = failure;
reader.onload = () => resolve(new Blob([reader.result]));
reader.readAsArrayBuffer(file);
}, failure);
};
fileSystem.root.getFile(fileName, {}, readEntry, failure);
});
}
resolveTestFileSystem().then(async (fileSystem) => {
audioBlob = await resolveFileBlob(fileSystem, 'id3_png_test.mp3');
videoBlob = await resolveFileBlob(fileSystem, '90rotation.mp4');
chrome.test.runTests([
// fileManagerPrivate.getContentMimeType tests.
testGetContentMimeTypeEmpty,
testGetContentMimeTypeImage,
testGetContentMimeTypeAudio,
testGetContentMimeTypeVideo,
testGetContentMimeTypeUnknownMimeTypeError,
// fileManagerPrivate.getContentMetadata tests.
testGetContentMetadataEmpty,
testGetContentMetadataAudioTags,
testGetContentMetadataAudioTagsImages,
testGetContentMetadataVideoTagsImages,
testGetContentMetadataRetainsInputMimeType,
testGetContentMetadataVideoResetsAudioMime,
testGetContentMetadataUnsupportedMimetypeError,
]);
});
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