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" |
24 #include "chrome/browser/extensions/blob_reader.h" | 26 #include "chrome/browser/extensions/blob_reader.h" |
25 #include "chrome/browser/extensions/extension_tab_util.h" | 27 #include "chrome/browser/extensions/extension_tab_util.h" |
26 #include "chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.h" | 28 #include "chrome/browser/media_galleries/fileapi/safe_media_metadata_parser.h" |
27 #include "chrome/browser/media_galleries/media_file_system_registry.h" | 29 #include "chrome/browser/media_galleries/media_file_system_registry.h" |
28 #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h" | 30 #include "chrome/browser/media_galleries/media_galleries_dialog_controller.h" |
29 #include "chrome/browser/media_galleries/media_galleries_histograms.h" | 31 #include "chrome/browser/media_galleries/media_galleries_histograms.h" |
30 #include "chrome/browser/media_galleries/media_galleries_preferences.h" | 32 #include "chrome/browser/media_galleries/media_galleries_preferences.h" |
31 #include "chrome/browser/media_galleries/media_galleries_scan_result_dialog_cont roller.h" | 33 #include "chrome/browser/media_galleries/media_galleries_scan_result_dialog_cont roller.h" |
32 #include "chrome/browser/media_galleries/media_scan_manager.h" | 34 #include "chrome/browser/media_galleries/media_scan_manager.h" |
33 #include "chrome/browser/platform_util.h" | 35 #include "chrome/browser/platform_util.h" |
34 #include "chrome/browser/profiles/profile.h" | 36 #include "chrome/browser/profiles/profile.h" |
35 #include "chrome/browser/ui/chrome_select_file_policy.h" | 37 #include "chrome/browser/ui/chrome_select_file_policy.h" |
36 #include "chrome/common/extensions/api/media_galleries.h" | 38 #include "chrome/common/extensions/api/media_galleries.h" |
37 #include "chrome/common/pref_names.h" | 39 #include "chrome/common/pref_names.h" |
38 #include "components/storage_monitor/storage_info.h" | 40 #include "components/storage_monitor/storage_info.h" |
39 #include "components/web_modal/web_contents_modal_dialog_manager.h" | 41 #include "components/web_modal/web_contents_modal_dialog_manager.h" |
40 #include "content/public/browser/browser_thread.h" | 42 #include "content/public/browser/browser_thread.h" |
41 #include "content/public/browser/child_process_security_policy.h" | 43 #include "content/public/browser/child_process_security_policy.h" |
44 #include "content/public/browser/fileapi/blob_storage_host.h" | |
45 #include "content/public/browser/render_frame_host.h" | |
42 #include "content/public/browser/render_process_host.h" | 46 #include "content/public/browser/render_process_host.h" |
43 #include "content/public/browser/render_view_host.h" | 47 #include "content/public/browser/render_view_host.h" |
44 #include "content/public/browser/web_contents.h" | 48 #include "content/public/browser/web_contents.h" |
45 #include "content/public/browser/web_contents_view.h" | 49 #include "content/public/browser/web_contents_view.h" |
46 #include "extensions/browser/event_router.h" | 50 #include "extensions/browser/event_router.h" |
47 #include "extensions/browser/extension_prefs.h" | 51 #include "extensions/browser/extension_prefs.h" |
48 #include "extensions/browser/extension_system.h" | 52 #include "extensions/browser/extension_system.h" |
49 #include "extensions/common/extension.h" | 53 #include "extensions/common/extension.h" |
50 #include "extensions/common/permissions/api_permission.h" | 54 #include "extensions/common/permissions/api_permission.h" |
51 #include "extensions/common/permissions/media_galleries_permission.h" | 55 #include "extensions/common/permissions/media_galleries_permission.h" |
52 #include "extensions/common/permissions/permissions_data.h" | 56 #include "extensions/common/permissions/permissions_data.h" |
53 #include "grit/generated_resources.h" | 57 #include "grit/generated_resources.h" |
54 #include "net/base/mime_sniffer.h" | 58 #include "net/base/mime_sniffer.h" |
55 #include "ui/base/l10n/l10n_util.h" | 59 #include "ui/base/l10n/l10n_util.h" |
60 #include "webkit/common/blob/blob_data.h" | |
56 | 61 |
57 using content::WebContents; | 62 using content::WebContents; |
58 using storage_monitor::MediaStorageUtil; | 63 using storage_monitor::MediaStorageUtil; |
59 using storage_monitor::StorageInfo; | 64 using storage_monitor::StorageInfo; |
60 using web_modal::WebContentsModalDialogManager; | 65 using web_modal::WebContentsModalDialogManager; |
61 | 66 |
62 namespace extensions { | 67 namespace extensions { |
63 | 68 |
64 namespace MediaGalleries = api::media_galleries; | 69 namespace MediaGalleries = api::media_galleries; |
65 namespace DropPermissionForMediaFileSystem = | 70 namespace DropPermissionForMediaFileSystem = |
(...skipping 11 matching lines...) Expand all Loading... | |
77 const char kNonExistentGalleryId[] = "Non-existent gallery id."; | 82 const char kNonExistentGalleryId[] = "Non-existent gallery id."; |
78 const char kNoScanPermission[] = "No permission to scan."; | 83 const char kNoScanPermission[] = "No permission to scan."; |
79 | 84 |
80 const char kDeviceIdKey[] = "deviceId"; | 85 const char kDeviceIdKey[] = "deviceId"; |
81 const char kGalleryIdKey[] = "galleryId"; | 86 const char kGalleryIdKey[] = "galleryId"; |
82 const char kIsAvailableKey[] = "isAvailable"; | 87 const char kIsAvailableKey[] = "isAvailable"; |
83 const char kIsMediaDeviceKey[] = "isMediaDevice"; | 88 const char kIsMediaDeviceKey[] = "isMediaDevice"; |
84 const char kIsRemovableKey[] = "isRemovable"; | 89 const char kIsRemovableKey[] = "isRemovable"; |
85 const char kNameKey[] = "name"; | 90 const char kNameKey[] = "name"; |
86 | 91 |
92 const char kMetadataKey[] = "metadata"; | |
93 const char kAttachedImagesKey[] = "attachedImages"; | |
94 const char kBlobUUIDKey[] = "blobUUID"; | |
95 const char kTypeKey[] = "type"; | |
96 const char kSizeKey[] = "size"; | |
97 | |
87 MediaFileSystemRegistry* media_file_system_registry() { | 98 MediaFileSystemRegistry* media_file_system_registry() { |
88 return g_browser_process->media_file_system_registry(); | 99 return g_browser_process->media_file_system_registry(); |
89 } | 100 } |
90 | 101 |
91 MediaScanManager* media_scan_manager() { | 102 MediaScanManager* media_scan_manager() { |
92 return media_file_system_registry()->media_scan_manager(); | 103 return media_file_system_registry()->media_scan_manager(); |
93 } | 104 } |
94 | 105 |
95 // Checks whether the MediaGalleries API is currently accessible (it may be | 106 // Checks whether the MediaGalleries API is currently accessible (it may be |
96 // disallowed even if an extension has the requisite permission). Then | 107 // disallowed even if an extension has the requisite permission). Then |
(...skipping 722 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
819 if (!args_->Get(1, &options_value)) | 830 if (!args_->Get(1, &options_value)) |
820 return false; | 831 return false; |
821 scoped_ptr<MediaGalleries::MediaMetadataOptions> options = | 832 scoped_ptr<MediaGalleries::MediaMetadataOptions> options = |
822 MediaGalleries::MediaMetadataOptions::FromValue(*options_value); | 833 MediaGalleries::MediaMetadataOptions::FromValue(*options_value); |
823 if (!options) | 834 if (!options) |
824 return false; | 835 return false; |
825 | 836 |
826 bool mime_type_only = options->metadata_type == | 837 bool mime_type_only = options->metadata_type == |
827 MediaGalleries::GET_METADATA_TYPE_MIMETYPEONLY; | 838 MediaGalleries::GET_METADATA_TYPE_MIMETYPEONLY; |
828 | 839 |
840 // Get attached images by default. | |
841 bool get_attached_images = | |
842 options->metadata_type == MediaGalleries::GET_METADATA_TYPE_ALL || | |
843 options->metadata_type == MediaGalleries::GET_METADATA_TYPE_NONE; | |
844 | |
829 return Setup(GetProfile(), &error_, base::Bind( | 845 return Setup(GetProfile(), &error_, base::Bind( |
830 &MediaGalleriesGetMetadataFunction::OnPreferencesInit, this, | 846 &MediaGalleriesGetMetadataFunction::OnPreferencesInit, this, |
831 mime_type_only, blob_uuid)); | 847 mime_type_only, get_attached_images, blob_uuid)); |
832 } | 848 } |
833 | 849 |
834 void MediaGalleriesGetMetadataFunction::OnPreferencesInit( | 850 void MediaGalleriesGetMetadataFunction::OnPreferencesInit( |
835 bool mime_type_only, const std::string& blob_uuid) { | 851 bool mime_type_only, bool get_attached_images, |
852 const std::string& blob_uuid) { | |
836 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 853 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
837 | 854 |
838 // BlobReader is self-deleting. | 855 // BlobReader is self-deleting. |
839 BlobReader* reader = new BlobReader( | 856 BlobReader* reader = new BlobReader( |
840 GetProfile(), | 857 GetProfile(), |
841 blob_uuid, | 858 blob_uuid, |
842 base::Bind(&MediaGalleriesGetMetadataFunction::SniffMimeType, this, | 859 base::Bind(&MediaGalleriesGetMetadataFunction::GetMetadata, this, |
843 mime_type_only, blob_uuid)); | 860 mime_type_only, get_attached_images, blob_uuid)); |
844 reader->SetByteRange(0, net::kMaxBytesToSniff); | 861 reader->SetByteRange(0, net::kMaxBytesToSniff); |
845 reader->Start(); | 862 reader->Start(); |
846 } | 863 } |
847 | 864 |
848 void MediaGalleriesGetMetadataFunction::SniffMimeType( | 865 void MediaGalleriesGetMetadataFunction::GetMetadata( |
849 bool mime_type_only, const std::string& blob_uuid, | 866 bool mime_type_only, bool get_attached_images, |
850 scoped_ptr<std::string> blob_header, int64 total_blob_length) { | 867 const std::string& blob_uuid, scoped_ptr<std::string> blob_header, |
868 int64 total_blob_length) { | |
851 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 869 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
852 | 870 |
853 std::string mime_type; | 871 std::string mime_type; |
854 bool mime_type_sniffed = net::SniffMimeTypeFromLocalData( | 872 bool mime_type_sniffed = net::SniffMimeTypeFromLocalData( |
855 blob_header->c_str(), blob_header->size(), &mime_type); | 873 blob_header->c_str(), blob_header->size(), &mime_type); |
856 | 874 |
857 if (!mime_type_sniffed) { | 875 if (!mime_type_sniffed) { |
858 SendResponse(false); | 876 SendResponse(false); |
859 return; | 877 return; |
860 } | 878 } |
861 | 879 |
862 if (mime_type_only) { | 880 if (mime_type_only) { |
863 MediaGalleries::MediaMetadata metadata; | 881 MediaGalleries::MediaMetadata metadata; |
864 metadata.mime_type = mime_type; | 882 metadata.mime_type = mime_type; |
865 SetResult(metadata.ToValue().release()); | 883 |
884 base::DictionaryValue* result_dictionary = new base::DictionaryValue; | |
885 result_dictionary->Set(kMetadataKey, metadata.ToValue().release()); | |
886 SetResult(result_dictionary); | |
866 SendResponse(true); | 887 SendResponse(true); |
867 return; | 888 return; |
868 } | 889 } |
869 | 890 |
870 scoped_refptr<metadata::SafeMediaMetadataParser> parser( | 891 scoped_refptr<metadata::SafeMediaMetadataParser> parser( |
871 new metadata::SafeMediaMetadataParser(GetProfile(), blob_uuid, | 892 new metadata::SafeMediaMetadataParser(GetProfile(), blob_uuid, |
872 total_blob_length, mime_type)); | 893 total_blob_length, mime_type, |
894 get_attached_images)); | |
873 parser->Start(base::Bind( | 895 parser->Start(base::Bind( |
874 &MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone, this)); | 896 &MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone, this)); |
875 } | 897 } |
876 | 898 |
877 void MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone( | 899 void MediaGalleriesGetMetadataFunction::OnSafeMediaMetadataParserDone( |
878 bool parse_success, base::DictionaryValue* metadata_dictionary) { | 900 bool parse_success, base::DictionaryValue* metadata_dictionary, |
901 const std::vector<metadata::AttachedImage>& attached_images) { | |
902 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
903 | |
879 if (!parse_success) { | 904 if (!parse_success) { |
880 SendResponse(false); | 905 SendResponse(false); |
881 return; | 906 return; |
882 } | 907 } |
883 | 908 |
884 SetResult(metadata_dictionary->DeepCopy()); | 909 if (attached_images.empty()) { |
910 base::DictionaryValue* result_dictionary = new base::DictionaryValue; | |
911 result_dictionary->Set(kMetadataKey, metadata_dictionary->DeepCopy()); | |
912 SetResult(result_dictionary); | |
913 SendResponse(true); | |
914 return; | |
915 } | |
916 | |
917 content::BrowserThread::PostTaskAndReplyWithResult( | |
918 content::BrowserThread::IO, | |
919 FROM_HERE, | |
920 base::Bind(&MediaGalleriesGetMetadataFunction::CreateBlobsOnIOThread, | |
921 this, attached_images), | |
922 base::Bind(&MediaGalleriesGetMetadataFunction::FinishWithBlobsOnUIThread, | |
923 this, base::Owned(metadata_dictionary->DeepCopy()), | |
924 attached_images)); | |
925 } | |
926 | |
927 std::vector<std::string> | |
928 MediaGalleriesGetMetadataFunction::CreateBlobsOnIOThread( | |
929 const std::vector<metadata::AttachedImage>& attached_images) { | |
930 content::BlobStorageHost* blob_storage = | |
931 render_view_host()->GetProcess()->GetBlobStorageHost(); | |
jam
2014/05/02 18:31:59
RenderViewHost and RenderProcessHost are not threa
tommycli
2014/05/07 21:39:05
Done.
| |
932 std::vector<std::string> blob_uuids; | |
933 | |
934 for (std::vector<metadata::AttachedImage>::const_iterator it = | |
935 attached_images.begin(); | |
936 it != attached_images.end(); ++it) { | |
937 // Here we notably use a UUID generated in the browser process instead of | |
938 // in WebKit. It is upper case and doesn't conform to UUID 4 specifications, | |
939 // but this doesn't seem to cause any harm. | |
940 std::string uuid = base::GenerateGUID(); | |
941 BlobData::Item item; | |
942 item.SetToBytes(it->data.c_str(), it->data.size()); | |
943 | |
944 // These should never return false. | |
945 CHECK(blob_storage->StartBuildingBlob(uuid)); | |
946 CHECK(blob_storage->AppendBlobDataItem(uuid, item)); | |
947 CHECK(blob_storage->FinishBuildingBlob(uuid, it->type)); | |
jam
2014/05/02 18:31:59
since you only need these three methods, can you c
tommycli
2014/05/07 21:39:05
Done.
| |
948 | |
949 blob_uuids.push_back(uuid); | |
950 } | |
951 | |
952 return blob_uuids; | |
953 } | |
954 | |
955 void MediaGalleriesGetMetadataFunction::FinishWithBlobsOnUIThread( | |
956 base::DictionaryValue* metadata_dictionary, | |
957 const std::vector<metadata::AttachedImage>& attached_images, | |
958 const std::vector<std::string>& blob_uuids) { | |
959 DCHECK(attached_images.size() == blob_uuids.size()); | |
960 | |
961 base::DictionaryValue* result_dictionary = new base::DictionaryValue; | |
962 result_dictionary->Set(kMetadataKey, metadata_dictionary->DeepCopy()); | |
963 | |
964 // The custom JS binding will reconstitute the blobs in the renderer. | |
965 base::ListValue* attached_images_list = new base::ListValue; | |
966 for (size_t i = 0; i < attached_images.size(); ++i) { | |
967 base::DictionaryValue* attached_image = new base::DictionaryValue; | |
968 attached_image->Set(kBlobUUIDKey, new base::StringValue(blob_uuids[i])); | |
969 attached_image->Set(kTypeKey, new base::StringValue( | |
970 attached_images[i].type)); | |
971 attached_image->Set(kSizeKey, new base::FundamentalValue( | |
972 base::checked_cast<int>(attached_images[i].data.size()))); | |
973 attached_images_list->Append(attached_image); | |
974 } | |
975 result_dictionary->Set(kAttachedImagesKey, attached_images_list); | |
976 | |
977 SetResult(result_dictionary); | |
885 SendResponse(true); | 978 SendResponse(true); |
886 } | 979 } |
887 | 980 |
888 } // namespace extensions | 981 } // namespace extensions |
OLD | NEW |