| 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 024efde11debb09e40c1130d6abb8d6812858795..9185bdd96ded357d173afb5a4d119b9328670ee2 100644
|
| --- a/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
|
| +++ b/chrome/browser/extensions/api/media_galleries/media_galleries_api.cc
|
| @@ -13,7 +13,9 @@
|
| #include "apps/app_window.h"
|
| #include "apps/app_window_registry.h"
|
| #include "base/callback.h"
|
| +#include "base/guid.h"
|
| #include "base/lazy_instance.h"
|
| +#include "base/numerics/safe_conversions.h"
|
| #include "base/platform_file.h"
|
| #include "base/stl_util.h"
|
| #include "base/strings/string_number_conversions.h"
|
| @@ -21,6 +23,7 @@
|
| #include "base/values.h"
|
| #include "chrome/browser/browser_process.h"
|
| #include "chrome/browser/extensions/api/file_system/file_system_api.h"
|
| +#include "chrome/browser/extensions/blob_holder.h"
|
| #include "chrome/browser/extensions/blob_reader.h"
|
| #include "chrome/browser/extensions/extension_tab_util.h"
|
| #include "chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.h"
|
| @@ -37,8 +40,11 @@
|
| #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/browser_context.h"
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/child_process_security_policy.h"
|
| +#include "content/public/browser/fileapi/blob_context.h"
|
| +#include "content/public/browser/render_frame_host.h"
|
| #include "content/public/browser/render_process_host.h"
|
| #include "content/public/browser/render_view_host.h"
|
| #include "content/public/browser/web_contents.h"
|
| @@ -52,6 +58,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;
|
| @@ -83,6 +90,12 @@ const char kIsMediaDeviceKey[] = "isMediaDevice";
|
| const char kIsRemovableKey[] = "isRemovable";
|
| const char kNameKey[] = "name";
|
|
|
| +const char kMetadataKey[] = "metadata";
|
| +const char kAttachedImagesKey[] = "attachedImages";
|
| +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();
|
| }
|
| @@ -825,28 +838,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,
|
| + 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;
|
| @@ -861,26 +881,116 @@ 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;
|
| }
|
|
|
| scoped_refptr<metadata::SafeMediaMetadataParser> parser(
|
| new metadata::SafeMediaMetadataParser(GetProfile(), blob_uuid,
|
| - total_blob_length, mime_type));
|
| + total_blob_length, mime_type,
|
| + get_attached_images));
|
| parser->Start(base::Bind(
|
| &MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone, this));
|
| }
|
|
|
| void MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone(
|
| - bool parse_success, base::DictionaryValue* metadata_dictionary) {
|
| + 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::GetBlobContext(GetProfile())->CreateMemoryBackedBlob(
|
| + 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<webkit_blob::BlobDataHandle> next_blob) {
|
| + 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->uuid());
|
| + WebContents* contents = WebContents::FromRenderViewHost(render_view_host());
|
| + extensions::BlobHolder::CreateForWebContents(contents);
|
| + extensions::BlobHolder* holder =
|
| + extensions::BlobHolder::FromWebContents(contents);
|
| + 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.
|
| + content::BlobContext* blob_context =
|
| + content::BrowserContext::GetBlobContext(GetProfile());
|
| + metadata::AttachedImage* next_image = &(*attached_images)[blob_uuids->size()];
|
| + blob_context->CreateMemoryBackedBlob(
|
| + 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(
|
| + 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;
|
| + result_dictionary->Set(kMetadataKey, metadata_dictionary->DeepCopy());
|
| +
|
| + // The custom JS binding will reconstitute 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(kAttachedImagesKey, attached_images_list);
|
| +
|
| + SetResult(result_dictionary);
|
| SendResponse(true);
|
| }
|
|
|
|
|