Chromium Code Reviews| Index: chrome/browser/extensions/api/media_galleries/media_galleries_api.cc |
| diff --git a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc |
| index 99b91997024669f80f5edd4062d7c41b12981122..a663e243c9ed80127fec49fd6e86cd4586732e5c 100644 |
| --- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc |
| +++ b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc |
| @@ -14,6 +14,7 @@ |
| #include "apps/app_window_registry.h" |
| #include "base/callback.h" |
| #include "base/lazy_instance.h" |
| +#include "base/numerics/safe_conversions.h" |
| #include "base/stl_util.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| @@ -36,11 +37,14 @@ |
| #include "chrome/common/pref_names.h" |
| #include "components/storage_monitor/storage_info.h" |
| #include "components/web_modal/web_contents_modal_dialog_manager.h" |
| +#include "content/public/browser/blob_handle.h" |
| +#include "content/public/browser/browser_context.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 "extensions/browser/blob_holder.h" |
| #include "extensions/browser/event_router.h" |
| #include "extensions/browser/extension_prefs.h" |
| #include "extensions/browser/extension_system.h" |
| @@ -51,6 +55,7 @@ |
| #include "grit/generated_resources.h" |
| #include "net/base/mime_sniffer.h" |
| #include "ui/base/l10n/l10n_util.h" |
| +#include "webkit/browser/blob/blob_data_handle.h" |
| using content::WebContents; |
| using storage_monitor::MediaStorageUtil; |
| @@ -82,6 +87,12 @@ const char kIsMediaDeviceKey[] = "isMediaDevice"; |
| const char kIsRemovableKey[] = "isRemovable"; |
| const char kNameKey[] = "name"; |
| +const char kMetadataKey[] = "metadata"; |
| +const char kAttachedImagesBlobInfoKey[] = "attachedImagesBlobInfo"; |
| +const char kBlobUUIDKey[] = "blobUUID"; |
| +const char kTypeKey[] = "type"; |
| +const char kSizeKey[] = "size"; |
| + |
| MediaFileSystemRegistry* media_file_system_registry() { |
| return g_browser_process->media_file_system_registry(); |
| } |
| @@ -824,28 +835,35 @@ bool MediaGalleriesGetMetadataFunction::RunAsync() { |
| bool mime_type_only = options->metadata_type == |
| MediaGalleries::GET_METADATA_TYPE_MIMETYPEONLY; |
| + // Get attached images by default. |
| + bool get_attached_images = |
| + options->metadata_type == MediaGalleries::GET_METADATA_TYPE_ALL || |
| + options->metadata_type == MediaGalleries::GET_METADATA_TYPE_NONE; |
| + |
| return Setup(GetProfile(), &error_, base::Bind( |
| &MediaGalleriesGetMetadataFunction::OnPreferencesInit, this, |
| - mime_type_only, blob_uuid)); |
| + mime_type_only, get_attached_images, blob_uuid)); |
| } |
| void MediaGalleriesGetMetadataFunction::OnPreferencesInit( |
| - bool mime_type_only, const std::string& blob_uuid) { |
| + bool mime_type_only, bool get_attached_images, |
|
vandebo (ex-Chrome)
2014/06/02 18:07:27
You should probably make an enum here instead of p
tommycli
2014/06/02 19:34:38
Done.
|
| + const std::string& blob_uuid) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| // BlobReader is self-deleting. |
| BlobReader* reader = new BlobReader( |
| GetProfile(), |
| blob_uuid, |
| - base::Bind(&MediaGalleriesGetMetadataFunction::SniffMimeType, this, |
| - mime_type_only, blob_uuid)); |
| + base::Bind(&MediaGalleriesGetMetadataFunction::GetMetadata, this, |
| + mime_type_only, get_attached_images, blob_uuid)); |
| reader->SetByteRange(0, net::kMaxBytesToSniff); |
| reader->Start(); |
| } |
| -void MediaGalleriesGetMetadataFunction::SniffMimeType( |
| - bool mime_type_only, const std::string& blob_uuid, |
| - scoped_ptr<std::string> blob_header, int64 total_blob_length) { |
| +void MediaGalleriesGetMetadataFunction::GetMetadata( |
| + bool mime_type_only, bool get_attached_images, |
| + const std::string& blob_uuid, scoped_ptr<std::string> blob_header, |
| + int64 total_blob_length) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| std::string mime_type; |
| @@ -860,16 +878,18 @@ void MediaGalleriesGetMetadataFunction::SniffMimeType( |
| if (mime_type_only) { |
| MediaGalleries::MediaMetadata metadata; |
| metadata.mime_type = mime_type; |
| - SetResult(metadata.ToValue().release()); |
| + |
| + base::DictionaryValue* result_dictionary = new base::DictionaryValue; |
| + result_dictionary->Set(kMetadataKey, metadata.ToValue().release()); |
| + SetResult(result_dictionary); |
| SendResponse(true); |
| return; |
| } |
| - // TODO(tommycli): Enable getting attached images. |
| scoped_refptr<metadata::SafeMediaMetadataParser> parser( |
| new metadata::SafeMediaMetadataParser(GetProfile(), blob_uuid, |
| total_blob_length, mime_type, |
| - false /* get_attached_images */)); |
| + get_attached_images)); |
| parser->Start(base::Bind( |
| &MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone, this)); |
| } |
| @@ -877,12 +897,99 @@ void MediaGalleriesGetMetadataFunction::SniffMimeType( |
| void MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone( |
| bool parse_success, scoped_ptr<base::DictionaryValue> metadata_dictionary, |
| scoped_ptr<std::vector<metadata::AttachedImage> > attached_images) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + |
| if (!parse_success) { |
| SendResponse(false); |
| return; |
| } |
| - SetResult(metadata_dictionary->DeepCopy()); |
| + DCHECK(attached_images.get()); |
| + if (attached_images->empty()) { |
| + base::DictionaryValue* result_dictionary = new base::DictionaryValue; |
| + result_dictionary->Set(kMetadataKey, metadata_dictionary.release()); |
| + SetResult(result_dictionary); |
| + SendResponse(true); |
| + return; |
| + } |
| + |
| + metadata::AttachedImage* first_image = &attached_images->front(); |
| + content::BrowserContext::CreateMemoryBackedBlob( |
| + GetProfile(), |
| + first_image->data.c_str(), |
| + first_image->data.size(), |
| + base::Bind(&MediaGalleriesGetMetadataFunction::ConstructNextBlob, |
| + this, base::Passed(&metadata_dictionary), |
| + base::Passed(&attached_images), |
| + base::Passed(make_scoped_ptr(new std::vector<std::string>)))); |
| +} |
| + |
| +void MediaGalleriesGetMetadataFunction::ConstructNextBlob( |
| + scoped_ptr<base::DictionaryValue> metadata_dictionary, |
| + scoped_ptr<std::vector<metadata::AttachedImage> > attached_images, |
| + scoped_ptr<std::vector<std::string> > blob_uuids, |
| + scoped_ptr<content::BlobHandle> next_blob) { |
|
vandebo (ex-Chrome)
2014/06/02 18:07:27
This is the current or previous blob, not the next
tommycli
2014/06/02 19:34:38
Done.
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + |
| + DCHECK(metadata_dictionary.get()); |
| + DCHECK(attached_images.get()); |
| + DCHECK(blob_uuids.get()); |
| + DCHECK(next_blob.get()); |
| + |
| + DCHECK(!attached_images->empty()); |
| + DCHECK_LT(blob_uuids->size(), attached_images->size()); |
| + |
| + // For the newly constructed blob, add its UUID to list and store reference. |
| + blob_uuids->push_back(next_blob->GetUUID()); |
| + WebContents* contents = WebContents::FromRenderViewHost(render_view_host()); |
| + extensions::BlobHolder* holder = |
| + extensions::BlobHolder::FromRenderProcessHost( |
| + contents->GetRenderProcessHost()); |
| + holder->HoldBlobReference(next_blob.Pass()); |
| + |
| + if (blob_uuids->size() == attached_images->size()) { |
| + FinishRequest(metadata_dictionary.Pass(), attached_images.Pass(), |
| + blob_uuids.Pass()); |
| + return; |
| + } |
| + |
| + // Construct the next Blob. |
| + metadata::AttachedImage* next_image = &(*attached_images)[blob_uuids->size()]; |
| + content::BrowserContext::CreateMemoryBackedBlob( |
| + GetProfile(), |
| + next_image->data.c_str(), |
| + next_image->data.size(), |
| + base::Bind(&MediaGalleriesGetMetadataFunction::ConstructNextBlob, |
| + this, base::Passed(&metadata_dictionary), |
| + base::Passed(&attached_images), base::Passed(&blob_uuids))); |
| +} |
| + |
| +void MediaGalleriesGetMetadataFunction::FinishRequest( |
|
vandebo (ex-Chrome)
2014/06/02 18:07:27
It seems like you could do all of this work in eit
tommycli
2014/06/02 19:34:38
Done.
|
| + scoped_ptr<base::DictionaryValue> metadata_dictionary, |
| + scoped_ptr<std::vector<metadata::AttachedImage> > attached_images, |
| + scoped_ptr<std::vector<std::string> > blob_uuids) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + DCHECK(metadata_dictionary.get()); |
| + DCHECK(attached_images->size() == blob_uuids->size()); |
| + |
| + base::DictionaryValue* result_dictionary = new base::DictionaryValue; |
|
vandebo (ex-Chrome)
2014/06/02 18:07:27
Why not do this in OnSafeMediaMetadataParserDone a
tommycli
2014/06/02 19:34:38
Done.
|
| + result_dictionary->Set(kMetadataKey, metadata_dictionary->DeepCopy()); |
| + |
| + // The custom JS binding takes ownership of the Blobs in the renderer. |
| + base::ListValue* attached_images_list = new base::ListValue; |
| + for (size_t i = 0; i < attached_images->size(); ++i) { |
| + base::DictionaryValue* attached_image = new base::DictionaryValue; |
| + attached_image->Set(kBlobUUIDKey, new base::StringValue((*blob_uuids)[i])); |
| + attached_image->Set(kTypeKey, new base::StringValue( |
| + (*attached_images)[i].type)); |
| + attached_image->Set(kSizeKey, new base::FundamentalValue( |
| + base::checked_cast<int>((*attached_images)[i].data.size()))); |
| + attached_images_list->Append(attached_image); |
| + } |
| + result_dictionary->Set(kAttachedImagesBlobInfoKey, attached_images_list); |
| + |
| + SetResult(result_dictionary); |
| + SetTransferredBlobUUIDs(*blob_uuids); |
| SendResponse(true); |
| } |