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 #import "content/browser/web_contents/web_drag_source_mac.h" | 5 #import "content/browser/web_contents/web_drag_source_mac.h" |
6 | 6 |
7 #include <sys/param.h> | 7 #include <sys/param.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
11 #include "base/mac/mac_logging.h" | 11 #include "base/mac/mac_logging.h" |
12 #include "base/mac/mac_util.h" | 12 #include "base/mac/mac_util.h" |
13 #include "base/pickle.h" | 13 #include "base/pickle.h" |
14 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
15 #include "base/strings/sys_string_conversions.h" | 15 #include "base/strings/sys_string_conversions.h" |
16 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
17 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
18 #include "base/threading/thread_restrictions.h" | 18 #include "base/threading/thread_restrictions.h" |
19 #include "content/browser/browser_thread_impl.h" | 19 #include "content/browser/browser_thread_impl.h" |
20 #include "content/browser/download/drag_download_file.h" | 20 #include "content/browser/download/drag_download_file.h" |
21 #include "content/browser/download/drag_download_util.h" | 21 #include "content/browser/download/drag_download_util.h" |
22 #include "content/browser/renderer_host/render_view_host_impl.h" | 22 #include "content/browser/renderer_host/render_view_host_impl.h" |
23 #include "content/browser/web_contents/web_contents_impl.h" | 23 #include "content/browser/web_contents/web_contents_impl.h" |
24 #include "content/public/browser/content_browser_client.h" | 24 #include "content/public/browser/content_browser_client.h" |
25 #include "content/public/common/content_client.h" | 25 #include "content/public/common/content_client.h" |
| 26 #include "content/public/common/drop_data.h" |
26 #include "content/public/common/url_constants.h" | 27 #include "content/public/common/url_constants.h" |
27 #include "grit/ui_resources.h" | 28 #include "grit/ui_resources.h" |
28 #include "net/base/escape.h" | 29 #include "net/base/escape.h" |
29 #include "net/base/file_stream.h" | 30 #include "net/base/file_stream.h" |
30 #include "net/base/mime_util.h" | 31 #include "net/base/mime_util.h" |
31 #include "net/base/net_util.h" | 32 #include "net/base/net_util.h" |
32 #include "ui/base/clipboard/custom_data_helper.h" | 33 #include "ui/base/clipboard/custom_data_helper.h" |
33 #include "ui/base/dragdrop/cocoa_dnd_util.h" | 34 #include "ui/base/dragdrop/cocoa_dnd_util.h" |
34 #include "ui/gfx/image/image.h" | 35 #include "ui/gfx/image/image.h" |
35 #include "webkit/common/webdropdata.h" | |
36 | 36 |
37 using base::SysNSStringToUTF8; | 37 using base::SysNSStringToUTF8; |
38 using base::SysUTF8ToNSString; | 38 using base::SysUTF8ToNSString; |
39 using base::SysUTF16ToNSString; | 39 using base::SysUTF16ToNSString; |
40 using content::BrowserThread; | 40 using content::BrowserThread; |
41 using content::DragDownloadFile; | 41 using content::DragDownloadFile; |
| 42 using content::DropData; |
42 using content::PromiseFileFinalizer; | 43 using content::PromiseFileFinalizer; |
43 using content::RenderViewHostImpl; | 44 using content::RenderViewHostImpl; |
44 using net::FileStream; | 45 using net::FileStream; |
45 | 46 |
46 namespace { | 47 namespace { |
47 | 48 |
48 // An unofficial standard pasteboard title type to be provided alongside the | 49 // An unofficial standard pasteboard title type to be provided alongside the |
49 // |NSURLPboardType|. | 50 // |NSURLPboardType|. |
50 NSString* const kNSURLTitlePboardType = @"public.url-name"; | 51 NSString* const kNSURLTitlePboardType = @"public.url-name"; |
51 | 52 |
52 // Converts a string16 into a FilePath. Use this method instead of | 53 // Converts a string16 into a FilePath. Use this method instead of |
53 // -[NSString fileSystemRepresentation] to prevent exceptions from being thrown. | 54 // -[NSString fileSystemRepresentation] to prevent exceptions from being thrown. |
54 // See http://crbug.com/78782 for more info. | 55 // See http://crbug.com/78782 for more info. |
55 base::FilePath FilePathFromFilename(const string16& filename) { | 56 base::FilePath FilePathFromFilename(const string16& filename) { |
56 NSString* str = SysUTF16ToNSString(filename); | 57 NSString* str = SysUTF16ToNSString(filename); |
57 char buf[MAXPATHLEN]; | 58 char buf[MAXPATHLEN]; |
58 if (![str getFileSystemRepresentation:buf maxLength:sizeof(buf)]) | 59 if (![str getFileSystemRepresentation:buf maxLength:sizeof(buf)]) |
59 return base::FilePath(); | 60 return base::FilePath(); |
60 return base::FilePath(buf); | 61 return base::FilePath(buf); |
61 } | 62 } |
62 | 63 |
63 // Returns a filename appropriate for the drop data | 64 // Returns a filename appropriate for the drop data |
64 // TODO(viettrungluu): Refactor to make it common across platforms, | 65 // TODO(viettrungluu): Refactor to make it common across platforms, |
65 // and move it somewhere sensible. | 66 // and move it somewhere sensible. |
66 base::FilePath GetFileNameFromDragData(const WebDropData& drop_data) { | 67 base::FilePath GetFileNameFromDragData(const DropData& drop_data) { |
67 base::FilePath file_name( | 68 base::FilePath file_name( |
68 FilePathFromFilename(drop_data.file_description_filename)); | 69 FilePathFromFilename(drop_data.file_description_filename)); |
69 | 70 |
70 // Images without ALT text will only have a file extension so we need to | 71 // Images without ALT text will only have a file extension so we need to |
71 // synthesize one from the provided extension and URL. | 72 // synthesize one from the provided extension and URL. |
72 if (file_name.empty()) { | 73 if (file_name.empty()) { |
73 // Retrieve the name from the URL. | 74 // Retrieve the name from the URL. |
74 string16 suggested_filename = | 75 string16 suggested_filename = |
75 net::GetSuggestedFilename(drop_data.url, "", "", "", "", ""); | 76 net::GetSuggestedFilename(drop_data.url, "", "", "", "", ""); |
76 const std::string extension = file_name.Extension(); | 77 const std::string extension = file_name.Extension(); |
77 file_name = FilePathFromFilename(suggested_filename); | 78 file_name = FilePathFromFilename(suggested_filename); |
78 file_name = file_name.ReplaceExtension(extension); | 79 file_name = file_name.ReplaceExtension(extension); |
79 } | 80 } |
80 | 81 |
81 return file_name; | 82 return file_name; |
82 } | 83 } |
83 | 84 |
84 // This helper's sole task is to write out data for a promised file; the caller | 85 // This helper's sole task is to write out data for a promised file; the caller |
85 // is responsible for opening the file. It takes the drop data and an open file | 86 // is responsible for opening the file. It takes the drop data and an open file |
86 // stream. | 87 // stream. |
87 void PromiseWriterHelper(const WebDropData& drop_data, | 88 void PromiseWriterHelper(const DropData& drop_data, |
88 scoped_ptr<FileStream> file_stream) { | 89 scoped_ptr<FileStream> file_stream) { |
89 DCHECK(file_stream); | 90 DCHECK(file_stream); |
90 file_stream->WriteSync(drop_data.file_contents.data(), | 91 file_stream->WriteSync(drop_data.file_contents.data(), |
91 drop_data.file_contents.length()); | 92 drop_data.file_contents.length()); |
92 } | 93 } |
93 | 94 |
94 // Returns the drop location from a pasteboard. | 95 // Returns the drop location from a pasteboard. |
95 NSString* GetDropLocation(NSPasteboard* pboard) { | 96 NSString* GetDropLocation(NSPasteboard* pboard) { |
96 // The API to get the drop location during a callback from | 97 // The API to get the drop location during a callback from |
97 // kPasteboardTypeFileURLPromise is PasteboardCopyPasteLocation, which takes | 98 // kPasteboardTypeFileURLPromise is PasteboardCopyPasteLocation, which takes |
(...skipping 30 matching lines...) Expand all Loading... |
128 - (void)fillPasteboard; | 129 - (void)fillPasteboard; |
129 - (NSImage*)dragImage; | 130 - (NSImage*)dragImage; |
130 | 131 |
131 @end // @interface WebDragSource(Private) | 132 @end // @interface WebDragSource(Private) |
132 | 133 |
133 | 134 |
134 @implementation WebDragSource | 135 @implementation WebDragSource |
135 | 136 |
136 - (id)initWithContents:(content::WebContentsImpl*)contents | 137 - (id)initWithContents:(content::WebContentsImpl*)contents |
137 view:(NSView*)contentsView | 138 view:(NSView*)contentsView |
138 dropData:(const WebDropData*)dropData | 139 dropData:(const DropData*)dropData |
139 image:(NSImage*)image | 140 image:(NSImage*)image |
140 offset:(NSPoint)offset | 141 offset:(NSPoint)offset |
141 pasteboard:(NSPasteboard*)pboard | 142 pasteboard:(NSPasteboard*)pboard |
142 dragOperationMask:(NSDragOperation)dragOperationMask { | 143 dragOperationMask:(NSDragOperation)dragOperationMask { |
143 if ((self = [super init])) { | 144 if ((self = [super init])) { |
144 contents_ = contents; | 145 contents_ = contents; |
145 DCHECK(contents_); | 146 DCHECK(contents_); |
146 | 147 |
147 contentsView_ = contentsView; | 148 contentsView_ = contentsView; |
148 DCHECK(contentsView_); | 149 DCHECK(contentsView_); |
149 | 150 |
150 dropData_.reset(new WebDropData(*dropData)); | 151 dropData_.reset(new DropData(*dropData)); |
151 DCHECK(dropData_.get()); | 152 DCHECK(dropData_.get()); |
152 | 153 |
153 dragImage_.reset([image retain]); | 154 dragImage_.reset([image retain]); |
154 imageOffset_ = offset; | 155 imageOffset_ = offset; |
155 | 156 |
156 pasteboard_.reset([pboard retain]); | 157 pasteboard_.reset([pboard retain]); |
157 DCHECK(pasteboard_.get()); | 158 DCHECK(pasteboard_.get()); |
158 | 159 |
159 dragOperationMask_ = dragOperationMask; | 160 dragOperationMask_ = dragOperationMask; |
160 | 161 |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
463 } | 464 } |
464 } | 465 } |
465 | 466 |
466 // HTML. | 467 // HTML. |
467 bool hasHTMLData = !dropData_->html.string().empty(); | 468 bool hasHTMLData = !dropData_->html.string().empty(); |
468 // Mail.app and TextEdit accept drags that have both HTML and image flavors on | 469 // Mail.app and TextEdit accept drags that have both HTML and image flavors on |
469 // them, but don't process them correctly <http://crbug.com/55879>. Therefore, | 470 // them, but don't process them correctly <http://crbug.com/55879>. Therefore, |
470 // if there is an image flavor, don't put the HTML data on as HTML, but rather | 471 // if there is an image flavor, don't put the HTML data on as HTML, but rather |
471 // put it on as this Chrome-only flavor. | 472 // put it on as this Chrome-only flavor. |
472 // | 473 // |
473 // (The only time that Blink fills in the WebDropData::file_contents is with | 474 // (The only time that Blink fills in the DropData::file_contents is with |
474 // an image drop, but the MIME time is tested anyway for paranoia's sake.) | 475 // an image drop, but the MIME time is tested anyway for paranoia's sake.) |
475 bool hasImageData = !dropData_->file_contents.empty() && | 476 bool hasImageData = !dropData_->file_contents.empty() && |
476 fileUTI_ && | 477 fileUTI_ && |
477 UTTypeConformsTo(fileUTI_.get(), kUTTypeImage); | 478 UTTypeConformsTo(fileUTI_.get(), kUTTypeImage); |
478 if (hasHTMLData) { | 479 if (hasHTMLData) { |
479 if (hasImageData) { | 480 if (hasImageData) { |
480 [pasteboard_ addTypes:@[ui::kChromeDragImageHTMLPboardType] | 481 [pasteboard_ addTypes:@[ui::kChromeDragImageHTMLPboardType] |
481 owner:contentsView_]; | 482 owner:contentsView_]; |
482 } else { | 483 } else { |
483 [pasteboard_ addTypes:@[NSHTMLPboardType] owner:contentsView_]; | 484 [pasteboard_ addTypes:@[NSHTMLPboardType] owner:contentsView_]; |
(...skipping 15 matching lines...) Expand all Loading... |
499 - (NSImage*)dragImage { | 500 - (NSImage*)dragImage { |
500 if (dragImage_) | 501 if (dragImage_) |
501 return dragImage_; | 502 return dragImage_; |
502 | 503 |
503 // Default to returning a generic image. | 504 // Default to returning a generic image. |
504 return content::GetContentClient()->GetNativeImageNamed( | 505 return content::GetContentClient()->GetNativeImageNamed( |
505 IDR_DEFAULT_FAVICON).ToNSImage(); | 506 IDR_DEFAULT_FAVICON).ToNSImage(); |
506 } | 507 } |
507 | 508 |
508 @end // @implementation WebDragSource (Private) | 509 @end // @implementation WebDragSource (Private) |
OLD | NEW |