Updates file type selector for fileSystem API

Allows developers to explicitly specify what accept types they would like to allow in their file selectors, as well as whether they allow all files as a last option.

BUG=133066
TEST=Test cases, manual testing

Review URL: https://chromiumcodereview.appspot.com/10692105

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150515 0039d316-1c4b-4281-b951-d872f2087c98
parent 5dfb5270
......@@ -9,6 +9,7 @@
#include "base/file_util.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/shell_window_registry.h"
#include "chrome/browser/platform_util.h"
......@@ -16,6 +17,8 @@
#include "chrome/browser/ui/extensions/shell_window.h"
#include "chrome/common/extensions/api/file_system.h"
#include "chrome/common/extensions/permissions/api_permission.h"
#include "grit/generated_resources.h"
#include "net/base/mime_util.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_process_host.h"
......@@ -23,6 +26,8 @@
#include "webkit/fileapi/file_system_types.h"
#include "webkit/fileapi/file_system_util.h"
#include "webkit/fileapi/isolated_context.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/dialogs/select_file_dialog.h"
using fileapi::IsolatedContext;
......@@ -132,6 +137,76 @@ bool DoCheckWritableFile(const FilePath& path) {
error == base::PLATFORM_FILE_ERROR_EXISTS;
}
// Expand the mime-types and extensions provided in an AcceptOption, returning
// them within the passed extension vector. Returns false if no valid types
// were found.
bool GetFileTypesFromAcceptOption(
const file_system::AcceptOption& accept_option,
std::vector<FilePath::StringType>* extensions,
string16* description) {
std::set<FilePath::StringType> extension_set;
int description_id = 0;
bool valid_type = false;
if (accept_option.mime_types.get()) {
std::vector<std::string>* list = accept_option.mime_types.get();
for (std::vector<std::string>::const_iterator iter = list->begin();
iter != list->end(); ++iter) {
std::vector<FilePath::StringType> inner;
std::string accept_type = *iter;
StringToLowerASCII(&accept_type);
if (*iter == "image/*") {
description_id = IDS_IMAGE_FILES;
net::GetImageExtensions(&inner);
} else if (*iter == "audio/*") {
description_id = IDS_AUDIO_FILES;
net::GetAudioExtensions(&inner);
} else if (*iter == "video/*") {
description_id = IDS_VIDEO_FILES;
net::GetVideoExtensions(&inner);
} else {
net::GetExtensionsForMimeType(*iter, &inner);
}
if (inner.empty())
continue;
if (description_id && valid_type)
description_id = 0; // We already have an accept type with label; if
// we find another, give up and use the default.
extension_set.insert(inner.begin(), inner.end());
valid_type = true;
}
}
if (accept_option.extensions.get()) {
std::vector<std::string>* list = accept_option.extensions.get();
for (std::vector<std::string>::const_iterator iter = list->begin();
iter != list->end(); ++iter) {
std::string extension = *iter;
StringToLowerASCII(&extension);
#if defined(OS_WIN)
extension_set.insert(UTF8ToWide(*iter));
#else
extension_set.insert(*iter);
#endif
}
}
extensions->assign(extension_set.begin(), extension_set.end());
if (extensions->empty())
return false;
if (accept_option.description.get())
*description = UTF8ToUTF16(*accept_option.description.get());
else if (description_id)
*description = l10n_util::GetStringUTF16(description_id);
return true;
}
} // namespace
namespace extensions {
......@@ -264,6 +339,7 @@ class FileSystemChooseFileFunction::FilePicker
FilePicker(FileSystemChooseFileFunction* function,
content::WebContents* web_contents,
const FilePath& suggested_name,
const ui::SelectFileDialog::FileTypeInfo& file_type_info,
ui::SelectFileDialog::Type picker_type,
EntryType entry_type)
: suggested_name_(suggested_name),
......@@ -271,14 +347,6 @@ class FileSystemChooseFileFunction::FilePicker
function_(function) {
select_file_dialog_ = ui::SelectFileDialog::Create(
this, new ChromeSelectFilePolicy(web_contents));
ui::SelectFileDialog::FileTypeInfo file_type_info;
FilePath::StringType extension = suggested_name.Extension();
if (!extension.empty()) {
extension.erase(extension.begin()); // drop the .
file_type_info.extensions.resize(1);
file_type_info.extensions[0].push_back(extension);
}
file_type_info.include_all_files = true;
gfx::NativeWindow owning_window = web_contents ?
platform_util::GetTopLevel(web_contents->GetNativeView()) : NULL;
......@@ -309,7 +377,7 @@ class FileSystemChooseFileFunction::FilePicker
virtual ~FilePicker() {}
private:
// SelectFileDialog::Listener implementation.
// ui::SelectFileDialog::Listener implementation.
virtual void FileSelected(const FilePath& path,
int index,
void* params) OVERRIDE {
......@@ -334,6 +402,7 @@ class FileSystemChooseFileFunction::FilePicker
bool FileSystemChooseFileFunction::ShowPicker(
const FilePath& suggested_name,
const ui::SelectFileDialog::FileTypeInfo& file_type_info,
ui::SelectFileDialog::Type picker_type,
EntryType entry_type) {
ShellWindowRegistry* registry = ShellWindowRegistry::Get(profile());
......@@ -350,7 +419,7 @@ bool FileSystemChooseFileFunction::ShowPicker(
// user has selected a file or cancelled the picker. At that point, the picker
// will delete itself, which will also free the function instance.
new FilePicker(this, shell_window->web_contents(), suggested_name,
picker_type, entry_type);
file_type_info, picker_type, entry_type);
return true;
}
......@@ -390,11 +459,72 @@ void FileSystemChooseFileFunction::FileSelectionCanceled() {
SendResponse(false);
}
void FileSystemChooseFileFunction::BuildFileTypeInfo(
ui::SelectFileDialog::FileTypeInfo* file_type_info,
const FilePath::StringType& suggested_extension,
const AcceptOptions* accepts,
const bool* acceptsAllTypes) {
file_type_info->include_all_files = true;
if (acceptsAllTypes)
file_type_info->include_all_files = *acceptsAllTypes;
bool need_suggestion = !file_type_info->include_all_files &&
!suggested_extension.empty();
if (accepts) {
typedef file_system::AcceptOption AcceptOption;
for (std::vector<linked_ptr<AcceptOption> >::const_iterator iter =
accepts->begin(); iter != accepts->end(); ++iter) {
string16 description;
std::vector<FilePath::StringType> extensions;
if (!GetFileTypesFromAcceptOption(**iter, &extensions, &description))
continue; // No extensions were found.
file_type_info->extensions.push_back(extensions);
file_type_info->extension_description_overrides.push_back(description);
// If we still need to find suggested_extension, hunt for it inside the
// extensions returned from GetFileTypesFromAcceptOption.
if (need_suggestion && std::find(extensions.begin(),
extensions.end(), suggested_extension) != extensions.end()) {
need_suggestion = false;
}
}
}
// If there's nothing in our accepted extension list or we couldn't find the
// suggested extension required, then default to accepting all types.
if (file_type_info->extensions.empty() || need_suggestion)
file_type_info->include_all_files = true;
}
void FileSystemChooseFileFunction::BuildSuggestion(
const std::string *opt_name,
FilePath* suggested_name,
FilePath::StringType* suggested_extension) {
if (opt_name) {
*suggested_name = FilePath::FromUTF8Unsafe(*opt_name);
// Don't allow any path components; shorten to the base name. This should
// result in a relative path, but in some cases may not. Clear the
// suggestion for safety if this is the case.
*suggested_name = suggested_name->BaseName();
if (suggested_name->IsAbsolute())
*suggested_name = FilePath();
*suggested_extension = suggested_name->Extension();
if (!suggested_extension->empty())
suggested_extension->erase(suggested_extension->begin()); // drop the .
}
}
bool FileSystemChooseFileFunction::RunImpl() {
scoped_ptr<ChooseFile::Params> params(ChooseFile::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
FilePath suggested_name;
ui::SelectFileDialog::FileTypeInfo file_type_info;
EntryType entry_type = READ_ONLY;
ui::SelectFileDialog::Type picker_type =
ui::SelectFileDialog::SELECT_OPEN_FILE;
......@@ -413,18 +543,12 @@ bool FileSystemChooseFileFunction::RunImpl() {
}
}
if (options->suggested_name.get()) {
suggested_name = FilePath::FromUTF8Unsafe(
*options->suggested_name.get());
FilePath::StringType suggested_extension;
BuildSuggestion(options->suggested_name.get(), &suggested_name,
&suggested_extension);
// Don't allow any path components; shorten to the base name. This should
// result in a relative path, but in some cases may not. Clear the
// suggestion for safety if this is the case.
suggested_name = suggested_name.BaseName();
if (suggested_name.IsAbsolute()) {
suggested_name = FilePath();
}
}
BuildFileTypeInfo(&file_type_info, suggested_extension,
options->accepts.get(), options->accepts_all_types.get());
}
if (entry_type == WRITABLE && !HasFileSystemWritePermission()) {
......@@ -432,7 +556,7 @@ bool FileSystemChooseFileFunction::RunImpl() {
return false;
}
return ShowPicker(suggested_name, picker_type, entry_type);
return ShowPicker(suggested_name, file_type_info, picker_type, entry_type);
}
} // namespace extensions
......@@ -6,6 +6,7 @@
#define CHROME_BROWSER_EXTENSIONS_API_FILE_SYSTEM_FILE_SYSTEM_API_H_
#include "chrome/browser/extensions/extension_function.h"
#include "chrome/common/extensions/api/file_system.h"
#include "ui/base/dialogs/select_file_dialog.h"
namespace extensions {
......@@ -72,12 +73,25 @@ class FileSystemChooseFileFunction : public FileSystemEntryFunction {
DECLARE_EXTENSION_FUNCTION_NAME("fileSystem.chooseFile");
typedef std::vector<linked_ptr<extensions::api::file_system::AcceptOption> >
AcceptOptions;
static void BuildFileTypeInfo(
ui::SelectFileDialog::FileTypeInfo* file_type_info,
const FilePath::StringType& suggested_extension,
const AcceptOptions* accepts,
const bool* acceptsAllTypes);
static void BuildSuggestion(const std::string* opt_name,
FilePath* suggested_name,
FilePath::StringType* suggested_extension);
protected:
class FilePicker;
virtual ~FileSystemChooseFileFunction() {}
virtual bool RunImpl() OVERRIDE;
bool ShowPicker(const FilePath& suggested_path,
const ui::SelectFileDialog::FileTypeInfo& file_type_info,
ui::SelectFileDialog::Type picker_type,
EntryType entry_type);
......
// 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.
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/string_split.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/api/file_system/file_system_api.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/dialogs/select_file_dialog.h"
using extensions::FileSystemChooseFileFunction;
using extensions::api::file_system::AcceptOption;
namespace {
void CheckExtensions(std::vector<FilePath::StringType>& expected,
std::vector<FilePath::StringType>& actual) {
EXPECT_EQ(expected.size(), actual.size());
if (expected.size() != actual.size())
return;
for (size_t i = 0; i < expected.size(); ++i) {
EXPECT_EQ(expected[i], actual[i]);
}
}
AcceptOption* BuildAcceptOption(std::string description,
std::string mime_types,
std::string extensions) {
AcceptOption* option = new AcceptOption();
if (!description.empty())
option->description.reset(new std::string(description));
if (!mime_types.empty()) {
option->mime_types.reset(new std::vector<std::string>());
base::SplitString(mime_types, ',', option->mime_types.get());
}
if (!extensions.empty()) {
option->extensions.reset(new std::vector<std::string>());
base::SplitString(extensions, ',', option->extensions.get());
}
return option;
}
#if defined(OS_WIN)
#define ToStringType UTF8ToWide
#else
#define ToStringType
#endif
} // namespace
class FileSystemApiUnitTest : public testing::Test {
};
TEST_F(FileSystemApiUnitTest, FileSystemChooseFileFunctionFileTypeInfoTest) {
// AcceptsAllTypes is ignored when no other extensions are available.
ui::SelectFileDialog::FileTypeInfo file_type_info;
bool acceptsAllTypes = false;
FileSystemChooseFileFunction::BuildFileTypeInfo(&file_type_info,
FilePath::StringType(), NULL, &acceptsAllTypes);
EXPECT_TRUE(file_type_info.include_all_files);
EXPECT_TRUE(file_type_info.extensions.empty());
// Test grouping of multiple types.
file_type_info = ui::SelectFileDialog::FileTypeInfo();
std::vector<linked_ptr<AcceptOption> > options;
options.push_back(linked_ptr<AcceptOption>(
BuildAcceptOption("", "application/x-chrome-extension", "jso")));
acceptsAllTypes = false;
FileSystemChooseFileFunction::BuildFileTypeInfo(&file_type_info,
FilePath::StringType(), &options, &acceptsAllTypes);
EXPECT_FALSE(file_type_info.include_all_files);
ASSERT_EQ(file_type_info.extensions.size(), (size_t) 1);
EXPECT_TRUE(file_type_info.extension_description_overrides[0].empty()) <<
"No override must be specified for boring accept types";
// Note here (and below) that the expectedTypes are sorted, because we use a
// set internally to generate the output: thus, the output is sorted.
std::vector<FilePath::StringType> expectedTypes;
expectedTypes.push_back(ToStringType("crx"));
expectedTypes.push_back(ToStringType("jso"));
CheckExtensions(expectedTypes, file_type_info.extensions[0]);
// Test that not satisfying the extension will force all types.
file_type_info = ui::SelectFileDialog::FileTypeInfo();
options.clear();
options.push_back(linked_ptr<AcceptOption>(
BuildAcceptOption("", "", "unrelated")));
acceptsAllTypes = false;
FileSystemChooseFileFunction::BuildFileTypeInfo(&file_type_info,
ToStringType(".jso"), &options, &acceptsAllTypes);
EXPECT_TRUE(file_type_info.include_all_files);
// Test multiple list entries, all containing their own types.
file_type_info = ui::SelectFileDialog::FileTypeInfo();
options.clear();
options.push_back(linked_ptr<AcceptOption>(
BuildAcceptOption("", "", "jso,js")));
options.push_back(linked_ptr<AcceptOption>(
BuildAcceptOption("", "", "cpp,cc")));
acceptsAllTypes = false;
FileSystemChooseFileFunction::BuildFileTypeInfo(&file_type_info,
FilePath::StringType(), &options, &acceptsAllTypes);
ASSERT_EQ(file_type_info.extensions.size(), options.size());
expectedTypes.clear();
expectedTypes.push_back(ToStringType("js"));
expectedTypes.push_back(ToStringType("jso"));
CheckExtensions(expectedTypes, file_type_info.extensions[0]);
expectedTypes.clear();
expectedTypes.push_back(ToStringType("cc"));
expectedTypes.push_back(ToStringType("cpp"));
CheckExtensions(expectedTypes, file_type_info.extensions[1]);
// Test accept type that causes description override.
file_type_info = ui::SelectFileDialog::FileTypeInfo();
options.clear();
options.push_back(linked_ptr<AcceptOption>(
BuildAcceptOption("", "image/*", "html")));
acceptsAllTypes = false;
FileSystemChooseFileFunction::BuildFileTypeInfo(&file_type_info,
FilePath::StringType(), &options, &acceptsAllTypes);
ASSERT_EQ(file_type_info.extension_description_overrides.size(), (size_t) 1);
EXPECT_FALSE(file_type_info.extension_description_overrides[0].empty()) <<
"Accept type \"image/*\" must generate description override";
// Test multiple accept types that cause description override causes us to
// still present the default.
file_type_info = ui::SelectFileDialog::FileTypeInfo();
options.clear();
options.push_back(linked_ptr<AcceptOption>(
BuildAcceptOption("", "image/*,audio/*,video/*", "")));
acceptsAllTypes = false;
FileSystemChooseFileFunction::BuildFileTypeInfo(&file_type_info,
FilePath::StringType(), &options, &acceptsAllTypes);
ASSERT_EQ(file_type_info.extension_description_overrides.size(), (size_t) 1);
EXPECT_TRUE(file_type_info.extension_description_overrides[0].empty());
// Test explicit description override.
file_type_info = ui::SelectFileDialog::FileTypeInfo();
options.clear();
options.push_back(linked_ptr<AcceptOption>(
BuildAcceptOption("File Types 101", "image/jpeg", "")));
acceptsAllTypes = false;
FileSystemChooseFileFunction::BuildFileTypeInfo(&file_type_info,
FilePath::StringType(), &options, &acceptsAllTypes);
EXPECT_EQ(file_type_info.extension_description_overrides[0],
UTF8ToUTF16("File Types 101"));
}
TEST_F(FileSystemApiUnitTest, FileSystemChooseFileFunctionSuggestionTest) {
std::string opt_name;
FilePath suggested_name;
FilePath::StringType suggested_extension;
opt_name = std::string("normal_path.txt");
FileSystemChooseFileFunction::BuildSuggestion(&opt_name, &suggested_name,
&suggested_extension);
EXPECT_FALSE(suggested_name.IsAbsolute());
EXPECT_EQ(suggested_name.MaybeAsASCII(), "normal_path.txt");
EXPECT_EQ(suggested_extension, ToStringType("txt"));
// We should provide just the basename, i.e., "path".
opt_name = std::string("/a/bad/path");
FileSystemChooseFileFunction::BuildSuggestion(&opt_name, &suggested_name,
&suggested_extension);
EXPECT_FALSE(suggested_name.IsAbsolute());
EXPECT_EQ(suggested_name.MaybeAsASCII(), "path");
EXPECT_TRUE(suggested_extension.empty());
#if !defined(OS_WIN)
// TODO(thorogood): Fix this test on Windows.
// Filter out absolute paths with no basename.
opt_name = std::string("/");
FileSystemChooseFileFunction::BuildSuggestion(&opt_name, &suggested_name,
&suggested_extension);
EXPECT_FALSE(suggested_name.IsAbsolute());
EXPECT_TRUE(suggested_name.MaybeAsASCII().empty());
EXPECT_TRUE(suggested_extension.empty());
#endif
}
......@@ -1226,6 +1226,7 @@
'browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc',
'browser/extensions/api/discovery/discovery_api_unittest.cc',
'browser/extensions/api/extension_action/extension_browser_actions_api_unittest.cc',
'browser/extensions/api/file_system/file_system_api_unittest.cc',
'browser/extensions/api/identity/web_auth_flow_unittest.cc',
'browser/extensions/api/idle/idle_api_unittest.cc',
'browser/extensions/api/omnibox/omnibox_unittest.cc',
......
......@@ -5,6 +5,21 @@
// File-level comment to appease parser. Eventually this will not be necessary.
namespace fileSystem {
dictionary AcceptOption {
// This is the optional text description for this option. If not present,
// a description will be automatically generated; typically containing an
// expanded list of valid extensions (e.g. "text/html" may expand to
// "*.html, *.htm").
DOMString? description;
// Mime-types to accept, e.g. "image/jpeg" or "audio/*". One of mimeTypes or
// extensions must contain at least one valid element.
DOMString[]? mimeTypes;
// Extensions to accept, e.g. "jpg", "gif", "crx".
DOMString[]? extensions;
};
dictionary ChooseFileOptions {
// Type of the prompt to show. Valid types are 'openFile',
// 'openWritableFile' or 'saveFile'.
......@@ -22,6 +37,15 @@ namespace fileSystem {
// The suggested file name that will be presented to the user as the
// default name to read or write. This is optional.
DOMString? suggestedName;
// The optional list of accept options for this file opener. Each option
// will be presented as a unique group to the end-user.
AcceptOption[]? accepts;
// Whether to accept all file types, in addition to the options specified
// in the accepts argument. The default is true. If the accepts field is
// unset or contains no valid entries, this will always be reset to true.
boolean? acceptsAllTypes;
};
callback GetDisplayPathCallback = void (DOMString displayPath);
callback FileEntryCallback = void ([instanceOf=FileEntry] object fileEntry);
......
......@@ -184,6 +184,10 @@
<a href="#types">Types</a>
<ol>
<li>
<a href="#type-fileSystem.AcceptOption">fileSystem.AcceptOption</a>
<ol>
</ol>
</li><li>
<a href="#type-fileSystem.ChooseFileOptions">fileSystem.ChooseFileOptions</a>
<ol>
</ol>
......@@ -647,6 +651,121 @@
<h3 id="types">Types</h3>
<!-- iterates over all types -->
<div class="apiItem">
<a name="type-fileSystem.AcceptOption"></a>
<h4>fileSystem.AcceptOption</h4>
<div>
<dt>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<span>object</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd class="todo">
Undocumented.
</dd>
<!-- OBJECT PROPERTIES -->
<dd>
<dl>
<div>
<div>
<dt>
<var>description</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>string</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>This is the optional text description for this option. If not present, a description will be automatically generated; typically containing an expanded list of valid extensions (e.g. \"text/html\" may expand to \"*.html, *.htm\").</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>extensions</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>
array of <span><span>
<span>
<span>string</span>
</span>
</span></span>
</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>Extensions to accept, e.g. \"jpg\", \"gif\", \"crx\".</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>mimeTypes</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>
array of <span><span>
<span>
<span>string</span>
</span>
</span></span>
</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>Mime-types to accept, e.g. \"image/jpeg\" or \"audio/*\". One of mimeTypes or extensions must contain at least one valid element.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div>
</dl>
</dd>
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div class="apiItem">
<a name="type-fileSystem.ChooseFileOptions"></a>
<h4>fileSystem.ChooseFileOptions</h4>
<div>
......@@ -672,6 +791,60 @@
<dl>
<div>
<div>
<dt>
<var>accepts</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>
array of <span><span>
<span>
<a href="fileSystem.html#type-fileSystem.AcceptOption">fileSystem.AcceptOption</a>
</span>
</span></span>
</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>The optional list of accept options for this file opener. Each option will be presented as a unique group to the end-user.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>acceptsAllTypes</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>boolean</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>Whether to accept all file types, in addition to the options specified in the accepts argument. The default is true. If the accepts field is unset or contains no valid entries, this will always be reset to true.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>suggestedName</var>
<em>
......
......@@ -215,6 +215,10 @@
<a href="#types">Types</a>
<ol>
<li>
<a href="#type-fileSystem.AcceptOption">AcceptOption</a>
<ol>
</ol>
</li><li>
<a href="#type-fileSystem.ChooseFileOptions">ChooseFileOptions</a>
<ol>
</ol>
......@@ -834,6 +838,121 @@
<h3 id="types">Types</h3>
<!-- iterates over all types -->
<div class="apiItem">
<a name="type-fileSystem.AcceptOption"></a>
<h4>fileSystem.AcceptOption</h4>
<div>
<dt>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span id="typeTemplate">
<span>
<span>object</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd class="todo">
Undocumented.
</dd>
<!-- OBJECT PROPERTIES -->
<dd>
<dl>
<div>
<div>
<dt>
<var>description</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>string</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>This is the optional text description for this option. If not present, a description will be automatically generated; typically containing an expanded list of valid extensions (e.g. \"text/html\" may expand to \"*.html, *.htm\").</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>extensions</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>
array of <span><span>
<span>
<span>string</span>
</span>
</span></span>
</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>Extensions to accept, e.g. \"jpg\", \"gif\", \"crx\".</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>mimeTypes</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>
array of <span><span>
<span>
<span>string</span>
</span>
</span></span>
</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>Mime-types to accept, e.g. \"image/jpeg\" or \"audio/*\". One of mimeTypes or extensions must contain at least one valid element.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div>
</dl>
</dd>
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div class="apiItem">
<a name="type-fileSystem.ChooseFileOptions"></a>
<h4>fileSystem.ChooseFileOptions</h4>
<div>
......@@ -859,6 +978,60 @@
<dl>
<div>
<div>
<dt>
<var>accepts</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>
array of <span><span>
<span>
<a href="fileSystem.html#type-fileSystem.AcceptOption">fileSystem.AcceptOption</a>
</span>
</span></span>
</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>The optional list of accept options for this file opener. Each option will be presented as a unique group to the end-user.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>acceptsAllTypes</var>
<em>
<!-- TYPE -->
<div style="display:inline">
(
<span class="optional">optional</span>
<span id="typeTemplate">
<span>
<span>boolean</span>
</span>
</span>
)
</div>
</em>
</dt>
<dd>Whether to accept all file types, in addition to the options specified in the accepts argument. The default is true. If the accepts field is unset or contains no valid entries, this will always be reset to true.</dd>
<!-- OBJECT PROPERTIES -->
<!-- OBJECT METHODS -->
<!-- OBJECT EVENT FIELDS -->
<!-- FUNCTION PARAMETERS -->
</div>
</div><div>
<div>
<dt>
<var>suggestedName</var>
<em>
......
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