| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // Implements the Chrome Extensions Media Galleries API. | 5 // Implements the Chrome Extensions Media Galleries API. |
| 6 | 6 |
| 7 #include "chrome/browser/extensions/api/media_galleries/media_galleries_api.h" | 7 #include "chrome/browser/extensions/api/media_galleries/media_galleries_api.h" |
| 8 | 8 |
| 9 #include <set> | 9 #include <set> |
| 10 #include <string> | 10 #include <string> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "apps/app_window.h" | 13 #include "apps/app_window.h" |
| 14 #include "apps/app_window_registry.h" | 14 #include "apps/app_window_registry.h" |
| 15 #include "base/callback.h" | 15 #include "base/callback.h" |
| 16 #include "base/guid.h" |
| 16 #include "base/lazy_instance.h" | 17 #include "base/lazy_instance.h" |
| 18 #include "base/numerics/safe_conversions.h" |
| 17 #include "base/platform_file.h" | 19 #include "base/platform_file.h" |
| 18 #include "base/stl_util.h" | 20 #include "base/stl_util.h" |
| 19 #include "base/strings/string_number_conversions.h" | 21 #include "base/strings/string_number_conversions.h" |
| 20 #include "base/strings/utf_string_conversions.h" | 22 #include "base/strings/utf_string_conversions.h" |
| 21 #include "base/values.h" | 23 #include "base/values.h" |
| 22 #include "chrome/browser/browser_process.h" | 24 #include "chrome/browser/browser_process.h" |
| 23 #include "chrome/browser/extensions/api/file_system/file_system_api.h" | 25 #include "chrome/browser/extensions/api/file_system/file_system_api.h" |
| 26 #include "chrome/browser/extensions/blob_holder.h" |
| 24 #include "chrome/browser/extensions/blob_reader.h" | 27 #include "chrome/browser/extensions/blob_reader.h" |
| 25 #include "chrome/browser/extensions/extension_tab_util.h" | 28 #include "chrome/browser/extensions/extension_tab_util.h" |
| 26 #include "chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.h" | 29 #include "chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.h" |
| 27 #include "chrome/browser/media_galleries/media_file_system_registry.h" | 30 #include "chrome/browser/media_galleries/media_file_system_registry.h" |
| 28 #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h" | 31 #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h" |
| 29 #include "chrome/browser/media_galleries/media_galleries_histograms.h" | 32 #include "chrome/browser/media_galleries/media_galleries_histograms.h" |
| 30 #include "chrome/browser/media_galleries/media_galleries_preferences.h" | 33 #include "chrome/browser/media_galleries/media_galleries_preferences.h" |
| 31 #include "chrome/browser/media_galleries/media_galleries_scan_result_dialog_cont
roller.h" | 34 #include "chrome/browser/media_galleries/media_galleries_scan_result_dialog_cont
roller.h" |
| 32 #include "chrome/browser/media_galleries/media_scan_manager.h" | 35 #include "chrome/browser/media_galleries/media_scan_manager.h" |
| 33 #include "chrome/browser/platform_util.h" | 36 #include "chrome/browser/platform_util.h" |
| 34 #include "chrome/browser/profiles/profile.h" | 37 #include "chrome/browser/profiles/profile.h" |
| 35 #include "chrome/browser/ui/chrome_select_file_policy.h" | 38 #include "chrome/browser/ui/chrome_select_file_policy.h" |
| 36 #include "chrome/common/extensions/api/media_galleries.h" | 39 #include "chrome/common/extensions/api/media_galleries.h" |
| 37 #include "chrome/common/pref_names.h" | 40 #include "chrome/common/pref_names.h" |
| 38 #include "components/storage_monitor/storage_info.h" | 41 #include "components/storage_monitor/storage_info.h" |
| 39 #include "components/web_modal/web_contents_modal_dialog_manager.h" | 42 #include "components/web_modal/web_contents_modal_dialog_manager.h" |
| 43 #include "content/public/browser/browser_context.h" |
| 40 #include "content/public/browser/browser_thread.h" | 44 #include "content/public/browser/browser_thread.h" |
| 41 #include "content/public/browser/child_process_security_policy.h" | 45 #include "content/public/browser/child_process_security_policy.h" |
| 46 #include "content/public/browser/fileapi/blob_context.h" |
| 47 #include "content/public/browser/render_frame_host.h" |
| 42 #include "content/public/browser/render_process_host.h" | 48 #include "content/public/browser/render_process_host.h" |
| 43 #include "content/public/browser/render_view_host.h" | 49 #include "content/public/browser/render_view_host.h" |
| 44 #include "content/public/browser/web_contents.h" | 50 #include "content/public/browser/web_contents.h" |
| 45 #include "extensions/browser/event_router.h" | 51 #include "extensions/browser/event_router.h" |
| 46 #include "extensions/browser/extension_prefs.h" | 52 #include "extensions/browser/extension_prefs.h" |
| 47 #include "extensions/browser/extension_system.h" | 53 #include "extensions/browser/extension_system.h" |
| 48 #include "extensions/common/extension.h" | 54 #include "extensions/common/extension.h" |
| 49 #include "extensions/common/permissions/api_permission.h" | 55 #include "extensions/common/permissions/api_permission.h" |
| 50 #include "extensions/common/permissions/media_galleries_permission.h" | 56 #include "extensions/common/permissions/media_galleries_permission.h" |
| 51 #include "extensions/common/permissions/permissions_data.h" | 57 #include "extensions/common/permissions/permissions_data.h" |
| 52 #include "grit/generated_resources.h" | 58 #include "grit/generated_resources.h" |
| 53 #include "net/base/mime_sniffer.h" | 59 #include "net/base/mime_sniffer.h" |
| 54 #include "ui/base/l10n/l10n_util.h" | 60 #include "ui/base/l10n/l10n_util.h" |
| 61 #include "webkit/browser/blob/blob_data_handle.h" |
| 55 | 62 |
| 56 using content::WebContents; | 63 using content::WebContents; |
| 57 using storage_monitor::MediaStorageUtil; | 64 using storage_monitor::MediaStorageUtil; |
| 58 using storage_monitor::StorageInfo; | 65 using storage_monitor::StorageInfo; |
| 59 using web_modal::WebContentsModalDialogManager; | 66 using web_modal::WebContentsModalDialogManager; |
| 60 | 67 |
| 61 namespace extensions { | 68 namespace extensions { |
| 62 | 69 |
| 63 namespace MediaGalleries = api::media_galleries; | 70 namespace MediaGalleries = api::media_galleries; |
| 64 namespace DropPermissionForMediaFileSystem = | 71 namespace DropPermissionForMediaFileSystem = |
| (...skipping 11 matching lines...) Expand all Loading... |
| 76 const char kNonExistentGalleryId[] = "Non-existent gallery id."; | 83 const char kNonExistentGalleryId[] = "Non-existent gallery id."; |
| 77 const char kNoScanPermission[] = "No permission to scan."; | 84 const char kNoScanPermission[] = "No permission to scan."; |
| 78 | 85 |
| 79 const char kDeviceIdKey[] = "deviceId"; | 86 const char kDeviceIdKey[] = "deviceId"; |
| 80 const char kGalleryIdKey[] = "galleryId"; | 87 const char kGalleryIdKey[] = "galleryId"; |
| 81 const char kIsAvailableKey[] = "isAvailable"; | 88 const char kIsAvailableKey[] = "isAvailable"; |
| 82 const char kIsMediaDeviceKey[] = "isMediaDevice"; | 89 const char kIsMediaDeviceKey[] = "isMediaDevice"; |
| 83 const char kIsRemovableKey[] = "isRemovable"; | 90 const char kIsRemovableKey[] = "isRemovable"; |
| 84 const char kNameKey[] = "name"; | 91 const char kNameKey[] = "name"; |
| 85 | 92 |
| 93 const char kMetadataKey[] = "metadata"; |
| 94 const char kAttachedImagesKey[] = "attachedImages"; |
| 95 const char kBlobUUIDKey[] = "blobUUID"; |
| 96 const char kTypeKey[] = "type"; |
| 97 const char kSizeKey[] = "size"; |
| 98 |
| 86 MediaFileSystemRegistry* media_file_system_registry() { | 99 MediaFileSystemRegistry* media_file_system_registry() { |
| 87 return g_browser_process->media_file_system_registry(); | 100 return g_browser_process->media_file_system_registry(); |
| 88 } | 101 } |
| 89 | 102 |
| 90 MediaScanManager* media_scan_manager() { | 103 MediaScanManager* media_scan_manager() { |
| 91 return media_file_system_registry()->media_scan_manager(); | 104 return media_file_system_registry()->media_scan_manager(); |
| 92 } | 105 } |
| 93 | 106 |
| 94 // Checks whether the MediaGalleries API is currently accessible (it may be | 107 // Checks whether the MediaGalleries API is currently accessible (it may be |
| 95 // disallowed even if an extension has the requisite permission). Then | 108 // disallowed even if an extension has the requisite permission). Then |
| (...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 818 if (!args_->Get(1, &options_value)) | 831 if (!args_->Get(1, &options_value)) |
| 819 return false; | 832 return false; |
| 820 scoped_ptr<MediaGalleries::MediaMetadataOptions> options = | 833 scoped_ptr<MediaGalleries::MediaMetadataOptions> options = |
| 821 MediaGalleries::MediaMetadataOptions::FromValue(*options_value); | 834 MediaGalleries::MediaMetadataOptions::FromValue(*options_value); |
| 822 if (!options) | 835 if (!options) |
| 823 return false; | 836 return false; |
| 824 | 837 |
| 825 bool mime_type_only = options->metadata_type == | 838 bool mime_type_only = options->metadata_type == |
| 826 MediaGalleries::GET_METADATA_TYPE_MIMETYPEONLY; | 839 MediaGalleries::GET_METADATA_TYPE_MIMETYPEONLY; |
| 827 | 840 |
| 841 // Get attached images by default. |
| 842 bool get_attached_images = |
| 843 options->metadata_type == MediaGalleries::GET_METADATA_TYPE_ALL || |
| 844 options->metadata_type == MediaGalleries::GET_METADATA_TYPE_NONE; |
| 845 |
| 828 return Setup(GetProfile(), &error_, base::Bind( | 846 return Setup(GetProfile(), &error_, base::Bind( |
| 829 &MediaGalleriesGetMetadataFunction::OnPreferencesInit, this, | 847 &MediaGalleriesGetMetadataFunction::OnPreferencesInit, this, |
| 830 mime_type_only, blob_uuid)); | 848 mime_type_only, get_attached_images, blob_uuid)); |
| 831 } | 849 } |
| 832 | 850 |
| 833 void MediaGalleriesGetMetadataFunction::OnPreferencesInit( | 851 void MediaGalleriesGetMetadataFunction::OnPreferencesInit( |
| 834 bool mime_type_only, const std::string& blob_uuid) { | 852 bool mime_type_only, bool get_attached_images, |
| 853 const std::string& blob_uuid) { |
| 835 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 854 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 836 | 855 |
| 837 // BlobReader is self-deleting. | 856 // BlobReader is self-deleting. |
| 838 BlobReader* reader = new BlobReader( | 857 BlobReader* reader = new BlobReader( |
| 839 GetProfile(), | 858 GetProfile(), |
| 840 blob_uuid, | 859 blob_uuid, |
| 841 base::Bind(&MediaGalleriesGetMetadataFunction::SniffMimeType, this, | 860 base::Bind(&MediaGalleriesGetMetadataFunction::GetMetadata, this, |
| 842 mime_type_only, blob_uuid)); | 861 mime_type_only, get_attached_images, blob_uuid)); |
| 843 reader->SetByteRange(0, net::kMaxBytesToSniff); | 862 reader->SetByteRange(0, net::kMaxBytesToSniff); |
| 844 reader->Start(); | 863 reader->Start(); |
| 845 } | 864 } |
| 846 | 865 |
| 847 void MediaGalleriesGetMetadataFunction::SniffMimeType( | 866 void MediaGalleriesGetMetadataFunction::GetMetadata( |
| 848 bool mime_type_only, const std::string& blob_uuid, | 867 bool mime_type_only, bool get_attached_images, |
| 849 scoped_ptr<std::string> blob_header, int64 total_blob_length) { | 868 const std::string& blob_uuid, scoped_ptr<std::string> blob_header, |
| 869 int64 total_blob_length) { |
| 850 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 870 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 851 | 871 |
| 852 std::string mime_type; | 872 std::string mime_type; |
| 853 bool mime_type_sniffed = net::SniffMimeTypeFromLocalData( | 873 bool mime_type_sniffed = net::SniffMimeTypeFromLocalData( |
| 854 blob_header->c_str(), blob_header->size(), &mime_type); | 874 blob_header->c_str(), blob_header->size(), &mime_type); |
| 855 | 875 |
| 856 if (!mime_type_sniffed) { | 876 if (!mime_type_sniffed) { |
| 857 SendResponse(false); | 877 SendResponse(false); |
| 858 return; | 878 return; |
| 859 } | 879 } |
| 860 | 880 |
| 861 if (mime_type_only) { | 881 if (mime_type_only) { |
| 862 MediaGalleries::MediaMetadata metadata; | 882 MediaGalleries::MediaMetadata metadata; |
| 863 metadata.mime_type = mime_type; | 883 metadata.mime_type = mime_type; |
| 864 SetResult(metadata.ToValue().release()); | 884 |
| 885 base::DictionaryValue* result_dictionary = new base::DictionaryValue; |
| 886 result_dictionary->Set(kMetadataKey, metadata.ToValue().release()); |
| 887 SetResult(result_dictionary); |
| 865 SendResponse(true); | 888 SendResponse(true); |
| 866 return; | 889 return; |
| 867 } | 890 } |
| 868 | 891 |
| 869 scoped_refptr<metadata::SafeMediaMetadataParser> parser( | 892 scoped_refptr<metadata::SafeMediaMetadataParser> parser( |
| 870 new metadata::SafeMediaMetadataParser(GetProfile(), blob_uuid, | 893 new metadata::SafeMediaMetadataParser(GetProfile(), blob_uuid, |
| 871 total_blob_length, mime_type)); | 894 total_blob_length, mime_type, |
| 895 get_attached_images)); |
| 872 parser->Start(base::Bind( | 896 parser->Start(base::Bind( |
| 873 &MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone, this)); | 897 &MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone, this)); |
| 874 } | 898 } |
| 875 | 899 |
| 876 void MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone( | 900 void MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone( |
| 877 bool parse_success, base::DictionaryValue* metadata_dictionary) { | 901 bool parse_success, scoped_ptr<base::DictionaryValue> metadata_dictionary, |
| 902 scoped_ptr<std::vector<metadata::AttachedImage>> attached_images) { |
| 903 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 904 |
| 878 if (!parse_success) { | 905 if (!parse_success) { |
| 879 SendResponse(false); | 906 SendResponse(false); |
| 880 return; | 907 return; |
| 881 } | 908 } |
| 882 | 909 |
| 883 SetResult(metadata_dictionary->DeepCopy()); | 910 DCHECK(attached_images.get()); |
| 911 if (attached_images->empty()) { |
| 912 base::DictionaryValue* result_dictionary = new base::DictionaryValue; |
| 913 result_dictionary->Set(kMetadataKey, metadata_dictionary.release()); |
| 914 SetResult(result_dictionary); |
| 915 SendResponse(true); |
| 916 return; |
| 917 } |
| 918 |
| 919 metadata::AttachedImage* first_image = &attached_images->front(); |
| 920 content::BrowserContext::GetBlobContext(GetProfile())->CreateMemoryBackedBlob( |
| 921 first_image->data.c_str(), |
| 922 first_image->data.size(), |
| 923 base::Bind(&MediaGalleriesGetMetadataFunction::ConstructNextBlob, |
| 924 this, base::Passed(&metadata_dictionary), |
| 925 base::Passed(&attached_images), |
| 926 base::Passed(make_scoped_ptr(new std::vector<std::string>)))); |
| 927 } |
| 928 |
| 929 void MediaGalleriesGetMetadataFunction::ConstructNextBlob( |
| 930 scoped_ptr<base::DictionaryValue> metadata_dictionary, |
| 931 scoped_ptr<std::vector<metadata::AttachedImage>> attached_images, |
| 932 scoped_ptr<std::vector<std::string>> blob_uuids, |
| 933 scoped_ptr<webkit_blob::BlobDataHandle> next_blob) { |
| 934 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 935 |
| 936 DCHECK(metadata_dictionary.get()); |
| 937 DCHECK(attached_images.get()); |
| 938 DCHECK(blob_uuids.get()); |
| 939 DCHECK(next_blob.get()); |
| 940 |
| 941 DCHECK(!attached_images->empty()); |
| 942 DCHECK_LT(blob_uuids->size(), attached_images->size()); |
| 943 |
| 944 // For the newly constructed blob, add its UUID to list and store reference. |
| 945 blob_uuids->push_back(next_blob->uuid()); |
| 946 WebContents* contents = WebContents::FromRenderViewHost(render_view_host()); |
| 947 extensions::BlobHolder::CreateForWebContents(contents); |
| 948 extensions::BlobHolder* holder = |
| 949 extensions::BlobHolder::FromWebContents(contents); |
| 950 holder->HoldBlobReference(next_blob.Pass()); |
| 951 |
| 952 if (blob_uuids->size() == attached_images->size()) { |
| 953 FinishRequest(metadata_dictionary.Pass(), attached_images.Pass(), |
| 954 blob_uuids.Pass()); |
| 955 return; |
| 956 } |
| 957 |
| 958 // Construct the next Blob. |
| 959 content::BlobContext* blob_context = |
| 960 content::BrowserContext::GetBlobContext(GetProfile()); |
| 961 metadata::AttachedImage* next_image = &(*attached_images)[blob_uuids->size()]; |
| 962 blob_context->CreateMemoryBackedBlob( |
| 963 next_image->data.c_str(), next_image->data.size(), |
| 964 base::Bind(&MediaGalleriesGetMetadataFunction::ConstructNextBlob, |
| 965 this, base::Passed(&metadata_dictionary), |
| 966 base::Passed(&attached_images), base::Passed(&blob_uuids))); |
| 967 } |
| 968 |
| 969 void MediaGalleriesGetMetadataFunction::FinishRequest( |
| 970 scoped_ptr<base::DictionaryValue> metadata_dictionary, |
| 971 scoped_ptr<std::vector<metadata::AttachedImage>> attached_images, |
| 972 scoped_ptr<std::vector<std::string>> blob_uuids) { |
| 973 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| 974 DCHECK(metadata_dictionary.get()); |
| 975 DCHECK(attached_images->size() == blob_uuids->size()); |
| 976 |
| 977 base::DictionaryValue* result_dictionary = new base::DictionaryValue; |
| 978 result_dictionary->Set(kMetadataKey, metadata_dictionary->DeepCopy()); |
| 979 |
| 980 // The custom JS binding will reconstitute the blobs in the renderer. |
| 981 base::ListValue* attached_images_list = new base::ListValue; |
| 982 for (size_t i = 0; i < attached_images->size(); ++i) { |
| 983 base::DictionaryValue* attached_image = new base::DictionaryValue; |
| 984 attached_image->Set(kBlobUUIDKey, new base::StringValue((*blob_uuids)[i])); |
| 985 attached_image->Set(kTypeKey, new base::StringValue( |
| 986 (*attached_images)[i].type)); |
| 987 attached_image->Set(kSizeKey, new base::FundamentalValue( |
| 988 base::checked_cast<int>((*attached_images)[i].data.size()))); |
| 989 attached_images_list->Append(attached_image); |
| 990 } |
| 991 result_dictionary->Set(kAttachedImagesKey, attached_images_list); |
| 992 |
| 993 SetResult(result_dictionary); |
| 884 SendResponse(true); | 994 SendResponse(true); |
| 885 } | 995 } |
| 886 | 996 |
| 887 } // namespace extensions | 997 } // namespace extensions |
| OLD | NEW |