| Index: content/browser/tab_contents/web_drag_source_mac.mm
|
| diff --git a/content/browser/tab_contents/web_drag_source_mac.mm b/content/browser/tab_contents/web_drag_source_mac.mm
|
| deleted file mode 100644
|
| index 68f46969c64db4526c04855e94299d08b89dabe0..0000000000000000000000000000000000000000
|
| --- a/content/browser/tab_contents/web_drag_source_mac.mm
|
| +++ /dev/null
|
| @@ -1,453 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#import "content/browser/tab_contents/web_drag_source_mac.h"
|
| -
|
| -#include <sys/param.h>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/file_path.h"
|
| -#include "base/pickle.h"
|
| -#include "base/string_util.h"
|
| -#include "base/sys_string_conversions.h"
|
| -#include "base/threading/thread.h"
|
| -#include "base/threading/thread_restrictions.h"
|
| -#include "base/utf_string_conversions.h"
|
| -#include "content/browser/browser_thread_impl.h"
|
| -#include "content/browser/download/drag_download_file.h"
|
| -#include "content/browser/download/drag_download_util.h"
|
| -#include "content/browser/renderer_host/render_view_host_impl.h"
|
| -#include "content/browser/tab_contents/tab_contents.h"
|
| -#include "content/public/browser/content_browser_client.h"
|
| -#include "content/public/common/content_client.h"
|
| -#include "content/public/common/url_constants.h"
|
| -#include "net/base/file_stream.h"
|
| -#include "net/base/net_util.h"
|
| -#include "ui/base/clipboard/custom_data_helper.h"
|
| -#include "ui/gfx/mac/nsimage_cache.h"
|
| -#include "webkit/glue/webdropdata.h"
|
| -
|
| -using base::SysNSStringToUTF8;
|
| -using base::SysUTF8ToNSString;
|
| -using base::SysUTF16ToNSString;
|
| -using content::BrowserThread;
|
| -using content::RenderViewHostImpl;
|
| -using net::FileStream;
|
| -
|
| -namespace {
|
| -
|
| -// An unofficial standard pasteboard title type to be provided alongside the
|
| -// |NSURLPboardType|.
|
| -NSString* const kNSURLTitlePboardType = @"public.url-name";
|
| -
|
| -// Converts a string16 into a FilePath. Use this method instead of
|
| -// -[NSString fileSystemRepresentation] to prevent exceptions from being thrown.
|
| -// See http://crbug.com/78782 for more info.
|
| -FilePath FilePathFromFilename(const string16& filename) {
|
| - NSString* str = SysUTF16ToNSString(filename);
|
| - char buf[MAXPATHLEN];
|
| - if (![str getFileSystemRepresentation:buf maxLength:sizeof(buf)])
|
| - return FilePath();
|
| - return FilePath(buf);
|
| -}
|
| -
|
| -// Returns a filename appropriate for the drop data
|
| -// TODO(viettrungluu): Refactor to make it common across platforms,
|
| -// and move it somewhere sensible.
|
| -FilePath GetFileNameFromDragData(const WebDropData& drop_data) {
|
| - FilePath file_name(FilePathFromFilename(drop_data.file_description_filename));
|
| - std::string extension = file_name.Extension();
|
| - file_name = file_name.BaseName().RemoveExtension();
|
| -
|
| - // Images without ALT text will only have a file extension so we need to
|
| - // synthesize one from the provided extension and URL.
|
| - if (file_name.empty()) {
|
| - // Retrieve the name from the URL.
|
| - string16 suggested_filename =
|
| - net::GetSuggestedFilename(drop_data.url, "", "", "", "", "");
|
| - file_name = FilePathFromFilename(suggested_filename);
|
| - }
|
| -
|
| - return file_name.ReplaceExtension(extension);
|
| -}
|
| -
|
| -// This helper's sole task is to write out data for a promised file; the caller
|
| -// is responsible for opening the file. It takes the drop data and an open file
|
| -// stream.
|
| -void PromiseWriterHelper(const WebDropData& drop_data,
|
| - FileStream* file_stream) {
|
| - DCHECK(file_stream);
|
| - file_stream->WriteSync(drop_data.file_contents.data(),
|
| - drop_data.file_contents.length());
|
| -
|
| - if (file_stream)
|
| - file_stream->CloseSync();
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -
|
| -@interface WebDragSource(Private)
|
| -
|
| -- (void)fillPasteboard;
|
| -- (NSImage*)dragImage;
|
| -
|
| -@end // @interface WebDragSource(Private)
|
| -
|
| -
|
| -@implementation WebDragSource
|
| -
|
| -- (id)initWithContents:(TabContents*)contents
|
| - view:(NSView*)contentsView
|
| - dropData:(const WebDropData*)dropData
|
| - image:(NSImage*)image
|
| - offset:(NSPoint)offset
|
| - pasteboard:(NSPasteboard*)pboard
|
| - dragOperationMask:(NSDragOperation)dragOperationMask {
|
| - if ((self = [super init])) {
|
| - contents_ = contents;
|
| - DCHECK(contents_);
|
| -
|
| - contentsView_ = contentsView;
|
| - DCHECK(contentsView_);
|
| -
|
| - dropData_.reset(new WebDropData(*dropData));
|
| - DCHECK(dropData_.get());
|
| -
|
| - dragImage_.reset([image retain]);
|
| - imageOffset_ = offset;
|
| -
|
| - pasteboard_.reset([pboard retain]);
|
| - DCHECK(pasteboard_.get());
|
| -
|
| - dragOperationMask_ = dragOperationMask;
|
| -
|
| - fileExtension_ = nil;
|
| -
|
| - [self fillPasteboard];
|
| - }
|
| -
|
| - return self;
|
| -}
|
| -
|
| -- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
|
| - return dragOperationMask_;
|
| -}
|
| -
|
| -- (void)lazyWriteToPasteboard:(NSPasteboard*)pboard forType:(NSString*)type {
|
| - // NSHTMLPboardType requires the character set to be declared. Otherwise, it
|
| - // assumes US-ASCII. Awesome.
|
| - const string16 kHtmlHeader = ASCIIToUTF16(
|
| - "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=UTF-8\">");
|
| -
|
| - // Be extra paranoid; avoid crashing.
|
| - if (!dropData_.get()) {
|
| - NOTREACHED() << "No drag-and-drop data available for lazy write.";
|
| - return;
|
| - }
|
| -
|
| - // HTML.
|
| - if ([type isEqualToString:NSHTMLPboardType]) {
|
| - DCHECK(!dropData_->text_html.empty());
|
| - // See comment on |kHtmlHeader| above.
|
| - [pboard setString:SysUTF16ToNSString(kHtmlHeader + dropData_->text_html)
|
| - forType:NSHTMLPboardType];
|
| -
|
| - // URL.
|
| - } else if ([type isEqualToString:NSURLPboardType]) {
|
| - DCHECK(dropData_->url.is_valid());
|
| - NSString* urlStr = SysUTF8ToNSString(dropData_->url.spec());
|
| - NSURL* url = [NSURL URLWithString:urlStr];
|
| - // If NSURL creation failed, check for a badly-escaped JavaScript URL.
|
| - // Strip out any existing escapes and then re-escape uniformly.
|
| - if (!url && urlStr && dropData_->url.SchemeIs(chrome::kJavaScriptScheme)) {
|
| - NSString* unEscapedStr = [urlStr
|
| - stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
| - NSString* escapedStr = [unEscapedStr
|
| - stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
| - url = [NSURL URLWithString:escapedStr];
|
| - }
|
| - [url writeToPasteboard:pboard];
|
| - // URL title.
|
| - } else if ([type isEqualToString:kNSURLTitlePboardType]) {
|
| - [pboard setString:SysUTF16ToNSString(dropData_->url_title)
|
| - forType:kNSURLTitlePboardType];
|
| -
|
| - // File contents.
|
| - } else if ([type isEqualToString:NSFileContentsPboardType] ||
|
| - (fileExtension_ &&
|
| - [type isEqualToString:NSCreateFileContentsPboardType(fileExtension_)])) {
|
| - // TODO(viettrungluu: find something which is known to accept
|
| - // NSFileContentsPboardType to check that this actually works!
|
| - scoped_nsobject<NSFileWrapper> file_wrapper(
|
| - [[NSFileWrapper alloc] initRegularFileWithContents:[NSData
|
| - dataWithBytes:dropData_->file_contents.data()
|
| - length:dropData_->file_contents.length()]]);
|
| - [file_wrapper setPreferredFilename:SysUTF8ToNSString(
|
| - GetFileNameFromDragData(*dropData_).value())];
|
| - [pboard writeFileWrapper:file_wrapper];
|
| -
|
| - // TIFF.
|
| - } else if ([type isEqualToString:NSTIFFPboardType]) {
|
| - // TODO(viettrungluu): This is a bit odd since we rely on Cocoa to render
|
| - // our image into a TIFF. This is also suboptimal since this is all done
|
| - // synchronously. I'm not sure there's much we can easily do about it.
|
| - scoped_nsobject<NSImage> image(
|
| - [[NSImage alloc] initWithData:[NSData
|
| - dataWithBytes:dropData_->file_contents.data()
|
| - length:dropData_->file_contents.length()]]);
|
| - [pboard setData:[image TIFFRepresentation] forType:NSTIFFPboardType];
|
| -
|
| - // Plain text.
|
| - } else if ([type isEqualToString:NSStringPboardType]) {
|
| - DCHECK(!dropData_->plain_text.empty());
|
| - [pboard setString:SysUTF16ToNSString(dropData_->plain_text)
|
| - forType:NSStringPboardType];
|
| -
|
| - // Custom MIME data.
|
| - } else if ([type isEqualToString:ui::kWebCustomDataPboardType]) {
|
| - Pickle pickle;
|
| - ui::WriteCustomDataToPickle(dropData_->custom_data, &pickle);
|
| - [pboard setData:[NSData dataWithBytes:pickle.data() length:pickle.size()]
|
| - forType:ui::kWebCustomDataPboardType];
|
| -
|
| - // Oops!
|
| - } else {
|
| - NOTREACHED() << "Asked for a drag pasteboard type we didn't offer.";
|
| - }
|
| -}
|
| -
|
| -- (NSPoint)convertScreenPoint:(NSPoint)screenPoint {
|
| - DCHECK([contentsView_ window]);
|
| - NSPoint basePoint = [[contentsView_ window] convertScreenToBase:screenPoint];
|
| - return [contentsView_ convertPoint:basePoint fromView:nil];
|
| -}
|
| -
|
| -- (void)startDrag {
|
| - NSEvent* currentEvent = [NSApp currentEvent];
|
| -
|
| - // Synthesize an event for dragging, since we can't be sure that
|
| - // [NSApp currentEvent] will return a valid dragging event.
|
| - NSWindow* window = [contentsView_ window];
|
| - NSPoint position = [window mouseLocationOutsideOfEventStream];
|
| - NSTimeInterval eventTime = [currentEvent timestamp];
|
| - NSEvent* dragEvent = [NSEvent mouseEventWithType:NSLeftMouseDragged
|
| - location:position
|
| - modifierFlags:NSLeftMouseDraggedMask
|
| - timestamp:eventTime
|
| - windowNumber:[window windowNumber]
|
| - context:nil
|
| - eventNumber:0
|
| - clickCount:1
|
| - pressure:1.0];
|
| -
|
| - if (dragImage_) {
|
| - position.x -= imageOffset_.x;
|
| - // Deal with Cocoa's flipped coordinate system.
|
| - position.y -= [dragImage_.get() size].height - imageOffset_.y;
|
| - }
|
| - // Per kwebster, offset arg is ignored, see -_web_DragImageForElement: in
|
| - // third_party/WebKit/Source/WebKit/mac/Misc/WebNSViewExtras.m.
|
| - [window dragImage:[self dragImage]
|
| - at:position
|
| - offset:NSZeroSize
|
| - event:dragEvent
|
| - pasteboard:pasteboard_
|
| - source:contentsView_
|
| - slideBack:YES];
|
| -}
|
| -
|
| -- (void)endDragAt:(NSPoint)screenPoint
|
| - operation:(NSDragOperation)operation {
|
| - contents_->SystemDragEnded();
|
| -
|
| - RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
|
| - contents_->GetRenderViewHost());
|
| - if (rvh) {
|
| - // Convert |screenPoint| to view coordinates and flip it.
|
| - NSPoint localPoint = NSMakePoint(0, 0);
|
| - if ([contentsView_ window])
|
| - localPoint = [self convertScreenPoint:screenPoint];
|
| - NSRect viewFrame = [contentsView_ frame];
|
| - localPoint.y = viewFrame.size.height - localPoint.y;
|
| - // Flip |screenPoint|.
|
| - NSRect screenFrame = [[[contentsView_ window] screen] frame];
|
| - screenPoint.y = screenFrame.size.height - screenPoint.y;
|
| -
|
| - // If AppKit returns a copy and move operation, mask off the move bit
|
| - // because WebCore does not understand what it means to do both, which
|
| - // results in an assertion failure/renderer crash.
|
| - if (operation == (NSDragOperationMove | NSDragOperationCopy))
|
| - operation &= ~NSDragOperationMove;
|
| -
|
| - rvh->DragSourceEndedAt(localPoint.x, localPoint.y,
|
| - screenPoint.x, screenPoint.y,
|
| - static_cast<WebKit::WebDragOperation>(operation));
|
| - }
|
| -
|
| - // Make sure the pasteboard owner isn't us.
|
| - [pasteboard_ declareTypes:[NSArray array] owner:nil];
|
| -}
|
| -
|
| -- (void)moveDragTo:(NSPoint)screenPoint {
|
| - RenderViewHostImpl* rvh = static_cast<RenderViewHostImpl*>(
|
| - contents_->GetRenderViewHost());
|
| - if (rvh) {
|
| - // Convert |screenPoint| to view coordinates and flip it.
|
| - NSPoint localPoint = NSMakePoint(0, 0);
|
| - if ([contentsView_ window])
|
| - localPoint = [self convertScreenPoint:screenPoint];
|
| - NSRect viewFrame = [contentsView_ frame];
|
| - localPoint.y = viewFrame.size.height - localPoint.y;
|
| - // Flip |screenPoint|.
|
| - NSRect screenFrame = [[[contentsView_ window] screen] frame];
|
| - screenPoint.y = screenFrame.size.height - screenPoint.y;
|
| -
|
| - rvh->DragSourceMovedTo(localPoint.x, localPoint.y,
|
| - screenPoint.x, screenPoint.y);
|
| - }
|
| -}
|
| -
|
| -- (NSString*)dragPromisedFileTo:(NSString*)path {
|
| - // Be extra paranoid; avoid crashing.
|
| - if (!dropData_.get()) {
|
| - NOTREACHED() << "No drag-and-drop data available for promised file.";
|
| - return nil;
|
| - }
|
| -
|
| - FilePath fileName = downloadFileName_.empty() ?
|
| - GetFileNameFromDragData(*dropData_) : downloadFileName_;
|
| - FilePath filePath(SysNSStringToUTF8(path));
|
| - filePath = filePath.Append(fileName);
|
| -
|
| - // CreateFileStreamForDrop() will call file_util::PathExists(),
|
| - // which is blocking. Since this operation is already blocking the
|
| - // UI thread on OSX, it should be reasonable to let it happen.
|
| - base::ThreadRestrictions::ScopedAllowIO allowIO;
|
| - FileStream* fileStream =
|
| - drag_download_util::CreateFileStreamForDrop(
|
| - &filePath, content::GetContentClient()->browser()->GetNetLog());
|
| - if (!fileStream)
|
| - return nil;
|
| -
|
| - if (downloadURL_.is_valid()) {
|
| - scoped_refptr<DragDownloadFile> dragFileDownloader(new DragDownloadFile(
|
| - filePath,
|
| - linked_ptr<net::FileStream>(fileStream),
|
| - downloadURL_,
|
| - contents_->GetURL(),
|
| - contents_->GetEncoding(),
|
| - contents_));
|
| -
|
| - // The finalizer will take care of closing and deletion.
|
| - dragFileDownloader->Start(
|
| - new drag_download_util::PromiseFileFinalizer(dragFileDownloader));
|
| - } else {
|
| - // The writer will take care of closing and deletion.
|
| - BrowserThread::PostTask(BrowserThread::FILE,
|
| - FROM_HERE,
|
| - base::Bind(&PromiseWriterHelper,
|
| - *dropData_,
|
| - base::Owned(fileStream)));
|
| - }
|
| -
|
| - // Once we've created the file, we should return the file name.
|
| - return SysUTF8ToNSString(filePath.BaseName().value());
|
| -}
|
| -
|
| -@end // @implementation WebDragSource
|
| -
|
| -
|
| -@implementation WebDragSource (Private)
|
| -
|
| -- (void)fillPasteboard {
|
| - DCHECK(pasteboard_.get());
|
| -
|
| - [pasteboard_ declareTypes:[NSArray array] owner:contentsView_];
|
| -
|
| - // HTML.
|
| - if (!dropData_->text_html.empty())
|
| - [pasteboard_ addTypes:[NSArray arrayWithObject:NSHTMLPboardType]
|
| - owner:contentsView_];
|
| -
|
| - // URL (and title).
|
| - if (dropData_->url.is_valid())
|
| - [pasteboard_ addTypes:[NSArray arrayWithObjects:NSURLPboardType,
|
| - kNSURLTitlePboardType, nil]
|
| - owner:contentsView_];
|
| -
|
| - std::string fileExtension;
|
| -
|
| - // File.
|
| - if (!dropData_->file_contents.empty() ||
|
| - !dropData_->download_metadata.empty()) {
|
| - if (dropData_->download_metadata.empty()) {
|
| - fileExtension = GetFileNameFromDragData(*dropData_).Extension();
|
| - } else {
|
| - string16 mimeType;
|
| - FilePath fileName;
|
| - if (drag_download_util::ParseDownloadMetadata(
|
| - dropData_->download_metadata,
|
| - &mimeType,
|
| - &fileName,
|
| - &downloadURL_)) {
|
| - // Generate the file name based on both mime type and proposed file
|
| - // name.
|
| - std::string defaultName =
|
| - content::GetContentClient()->browser()->GetDefaultDownloadName();
|
| - downloadFileName_ =
|
| - net::GenerateFileName(downloadURL_,
|
| - std::string(),
|
| - std::string(),
|
| - fileName.value(),
|
| - UTF16ToUTF8(mimeType),
|
| - defaultName);
|
| - fileExtension = downloadFileName_.Extension();
|
| - }
|
| - }
|
| -
|
| - if (!fileExtension.empty()) {
|
| - // Strip the leading dot.
|
| - fileExtension_ = SysUTF8ToNSString(fileExtension.substr(1));
|
| - // File contents (with and without specific type), and file (HFS) promise.
|
| - // TODO(viettrungluu): others?
|
| - NSArray* types = [NSArray arrayWithObjects:
|
| - NSFileContentsPboardType,
|
| - NSCreateFileContentsPboardType(fileExtension_),
|
| - NSFilesPromisePboardType,
|
| - nil];
|
| - [pasteboard_ addTypes:types owner:contentsView_];
|
| -
|
| - if (!dropData_->file_contents.empty()) {
|
| - [pasteboard_ addTypes:[NSArray arrayWithObject:NSTIFFPboardType]
|
| - owner:contentsView_];
|
| - }
|
| -
|
| - // For the file promise, we need to specify the extension.
|
| - [pasteboard_ setPropertyList:[NSArray arrayWithObject:fileExtension_]
|
| - forType:NSFilesPromisePboardType];
|
| - }
|
| - }
|
| -
|
| - // Plain text.
|
| - if (!dropData_->plain_text.empty())
|
| - [pasteboard_ addTypes:[NSArray arrayWithObject:NSStringPboardType]
|
| - owner:contentsView_];
|
| -
|
| - if (!dropData_->custom_data.empty()) {
|
| - [pasteboard_
|
| - addTypes:[NSArray arrayWithObject:ui::kWebCustomDataPboardType]
|
| - owner:contentsView_];
|
| - }
|
| -}
|
| -
|
| -- (NSImage*)dragImage {
|
| - if (dragImage_)
|
| - return dragImage_;
|
| -
|
| - // Default to returning a generic image.
|
| - return gfx::GetCachedImageWithName(@"nav.pdf");
|
| -}
|
| -
|
| -@end // @implementation WebDragSource (Private)
|
|
|