Chromium Code Reviews| Index: chrome/browser/extensions/api/media_galleries/media_galleries_api.cc |
| =================================================================== |
| --- chrome/browser/extensions/api/media_galleries/media_galleries_api.cc (revision 237402) |
| +++ chrome/browser/extensions/api/media_galleries/media_galleries_api.cc (working copy) |
| @@ -17,12 +17,14 @@ |
| #include "base/stl_util.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| +#include "base/task_runner_util.h" |
| #include "base/values.h" |
| #include "chrome/browser/browser_process.h" |
| #include "chrome/browser/media_galleries/media_file_system_registry.h" |
| #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h" |
| #include "chrome/browser/media_galleries/media_galleries_histograms.h" |
| #include "chrome/browser/media_galleries/media_galleries_preferences.h" |
| +#include "chrome/browser/platform_util.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/storage_monitor/storage_info.h" |
| #include "chrome/browser/ui/chrome_select_file_policy.h" |
| @@ -30,10 +32,12 @@ |
| #include "chrome/common/extensions/permissions/media_galleries_permission.h" |
| #include "chrome/common/pref_names.h" |
| #include "components/web_modal/web_contents_modal_dialog_manager.h" |
| +#include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/child_process_security_policy.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/render_view_host.h" |
| #include "content/public/browser/web_contents.h" |
| +#include "content/public/browser/web_contents_view.h" |
| #include "extensions/common/extension.h" |
| #include "extensions/common/permissions/api_permission.h" |
| #include "extensions/common/permissions/permissions_data.h" |
| @@ -45,11 +49,14 @@ |
| namespace MediaGalleries = api::media_galleries; |
| namespace GetMediaFileSystems = MediaGalleries::GetMediaFileSystems; |
| +namespace ManageMediaLocations = MediaGalleries::ManageMediaLocations; |
| namespace { |
| const char kDisallowedByPolicy[] = |
| "Media Galleries API is disallowed by policy: "; |
| +const char kInvalidManageRequestType[] = |
| + "Invalid manageMediaLocations request type"; |
| const char kDeviceIdKey[] = "deviceId"; |
| const char kGalleryIdKey[] = "galleryId"; |
| @@ -74,88 +81,115 @@ |
| return g_browser_process->media_file_system_registry(); |
| } |
| -} // namespace |
| +class SelectDirectoryDialog : public ui::SelectFileDialog::Listener, |
|
vandebo (ex-Chrome)
2013/12/02 18:01:30
Should this live in c/b/media_galleries?
Should it
Lei Zhang
2013/12/03 03:33:23
Probably not? The two workflows are different and
vandebo (ex-Chrome)
2013/12/03 21:08:02
They both have a directory picker which results in
|
| + public base::RefCounted<SelectDirectoryDialog> { |
| + public: |
| + // Selected file path, or an empty path if the user canceled. |
| + typedef base::Callback<void(const base::FilePath&)> Callback; |
| -MediaGalleriesGetMediaFileSystemsFunction:: |
| - ~MediaGalleriesGetMediaFileSystemsFunction() {} |
| + SelectDirectoryDialog(WebContents* web_contents, const Callback& callback) |
| + : web_contents_(web_contents), |
| + callback_(callback) { |
| + select_file_dialog_ = ui::SelectFileDialog::Create( |
| + this, new ChromeSelectFilePolicy(web_contents)); |
| + } |
| -bool MediaGalleriesGetMediaFileSystemsFunction::RunImpl() { |
| - if (!ApiIsAccessible(&error_)) |
| - return false; |
| + void Show() { |
| + AddRef(); // Balanced in the three listener outcomes. |
| + select_file_dialog_->SelectFile( |
| + ui::SelectFileDialog::SELECT_FOLDER, |
| + base::string16(), |
| + base::FilePath(), |
| + NULL, |
| + 0, |
| + base::FilePath::StringType(), |
| + platform_util::GetTopLevel(web_contents_->GetView()->GetNativeView()), |
| + NULL); |
| + } |
| - media_galleries::UsageCount(media_galleries::GET_MEDIA_FILE_SYSTEMS); |
| - scoped_ptr<GetMediaFileSystems::Params> params( |
| - GetMediaFileSystems::Params::Create(*args_)); |
| - EXTENSION_FUNCTION_VALIDATE(params.get()); |
| - MediaGalleries::GetMediaFileSystemsInteractivity interactive = |
| - MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO; |
| - if (params->details.get() && params->details->interactive != MediaGalleries:: |
| - GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE) { |
| - interactive = params->details->interactive; |
| + // ui::SelectFileDialog::Listener implementation. |
| + virtual void FileSelected(const base::FilePath& path, |
| + int index, |
| + void* params) OVERRIDE { |
| + callback_.Run(path); |
| + Release(); // Balanced in Show(). |
| } |
| - MediaGalleriesPreferences* preferences = |
| - media_file_system_registry()->GetPreferences(GetProfile()); |
| - preferences->EnsureInitialized(base::Bind( |
| - &MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit, |
| - this, |
| - interactive)); |
| - return true; |
| -} |
| + virtual void MultiFilesSelected(const std::vector<base::FilePath>& files, |
| + void* params) OVERRIDE { |
| + Release(); // Balanced in Show(). |
|
vandebo (ex-Chrome)
2013/12/02 18:01:30
Should the callback be called with an empty path i
Lei Zhang
2013/12/03 03:33:23
No, we should never handle a NOTREACHED() per the
|
| + NOTREACHED() << "Should not be able to select multiple files"; |
| + } |
| -void MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit( |
| - MediaGalleries::GetMediaFileSystemsInteractivity interactive) { |
| - switch (interactive) { |
| - case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_YES: { |
| - // The MediaFileSystemRegistry only updates preferences for extensions |
| - // that it knows are in use. Since this may be the first call to |
| - // chrome.getMediaFileSystems for this extension, call |
| - // GetMediaFileSystemsForExtension() here solely so that |
| - // MediaFileSystemRegistry will send preference changes. |
| - GetMediaFileSystemsForExtension(base::Bind( |
| - &MediaGalleriesGetMediaFileSystemsFunction::AlwaysShowDialog, this)); |
| - return; |
| - } |
| - case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_IF_NEEDED: { |
| - GetMediaFileSystemsForExtension(base::Bind( |
| - &MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries, |
| - this)); |
| - return; |
| - } |
| - case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO: |
| - GetAndReturnGalleries(); |
| - return; |
| - case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE: |
| - NOTREACHED(); |
| + virtual void FileSelectionCanceled(void* params) OVERRIDE { |
| + callback_.Run(base::FilePath()); |
| + Release(); // Balanced in Show(). |
| } |
| - SendResponse(false); |
| -} |
| -void MediaGalleriesGetMediaFileSystemsFunction::AlwaysShowDialog( |
| - const std::vector<MediaFileSystemInfo>& /*filesystems*/) { |
| - ShowDialog(); |
| + private: |
| + friend class base::RefCounted<SelectDirectoryDialog>; |
| + virtual ~SelectDirectoryDialog() {} |
| + |
| + scoped_refptr<ui::SelectFileDialog> select_file_dialog_; |
| + WebContents* web_contents_; |
| + Callback callback_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(SelectDirectoryDialog); |
| +}; |
| + |
| +} // namespace |
| + |
| +MediaGalleriesGetMediaFileSystemsBase:: |
| + ~MediaGalleriesGetMediaFileSystemsBase() {} |
| + |
| +void MediaGalleriesGetMediaFileSystemsBase::ReadPrefsAndShowDialog() { |
| + // The MediaFileSystemRegistry only updates preferences for extensions |
| + // that it knows are in use. Since this may be the first call to |
| + // chrome.{getMediaFileSystems, manageMediaLocations} for this extension, |
| + // call GetMediaFileSystemsForExtension() here solely so that |
| + // MediaFileSystemRegistry will send preference changes. |
| + GetMediaFileSystemsForExtension(base::Bind( |
| + &MediaGalleriesGetMediaFileSystemsBase::AlwaysShowDialog, this)); |
| } |
| -void MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries( |
| - const std::vector<MediaFileSystemInfo>& filesystems) { |
| - if (filesystems.empty()) |
| - ShowDialog(); |
| - else |
| - ReturnGalleries(filesystems); |
| +void MediaGalleriesGetMediaFileSystemsBase::ShowDialog() { |
| + media_galleries::UsageCount(media_galleries::SHOW_DIALOG); |
| + |
| + WebContents* contents = GetWebContents(); |
| + if (!contents) { |
| + SendResponse(false); |
| + return; |
| + } |
| + |
| + // Controller will delete itself. |
|
vandebo (ex-Chrome)
2013/12/02 18:01:30
nit: move to line 166
Lei Zhang
2013/12/03 03:33:23
Done.
|
| + base::Closure cb = base::Bind( |
|
vandebo (ex-Chrome)
2013/12/02 18:01:30
nit: cb -> callback. Would it be more consistent
Lei Zhang
2013/12/03 03:33:23
I inlined it, but now it's 5 lines. Meh.
vandebo (ex-Chrome)
2013/12/03 21:08:02
How about:
new MediaGalleriesDialogController(
Lei Zhang
2013/12/05 05:52:15
Done.
|
| + &MediaGalleriesGetMediaFileSystemsBase::GetAndReturnGalleries, this); |
| + new MediaGalleriesDialogController(contents, *GetExtension(), cb); |
| } |
| -void MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries() { |
| +void MediaGalleriesGetMediaFileSystemsBase::GetAndReturnGalleries() { |
| GetMediaFileSystemsForExtension(base::Bind( |
| - &MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries, this)); |
| + &MediaGalleriesGetMediaFileSystemsBase::ReturnGalleries, this)); |
| } |
| -void MediaGalleriesGetMediaFileSystemsFunction::ReturnGalleries( |
| +void MediaGalleriesGetMediaFileSystemsBase::ReturnGalleries( |
| const std::vector<MediaFileSystemInfo>& filesystems) { |
| - content::RenderViewHost* rvh = render_view_host(); |
| - if (!rvh) { |
| + base::ListValue* list = ConstructFileSystemList(filesystems); |
|
vandebo (ex-Chrome)
2013/12/02 18:01:30
Should this be scoped_ptr<base::ListValue> list ?
Lei Zhang
2013/12/03 03:33:23
Done. We haven't always used scoped_ptrs in all ca
|
| + if (!list) { |
| SendResponse(false); |
|
vandebo (ex-Chrome)
2013/12/02 18:01:30
The API didn't necessarily fail if there's an empt
Lei Zhang
2013/12/03 03:33:23
This is not the empty list case. |list| is only NU
|
| return; |
| } |
| + |
| + SetResult(list); |
| + SendResponse(true); |
| +} |
| + |
| +base::ListValue* MediaGalleriesGetMediaFileSystemsBase::ConstructFileSystemList( |
| + const std::vector<MediaFileSystemInfo>& filesystems) { |
| + content::RenderViewHost* rvh = render_view_host(); |
| + if (!rvh) |
| + return NULL; |
| + |
| MediaGalleriesPermission::CheckParam read_param( |
| MediaGalleriesPermission::kReadPermission); |
| bool has_read_permission = PermissionsData::CheckAPIPermissionWithParam( |
| @@ -214,49 +248,103 @@ |
| } |
| } |
| - // The custom JS binding will use this list to create DOMFileSystem objects. |
| - SetResult(list); |
| - SendResponse(true); |
| + return list; |
| } |
| -void MediaGalleriesGetMediaFileSystemsFunction::ShowDialog() { |
| - media_galleries::UsageCount(media_galleries::SHOW_DIALOG); |
| +void MediaGalleriesGetMediaFileSystemsBase::GetMediaFileSystemsForExtension( |
| + const MediaFileSystemsCallback& cb) { |
| + if (!render_view_host()) { |
| + cb.Run(std::vector<MediaFileSystemInfo>()); |
| + return; |
| + } |
| + DCHECK(GetMediaGalleriesPreferences()->IsInitialized()); |
| + media_file_system_registry()->GetMediaFileSystemsForExtension( |
| + render_view_host(), GetExtension(), cb); |
| +} |
| + |
| +WebContents* MediaGalleriesGetMediaFileSystemsBase::GetWebContents() { |
| WebContents* contents = WebContents::FromRenderViewHost(render_view_host()); |
| WebContentsModalDialogManager* web_contents_modal_dialog_manager = |
| WebContentsModalDialogManager::FromWebContents(contents); |
| - if (!web_contents_modal_dialog_manager) { |
| - // If there is no WebContentsModalDialogManager, then this contents is |
| - // probably the background page for an app. Try to find a shell window to |
| - // host the dialog. |
| - apps::ShellWindow* window = apps::ShellWindowRegistry::Get( |
| - GetProfile())->GetCurrentShellWindowForApp(GetExtension()->id()); |
| - if (window) { |
| - contents = window->web_contents(); |
| - } else { |
| - // Abort showing the dialog. TODO(estade) Perhaps return an error instead. |
| - GetAndReturnGalleries(); |
| - return; |
| - } |
| + if (web_contents_modal_dialog_manager) |
| + return contents; |
| + |
| + // If there is no WebContentsModalDialogManager, then this contents is |
| + // probably the background page for an app. Try to find a shell window to |
| + // host the dialog. |
| + apps::ShellWindow* window = apps::ShellWindowRegistry::Get( |
| + GetProfile())->GetCurrentShellWindowForApp(GetExtension()->id()); |
| + return window ? window->web_contents() : NULL; |
| +} |
| + |
| +MediaGalleriesPreferences* |
| +MediaGalleriesGetMediaFileSystemsBase::GetMediaGalleriesPreferences() { |
| + return media_file_system_registry()->GetPreferences(GetProfile()); |
| +} |
| + |
| +void MediaGalleriesGetMediaFileSystemsBase::AlwaysShowDialog( |
| + const std::vector<MediaFileSystemInfo>& /*filesystems*/) { |
| + ShowDialog(); |
| +} |
| + |
| + |
| +MediaGalleriesGetMediaFileSystemsFunction:: |
| + ~MediaGalleriesGetMediaFileSystemsFunction() {} |
| + |
| +bool MediaGalleriesGetMediaFileSystemsFunction::RunImpl() { |
| + if (!ApiIsAccessible(&error_)) |
| + return false; |
| + |
| + media_galleries::UsageCount(media_galleries::GET_MEDIA_FILE_SYSTEMS); |
| + scoped_ptr<GetMediaFileSystems::Params> params( |
| + GetMediaFileSystems::Params::Create(*args_)); |
| + EXTENSION_FUNCTION_VALIDATE(params.get()); |
| + MediaGalleries::GetMediaFileSystemsInteractivity interactive = |
| + MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO; |
| + if (params->details.get() && params->details->interactive != MediaGalleries:: |
| + GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE) { |
| + interactive = params->details->interactive; |
| } |
| - // Controller will delete itself. |
| - base::Closure cb = base::Bind( |
| - &MediaGalleriesGetMediaFileSystemsFunction::GetAndReturnGalleries, this); |
| - new MediaGalleriesDialogController(contents, *GetExtension(), cb); |
| + MediaGalleriesPreferences* preferences = GetMediaGalleriesPreferences(); |
| + preferences->EnsureInitialized(base::Bind( |
| + &MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit, |
| + this, |
| + interactive)); |
| + return true; |
| } |
| -void MediaGalleriesGetMediaFileSystemsFunction::GetMediaFileSystemsForExtension( |
| - const MediaFileSystemsCallback& cb) { |
| - if (!render_view_host()) { |
| - cb.Run(std::vector<MediaFileSystemInfo>()); |
| - return; |
| +void MediaGalleriesGetMediaFileSystemsFunction::OnPreferencesInit( |
| + MediaGalleries::GetMediaFileSystemsInteractivity interactive) { |
| + switch (interactive) { |
| + case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_YES: { |
| + ReadPrefsAndShowDialog(); |
| + return; |
| + } |
| + case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_IF_NEEDED: { |
| + GetMediaFileSystemsForExtension(base::Bind( |
| + &MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries, |
| + this)); |
| + return; |
| + } |
| + case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NO: |
| + GetAndReturnGalleries(); |
| + return; |
| + case MediaGalleries::GET_MEDIA_FILE_SYSTEMS_INTERACTIVITY_NONE: |
| + NOTREACHED(); |
| } |
| - MediaFileSystemRegistry* registry = media_file_system_registry(); |
| - DCHECK(registry->GetPreferences(GetProfile())->IsInitialized()); |
| - registry->GetMediaFileSystemsForExtension( |
| - render_view_host(), GetExtension(), cb); |
| + SendResponse(false); |
| } |
| +void MediaGalleriesGetMediaFileSystemsFunction::ShowDialogIfNoGalleries( |
| + const std::vector<MediaFileSystemInfo>& filesystems) { |
| + if (filesystems.empty()) |
| + ShowDialog(); |
| + else |
| + ReturnGalleries(filesystems); |
| +} |
| + |
| + |
| MediaGalleriesGetAllMediaFileSystemMetadataFunction:: |
| ~MediaGalleriesGetAllMediaFileSystemMetadataFunction() {} |
| @@ -275,8 +363,8 @@ |
| } |
| void MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnPreferencesInit() { |
| - MediaFileSystemRegistry* registry = media_file_system_registry(); |
| - MediaGalleriesPreferences* prefs = registry->GetPreferences(GetProfile()); |
| + MediaGalleriesPreferences* prefs = |
| + media_file_system_registry()->GetPreferences(GetProfile()); |
| DCHECK(prefs->IsInitialized()); |
| MediaGalleryPrefIdSet permitted_gallery_ids = |
| prefs->GalleriesForExtension(*GetExtension()); |
| @@ -302,8 +390,8 @@ |
| void MediaGalleriesGetAllMediaFileSystemMetadataFunction::OnGetGalleries( |
| const MediaGalleryPrefIdSet& permitted_gallery_ids, |
| const MediaStorageUtil::DeviceIdSet* available_devices) { |
| - MediaFileSystemRegistry* registry = media_file_system_registry(); |
| - MediaGalleriesPreferences* prefs = registry->GetPreferences(GetProfile()); |
| + MediaGalleriesPreferences* prefs = |
| + media_file_system_registry()->GetPreferences(GetProfile()); |
| base::ListValue* list = new base::ListValue(); |
| const MediaGalleriesPrefInfoMap& galleries = prefs->known_galleries(); |
| @@ -325,4 +413,115 @@ |
| SendResponse(true); |
| } |
| +MediaGalleriesManageMediaLocationsFunction:: |
| + ~MediaGalleriesManageMediaLocationsFunction() {} |
| + |
| +bool MediaGalleriesManageMediaLocationsFunction::RunImpl() { |
| + if (!ApiIsAccessible(&error_)) |
| + return false; |
| + |
| + media_galleries::UsageCount(media_galleries::MANAGE_MEDIA_LOCATIONS); |
| + scoped_ptr<ManageMediaLocations::Params> params( |
| + ManageMediaLocations::Params::Create(*args_)); |
| + EXTENSION_FUNCTION_VALIDATE(params.get()); |
| + if (params->details.type == MediaGalleries::MANAGE_REQUEST_TYPE_NONE) |
| + EXTENSION_FUNCTION_ERROR(kInvalidManageRequestType); // returns false |
| + |
| + MediaGalleriesPreferences* preferences = GetMediaGalleriesPreferences(); |
| + preferences->EnsureInitialized(base::Bind( |
| + &MediaGalleriesManageMediaLocationsFunction::OnPreferencesInit, |
| + this, |
| + params->details.type)); |
| + return true; |
| +} |
| + |
| +void MediaGalleriesManageMediaLocationsFunction::OnPreferencesInit( |
| + MediaGalleries::ManageRequestType request_type) { |
| + switch (request_type) { |
| + case MediaGalleries::MANAGE_REQUEST_TYPE_MANAGE: { |
| + ReadPrefsAndShowDialog(); |
| + return; |
| + } |
| + case MediaGalleries::MANAGE_REQUEST_TYPE_DIRECTORY_PROMPT: { |
| + WebContents* contents = GetWebContents(); |
| + if (!contents) { |
| + SendResponse(false); |
| + return; |
| + } |
| + SelectDirectoryDialog::Callback cb = base::Bind( |
| + &MediaGalleriesManageMediaLocationsFunction::OnDirectorySelected, |
| + this); |
| + scoped_refptr<SelectDirectoryDialog> select_directory_dialog = |
| + new SelectDirectoryDialog(contents, cb); |
| + select_directory_dialog->Show(); |
| + return; |
| + } |
| + case MediaGalleries::MANAGE_REQUEST_TYPE_NONE: |
| + NOTREACHED(); |
| + } |
| + SendResponse(false); |
| +} |
| + |
| +void MediaGalleriesManageMediaLocationsFunction::OnDirectorySelected( |
| + const base::FilePath& selected_directory) { |
| + if (selected_directory.empty()) { |
| + base::ListValue* empty_list = new base::ListValue(); |
|
vandebo (ex-Chrome)
2013/12/02 18:01:30
nit: inline in next line
Lei Zhang
2013/12/03 03:33:23
Done.
|
| + SetResult(empty_list); |
| + SendResponse(true); |
| + return; |
| + } |
| + |
| + bool posted = base::PostTaskAndReplyWithResult( |
|
vandebo (ex-Chrome)
2013/12/02 18:01:30
This appears to be different than MediaGalleriesDi
Lei Zhang
2013/12/03 03:33:23
MediaGalleriesDialogController::FileSelected has t
|
| + content::BrowserThread::GetBlockingPool(), |
| + FROM_HERE, |
| + base::Bind(&base::PathExists, selected_directory), |
| + base::Bind( |
| + &MediaGalleriesManageMediaLocationsFunction::OnDirectoryChecked, |
| + this, |
| + selected_directory)); |
| + if (posted) |
| + return; |
| + SendResponse(false); |
| +} |
| + |
| +void MediaGalleriesManageMediaLocationsFunction::OnDirectoryChecked( |
| + const base::FilePath& selected_directory, bool exists) { |
| + DCHECK(!selected_directory.empty()); |
| + |
| + if (!exists) { |
| + SendResponse(false); |
| + return; |
| + } |
| + |
| + MediaGalleryPrefInfo gallery; |
| + MediaGalleriesPreferences* preferences = GetMediaGalleriesPreferences(); |
| + MediaGalleryPrefId pref_id = |
| + preferences->AddGalleryByPath(selected_directory); |
| + preferences->SetGalleryPermissionForExtension(*GetExtension(), pref_id, true); |
| + |
| + GetMediaFileSystemsForExtension(base::Bind( |
| + &MediaGalleriesManageMediaLocationsFunction::FindGalleryWithPrefId, |
| + this, |
| + pref_id)); |
| +} |
| + |
| +void MediaGalleriesManageMediaLocationsFunction::FindGalleryWithPrefId( |
| + MediaGalleryPrefId pref_id, |
| + const std::vector<MediaFileSystemInfo>& filesystems) { |
| + for (size_t i = 0; i < filesystems.size(); i++) { |
| + if (filesystems[i].pref_id == pref_id) { |
| + std::vector<MediaFileSystemInfo> found_filesystem; |
| + found_filesystem.push_back(filesystems[i]); |
| + base::ListValue* list = ConstructFileSystemList(found_filesystem); |
|
vandebo (ex-Chrome)
2013/12/02 18:01:30
Ahh, I see - you're returning a set of zero or one
Lei Zhang
2013/12/03 03:33:23
Leaving this one open. I'll check tomorrow if file
|
| + if (!list) |
| + break; |
| + |
| + SetResult(list); |
| + SendResponse(true); |
| + return; |
| + } |
| + } |
| + SendResponse(false); |
| +} |
| + |
| } // namespace extensions |