mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Mac:
- Add HTML5 drag&drop support (issue #140). - Client application must now provide NSApplication implementing CefAppProtocol and call CefRunMessageLoop() (issue #248). git-svn-id: https://chromiumembedded.googlecode.com/svn/trunk@269 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
24
cef.gyp
24
cef.gyp
@@ -165,6 +165,7 @@
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
'sources': [
|
'sources': [
|
||||||
|
'include/cef_application_mac.h',
|
||||||
'tests/cefclient/cefclient_mac.mm',
|
'tests/cefclient/cefclient_mac.mm',
|
||||||
'tests/cefclient/client_handler_mac.mm',
|
'tests/cefclient/client_handler_mac.mm',
|
||||||
'tests/cefclient/resource_util_mac.mm',
|
'tests/cefclient/resource_util_mac.mm',
|
||||||
@@ -413,6 +414,11 @@
|
|||||||
],
|
],
|
||||||
'xcode_settings': {
|
'xcode_settings': {
|
||||||
'INSTALL_PATH': '@executable_path',
|
'INSTALL_PATH': '@executable_path',
|
||||||
|
# The libcef_static target contains ObjC categories. Passing the -ObjC flag
|
||||||
|
# is necessary to properly load them and avoid a "selector not recognized"
|
||||||
|
# runtime error. See http://developer.apple.com/library/mac/#qa/qa1490/_index.html
|
||||||
|
# for more information.
|
||||||
|
'OTHER_LDFLAGS': ['-Wl,-ObjC'],
|
||||||
},
|
},
|
||||||
'conditions': [
|
'conditions': [
|
||||||
['OS=="win"', {
|
['OS=="win"', {
|
||||||
@@ -680,6 +686,8 @@
|
|||||||
'libcef/cef_time_util.h',
|
'libcef/cef_time_util.h',
|
||||||
'libcef/drag_download_file.cc',
|
'libcef/drag_download_file.cc',
|
||||||
'libcef/drag_download_file.h',
|
'libcef/drag_download_file.h',
|
||||||
|
'libcef/drag_download_util.cc',
|
||||||
|
'libcef/drag_download_util.h',
|
||||||
'libcef/dom_storage_area.cc',
|
'libcef/dom_storage_area.cc',
|
||||||
'libcef/dom_storage_area.h',
|
'libcef/dom_storage_area.h',
|
||||||
'libcef/dom_storage_common.h',
|
'libcef/dom_storage_common.h',
|
||||||
@@ -693,6 +701,8 @@
|
|||||||
'libcef/dom_event_impl.h',
|
'libcef/dom_event_impl.h',
|
||||||
'libcef/dom_node_impl.cc',
|
'libcef/dom_node_impl.cc',
|
||||||
'libcef/dom_node_impl.h',
|
'libcef/dom_node_impl.h',
|
||||||
|
'libcef/download_util.cc',
|
||||||
|
'libcef/download_util.h',
|
||||||
'libcef/external_protocol_handler.h',
|
'libcef/external_protocol_handler.h',
|
||||||
'libcef/http_header_utils.cc',
|
'libcef/http_header_utils.cc',
|
||||||
'libcef/http_header_utils.h',
|
'libcef/http_header_utils.h',
|
||||||
@@ -753,6 +763,7 @@
|
|||||||
}],
|
}],
|
||||||
[ 'OS=="mac"', {
|
[ 'OS=="mac"', {
|
||||||
'sources': [
|
'sources': [
|
||||||
|
'include/cef_application_mac.h',
|
||||||
'include/internal/cef_types_mac.h',
|
'include/internal/cef_types_mac.h',
|
||||||
'include/internal/cef_mac.h',
|
'include/internal/cef_mac.h',
|
||||||
'libcef/browser_impl_mac.mm',
|
'libcef/browser_impl_mac.mm',
|
||||||
@@ -766,6 +777,19 @@
|
|||||||
'libcef/external_protocol_handler_mac.mm',
|
'libcef/external_protocol_handler_mac.mm',
|
||||||
'libcef/webview_host_mac.mm',
|
'libcef/webview_host_mac.mm',
|
||||||
'libcef/webwidget_host_mac.mm',
|
'libcef/webwidget_host_mac.mm',
|
||||||
|
'libcef/web_drag_source_mac.h',
|
||||||
|
'libcef/web_drag_source_mac.mm',
|
||||||
|
'libcef/web_drag_utils_mac.h',
|
||||||
|
'libcef/web_drag_utils_mac.mm',
|
||||||
|
'libcef/web_drop_target_mac.h',
|
||||||
|
'libcef/web_drop_target_mac.mm',
|
||||||
|
# Build necessary Mozilla sources
|
||||||
|
'../third_party/mozilla/NSPasteboard+Utils.h',
|
||||||
|
'../third_party/mozilla/NSPasteboard+Utils.mm',
|
||||||
|
'../third_party/mozilla/NSString+Utils.h',
|
||||||
|
'../third_party/mozilla/NSString+Utils.mm',
|
||||||
|
'../third_party/mozilla/NSURL+Utils.h',
|
||||||
|
'../third_party/mozilla/NSURL+Utils.m',
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
|
[ 'OS=="linux" or OS=="freebsd" or OS=="openbsd"', {
|
||||||
|
82
include/cef_application_mac.h
Normal file
82
include/cef_application_mac.h
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved.
|
||||||
|
//
|
||||||
|
// Redistribution and use in source and binary forms, with or without
|
||||||
|
// modification, are permitted provided that the following conditions are
|
||||||
|
// met:
|
||||||
|
//
|
||||||
|
// * Redistributions of source code must retain the above copyright
|
||||||
|
// notice, this list of conditions and the following disclaimer.
|
||||||
|
// * Redistributions in binary form must reproduce the above
|
||||||
|
// copyright notice, this list of conditions and the following disclaimer
|
||||||
|
// in the documentation and/or other materials provided with the
|
||||||
|
// distribution.
|
||||||
|
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||||
|
// Framework nor the names of its contributors may be used to endorse
|
||||||
|
// or promote products derived from this software without specific prior
|
||||||
|
// written permission.
|
||||||
|
//
|
||||||
|
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
#ifndef _CEF_APPLICATION_MAC_H
|
||||||
|
#define _CEF_APPLICATION_MAC_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "cef.h"
|
||||||
|
|
||||||
|
#if defined(OS_MACOSX) && defined(__OBJC__)
|
||||||
|
|
||||||
|
#ifdef BUILDING_CEF_SHARED
|
||||||
|
|
||||||
|
// Use the existing CrAppProtocol definition.
|
||||||
|
#include "base/message_pump_mac.h"
|
||||||
|
|
||||||
|
#else // BUILDING_CEF_SHARED
|
||||||
|
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
|
// Copy of CrAppProtocol definition from base/message_pump_mac.h.
|
||||||
|
@protocol CrAppProtocol
|
||||||
|
// Must return true if -[NSApplication sendEvent:] is currently on the stack.
|
||||||
|
- (BOOL)isHandlingSendEvent;
|
||||||
|
@end
|
||||||
|
|
||||||
|
#endif // BUILDING_CEF_SHARED
|
||||||
|
|
||||||
|
// All CEF client applications must subclass NSApplication and implement this
|
||||||
|
// protocol.
|
||||||
|
@protocol CefAppProtocol<CrAppProtocol>
|
||||||
|
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent;
|
||||||
|
@end
|
||||||
|
|
||||||
|
// Controls the state of |isHandlingSendEvent| in the event loop so that it is
|
||||||
|
// reset properly.
|
||||||
|
class CefScopedSendingEvent {
|
||||||
|
public:
|
||||||
|
CefScopedSendingEvent()
|
||||||
|
: app_(static_cast<NSApplication<CefAppProtocol>*>(
|
||||||
|
[NSApplication sharedApplication])),
|
||||||
|
handling_([app_ isHandlingSendEvent]) {
|
||||||
|
[app_ setHandlingSendEvent:YES];
|
||||||
|
}
|
||||||
|
~CefScopedSendingEvent() {
|
||||||
|
[app_ setHandlingSendEvent:handling_];
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
NSApplication<CefAppProtocol>* app_;
|
||||||
|
BOOL handling_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // defined(OS_MACOSX) && defined(__OBJC__)
|
||||||
|
|
||||||
|
#endif // _CEF_APPLICATION_MAC_H
|
@@ -9,6 +9,8 @@
|
|||||||
#include "browser_webview_delegate.h"
|
#include "browser_webview_delegate.h"
|
||||||
#include "cef_thread.h"
|
#include "cef_thread.h"
|
||||||
#include "drag_download_file.h"
|
#include "drag_download_file.h"
|
||||||
|
#include "drag_download_util.h"
|
||||||
|
#include "download_util.h"
|
||||||
#include "web_drag_source_win.h"
|
#include "web_drag_source_win.h"
|
||||||
#include "web_drag_utils_win.h"
|
#include "web_drag_utils_win.h"
|
||||||
#include "web_drop_target_win.h"
|
#include "web_drop_target_win.h"
|
||||||
@@ -17,16 +19,8 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "base/file_path.h"
|
|
||||||
#include "base/message_loop.h"
|
|
||||||
#include "base/string_util.h"
|
|
||||||
#include "base/task.h"
|
|
||||||
#include "base/threading/platform_thread.h"
|
|
||||||
#include "base/threading/thread.h"
|
|
||||||
#include "base/threading/thread_restrictions.h"
|
|
||||||
#include "base/utf_string_conversions.h"
|
#include "base/utf_string_conversions.h"
|
||||||
#include "net/base/file_stream.h"
|
#include "net/base/file_stream.h"
|
||||||
#include "net/base/mime_util.h"
|
|
||||||
#include "net/base/net_util.h"
|
#include "net/base/net_util.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
||||||
@@ -71,214 +65,6 @@ LRESULT CALLBACK MsgFilterProc(int code, WPARAM wparam, LPARAM lparam) {
|
|||||||
return CallNextHookEx(msg_hook, code, wparam, lparam);
|
return CallNextHookEx(msg_hook, code, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the download metadata set in DataTransfer.setData. The metadata
|
|
||||||
// consists of a set of the following values separated by ":"
|
|
||||||
// * MIME type
|
|
||||||
// * File name
|
|
||||||
// * URL
|
|
||||||
// If the file name contains special characters, they need to be escaped
|
|
||||||
// appropriately.
|
|
||||||
// For example, we can have
|
|
||||||
// text/plain:example.txt:http://example.com/example.txt
|
|
||||||
// From chrome/browser/download/drag_download_util.cc
|
|
||||||
bool ParseDownloadMetadata(const string16& metadata,
|
|
||||||
string16* mime_type,
|
|
||||||
FilePath* file_name,
|
|
||||||
GURL* url) {
|
|
||||||
const char16 separator = L':';
|
|
||||||
|
|
||||||
size_t mime_type_end_pos = metadata.find(separator);
|
|
||||||
if (mime_type_end_pos == string16::npos)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
size_t file_name_end_pos = metadata.find(separator, mime_type_end_pos + 1);
|
|
||||||
if (file_name_end_pos == string16::npos)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
GURL parsed_url = GURL(metadata.substr(file_name_end_pos + 1));
|
|
||||||
if (!parsed_url.is_valid())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (mime_type)
|
|
||||||
*mime_type = metadata.substr(0, mime_type_end_pos);
|
|
||||||
if (file_name) {
|
|
||||||
string16 file_name_str = metadata.substr(
|
|
||||||
mime_type_end_pos + 1, file_name_end_pos - mime_type_end_pos - 1);
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
*file_name = FilePath(file_name_str);
|
|
||||||
#else
|
|
||||||
*file_name = FilePath(UTF16ToUTF8(file_name_str));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if (url)
|
|
||||||
*url = parsed_url;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
// Returns whether the specified extension is automatically integrated into the
|
|
||||||
// windows shell.
|
|
||||||
// From chrome/browser/download/download_util.cc
|
|
||||||
bool IsShellIntegratedExtension(const string16& extension) {
|
|
||||||
string16 extension_lower = StringToLowerASCII(extension);
|
|
||||||
|
|
||||||
static const wchar_t* const integrated_extensions[] = {
|
|
||||||
// See <http://msdn.microsoft.com/en-us/library/ms811694.aspx>.
|
|
||||||
L"local",
|
|
||||||
// Right-clicking on shortcuts can be magical.
|
|
||||||
L"lnk",
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i = 0; i < arraysize(integrated_extensions); ++i) {
|
|
||||||
if (extension_lower == integrated_extensions[i])
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See <http://www.juniper.net/security/auto/vulnerabilities/vuln2612.html>.
|
|
||||||
// That vulnerability report is not exactly on point, but files become magical
|
|
||||||
// if their end in a CLSID. Here we block extensions that look like CLSIDs.
|
|
||||||
if (extension_lower.size() > 0 && extension_lower.at(0) == L'{' &&
|
|
||||||
extension_lower.at(extension_lower.length() - 1) == L'}')
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns whether the specified file name is a reserved name on windows.
|
|
||||||
// This includes names like "com2.zip" (which correspond to devices) and
|
|
||||||
// desktop.ini and thumbs.db which have special meaning to the windows shell.
|
|
||||||
// From chrome/browser/download/download_util.cc
|
|
||||||
bool IsReservedName(const string16& filename) {
|
|
||||||
// This list is taken from the MSDN article "Naming a file"
|
|
||||||
// http://msdn2.microsoft.com/en-us/library/aa365247(VS.85).aspx
|
|
||||||
// I also added clock$ because GetSaveFileName seems to consider it as a
|
|
||||||
// reserved name too.
|
|
||||||
static const wchar_t* const known_devices[] = {
|
|
||||||
L"con", L"prn", L"aux", L"nul", L"com1", L"com2", L"com3", L"com4", L"com5",
|
|
||||||
L"com6", L"com7", L"com8", L"com9", L"lpt1", L"lpt2", L"lpt3", L"lpt4",
|
|
||||||
L"lpt5", L"lpt6", L"lpt7", L"lpt8", L"lpt9", L"clock$"
|
|
||||||
};
|
|
||||||
string16 filename_lower = StringToLowerASCII(filename);
|
|
||||||
|
|
||||||
for (int i = 0; i < arraysize(known_devices); ++i) {
|
|
||||||
// Exact match.
|
|
||||||
if (filename_lower == known_devices[i])
|
|
||||||
return true;
|
|
||||||
// Starts with "DEVICE.".
|
|
||||||
if (filename_lower.find(string16(known_devices[i]) + L".") == 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const wchar_t* const magic_names[] = {
|
|
||||||
// These file names are used by the "Customize folder" feature of the shell.
|
|
||||||
L"desktop.ini",
|
|
||||||
L"thumbs.db",
|
|
||||||
};
|
|
||||||
|
|
||||||
for (int i = 0; i < arraysize(magic_names); ++i) {
|
|
||||||
if (filename_lower == magic_names[i])
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif // OS_WIN
|
|
||||||
|
|
||||||
// Create an extension based on the file name and mime type.
|
|
||||||
// From chrome/browser/download/download_util.cc
|
|
||||||
void GenerateExtension(const FilePath& file_name,
|
|
||||||
const std::string& mime_type,
|
|
||||||
FilePath::StringType* generated_extension) {
|
|
||||||
// We're worried about two things here:
|
|
||||||
//
|
|
||||||
// 1) Usability. If the site fails to provide a file extension, we want to
|
|
||||||
// guess a reasonable file extension based on the content type.
|
|
||||||
//
|
|
||||||
// 2) Shell integration. Some file extensions automatically integrate with
|
|
||||||
// the shell. We block these extensions to prevent a malicious web site
|
|
||||||
// from integrating with the user's shell.
|
|
||||||
|
|
||||||
// See if our file name already contains an extension.
|
|
||||||
FilePath::StringType extension = file_name.Extension();
|
|
||||||
if (!extension.empty())
|
|
||||||
extension.erase(extension.begin()); // Erase preceding '.'.
|
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
static const FilePath::CharType default_extension[] =
|
|
||||||
FILE_PATH_LITERAL("download");
|
|
||||||
|
|
||||||
// Rename shell-integrated extensions.
|
|
||||||
if (IsShellIntegratedExtension(extension))
|
|
||||||
extension.assign(default_extension);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (extension.empty()) {
|
|
||||||
// The GetPreferredExtensionForMimeType call will end up going to disk. Do
|
|
||||||
// this on another thread to avoid slowing the IO thread.
|
|
||||||
// http://crbug.com/61827
|
|
||||||
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
|
||||||
net::GetPreferredExtensionForMimeType(mime_type, &extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
generated_extension->swap(extension);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Used to make sure we have a safe file extension and filename for a
|
|
||||||
// download. |file_name| can either be just the file name or it can be a
|
|
||||||
// full path to a file.
|
|
||||||
// From chrome/browser/download/download_util.cc
|
|
||||||
void GenerateSafeFileName(const std::string& mime_type, FilePath* file_name) {
|
|
||||||
// Make sure we get the right file extension
|
|
||||||
FilePath::StringType extension;
|
|
||||||
GenerateExtension(*file_name, mime_type, &extension);
|
|
||||||
*file_name = file_name->ReplaceExtension(extension);
|
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
// Prepend "_" to the file name if it's a reserved name
|
|
||||||
FilePath::StringType leaf_name = file_name->BaseName().value();
|
|
||||||
DCHECK(!leaf_name.empty());
|
|
||||||
if (IsReservedName(leaf_name)) {
|
|
||||||
leaf_name = FilePath::StringType(FILE_PATH_LITERAL("_")) + leaf_name;
|
|
||||||
*file_name = file_name->DirName();
|
|
||||||
if (file_name->value() == FilePath::kCurrentDirectory) {
|
|
||||||
*file_name = FilePath(leaf_name);
|
|
||||||
} else {
|
|
||||||
*file_name = file_name->Append(leaf_name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a file name based on the response from the server.
|
|
||||||
// From chrome/browser/download/download_util.cc
|
|
||||||
void GenerateFileName(const GURL& url,
|
|
||||||
const std::string& content_disposition,
|
|
||||||
const std::string& referrer_charset,
|
|
||||||
const std::string& mime_type,
|
|
||||||
FilePath* generated_name) {
|
|
||||||
string16 new_name = net::GetSuggestedFilename(GURL(url),
|
|
||||||
content_disposition,
|
|
||||||
referrer_charset,
|
|
||||||
"",
|
|
||||||
string16(L"download"));
|
|
||||||
|
|
||||||
// TODO(evan): this code is totally wrong -- we should just generate
|
|
||||||
// Unicode filenames and do all this encoding switching at the end.
|
|
||||||
// However, I'm just shuffling wrong code around, at least not adding
|
|
||||||
// to it.
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
*generated_name = FilePath(new_name);
|
|
||||||
#else
|
|
||||||
*generated_name = FilePath(
|
|
||||||
base::SysWideToNativeMB(UTF16ToWide(new_name)));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
DCHECK(!generated_name->empty());
|
|
||||||
|
|
||||||
GenerateSafeFileName(mime_type, generated_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
class DragDropThread : public base::Thread {
|
class DragDropThread : public base::Thread {
|
||||||
@@ -406,21 +192,22 @@ void BrowserDragDelegate::PrepareDragForDownload(
|
|||||||
string16 mime_type;
|
string16 mime_type;
|
||||||
FilePath file_name;
|
FilePath file_name;
|
||||||
GURL download_url;
|
GURL download_url;
|
||||||
if (!ParseDownloadMetadata(drop_data.download_metadata,
|
if (!drag_download_util::ParseDownloadMetadata(drop_data.download_metadata,
|
||||||
&mime_type,
|
&mime_type,
|
||||||
&file_name,
|
&file_name,
|
||||||
&download_url))
|
&download_url))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Generate the download filename.
|
// Generate the download filename.
|
||||||
std::string content_disposition =
|
std::string content_disposition =
|
||||||
"attachment; filename=" + UTF16ToUTF8(file_name.value());
|
"attachment; filename=" + UTF16ToUTF8(file_name.value());
|
||||||
FilePath generated_file_name;
|
FilePath generated_file_name;
|
||||||
GenerateFileName(download_url,
|
download_util::GenerateFileName(download_url,
|
||||||
content_disposition,
|
content_disposition,
|
||||||
std::string(),
|
std::string(),
|
||||||
UTF16ToUTF8(mime_type),
|
UTF16ToUTF8(mime_type),
|
||||||
&generated_file_name);
|
std::string(),
|
||||||
|
&generated_file_name);
|
||||||
|
|
||||||
// Provide the data as file (CF_HDROP). A temporary download file with the
|
// Provide the data as file (CF_HDROP). A temporary download file with the
|
||||||
// Zone.Identifier ADS (Alternate Data Stream) attached will be created.
|
// Zone.Identifier ADS (Alternate Data Stream) attached will be created.
|
||||||
|
@@ -700,6 +700,8 @@ void CefBrowserImpl::UIT_DestroyBrowser()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UIT_GetWebViewDelegate()->RevokeDragDrop();
|
||||||
#else
|
#else
|
||||||
// Call OnBeforeClose() here for platforms that don't support modal dialogs.
|
// Call OnBeforeClose() here for platforms that don't support modal dialogs.
|
||||||
if (client_.get()) {
|
if (client_.get()) {
|
||||||
@@ -711,8 +713,6 @@ void CefBrowserImpl::UIT_DestroyBrowser()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UIT_GetWebViewDelegate()->RevokeDragDrop();
|
|
||||||
|
|
||||||
// If the current browser window is a dev tools client then disconnect from
|
// If the current browser window is a dev tools client then disconnect from
|
||||||
// the agent and destroy the client before destroying the window.
|
// the agent and destroy the client before destroying the window.
|
||||||
UIT_DestroyDevToolsClient();
|
UIT_DestroyDevToolsClient();
|
||||||
|
@@ -59,7 +59,6 @@ void CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
|
|||||||
WebViewHost::Create(window_info_.m_ParentWidget, gfx::Rect(),
|
WebViewHost::Create(window_info_.m_ParentWidget, gfx::Rect(),
|
||||||
delegate_.get(), NULL, dev_tools_agent_.get(),
|
delegate_.get(), NULL, dev_tools_agent_.get(),
|
||||||
prefs));
|
prefs));
|
||||||
delegate_->RegisterDragDrop();
|
|
||||||
|
|
||||||
if (!settings_.developer_tools_disabled)
|
if (!settings_.developer_tools_disabled)
|
||||||
dev_tools_agent_->SetWebView(webviewhost_->webview());
|
dev_tools_agent_->SetWebView(webviewhost_->webview());
|
||||||
|
@@ -86,7 +86,6 @@ void CefBrowserImpl::UIT_CreateBrowser(const CefString& url)
|
|||||||
webviewhost_.reset(
|
webviewhost_.reset(
|
||||||
WebViewHost::Create(parentView, contentRect, delegate_.get(),
|
WebViewHost::Create(parentView, contentRect, delegate_.get(),
|
||||||
NULL, dev_tools_agent_.get(), prefs));
|
NULL, dev_tools_agent_.get(), prefs));
|
||||||
delegate_->RegisterDragDrop();
|
|
||||||
|
|
||||||
if (!settings_.developer_tools_disabled)
|
if (!settings_.developer_tools_disabled)
|
||||||
dev_tools_agent_->SetWebView(webviewhost_->webview());
|
dev_tools_agent_->SetWebView(webviewhost_->webview());
|
||||||
|
@@ -34,12 +34,10 @@
|
|||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebData.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragData.h"
|
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileError.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileError.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystemCallbacks.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFileSystemCallbacks.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebHistoryItem.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebImage.h"
|
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebKit.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebKitClient.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebKitClient.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebNode.h"
|
||||||
@@ -61,7 +59,6 @@
|
|||||||
#include "webkit/appcache/web_application_cache_host_impl.h"
|
#include "webkit/appcache/web_application_cache_host_impl.h"
|
||||||
#include "webkit/glue/glue_serialize.h"
|
#include "webkit/glue/glue_serialize.h"
|
||||||
#include "webkit/glue/media/video_renderer_impl.h"
|
#include "webkit/glue/media/video_renderer_impl.h"
|
||||||
#include "webkit/glue/webdropdata.h"
|
|
||||||
#include "webkit/glue/webpreferences.h"
|
#include "webkit/glue/webpreferences.h"
|
||||||
#include "webkit/glue/webkit_glue.h"
|
#include "webkit/glue/webkit_glue.h"
|
||||||
#include "webkit/glue/webmediaplayer_impl.h"
|
#include "webkit/glue/webmediaplayer_impl.h"
|
||||||
@@ -71,7 +68,6 @@
|
|||||||
#include "webkit/plugins/npapi/webplugin_impl.h"
|
#include "webkit/plugins/npapi/webplugin_impl.h"
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
// TODO(port): make these files work everywhere.
|
|
||||||
#include "browser_drag_delegate_win.h"
|
#include "browser_drag_delegate_win.h"
|
||||||
#include "web_drop_target_win.h"
|
#include "web_drop_target_win.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -84,8 +80,6 @@ using WebKit::WebContextMenuData;
|
|||||||
using WebKit::WebCookieJar;
|
using WebKit::WebCookieJar;
|
||||||
using WebKit::WebData;
|
using WebKit::WebData;
|
||||||
using WebKit::WebDataSource;
|
using WebKit::WebDataSource;
|
||||||
using WebKit::WebDragData;
|
|
||||||
using WebKit::WebDragOperationsMask;
|
|
||||||
using WebKit::WebEditingAction;
|
using WebKit::WebEditingAction;
|
||||||
using WebKit::WebFileChooserParams;
|
using WebKit::WebFileChooserParams;
|
||||||
using WebKit::WebFileSystem;
|
using WebKit::WebFileSystem;
|
||||||
@@ -93,7 +87,6 @@ using WebKit::WebFileSystemCallbacks;
|
|||||||
using WebKit::WebFormElement;
|
using WebKit::WebFormElement;
|
||||||
using WebKit::WebFrame;
|
using WebKit::WebFrame;
|
||||||
using WebKit::WebHistoryItem;
|
using WebKit::WebHistoryItem;
|
||||||
using WebKit::WebImage;
|
|
||||||
using WebKit::WebMediaPlayer;
|
using WebKit::WebMediaPlayer;
|
||||||
using WebKit::WebMediaPlayerClient;
|
using WebKit::WebMediaPlayerClient;
|
||||||
using WebKit::WebNavigationType;
|
using WebKit::WebNavigationType;
|
||||||
@@ -446,27 +439,6 @@ void BrowserWebViewDelegate::setToolTipText(
|
|||||||
GetWidgetHost()->SetTooltipText(tooltipStr);
|
GetWidgetHost()->SetTooltipText(tooltipStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserWebViewDelegate::startDragging(
|
|
||||||
const WebDragData& data,
|
|
||||||
WebDragOperationsMask mask,
|
|
||||||
const WebImage& image,
|
|
||||||
const WebPoint& image_offset) {
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
// Dragging is not supported when window rendering is disabled.
|
|
||||||
if (browser_->IsWindowRenderingDisabled()) {
|
|
||||||
EndDragging();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
drag_delegate_ = new BrowserDragDelegate(this);
|
|
||||||
drag_delegate_->StartDragging(WebDropData(data), mask, image.getSkBitmap(),
|
|
||||||
image_offset);
|
|
||||||
#else
|
|
||||||
// TODO(port): Support drag and drop.
|
|
||||||
EndDragging();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserWebViewDelegate::focusNext() {
|
void BrowserWebViewDelegate::focusNext() {
|
||||||
CefRefPtr<CefClient> client = browser_->GetClient();
|
CefRefPtr<CefClient> client = browser_->GetClient();
|
||||||
if (client.get()) {
|
if (client.get()) {
|
||||||
@@ -986,22 +958,6 @@ void BrowserWebViewDelegate::SetSelectTrailingWhitespaceEnabled(bool enabled) {
|
|||||||
// allows both.
|
// allows both.
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserWebViewDelegate::RegisterDragDrop() {
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
// TODO(port): add me once drag and drop works.
|
|
||||||
DCHECK(!drop_target_);
|
|
||||||
drop_target_ = new WebDropTarget(browser_->UIT_GetWebViewWndHandle(),
|
|
||||||
browser_->UIT_GetWebView());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserWebViewDelegate::RevokeDragDrop() {
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
if (drop_target_.get())
|
|
||||||
::RevokeDragDrop(browser_->UIT_GetWebViewWndHandle());
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserWebViewDelegate::SetCustomPolicyDelegate(bool is_custom,
|
void BrowserWebViewDelegate::SetCustomPolicyDelegate(bool is_custom,
|
||||||
bool is_permissive) {
|
bool is_permissive) {
|
||||||
policy_delegate_enabled_ = is_custom;
|
policy_delegate_enabled_ = is_custom;
|
||||||
@@ -1062,13 +1018,6 @@ WebWidgetHost* BrowserWebViewDelegate::GetWidgetHost() {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BrowserWebViewDelegate::EndDragging() {
|
|
||||||
browser_->UIT_GetWebView()->dragSourceSystemDragEnded();
|
|
||||||
#if defined(OS_WIN)
|
|
||||||
drag_delegate_ = NULL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void BrowserWebViewDelegate::UpdateForCommittedLoad(WebFrame* frame,
|
void BrowserWebViewDelegate::UpdateForCommittedLoad(WebFrame* frame,
|
||||||
bool is_new_navigation) {
|
bool is_new_navigation) {
|
||||||
// Code duplicated from RenderView::DidCommitLoadForFrame.
|
// Code duplicated from RenderView::DidCommitLoadForFrame.
|
||||||
|
@@ -214,6 +214,13 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient,
|
|||||||
|
|
||||||
// Additional accessors
|
// Additional accessors
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_WIN)
|
||||||
|
// Sets the webview as a drop target.
|
||||||
|
void RegisterDragDrop();
|
||||||
|
void RevokeDragDrop();
|
||||||
|
|
||||||
|
// Called after dragging has finished.
|
||||||
|
void EndDragging();
|
||||||
|
|
||||||
BrowserDragDelegate* drag_delegate() { return drag_delegate_.get(); }
|
BrowserDragDelegate* drag_delegate() { return drag_delegate_.get(); }
|
||||||
WebDropTarget* drop_target() { return drop_target_.get(); }
|
WebDropTarget* drop_target() { return drop_target_.get(); }
|
||||||
#endif
|
#endif
|
||||||
@@ -222,12 +229,6 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient,
|
|||||||
pending_extra_data_.reset(extra_data);
|
pending_extra_data_.reset(extra_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the webview as a drop target.
|
|
||||||
void RegisterDragDrop();
|
|
||||||
void RevokeDragDrop();
|
|
||||||
|
|
||||||
void ResetDragDrop();
|
|
||||||
|
|
||||||
void SetCustomPolicyDelegate(bool is_custom, bool is_permissive);
|
void SetCustomPolicyDelegate(bool is_custom, bool is_permissive);
|
||||||
void WaitForPolicyDelegate();
|
void WaitForPolicyDelegate();
|
||||||
|
|
||||||
@@ -255,9 +256,6 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient,
|
|||||||
void ClosePopupMenu();
|
void ClosePopupMenu();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Called after dragging has finished.
|
|
||||||
void EndDragging();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Default handling of JavaScript messages.
|
// Default handling of JavaScript messages.
|
||||||
void ShowJavaScriptAlert(WebKit::WebFrame* webframe,
|
void ShowJavaScriptAlert(WebKit::WebFrame* webframe,
|
||||||
|
@@ -177,6 +177,15 @@ WebRect BrowserWebViewDelegate::windowResizerRect() {
|
|||||||
return WebRect();
|
return WebRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BrowserWebViewDelegate::startDragging(
|
||||||
|
const WebDragData& data,
|
||||||
|
WebDragOperationsMask mask,
|
||||||
|
const WebImage& image,
|
||||||
|
const WebPoint& image_offset) {
|
||||||
|
// TODO(port): Support drag and drop.
|
||||||
|
browser_->UIT_GetWebView()->dragSourceSystemDragEnded();
|
||||||
|
}
|
||||||
|
|
||||||
void BrowserWebViewDelegate::runModal() {
|
void BrowserWebViewDelegate::runModal() {
|
||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
@@ -3,23 +3,35 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "browser_webview_delegate.h"
|
#include "browser_webview_delegate.h"
|
||||||
|
#import "browser_webview_mac.h"
|
||||||
#include "browser_impl.h"
|
#include "browser_impl.h"
|
||||||
|
#import "include/cef_application_mac.h"
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
#include "base/mac/mac_util.h"
|
||||||
#include "base/sys_string_conversions.h"
|
#include "base/sys_string_conversions.h"
|
||||||
|
#include "skia/ext/skia_utils_mac.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragData.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebImage.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupMenu.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPopupMenu.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
|
||||||
#include "webkit/glue/webcursor.h"
|
#include "webkit/glue/webcursor.h"
|
||||||
|
#include "webkit/glue/webdropdata.h"
|
||||||
#include "webkit/plugins/npapi/plugin_list.h"
|
#include "webkit/plugins/npapi/plugin_list.h"
|
||||||
#include "webkit/plugins/npapi/webplugin_delegate_impl.h"
|
#include "webkit/plugins/npapi/webplugin_delegate_impl.h"
|
||||||
#include "webkit/glue/webmenurunner_mac.h"
|
#include "webkit/glue/webmenurunner_mac.h"
|
||||||
|
|
||||||
using WebKit::WebCursorInfo;
|
using WebKit::WebCursorInfo;
|
||||||
|
using WebKit::WebDragData;
|
||||||
|
using WebKit::WebDragOperationsMask;
|
||||||
using WebKit::WebExternalPopupMenu;
|
using WebKit::WebExternalPopupMenu;
|
||||||
using WebKit::WebExternalPopupMenuClient;
|
using WebKit::WebExternalPopupMenuClient;
|
||||||
|
using WebKit::WebImage;
|
||||||
using WebKit::WebNavigationPolicy;
|
using WebKit::WebNavigationPolicy;
|
||||||
|
using WebKit::WebPoint;
|
||||||
using WebKit::WebPopupMenuInfo;
|
using WebKit::WebPopupMenuInfo;
|
||||||
using WebKit::WebRect;
|
using WebKit::WebRect;
|
||||||
using WebKit::WebWidget;
|
using WebKit::WebWidget;
|
||||||
@@ -109,6 +121,39 @@ WebRect BrowserWebViewDelegate::windowResizerRect() {
|
|||||||
return gfx::Rect(NSRectToCGRect(resize_rect));
|
return gfx::Rect(NSRectToCGRect(resize_rect));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BrowserWebViewDelegate::startDragging(const WebDragData& data,
|
||||||
|
WebDragOperationsMask mask,
|
||||||
|
const WebImage& image,
|
||||||
|
const WebPoint& image_offset) {
|
||||||
|
WebWidgetHost* host = GetWidgetHost();
|
||||||
|
if (!host)
|
||||||
|
return;
|
||||||
|
|
||||||
|
BrowserWebView *view = static_cast<BrowserWebView*>(host->view_handle());
|
||||||
|
if (!view)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// By allowing nested tasks, the code below also allows Close(),
|
||||||
|
// which would deallocate |this|. The same problem can occur while
|
||||||
|
// processing -sendEvent:, so Close() is deferred in that case.
|
||||||
|
// Drags from web content do not come via -sendEvent:, this sets the
|
||||||
|
// same flag -sendEvent: would.
|
||||||
|
CefScopedSendingEvent sendingEventScoper;
|
||||||
|
|
||||||
|
// The drag invokes a nested event loop, arrange to continue
|
||||||
|
// processing events.
|
||||||
|
MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
|
||||||
|
NSDragOperation op_mask = static_cast<NSDragOperation>(mask);
|
||||||
|
const SkBitmap& bitmap = gfx::CGImageToSkBitmap(image.getCGImageRef());
|
||||||
|
CGColorSpaceRef color_space = base::mac::GetSystemColorSpace();
|
||||||
|
NSImage* ns_image = gfx::SkBitmapToNSImageWithColorSpace(bitmap, color_space);
|
||||||
|
NSPoint offset = NSPointFromCGPoint(gfx::Point(image_offset).ToCGPoint());
|
||||||
|
[view startDragWithDropData:WebDropData(data)
|
||||||
|
dragOperationMask:op_mask
|
||||||
|
image:ns_image
|
||||||
|
offset:offset];
|
||||||
|
}
|
||||||
|
|
||||||
void BrowserWebViewDelegate::runModal() {
|
void BrowserWebViewDelegate::runModal() {
|
||||||
NOTIMPLEMENTED();
|
NOTIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2008-2009 The Chromium Embedded Framework Authors.
|
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
|
||||||
// Portions copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
// Portions copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
@@ -7,10 +7,12 @@
|
|||||||
// as the WebViewDelegate for the BrowserWebHost. The host is expected to
|
// as the WebViewDelegate for the BrowserWebHost. The host is expected to
|
||||||
// have initialized a MessageLoop before these methods are called.
|
// have initialized a MessageLoop before these methods are called.
|
||||||
|
|
||||||
#include "browser_webview_delegate.h"
|
#include "browser_drag_delegate_win.h"
|
||||||
#include "browser_navigation_controller.h"
|
#include "browser_navigation_controller.h"
|
||||||
#include "browser_impl.h"
|
#include "browser_impl.h"
|
||||||
|
#include "browser_webview_delegate.h"
|
||||||
#include "cef_context.h"
|
#include "cef_context.h"
|
||||||
|
#include "web_drop_target_win.h"
|
||||||
|
|
||||||
#include <objidl.h>
|
#include <objidl.h>
|
||||||
#include <shlobj.h>
|
#include <shlobj.h>
|
||||||
@@ -21,7 +23,10 @@
|
|||||||
#include "net/base/net_errors.h"
|
#include "net/base/net_errors.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebContextMenuData.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragData.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebImage.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebRect.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
|
||||||
#include "ui/gfx/gdi_util.h"
|
#include "ui/gfx/gdi_util.h"
|
||||||
@@ -38,10 +43,14 @@
|
|||||||
using webkit::npapi::WebPluginDelegateImpl;
|
using webkit::npapi::WebPluginDelegateImpl;
|
||||||
using WebKit::WebContextMenuData;
|
using WebKit::WebContextMenuData;
|
||||||
using WebKit::WebCursorInfo;
|
using WebKit::WebCursorInfo;
|
||||||
|
using WebKit::WebDragData;
|
||||||
|
using WebKit::WebDragOperationsMask;
|
||||||
using WebKit::WebExternalPopupMenu;
|
using WebKit::WebExternalPopupMenu;
|
||||||
using WebKit::WebExternalPopupMenuClient;
|
using WebKit::WebExternalPopupMenuClient;
|
||||||
using WebKit::WebFrame;
|
using WebKit::WebFrame;
|
||||||
|
using WebKit::WebImage;
|
||||||
using WebKit::WebNavigationPolicy;
|
using WebKit::WebNavigationPolicy;
|
||||||
|
using WebKit::WebPoint;
|
||||||
using WebKit::WebPopupMenuInfo;
|
using WebKit::WebPopupMenuInfo;
|
||||||
using WebKit::WebRect;
|
using WebKit::WebRect;
|
||||||
using WebKit::WebWidget;
|
using WebKit::WebWidget;
|
||||||
@@ -169,6 +178,22 @@ WebRect BrowserWebViewDelegate::windowResizerRect() {
|
|||||||
return WebRect();
|
return WebRect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BrowserWebViewDelegate::startDragging(
|
||||||
|
const WebDragData& data,
|
||||||
|
WebDragOperationsMask mask,
|
||||||
|
const WebImage& image,
|
||||||
|
const WebPoint& image_offset) {
|
||||||
|
// Dragging is not supported when window rendering is disabled.
|
||||||
|
if (browser_->IsWindowRenderingDisabled()) {
|
||||||
|
EndDragging();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
drag_delegate_ = new BrowserDragDelegate(this);
|
||||||
|
drag_delegate_->StartDragging(WebDropData(data), mask, image.getSkBitmap(),
|
||||||
|
image_offset);
|
||||||
|
}
|
||||||
|
|
||||||
void BrowserWebViewDelegate::runModal() {
|
void BrowserWebViewDelegate::runModal() {
|
||||||
WebWidgetHost* host = GetWidgetHost();
|
WebWidgetHost* host = GetWidgetHost();
|
||||||
if (!host)
|
if (!host)
|
||||||
@@ -535,6 +560,22 @@ end:
|
|||||||
|
|
||||||
// Private methods ------------------------------------------------------------
|
// Private methods ------------------------------------------------------------
|
||||||
|
|
||||||
|
void BrowserWebViewDelegate::RegisterDragDrop() {
|
||||||
|
DCHECK(!drop_target_);
|
||||||
|
drop_target_ = new WebDropTarget(browser_->UIT_GetWebViewWndHandle(),
|
||||||
|
browser_->UIT_GetWebView());
|
||||||
|
}
|
||||||
|
|
||||||
|
void BrowserWebViewDelegate::RevokeDragDrop() {
|
||||||
|
if (drop_target_.get())
|
||||||
|
::RevokeDragDrop(browser_->UIT_GetWebViewWndHandle());
|
||||||
|
}
|
||||||
|
|
||||||
|
void BrowserWebViewDelegate::EndDragging() {
|
||||||
|
browser_->UIT_GetWebView()->dragSourceSystemDragEnded();
|
||||||
|
drag_delegate_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void BrowserWebViewDelegate::ShowJavaScriptAlert(WebFrame* webframe,
|
void BrowserWebViewDelegate::ShowJavaScriptAlert(WebFrame* webframe,
|
||||||
const CefString& message)
|
const CefString& message)
|
||||||
{
|
{
|
||||||
|
@@ -3,8 +3,12 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#import <Cocoa/Cocoa.h>
|
#import <Cocoa/Cocoa.h>
|
||||||
|
#include "base/memory/scoped_nsobject.h"
|
||||||
|
|
||||||
class CefBrowserImpl;
|
class CefBrowserImpl;
|
||||||
|
@class WebDragSource;
|
||||||
|
@class WebDropTarget;
|
||||||
|
struct WebDropData;
|
||||||
|
|
||||||
// A view to wrap the WebCore view and help it live in a Cocoa world. The
|
// A view to wrap the WebCore view and help it live in a Cocoa world. The
|
||||||
// (rough) equivalent of Apple's WebView.
|
// (rough) equivalent of Apple's WebView.
|
||||||
@@ -13,6 +17,9 @@ class CefBrowserImpl;
|
|||||||
@private
|
@private
|
||||||
CefBrowserImpl *browser_; // weak
|
CefBrowserImpl *browser_; // weak
|
||||||
NSTrackingArea *trackingArea_;
|
NSTrackingArea *trackingArea_;
|
||||||
|
|
||||||
|
scoped_nsobject<WebDragSource> dragSource_;
|
||||||
|
scoped_nsobject<WebDropTarget> dropTarget_;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)mouseDown:(NSEvent *)theEvent;
|
- (void)mouseDown:(NSEvent *)theEvent;
|
||||||
@@ -33,6 +40,12 @@ class CefBrowserImpl;
|
|||||||
- (BOOL)isOpaque;
|
- (BOOL)isOpaque;
|
||||||
- (void)setFrame:(NSRect)frameRect;
|
- (void)setFrame:(NSRect)frameRect;
|
||||||
|
|
||||||
|
// Called from BrowserWebViewDelegate::startDragging() to initiate dragging.
|
||||||
|
- (void)startDragWithDropData:(const WebDropData&)dropData
|
||||||
|
dragOperationMask:(NSDragOperation)operationMask
|
||||||
|
image:(NSImage*)image
|
||||||
|
offset:(NSPoint)offset;
|
||||||
|
|
||||||
@property (nonatomic, assign) CefBrowserImpl *browser;
|
@property (nonatomic, assign) CefBrowserImpl *browser;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@@ -8,9 +8,12 @@
|
|||||||
|
|
||||||
#include "browser_impl.h"
|
#include "browser_impl.h"
|
||||||
#include "cef_context.h"
|
#include "cef_context.h"
|
||||||
|
#import "web_drag_source_mac.h"
|
||||||
|
#import "web_drop_target_mac.h"
|
||||||
#include "webwidget_host.h"
|
#include "webwidget_host.h"
|
||||||
|
|
||||||
#include "base/memory/scoped_ptr.h"
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#import "third_party/mozilla/NSPasteboard+Utils.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
|
||||||
#include "ui/gfx/rect.h"
|
#include "ui/gfx/rect.h"
|
||||||
@@ -22,13 +25,20 @@
|
|||||||
- (id)initWithFrame:(NSRect)frame {
|
- (id)initWithFrame:(NSRect)frame {
|
||||||
self = [super initWithFrame:frame];
|
self = [super initWithFrame:frame];
|
||||||
if (self) {
|
if (self) {
|
||||||
|
dropTarget_.reset([[WebDropTarget alloc] initWithWebView:self]);
|
||||||
|
|
||||||
|
// Register the view to handle the appropriate drag types.
|
||||||
|
NSArray* types = [NSArray arrayWithObjects:NSStringPboardType,
|
||||||
|
NSHTMLPboardType, NSURLPboardType, nil];
|
||||||
|
[self registerForDraggedTypes:types];
|
||||||
|
|
||||||
trackingArea_ =
|
trackingArea_ =
|
||||||
[[NSTrackingArea alloc] initWithRect:frame
|
[[NSTrackingArea alloc] initWithRect:frame
|
||||||
options:NSTrackingMouseMoved |
|
options:NSTrackingMouseMoved |
|
||||||
NSTrackingActiveInActiveApp |
|
NSTrackingActiveInActiveApp |
|
||||||
NSTrackingInVisibleRect
|
NSTrackingInVisibleRect
|
||||||
owner:self
|
owner:self
|
||||||
userInfo:nil];
|
userInfo:nil];
|
||||||
[self addTrackingArea:trackingArea_];
|
[self addTrackingArea:trackingArea_];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
@@ -170,9 +180,91 @@
|
|||||||
|
|
||||||
- (void)setFrame:(NSRect)frameRect {
|
- (void)setFrame:(NSRect)frameRect {
|
||||||
[super setFrame:frameRect];
|
[super setFrame:frameRect];
|
||||||
if (browser_ && browser_->UIT_GetWebView())
|
if (browser_ && browser_->UIT_GetWebView()) {
|
||||||
browser_->UIT_GetWebViewHost()->Resize(gfx::Rect(NSRectToCGRect(frameRect)));
|
browser_->UIT_GetWebViewHost()->Resize(
|
||||||
|
gfx::Rect(NSRectToCGRect(frameRect)));
|
||||||
|
}
|
||||||
[self setNeedsDisplay:YES];
|
[self setNeedsDisplay:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)startDragWithDropData:(const WebDropData&)dropData
|
||||||
|
dragOperationMask:(NSDragOperation)operationMask
|
||||||
|
image:(NSImage*)image
|
||||||
|
offset:(NSPoint)offset {
|
||||||
|
dragSource_.reset([[WebDragSource alloc]
|
||||||
|
initWithWebView:self
|
||||||
|
dropData:&dropData
|
||||||
|
image:image
|
||||||
|
offset:offset
|
||||||
|
pasteboard:[NSPasteboard pasteboardWithName:NSDragPboard]
|
||||||
|
dragOperationMask:operationMask]);
|
||||||
|
[dragSource_ startDrag];
|
||||||
|
}
|
||||||
|
|
||||||
|
// NSPasteboardOwner methods
|
||||||
|
|
||||||
|
- (void)pasteboard:(NSPasteboard*)sender provideDataForType:(NSString*)type {
|
||||||
|
[dragSource_ lazyWriteToPasteboard:sender
|
||||||
|
forType:type];
|
||||||
|
}
|
||||||
|
|
||||||
|
// NSDraggingSource methods
|
||||||
|
|
||||||
|
// Returns what kind of drag operations are available. This is a required
|
||||||
|
// method for NSDraggingSource.
|
||||||
|
- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
|
||||||
|
if (dragSource_.get())
|
||||||
|
return [dragSource_ draggingSourceOperationMaskForLocal:isLocal];
|
||||||
|
// No web drag source - this is the case for dragging a file from the
|
||||||
|
// downloads manager. Default to copy operation. Note: It is desirable to
|
||||||
|
// allow the user to either move or copy, but this requires additional
|
||||||
|
// plumbing to update the download item's path once its moved.
|
||||||
|
return NSDragOperationCopy;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when a drag initiated in our view ends.
|
||||||
|
- (void)draggedImage:(NSImage*)anImage
|
||||||
|
endedAt:(NSPoint)screenPoint
|
||||||
|
operation:(NSDragOperation)operation {
|
||||||
|
[dragSource_ endDragAt:screenPoint operation:operation];
|
||||||
|
|
||||||
|
// Might as well throw out this object now.
|
||||||
|
dragSource_.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when a drag initiated in our view moves.
|
||||||
|
- (void)draggedImage:(NSImage*)draggedImage movedTo:(NSPoint)screenPoint {
|
||||||
|
[dragSource_ moveDragTo:screenPoint];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when we're informed where a file should be dropped.
|
||||||
|
- (NSArray*)namesOfPromisedFilesDroppedAtDestination:(NSURL*)dropDest {
|
||||||
|
if (![dropDest isFileURL])
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
NSString* file_name = [dragSource_ dragPromisedFileTo:[dropDest path]];
|
||||||
|
if (!file_name)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
return [NSArray arrayWithObject:file_name];
|
||||||
|
}
|
||||||
|
|
||||||
|
// NSDraggingDestination methods
|
||||||
|
|
||||||
|
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender {
|
||||||
|
return [dropTarget_ draggingEntered:sender view:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)draggingExited:(id<NSDraggingInfo>)sender {
|
||||||
|
[dropTarget_ draggingExited:sender];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender {
|
||||||
|
return [dropTarget_ draggingUpdated:sender view:self];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender {
|
||||||
|
return [dropTarget_ performDragOperation:sender view:self];
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@@ -3,67 +3,22 @@
|
|||||||
// Use of this source code is governed by a BSD-style license that can be
|
// Use of this source code is governed by a BSD-style license that can be
|
||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
|
#import <AppKit/AppKit.h>
|
||||||
|
|
||||||
#include "include/cef.h"
|
#include "include/cef.h"
|
||||||
|
#import "include/cef_application_mac.h"
|
||||||
#include "cef_process_ui_thread.h"
|
#include "cef_process_ui_thread.h"
|
||||||
#include "browser_webkit_glue.h"
|
#include "browser_webkit_glue.h"
|
||||||
#include "base/message_pump_mac.h"
|
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/mac/WebCoreSupport/WebSystemInterface.h"
|
#include "third_party/WebKit/Source/WebKit/mac/WebCoreSupport/WebSystemInterface.h"
|
||||||
|
|
||||||
// CrAppProtocol implementation.
|
|
||||||
@interface CrApplication : NSApplication<CrAppProtocol> {
|
|
||||||
@private
|
|
||||||
BOOL handlingSendEvent_;
|
|
||||||
}
|
|
||||||
- (BOOL)isHandlingSendEvent;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation CrApplication
|
|
||||||
- (BOOL)isHandlingSendEvent {
|
|
||||||
return handlingSendEvent_;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)sendEvent:(NSEvent*)event {
|
|
||||||
BOOL wasHandlingSendEvent = handlingSendEvent_;
|
|
||||||
handlingSendEvent_ = YES;
|
|
||||||
[super sendEvent:event];
|
|
||||||
handlingSendEvent_ = wasHandlingSendEvent;
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// Memory autorelease pool.
|
|
||||||
static NSAutoreleasePool* g_autopool = nil;
|
|
||||||
|
|
||||||
void RunLoopObserver(CFRunLoopObserverRef observer, CFRunLoopActivity activity,
|
|
||||||
void* info)
|
|
||||||
{
|
|
||||||
CefDoMessageLoopWork();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void CefProcessUIThread::PlatformInit() {
|
void CefProcessUIThread::PlatformInit() {
|
||||||
// Initialize the CrApplication instance.
|
// The NSApplication instance must implement the CefAppProtocol protocol.
|
||||||
[CrApplication sharedApplication];
|
DCHECK([[NSApplication sharedApplication]
|
||||||
g_autopool = [[NSAutoreleasePool alloc] init];
|
conformsToProtocol:@protocol(CefAppProtocol)]);
|
||||||
|
|
||||||
InitWebCoreSystemInterface();
|
InitWebCoreSystemInterface();
|
||||||
|
|
||||||
// Register the run loop observer.
|
|
||||||
CFRunLoopObserverRef observer =
|
|
||||||
CFRunLoopObserverCreate(NULL,
|
|
||||||
kCFRunLoopBeforeWaiting,
|
|
||||||
YES, /* repeat */
|
|
||||||
0,
|
|
||||||
&RunLoopObserver,
|
|
||||||
NULL);
|
|
||||||
if (observer) {
|
|
||||||
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer,
|
|
||||||
kCFRunLoopCommonModes);
|
|
||||||
}
|
|
||||||
|
|
||||||
webkit_glue::InitializeDataPak();
|
webkit_glue::InitializeDataPak();
|
||||||
|
|
||||||
// On Mac, the select popup menus are rendered by the browser.
|
// On Mac, the select popup menus are rendered by the browser.
|
||||||
@@ -71,6 +26,4 @@ void CefProcessUIThread::PlatformInit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CefProcessUIThread::PlatformCleanUp() {
|
void CefProcessUIThread::PlatformCleanUp() {
|
||||||
[g_autopool release];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
188
libcef/download_util.cc
Normal file
188
libcef/download_util.cc
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2011 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.
|
||||||
|
|
||||||
|
#include "download_util.h"
|
||||||
|
|
||||||
|
#include "base/file_path.h"
|
||||||
|
#include "base/string16.h"
|
||||||
|
#include "base/string_util.h"
|
||||||
|
#include "base/sys_string_conversions.h"
|
||||||
|
#include "base/utf_string_conversions.h"
|
||||||
|
#include "base/threading/thread.h"
|
||||||
|
#include "base/threading/thread_restrictions.h"
|
||||||
|
#include "googleurl/src/gurl.h"
|
||||||
|
#include "net/base/mime_util.h"
|
||||||
|
#include "net/base/net_util.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
// Returns whether the specified extension is automatically integrated into the
|
||||||
|
// windows shell.
|
||||||
|
// From chrome/browser/download/download_util.cc
|
||||||
|
bool IsShellIntegratedExtension(const string16& extension) {
|
||||||
|
string16 extension_lower = StringToLowerASCII(extension);
|
||||||
|
|
||||||
|
static const wchar_t* const integrated_extensions[] = {
|
||||||
|
// See <http://msdn.microsoft.com/en-us/library/ms811694.aspx>.
|
||||||
|
L"local",
|
||||||
|
// Right-clicking on shortcuts can be magical.
|
||||||
|
L"lnk",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < arraysize(integrated_extensions); ++i) {
|
||||||
|
if (extension_lower == integrated_extensions[i])
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// See <http://www.juniper.net/security/auto/vulnerabilities/vuln2612.html>.
|
||||||
|
// That vulnerability report is not exactly on point, but files become magical
|
||||||
|
// if their end in a CLSID. Here we block extensions that look like CLSIDs.
|
||||||
|
if (extension_lower.size() > 0 && extension_lower.at(0) == L'{' &&
|
||||||
|
extension_lower.at(extension_lower.length() - 1) == L'}')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns whether the specified file name is a reserved name on windows.
|
||||||
|
// This includes names like "com2.zip" (which correspond to devices) and
|
||||||
|
// desktop.ini and thumbs.db which have special meaning to the windows shell.
|
||||||
|
// From chrome/browser/download/download_util.cc
|
||||||
|
bool IsReservedName(const string16& filename) {
|
||||||
|
// This list is taken from the MSDN article "Naming a file"
|
||||||
|
// http://msdn2.microsoft.com/en-us/library/aa365247(VS.85).aspx
|
||||||
|
// I also added clock$ because GetSaveFileName seems to consider it as a
|
||||||
|
// reserved name too.
|
||||||
|
static const wchar_t* const known_devices[] = {
|
||||||
|
L"con", L"prn", L"aux", L"nul", L"com1", L"com2", L"com3", L"com4", L"com5",
|
||||||
|
L"com6", L"com7", L"com8", L"com9", L"lpt1", L"lpt2", L"lpt3", L"lpt4",
|
||||||
|
L"lpt5", L"lpt6", L"lpt7", L"lpt8", L"lpt9", L"clock$"
|
||||||
|
};
|
||||||
|
string16 filename_lower = StringToLowerASCII(filename);
|
||||||
|
|
||||||
|
for (int i = 0; i < arraysize(known_devices); ++i) {
|
||||||
|
// Exact match.
|
||||||
|
if (filename_lower == known_devices[i])
|
||||||
|
return true;
|
||||||
|
// Starts with "DEVICE.".
|
||||||
|
if (filename_lower.find(string16(known_devices[i]) + L".") == 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const wchar_t* const magic_names[] = {
|
||||||
|
// These file names are used by the "Customize folder" feature of the shell.
|
||||||
|
L"desktop.ini",
|
||||||
|
L"thumbs.db",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < arraysize(magic_names); ++i) {
|
||||||
|
if (filename_lower == magic_names[i])
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif // OS_WIN
|
||||||
|
|
||||||
|
// Create an extension based on the file name and mime type.
|
||||||
|
// From chrome/browser/download/download_util.cc
|
||||||
|
void GenerateExtension(const FilePath& file_name,
|
||||||
|
const std::string& mime_type,
|
||||||
|
FilePath::StringType* generated_extension) {
|
||||||
|
// We're worried about two things here:
|
||||||
|
//
|
||||||
|
// 1) Usability. If the site fails to provide a file extension, we want to
|
||||||
|
// guess a reasonable file extension based on the content type.
|
||||||
|
//
|
||||||
|
// 2) Shell integration. Some file extensions automatically integrate with
|
||||||
|
// the shell. We block these extensions to prevent a malicious web site
|
||||||
|
// from integrating with the user's shell.
|
||||||
|
|
||||||
|
// See if our file name already contains an extension.
|
||||||
|
FilePath::StringType extension = file_name.Extension();
|
||||||
|
if (!extension.empty())
|
||||||
|
extension.erase(extension.begin()); // Erase preceding '.'.
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
static const FilePath::CharType default_extension[] =
|
||||||
|
FILE_PATH_LITERAL("download");
|
||||||
|
|
||||||
|
// Rename shell-integrated extensions.
|
||||||
|
if (IsShellIntegratedExtension(extension))
|
||||||
|
extension.assign(default_extension);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (extension.empty()) {
|
||||||
|
// The GetPreferredExtensionForMimeType call will end up going to disk. Do
|
||||||
|
// this on another thread to avoid slowing the IO thread.
|
||||||
|
// http://crbug.com/61827
|
||||||
|
base::ThreadRestrictions::ScopedAllowIO allow_io;
|
||||||
|
net::GetPreferredExtensionForMimeType(mime_type, &extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
generated_extension->swap(extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used to make sure we have a safe file extension and filename for a
|
||||||
|
// download. |file_name| can either be just the file name or it can be a
|
||||||
|
// full path to a file.
|
||||||
|
// From chrome/browser/download/download_util.cc
|
||||||
|
void GenerateSafeFileName(const std::string& mime_type, FilePath* file_name) {
|
||||||
|
// Make sure we get the right file extension
|
||||||
|
FilePath::StringType extension;
|
||||||
|
GenerateExtension(*file_name, mime_type, &extension);
|
||||||
|
*file_name = file_name->ReplaceExtension(extension);
|
||||||
|
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
// Prepend "_" to the file name if it's a reserved name
|
||||||
|
FilePath::StringType leaf_name = file_name->BaseName().value();
|
||||||
|
DCHECK(!leaf_name.empty());
|
||||||
|
if (IsReservedName(leaf_name)) {
|
||||||
|
leaf_name = FilePath::StringType(FILE_PATH_LITERAL("_")) + leaf_name;
|
||||||
|
*file_name = file_name->DirName();
|
||||||
|
if (file_name->value() == FilePath::kCurrentDirectory) {
|
||||||
|
*file_name = FilePath(leaf_name);
|
||||||
|
} else {
|
||||||
|
*file_name = file_name->Append(leaf_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
namespace download_util {
|
||||||
|
|
||||||
|
// Create a file name based on the response from the server.
|
||||||
|
// From chrome/browser/download/download_util.cc
|
||||||
|
void GenerateFileName(const GURL& url,
|
||||||
|
const std::string& content_disposition,
|
||||||
|
const std::string& referrer_charset,
|
||||||
|
const std::string& mime_type,
|
||||||
|
const std::string& suggested_name,
|
||||||
|
FilePath* generated_name) {
|
||||||
|
string16 new_name = net::GetSuggestedFilename(GURL(url),
|
||||||
|
content_disposition,
|
||||||
|
referrer_charset,
|
||||||
|
suggested_name,
|
||||||
|
ASCIIToUTF16("download"));
|
||||||
|
|
||||||
|
// TODO(evan): this code is totally wrong -- we should just generate
|
||||||
|
// Unicode filenames and do all this encoding switching at the end.
|
||||||
|
// However, I'm just shuffling wrong code around, at least not adding
|
||||||
|
// to it.
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
*generated_name = FilePath(new_name);
|
||||||
|
#else
|
||||||
|
*generated_name = FilePath(base::SysWideToNativeMB(UTF16ToWide(new_name)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
DCHECK(!generated_name->empty());
|
||||||
|
|
||||||
|
GenerateSafeFileName(mime_type, generated_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace download_util
|
27
libcef/download_util.h
Normal file
27
libcef/download_util.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2011 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.
|
||||||
|
|
||||||
|
#ifndef _DOWNLOAD_UTIL_H
|
||||||
|
#define _DOWNLOAD_UTIL_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class GURL;
|
||||||
|
class FilePath;
|
||||||
|
|
||||||
|
namespace download_util {
|
||||||
|
|
||||||
|
// Create a file name based on the response from the server.
|
||||||
|
void GenerateFileName(const GURL& url,
|
||||||
|
const std::string& content_disposition,
|
||||||
|
const std::string& referrer_charset,
|
||||||
|
const std::string& mime_type,
|
||||||
|
const std::string& suggested_name,
|
||||||
|
FilePath* generated_name);
|
||||||
|
|
||||||
|
} // namespace download_util
|
||||||
|
|
||||||
|
#endif // _DOWNLOAD_UTIL_H
|
113
libcef/drag_download_util.cc
Normal file
113
libcef/drag_download_util.cc
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
// Copyright (c) 2011 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.
|
||||||
|
|
||||||
|
#include "cef_thread.h"
|
||||||
|
#include "drag_download_util.h"
|
||||||
|
|
||||||
|
#include "base/string_util.h"
|
||||||
|
#include "base/file_path.h"
|
||||||
|
#include "base/file_util.h"
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#include "base/task.h"
|
||||||
|
#include "base/string_number_conversions.h"
|
||||||
|
#include "base/utf_string_conversions.h"
|
||||||
|
#include "googleurl/src/gurl.h"
|
||||||
|
#include "net/base/file_stream.h"
|
||||||
|
#include "net/base/net_errors.h"
|
||||||
|
|
||||||
|
using net::FileStream;
|
||||||
|
|
||||||
|
namespace drag_download_util {
|
||||||
|
|
||||||
|
bool ParseDownloadMetadata(const string16& metadata,
|
||||||
|
string16* mime_type,
|
||||||
|
FilePath* file_name,
|
||||||
|
GURL* url) {
|
||||||
|
const char16 separator = L':';
|
||||||
|
|
||||||
|
size_t mime_type_end_pos = metadata.find(separator);
|
||||||
|
if (mime_type_end_pos == string16::npos)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
size_t file_name_end_pos = metadata.find(separator, mime_type_end_pos + 1);
|
||||||
|
if (file_name_end_pos == string16::npos)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
GURL parsed_url = GURL(metadata.substr(file_name_end_pos + 1));
|
||||||
|
if (!parsed_url.is_valid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mime_type)
|
||||||
|
*mime_type = metadata.substr(0, mime_type_end_pos);
|
||||||
|
if (file_name) {
|
||||||
|
string16 file_name_str = metadata.substr(
|
||||||
|
mime_type_end_pos + 1, file_name_end_pos - mime_type_end_pos - 1);
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
*file_name = FilePath(file_name_str);
|
||||||
|
#else
|
||||||
|
*file_name = FilePath(UTF16ToUTF8(file_name_str));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (url)
|
||||||
|
*url = parsed_url;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileStream* CreateFileStreamForDrop(FilePath* file_path) {
|
||||||
|
DCHECK(file_path && !file_path->empty());
|
||||||
|
|
||||||
|
scoped_ptr<FileStream> file_stream(new FileStream);
|
||||||
|
const int kMaxSeq = 99;
|
||||||
|
for (int seq = 0; seq <= kMaxSeq; seq++) {
|
||||||
|
FilePath new_file_path;
|
||||||
|
if (seq == 0) {
|
||||||
|
new_file_path = *file_path;
|
||||||
|
} else {
|
||||||
|
#if defined(OS_WIN)
|
||||||
|
string16 suffix = ASCIIToUTF16("-") + base::IntToString16(seq);
|
||||||
|
#else
|
||||||
|
std::string suffix = std::string("-") + base::IntToString(seq);
|
||||||
|
#endif
|
||||||
|
new_file_path = file_path->InsertBeforeExtension(suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explicitly (and redundantly check) for file -- despite the fact that our
|
||||||
|
// open won't overwrite -- just to avoid log spew.
|
||||||
|
if (!file_util::PathExists(new_file_path) &&
|
||||||
|
file_stream->Open(new_file_path, base::PLATFORM_FILE_CREATE |
|
||||||
|
base::PLATFORM_FILE_WRITE) == net::OK) {
|
||||||
|
*file_path = new_file_path;
|
||||||
|
return file_stream.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PromiseFileFinalizer::PromiseFileFinalizer(
|
||||||
|
DragDownloadFile* drag_file_downloader)
|
||||||
|
: drag_file_downloader_(drag_file_downloader) {
|
||||||
|
}
|
||||||
|
|
||||||
|
PromiseFileFinalizer::~PromiseFileFinalizer() {}
|
||||||
|
|
||||||
|
void PromiseFileFinalizer::Cleanup() {
|
||||||
|
if (drag_file_downloader_.get())
|
||||||
|
drag_file_downloader_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PromiseFileFinalizer::OnDownloadCompleted(const FilePath& file_path) {
|
||||||
|
CefThread::PostTask(
|
||||||
|
CefThread::UI, FROM_HERE,
|
||||||
|
NewRunnableMethod(this, &PromiseFileFinalizer::Cleanup));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PromiseFileFinalizer::OnDownloadAborted() {
|
||||||
|
CefThread::PostTask(
|
||||||
|
CefThread::UI, FROM_HERE,
|
||||||
|
NewRunnableMethod(this, &PromiseFileFinalizer::Cleanup));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace drag_download_util
|
63
libcef/drag_download_util.h
Normal file
63
libcef/drag_download_util.h
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
// Copyright (c) 2011 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.
|
||||||
|
|
||||||
|
#ifndef _DRAG_DOWNLOAD_UTIL_H
|
||||||
|
#define _DRAG_DOWNLOAD_UTIL_H
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "drag_download_file.h"
|
||||||
|
|
||||||
|
#include "base/basictypes.h"
|
||||||
|
#include "base/memory/ref_counted.h"
|
||||||
|
#include "base/string16.h"
|
||||||
|
#include "ui/base/dragdrop/download_file_interface.h"
|
||||||
|
|
||||||
|
class FilePath;
|
||||||
|
class GURL;
|
||||||
|
namespace net {
|
||||||
|
class FileStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace drag_download_util {
|
||||||
|
|
||||||
|
// Parse the download metadata set in DataTransfer.setData. The metadata
|
||||||
|
// consists of a set of the following values separated by ":"
|
||||||
|
// * MIME type
|
||||||
|
// * File name
|
||||||
|
// * URL
|
||||||
|
// If the file name contains special characters, they need to be escaped
|
||||||
|
// appropriately.
|
||||||
|
// For example, we can have
|
||||||
|
// text/plain:example.txt:http://example.com/example.txt
|
||||||
|
bool ParseDownloadMetadata(const string16& metadata,
|
||||||
|
string16* mime_type,
|
||||||
|
FilePath* file_name,
|
||||||
|
GURL* url);
|
||||||
|
|
||||||
|
// Create a new file at the specified path. If the file already exists, try to
|
||||||
|
// insert the sequential unifier to produce a new file, like foo-01.txt.
|
||||||
|
// Return a FileStream if successful.
|
||||||
|
net::FileStream* CreateFileStreamForDrop(FilePath* file_path);
|
||||||
|
|
||||||
|
// Implementation of DownloadFileObserver to finalize the download process.
|
||||||
|
class PromiseFileFinalizer : public ui::DownloadFileObserver {
|
||||||
|
public:
|
||||||
|
explicit PromiseFileFinalizer(DragDownloadFile* drag_file_downloader);
|
||||||
|
virtual ~PromiseFileFinalizer();
|
||||||
|
|
||||||
|
// DownloadFileObserver methods.
|
||||||
|
virtual void OnDownloadCompleted(const FilePath& file_path);
|
||||||
|
virtual void OnDownloadAborted();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Cleanup();
|
||||||
|
|
||||||
|
scoped_refptr<DragDownloadFile> drag_file_downloader_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(PromiseFileFinalizer);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace drag_download_util
|
||||||
|
|
||||||
|
#endif // _DRAG_DOWNLOAD_UTIL_H
|
82
libcef/web_drag_source_mac.h
Normal file
82
libcef/web_drag_source_mac.h
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2011 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 <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
#include "base/file_path.h"
|
||||||
|
#include "base/memory/scoped_nsobject.h"
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
|
#include "googleurl/src/gurl.h"
|
||||||
|
#include "ui/gfx/native_widget_types.h"
|
||||||
|
|
||||||
|
struct WebDropData;
|
||||||
|
@class BrowserWebView;
|
||||||
|
|
||||||
|
// A class that handles tracking and event processing for a drag and drop
|
||||||
|
// originating from the content area.
|
||||||
|
@interface WebDragSource : NSObject {
|
||||||
|
@private
|
||||||
|
// Our web view. Weak reference (owns or co-owns us).
|
||||||
|
BrowserWebView* view_;
|
||||||
|
|
||||||
|
// Our drop data. Should only be initialized once.
|
||||||
|
scoped_ptr<WebDropData> dropData_;
|
||||||
|
|
||||||
|
// The image to show as drag image. Can be nil.
|
||||||
|
scoped_nsobject<NSImage> dragImage_;
|
||||||
|
|
||||||
|
// The offset to draw |dragImage_| at.
|
||||||
|
NSPoint imageOffset_;
|
||||||
|
|
||||||
|
// Our pasteboard.
|
||||||
|
scoped_nsobject<NSPasteboard> pasteboard_;
|
||||||
|
|
||||||
|
// A mask of the allowed drag operations.
|
||||||
|
NSDragOperation dragOperationMask_;
|
||||||
|
|
||||||
|
// The file name to be saved to for a drag-out download.
|
||||||
|
FilePath downloadFileName_;
|
||||||
|
|
||||||
|
// The URL to download from for a drag-out download.
|
||||||
|
GURL downloadURL_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize a WebDragSource object for a drag (originating on the given
|
||||||
|
// BrowserWebView and with the given dropData and pboard). Fill the pasteboard
|
||||||
|
// with data types appropriate for dropData.
|
||||||
|
- (id)initWithWebView:(BrowserWebView*)view
|
||||||
|
dropData:(const WebDropData*)dropData
|
||||||
|
image:(NSImage*)image
|
||||||
|
offset:(NSPoint)offset
|
||||||
|
pasteboard:(NSPasteboard*)pboard
|
||||||
|
dragOperationMask:(NSDragOperation)dragOperationMask;
|
||||||
|
|
||||||
|
// Returns a mask of the allowed drag operations.
|
||||||
|
- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal;
|
||||||
|
|
||||||
|
// Call when asked to do a lazy write to the pasteboard; hook up to
|
||||||
|
// -pasteboard:provideDataForType: (on the BrowserWebView).
|
||||||
|
- (void)lazyWriteToPasteboard:(NSPasteboard*)pboard
|
||||||
|
forType:(NSString*)type;
|
||||||
|
|
||||||
|
// Start the drag (on the originally provided BrowserWebView); can do this right
|
||||||
|
// after -initWithContentsView:....
|
||||||
|
- (void)startDrag;
|
||||||
|
|
||||||
|
// End the drag and clear the pasteboard; hook up to
|
||||||
|
// -draggedImage:endedAt:operation:.
|
||||||
|
- (void)endDragAt:(NSPoint)screenPoint
|
||||||
|
operation:(NSDragOperation)operation;
|
||||||
|
|
||||||
|
// Drag moved; hook up to -draggedImage:movedTo:.
|
||||||
|
- (void)moveDragTo:(NSPoint)screenPoint;
|
||||||
|
|
||||||
|
// Call to drag a promised file to the given path (should be called before
|
||||||
|
// -endDragAt:...); hook up to -namesOfPromisedFilesDroppedAtDestination:.
|
||||||
|
// Returns the file name (not including path) of the file deposited (or which
|
||||||
|
// will be deposited).
|
||||||
|
- (NSString*)dragPromisedFileTo:(NSString*)path;
|
||||||
|
|
||||||
|
@end
|
456
libcef/web_drag_source_mac.mm
Normal file
456
libcef/web_drag_source_mac.mm
Normal file
@@ -0,0 +1,456 @@
|
|||||||
|
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2011 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.
|
||||||
|
|
||||||
|
#include "browser_impl.h"
|
||||||
|
#import "browser_webview_mac.h"
|
||||||
|
#include "drag_download_util.h"
|
||||||
|
#include "download_util.h"
|
||||||
|
#import "web_drag_source_mac.h"
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include "base/file_path.h"
|
||||||
|
#include "base/string_util.h"
|
||||||
|
#include "base/sys_string_conversions.h"
|
||||||
|
#include "base/task.h"
|
||||||
|
#include "base/threading/thread.h"
|
||||||
|
#include "base/threading/thread_restrictions.h"
|
||||||
|
#include "base/utf_string_conversions.h"
|
||||||
|
#include "net/base/file_stream.h"
|
||||||
|
#include "net/base/net_util.h"
|
||||||
|
#import "third_party/mozilla/NSPasteboard+Utils.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
|
||||||
|
#include "ui/gfx/mac/nsimage_cache.h"
|
||||||
|
#include "webkit/glue/webdropdata.h"
|
||||||
|
|
||||||
|
using base::SysNSStringToUTF8;
|
||||||
|
using base::SysUTF8ToNSString;
|
||||||
|
using base::SysUTF16ToNSString;
|
||||||
|
using net::FileStream;
|
||||||
|
using WebKit::WebDragOperationNone;
|
||||||
|
using WebKit::WebView;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
// Images without ALT text will only have a file extension so we need to
|
||||||
|
// synthesize one from the provided extension and URL.
|
||||||
|
FilePath file_name(FilePathFromFilename(drop_data.file_description_filename));
|
||||||
|
file_name = file_name.BaseName().RemoveExtension();
|
||||||
|
|
||||||
|
if (file_name.empty()) {
|
||||||
|
// Retrieve the name from the URL.
|
||||||
|
string16 suggested_filename =
|
||||||
|
net::GetSuggestedFilename(drop_data.url, "", "", "", string16());
|
||||||
|
file_name = FilePathFromFilename(suggested_filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
file_name = file_name.ReplaceExtension(UTF16ToUTF8(drop_data.file_extension));
|
||||||
|
|
||||||
|
return file_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This class's sole task is to write out data for a promised file; the caller
|
||||||
|
// is responsible for opening the file.
|
||||||
|
class PromiseWriterTask : public Task {
|
||||||
|
public:
|
||||||
|
// Assumes ownership of file_stream.
|
||||||
|
PromiseWriterTask(const WebDropData& drop_data,
|
||||||
|
FileStream* file_stream);
|
||||||
|
virtual ~PromiseWriterTask();
|
||||||
|
virtual void Run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
WebDropData drop_data_;
|
||||||
|
|
||||||
|
// This class takes ownership of file_stream_ and will close and delete it.
|
||||||
|
scoped_ptr<FileStream> file_stream_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Takes the drop data and an open file stream (which it takes ownership of and
|
||||||
|
// will close and delete).
|
||||||
|
PromiseWriterTask::PromiseWriterTask(const WebDropData& drop_data,
|
||||||
|
FileStream* file_stream) :
|
||||||
|
drop_data_(drop_data) {
|
||||||
|
file_stream_.reset(file_stream);
|
||||||
|
DCHECK(file_stream_.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
PromiseWriterTask::~PromiseWriterTask() {
|
||||||
|
DCHECK(file_stream_.get());
|
||||||
|
if (file_stream_.get())
|
||||||
|
file_stream_->Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PromiseWriterTask::Run() {
|
||||||
|
CHECK(file_stream_.get());
|
||||||
|
file_stream_->Write(drop_data_.file_contents.data(),
|
||||||
|
drop_data_.file_contents.length(),
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
// Let our destructor take care of business.
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
|
||||||
|
@interface WebDragSource(Private)
|
||||||
|
|
||||||
|
- (void)fillPasteboard;
|
||||||
|
- (NSImage*)dragImage;
|
||||||
|
|
||||||
|
@end // @interface WebDragSource(Private)
|
||||||
|
|
||||||
|
|
||||||
|
@implementation WebDragSource
|
||||||
|
|
||||||
|
- (id)initWithWebView:(BrowserWebView*)view
|
||||||
|
dropData:(const WebDropData*)dropData
|
||||||
|
image:(NSImage*)image
|
||||||
|
offset:(NSPoint)offset
|
||||||
|
pasteboard:(NSPasteboard*)pboard
|
||||||
|
dragOperationMask:(NSDragOperation)dragOperationMask {
|
||||||
|
if ((self = [super init])) {
|
||||||
|
view_ = view;
|
||||||
|
DCHECK(view_);
|
||||||
|
|
||||||
|
dropData_.reset(new WebDropData(*dropData));
|
||||||
|
DCHECK(dropData_.get());
|
||||||
|
|
||||||
|
dragImage_.reset([image retain]);
|
||||||
|
imageOffset_ = offset;
|
||||||
|
|
||||||
|
pasteboard_.reset([pboard retain]);
|
||||||
|
DCHECK(pasteboard_.get());
|
||||||
|
|
||||||
|
dragOperationMask_ = dragOperationMask;
|
||||||
|
|
||||||
|
[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.
|
||||||
|
static 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.
|
||||||
|
if (!url && urlStr && dropData_->url.SchemeIs("javascript")) {
|
||||||
|
NSString *escapedStr =
|
||||||
|
[urlStr 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] ||
|
||||||
|
[type isEqualToString:NSCreateFileContentsPboardType(
|
||||||
|
SysUTF16ToNSString(dropData_->file_extension))]) {
|
||||||
|
// 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];
|
||||||
|
|
||||||
|
// Oops!
|
||||||
|
} else {
|
||||||
|
NOTREACHED() << "Asked for a drag pasteboard type we didn't offer.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSPoint)convertScreenPoint:(NSPoint)screenPoint {
|
||||||
|
NSPoint basePoint = [[view_ window] convertScreenToBase:screenPoint];
|
||||||
|
return [view_ 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 = [view_ 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:view_
|
||||||
|
slideBack:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)endDragAt:(NSPoint)screenPoint
|
||||||
|
operation:(NSDragOperation)operation {
|
||||||
|
// Convert |screenPoint| to view coordinates and flip it.
|
||||||
|
NSWindow* window = [view_ window];
|
||||||
|
NSPoint localPoint = [self convertScreenPoint:screenPoint];
|
||||||
|
NSRect viewFrame = [window frame];
|
||||||
|
localPoint.y = viewFrame.size.height - localPoint.y;
|
||||||
|
// Flip |screenPoint|.
|
||||||
|
NSRect screenFrame = [[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;
|
||||||
|
|
||||||
|
// TODO: Figure out why |operation| is always NSDragOperationNone.
|
||||||
|
if (operation == NSDragOperationNone)
|
||||||
|
operation = NSDragOperationCopy;
|
||||||
|
|
||||||
|
WebView* webview = view_.browser->UIT_GetWebView();
|
||||||
|
|
||||||
|
gfx::Point client(localPoint.x, localPoint.y);
|
||||||
|
gfx::Point screen(screenPoint.x, screenPoint.y);
|
||||||
|
webview->dragSourceEndedAt(client, screen,
|
||||||
|
static_cast<WebKit::WebDragOperation>(operation));
|
||||||
|
|
||||||
|
// Make sure the pasteboard owner isn't us.
|
||||||
|
[pasteboard_ declareTypes:[NSArray array] owner:nil];
|
||||||
|
|
||||||
|
webview->dragSourceSystemDragEnded();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)moveDragTo:(NSPoint)screenPoint {
|
||||||
|
// Convert |screenPoint| to view coordinates and flip it.
|
||||||
|
NSWindow* window = [view_ window];
|
||||||
|
NSPoint localPoint = [self convertScreenPoint:screenPoint];
|
||||||
|
NSRect viewFrame = [window frame];
|
||||||
|
localPoint.y = viewFrame.size.height - localPoint.y;
|
||||||
|
// Flip |screenPoint|.
|
||||||
|
NSRect screenFrame = [[window screen] frame];
|
||||||
|
screenPoint.y = screenFrame.size.height - screenPoint.y;
|
||||||
|
|
||||||
|
WebView* webview = view_.browser->UIT_GetWebView();
|
||||||
|
|
||||||
|
gfx::Point client(localPoint.x, localPoint.y);
|
||||||
|
gfx::Point screen(screenPoint.x, screenPoint.y);
|
||||||
|
webview->dragSourceMovedTo(client, screen, WebDragOperationNone);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (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);
|
||||||
|
if (!fileStream)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
if (downloadURL_.is_valid()) {
|
||||||
|
WebView* webview = view_.browser->UIT_GetWebView();
|
||||||
|
const GURL& page_url = webview->mainFrame()->document().url();
|
||||||
|
const std::string& page_encoding =
|
||||||
|
webview->mainFrame()->document().encoding().utf8();
|
||||||
|
|
||||||
|
scoped_refptr<DragDownloadFile> dragFileDownloader(new DragDownloadFile(
|
||||||
|
filePath,
|
||||||
|
linked_ptr<net::FileStream>(fileStream),
|
||||||
|
downloadURL_,
|
||||||
|
page_url,
|
||||||
|
page_encoding,
|
||||||
|
view_.browser->UIT_GetWebViewDelegate()));
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
CefThread::PostTask(CefThread::FILE, FROM_HERE,
|
||||||
|
new PromiseWriterTask(*dropData_, fileStream));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Once we've created the file, we should return the file name.
|
||||||
|
return SysUTF8ToNSString(filePath.BaseName().value());
|
||||||
|
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end // @implementation WebDragSource
|
||||||
|
|
||||||
|
|
||||||
|
@implementation WebDragSource (Private)
|
||||||
|
|
||||||
|
- (void)fillPasteboard {
|
||||||
|
DCHECK(pasteboard_.get());
|
||||||
|
|
||||||
|
[pasteboard_ declareTypes:[NSArray array] owner:view_];
|
||||||
|
|
||||||
|
// HTML.
|
||||||
|
if (!dropData_->text_html.empty())
|
||||||
|
[pasteboard_ addTypes:[NSArray arrayWithObject:NSHTMLPboardType]
|
||||||
|
owner:view_];
|
||||||
|
|
||||||
|
// URL (and title).
|
||||||
|
if (dropData_->url.is_valid())
|
||||||
|
[pasteboard_ addTypes:[NSArray arrayWithObjects:NSURLPboardType,
|
||||||
|
kNSURLTitlePboardType, nil]
|
||||||
|
owner:view_];
|
||||||
|
|
||||||
|
// File.
|
||||||
|
if (!dropData_->file_contents.empty() ||
|
||||||
|
!dropData_->download_metadata.empty()) {
|
||||||
|
NSString* fileExtension = 0;
|
||||||
|
|
||||||
|
if (dropData_->download_metadata.empty()) {
|
||||||
|
// |dropData_->file_extension| comes with the '.', which we must strip.
|
||||||
|
fileExtension = (dropData_->file_extension.length() > 0) ?
|
||||||
|
SysUTF16ToNSString(dropData_->file_extension.substr(1)) : @"";
|
||||||
|
} else {
|
||||||
|
string16 mimeType;
|
||||||
|
FilePath fileName;
|
||||||
|
if (drag_download_util::ParseDownloadMetadata(
|
||||||
|
dropData_->download_metadata,
|
||||||
|
&mimeType,
|
||||||
|
&fileName,
|
||||||
|
&downloadURL_)) {
|
||||||
|
download_util::GenerateFileName(
|
||||||
|
downloadURL_,
|
||||||
|
std::string(),
|
||||||
|
std::string(),
|
||||||
|
UTF16ToUTF8(mimeType),
|
||||||
|
fileName.value(),
|
||||||
|
&downloadFileName_);
|
||||||
|
fileExtension = SysUTF8ToNSString(downloadFileName_.Extension());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileExtension) {
|
||||||
|
// File contents (with and without specific type), file (HFS) promise,
|
||||||
|
// TIFF.
|
||||||
|
// TODO(viettrungluu): others?
|
||||||
|
[pasteboard_ addTypes:[NSArray arrayWithObjects:
|
||||||
|
NSFileContentsPboardType,
|
||||||
|
NSCreateFileContentsPboardType(fileExtension),
|
||||||
|
NSFilesPromisePboardType,
|
||||||
|
NSTIFFPboardType,
|
||||||
|
nil]
|
||||||
|
owner:view_];
|
||||||
|
|
||||||
|
// 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:view_];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSImage*)dragImage {
|
||||||
|
if (dragImage_)
|
||||||
|
return dragImage_;
|
||||||
|
|
||||||
|
// Default to returning a generic image.
|
||||||
|
return gfx::GetCachedImageWithName(@"nav.pdf");
|
||||||
|
}
|
||||||
|
|
||||||
|
@end // @implementation WebDragSource (Private)
|
37
libcef/web_drag_utils_mac.h
Normal file
37
libcef/web_drag_utils_mac.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// Copyright (c) 2011 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.
|
||||||
|
|
||||||
|
#ifndef _WEB_DRAG_UTILS_MAC
|
||||||
|
#define _WEB_DRAG_UTILS_MAC
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
#include "base/basictypes.h"
|
||||||
|
#include "googleurl/src/gurl.h"
|
||||||
|
|
||||||
|
namespace drag_util {
|
||||||
|
|
||||||
|
// Populates the |url| and |title| with URL data in |pboard|. There may be more
|
||||||
|
// than one, but we only handle dropping the first. |url| must not be |NULL|;
|
||||||
|
// |title| is an optional parameter. Returns |YES| if URL data was obtained from
|
||||||
|
// the pasteboard, |NO| otherwise. If |convert_filenames| is |YES|, the function
|
||||||
|
// will also attempt to convert filenames in |pboard| to file URLs.
|
||||||
|
BOOL PopulateURLAndTitleFromPasteBoard(GURL* url,
|
||||||
|
string16* title,
|
||||||
|
NSPasteboard* pboard,
|
||||||
|
BOOL convert_filenames);
|
||||||
|
|
||||||
|
// Returns the first file URL from |info|, if there is one. If |info| doesn't
|
||||||
|
// contain any file URLs, an empty |GURL| is returned.
|
||||||
|
GURL GetFileURLFromDropData(id<NSDraggingInfo> info);
|
||||||
|
|
||||||
|
// Determines whether the given drag and drop operation contains content that
|
||||||
|
// is supported by the web view. In particular, if the content is a local file
|
||||||
|
// URL, this checks if it is of a type that can be shown in the tab contents.
|
||||||
|
BOOL IsUnsupportedDropData(id<NSDraggingInfo> info);
|
||||||
|
|
||||||
|
} // namespace drag_util
|
||||||
|
|
||||||
|
#endif // _WEB_DRAG_UTILS_MAC
|
101
libcef/web_drag_utils_mac.mm
Normal file
101
libcef/web_drag_utils_mac.mm
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
// Copyright (c) 2011 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 "web_drag_utils_mac.h"
|
||||||
|
|
||||||
|
#include "base/basictypes.h"
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "base/sys_string_conversions.h"
|
||||||
|
#include "googleurl/src/gurl.h"
|
||||||
|
#include "net/base/mime_util.h"
|
||||||
|
#include "net/base/net_util.h"
|
||||||
|
#import "third_party/mozilla/NSPasteboard+Utils.h"
|
||||||
|
#include "webkit/plugins/npapi/plugin_list.h"
|
||||||
|
|
||||||
|
namespace drag_util {
|
||||||
|
|
||||||
|
BOOL PopulateURLAndTitleFromPasteBoard(GURL* url,
|
||||||
|
string16* title,
|
||||||
|
NSPasteboard* pboard,
|
||||||
|
BOOL convert_filenames) {
|
||||||
|
CHECK(url);
|
||||||
|
|
||||||
|
// Bail out early if there's no URL data.
|
||||||
|
if (![pboard containsURLData])
|
||||||
|
return NO;
|
||||||
|
|
||||||
|
// -getURLs:andTitles:convertingFilenames: will already validate URIs so we
|
||||||
|
// don't need to again. The arrays returned are both of NSStrings.
|
||||||
|
NSArray* url_array = nil;
|
||||||
|
NSArray* title_array = nil;
|
||||||
|
[pboard getURLs:&url_array andTitles:&title_array
|
||||||
|
convertingFilenames:convert_filenames];
|
||||||
|
DCHECK_EQ([url_array count], [title_array count]);
|
||||||
|
// It's possible that no URLs were actually provided!
|
||||||
|
if (![url_array count])
|
||||||
|
return NO;
|
||||||
|
NSString* url_string = [url_array objectAtIndex:0];
|
||||||
|
if ([url_string length]) {
|
||||||
|
// Check again just to make sure to not assign NULL into a std::string,
|
||||||
|
// which throws an exception.
|
||||||
|
const char* utf8_url = [url_string UTF8String];
|
||||||
|
if (utf8_url) {
|
||||||
|
*url = GURL(utf8_url);
|
||||||
|
// Extra paranoia check.
|
||||||
|
if (title && [title_array count])
|
||||||
|
*title = base::SysNSStringToUTF16([title_array objectAtIndex:0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
GURL GetFileURLFromDropData(id<NSDraggingInfo> info) {
|
||||||
|
if ([[info draggingPasteboard] containsURLData]) {
|
||||||
|
GURL url;
|
||||||
|
PopulateURLAndTitleFromPasteBoard(&url,
|
||||||
|
NULL,
|
||||||
|
[info draggingPasteboard],
|
||||||
|
YES);
|
||||||
|
|
||||||
|
if (url.SchemeIs("file"))
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
return GURL();
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL IsSupportedFileURL(const GURL& url) {
|
||||||
|
FilePath full_path;
|
||||||
|
net::FileURLToFilePath(url, &full_path);
|
||||||
|
|
||||||
|
std::string mime_type;
|
||||||
|
net::GetMimeTypeFromFile(full_path, &mime_type);
|
||||||
|
|
||||||
|
// This logic mirrors |BufferedResourceHandler::ShouldDownload()|.
|
||||||
|
// TODO(asvitkine): Refactor this out to a common location instead of
|
||||||
|
// duplicating code.
|
||||||
|
if (net::IsSupportedMimeType(mime_type))
|
||||||
|
return YES;
|
||||||
|
|
||||||
|
// Check whether there is a plugin that supports the mime type. (e.g. PDF)
|
||||||
|
webkit::npapi::PluginList* list = webkit::npapi::PluginList::Singleton();
|
||||||
|
webkit::npapi::WebPluginInfo info;
|
||||||
|
if (list->PluginsLoaded() &&
|
||||||
|
list->GetPluginInfo(GURL(), mime_type, false, &info, NULL)) {
|
||||||
|
return webkit::npapi::IsPluginEnabled(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL IsUnsupportedDropData(id<NSDraggingInfo> info) {
|
||||||
|
GURL url = GetFileURLFromDropData(info);
|
||||||
|
if (!url.is_empty()) {
|
||||||
|
// If dragging a file, only allow dropping supported file types (that the
|
||||||
|
// web view can display).
|
||||||
|
return !IsSupportedFileURL(url);
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace drag_util
|
69
libcef/web_drop_target_mac.h
Normal file
69
libcef/web_drop_target_mac.h
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2011 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 <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
|
#include "base/string16.h"
|
||||||
|
|
||||||
|
class GURL;
|
||||||
|
struct WebDropData;
|
||||||
|
@class BrowserWebView;
|
||||||
|
class WebViewHost;
|
||||||
|
|
||||||
|
// A class that handles tracking and event processing for a drag and drop
|
||||||
|
// over the content area. Assumes something else initiates the drag, this is
|
||||||
|
// only for processing during a drag.
|
||||||
|
|
||||||
|
@interface WebDropTarget : NSObject {
|
||||||
|
@private
|
||||||
|
// Our associated WebView. Weak reference.
|
||||||
|
BrowserWebView* view_;
|
||||||
|
|
||||||
|
// Updated asynchronously during a drag to tell us whether or not we should
|
||||||
|
// allow the drop.
|
||||||
|
NSDragOperation current_operation_;
|
||||||
|
|
||||||
|
// Keep track of the WebViewHost we're dragging over. If it changes during a
|
||||||
|
// drag, we need to re-send the DragEnter message.
|
||||||
|
WebViewHost* current_wvh_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// |view| is the WebView representing this browser window, used to communicate
|
||||||
|
// drag&drop messages to WebCore and handle navigation on a successful drop
|
||||||
|
// (if necessary).
|
||||||
|
- (id)initWithWebView:(BrowserWebView*)view;
|
||||||
|
|
||||||
|
// Sets the current operation negotiated by the source and destination,
|
||||||
|
// which determines whether or not we should allow the drop. Takes effect the
|
||||||
|
// next time |-draggingUpdated:| is called.
|
||||||
|
- (void)setCurrentOperation: (NSDragOperation)operation;
|
||||||
|
|
||||||
|
// Messages to send during the tracking of a drag, ususally upon receiving
|
||||||
|
// calls from the view system. Communicates the drag messages to WebCore.
|
||||||
|
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info
|
||||||
|
view:(NSView*)view;
|
||||||
|
- (void)draggingExited:(id<NSDraggingInfo>)info;
|
||||||
|
- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info
|
||||||
|
view:(NSView*)view;
|
||||||
|
- (BOOL)performDragOperation:(id<NSDraggingInfo>)info
|
||||||
|
view:(NSView*)view;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
// Public use only for unit tests.
|
||||||
|
@interface WebDropTarget(Testing)
|
||||||
|
// Given |data|, which should not be nil, fill it in using the contents of the
|
||||||
|
// given pasteboard.
|
||||||
|
- (void)populateWebDropData:(WebDropData*)data
|
||||||
|
fromPasteboard:(NSPasteboard*)pboard;
|
||||||
|
// Given a point in window coordinates and a view in that window, return a
|
||||||
|
// flipped point in the coordinate system of |view|.
|
||||||
|
- (NSPoint)flipWindowPointToView:(const NSPoint&)windowPoint
|
||||||
|
view:(NSView*)view;
|
||||||
|
// Given a point in window coordinates and a view in that window, return a
|
||||||
|
// flipped point in screen coordinates.
|
||||||
|
- (NSPoint)flipWindowPointToScreen:(const NSPoint&)windowPoint
|
||||||
|
view:(NSView*)view;
|
||||||
|
@end
|
234
libcef/web_drop_target_mac.mm
Normal file
234
libcef/web_drop_target_mac.mm
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
// Copyright (c) 2011 The Chromium Embedded Framework Authors.
|
||||||
|
// Portions copyright (c) 2011 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.
|
||||||
|
|
||||||
|
#include "browser_impl.h"
|
||||||
|
#import "browser_webview_mac.h"
|
||||||
|
#include "cef_context.h"
|
||||||
|
#import "web_drop_target_mac.h"
|
||||||
|
#import "web_drag_utils_mac.h"
|
||||||
|
|
||||||
|
#include "base/logging.h"
|
||||||
|
#include "base/sys_string_conversions.h"
|
||||||
|
#import "third_party/mozilla/NSPasteboard+Utils.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragData.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDragOperation.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebPoint.h"
|
||||||
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
|
||||||
|
#include "webkit/glue/webdropdata.h"
|
||||||
|
#include "webkit/glue/window_open_disposition.h"
|
||||||
|
|
||||||
|
using WebKit::WebDragOperationsMask;
|
||||||
|
using WebKit::WebPoint;
|
||||||
|
using WebKit::WebView;
|
||||||
|
|
||||||
|
@implementation WebDropTarget
|
||||||
|
|
||||||
|
// |view| is the WebView representing this browser window, used to communicate
|
||||||
|
// drag&drop messages to WebCore and handle navigation on a successful drop
|
||||||
|
// (if necessary).
|
||||||
|
- (id)initWithWebView:(BrowserWebView*)view {
|
||||||
|
if ((self = [super init]))
|
||||||
|
view_ = view;
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call to set whether or not we should allow the drop. Takes effect the
|
||||||
|
// next time |-draggingUpdated:| is called.
|
||||||
|
- (void)setCurrentOperation: (NSDragOperation)operation {
|
||||||
|
current_operation_ = operation;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a point in window coordinates and a view in that window, return a
|
||||||
|
// flipped point in the coordinate system of |view|.
|
||||||
|
- (NSPoint)flipWindowPointToView:(const NSPoint&)windowPoint
|
||||||
|
view:(NSView*)view {
|
||||||
|
DCHECK(view);
|
||||||
|
NSPoint viewPoint = [view convertPoint:windowPoint fromView:nil];
|
||||||
|
NSRect viewFrame = [view frame];
|
||||||
|
viewPoint.y = viewFrame.size.height - viewPoint.y;
|
||||||
|
return viewPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given a point in window coordinates and a view in that window, return a
|
||||||
|
// flipped point in screen coordinates.
|
||||||
|
- (NSPoint)flipWindowPointToScreen:(const NSPoint&)windowPoint
|
||||||
|
view:(NSView*)view {
|
||||||
|
DCHECK(view);
|
||||||
|
NSPoint screenPoint = [[view window] convertBaseToScreen:windowPoint];
|
||||||
|
NSScreen* screen = [[view window] screen];
|
||||||
|
NSRect screenFrame = [screen frame];
|
||||||
|
screenPoint.y = screenFrame.size.height - screenPoint.y;
|
||||||
|
return screenPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return YES if the drop site only allows drops that would navigate. If this
|
||||||
|
// is the case, we don't want to pass messages to the renderer because there's
|
||||||
|
// really no point (i.e., there's nothing that cares about the mouse position or
|
||||||
|
// entering and exiting). One example is an interstitial page (e.g., safe
|
||||||
|
// browsing warning).
|
||||||
|
- (BOOL)onlyAllowsNavigation {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Messages to send during the tracking of a drag, usually upon receiving
|
||||||
|
// calls from the view system. Communicates the drag messages to WebCore.
|
||||||
|
|
||||||
|
- (NSDragOperation)draggingEntered:(id<NSDraggingInfo>)info
|
||||||
|
view:(NSView*)view {
|
||||||
|
// Save off the current WebViewHost so we can tell if it changes during a
|
||||||
|
// drag. If it does, we need to send a new enter message in draggingUpdated:.
|
||||||
|
current_wvh_ = _Context->current_webviewhost();
|
||||||
|
DCHECK(current_wvh_);
|
||||||
|
|
||||||
|
if ([self onlyAllowsNavigation]) {
|
||||||
|
if ([[info draggingPasteboard] containsURLData])
|
||||||
|
return NSDragOperationCopy;
|
||||||
|
return NSDragOperationNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebView* webview = view_.browser->UIT_GetWebView();
|
||||||
|
|
||||||
|
// Fill out a WebDropData from pasteboard.
|
||||||
|
WebDropData data;
|
||||||
|
[self populateWebDropData:&data fromPasteboard:[info draggingPasteboard]];
|
||||||
|
|
||||||
|
// Create the appropriate mouse locations for WebCore. The draggingLocation
|
||||||
|
// is in window coordinates. Both need to be flipped.
|
||||||
|
NSPoint windowPoint = [info draggingLocation];
|
||||||
|
NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
|
||||||
|
NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
|
||||||
|
NSDragOperation mask = [info draggingSourceOperationMask];
|
||||||
|
webview->dragTargetDragEnter(data.ToDragData(),
|
||||||
|
WebPoint(viewPoint.x, viewPoint.y),
|
||||||
|
WebPoint(screenPoint.x, screenPoint.y),
|
||||||
|
static_cast<WebDragOperationsMask>(mask));
|
||||||
|
|
||||||
|
// We won't know the true operation (whether the drag is allowed) until we
|
||||||
|
// hear back from the renderer. For now, be optimistic:
|
||||||
|
current_operation_ = NSDragOperationCopy;
|
||||||
|
return current_operation_;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)draggingExited:(id<NSDraggingInfo>)info {
|
||||||
|
DCHECK(current_wvh_);
|
||||||
|
if (current_wvh_ != _Context->current_webviewhost())
|
||||||
|
return;
|
||||||
|
|
||||||
|
WebView* webview = view_.browser->UIT_GetWebView();
|
||||||
|
|
||||||
|
// Nothing to do in the interstitial case.
|
||||||
|
|
||||||
|
webview->dragTargetDragLeave();
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)info
|
||||||
|
view:(NSView*)view {
|
||||||
|
DCHECK(current_wvh_);
|
||||||
|
if (current_wvh_ != _Context->current_webviewhost())
|
||||||
|
[self draggingEntered:info view:view];
|
||||||
|
|
||||||
|
if ([self onlyAllowsNavigation]) {
|
||||||
|
if ([[info draggingPasteboard] containsURLData])
|
||||||
|
return NSDragOperationCopy;
|
||||||
|
return NSDragOperationNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
WebView* webview = view_.browser->UIT_GetWebView();
|
||||||
|
|
||||||
|
// Create the appropriate mouse locations for WebCore. The draggingLocation
|
||||||
|
// is in window coordinates.
|
||||||
|
NSPoint windowPoint = [info draggingLocation];
|
||||||
|
NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
|
||||||
|
NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
|
||||||
|
NSDragOperation mask = [info draggingSourceOperationMask];
|
||||||
|
webview->dragTargetDragOver(WebPoint(viewPoint.x, viewPoint.y),
|
||||||
|
WebPoint(screenPoint.x, screenPoint.y),
|
||||||
|
static_cast<WebDragOperationsMask>(mask));
|
||||||
|
|
||||||
|
return current_operation_;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)performDragOperation:(id<NSDraggingInfo>)info
|
||||||
|
view:(NSView*)view {
|
||||||
|
DCHECK(current_wvh_);
|
||||||
|
if (current_wvh_ != _Context->current_webviewhost())
|
||||||
|
[self draggingEntered:info view:view];
|
||||||
|
|
||||||
|
// Check if we only allow navigation and navigate to a url on the pasteboard.
|
||||||
|
if ([self onlyAllowsNavigation]) {
|
||||||
|
NSPasteboard* pboard = [info draggingPasteboard];
|
||||||
|
if ([pboard containsURLData]) {
|
||||||
|
GURL url;
|
||||||
|
drag_util::PopulateURLAndTitleFromPasteBoard(&url, NULL, pboard, YES);
|
||||||
|
view_.browser->GetMainFrame()->LoadURL(url.spec());
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_wvh_ = NULL;
|
||||||
|
|
||||||
|
WebView* webview = view_.browser->UIT_GetWebView();
|
||||||
|
|
||||||
|
// Create the appropriate mouse locations for WebCore. The draggingLocation
|
||||||
|
// is in window coordinates. Both need to be flipped.
|
||||||
|
NSPoint windowPoint = [info draggingLocation];
|
||||||
|
NSPoint viewPoint = [self flipWindowPointToView:windowPoint view:view];
|
||||||
|
NSPoint screenPoint = [self flipWindowPointToScreen:windowPoint view:view];
|
||||||
|
webview->dragTargetDrop(gfx::Point(viewPoint.x, viewPoint.y),
|
||||||
|
gfx::Point(screenPoint.x, screenPoint.y));
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Given |data|, which should not be nil, fill it in using the contents of the
|
||||||
|
// given pasteboard.
|
||||||
|
- (void)populateWebDropData:(WebDropData*)data
|
||||||
|
fromPasteboard:(NSPasteboard*)pboard {
|
||||||
|
DCHECK(data);
|
||||||
|
DCHECK(pboard);
|
||||||
|
NSArray* types = [pboard types];
|
||||||
|
|
||||||
|
// Get URL if possible. To avoid exposing file system paths to web content,
|
||||||
|
// filenames in the drag are not converted to file URLs.
|
||||||
|
drag_util::PopulateURLAndTitleFromPasteBoard(&data->url,
|
||||||
|
&data->url_title,
|
||||||
|
pboard,
|
||||||
|
NO);
|
||||||
|
|
||||||
|
// Get plain text.
|
||||||
|
if ([types containsObject:NSStringPboardType]) {
|
||||||
|
data->plain_text =
|
||||||
|
base::SysNSStringToUTF16([pboard stringForType:NSStringPboardType]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get HTML. If there's no HTML, try RTF.
|
||||||
|
if ([types containsObject:NSHTMLPboardType]) {
|
||||||
|
data->text_html =
|
||||||
|
base::SysNSStringToUTF16([pboard stringForType:NSHTMLPboardType]);
|
||||||
|
} else if ([types containsObject:NSRTFPboardType]) {
|
||||||
|
NSString* html = [pboard htmlFromRtf];
|
||||||
|
data->text_html = base::SysNSStringToUTF16(html);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get files.
|
||||||
|
if ([types containsObject:NSFilenamesPboardType]) {
|
||||||
|
NSArray* files = [pboard propertyListForType:NSFilenamesPboardType];
|
||||||
|
if ([files isKindOfClass:[NSArray class]] && [files count]) {
|
||||||
|
for (NSUInteger i = 0; i < [files count]; i++) {
|
||||||
|
NSString* filename = [files objectAtIndex:i];
|
||||||
|
BOOL isDir = NO;
|
||||||
|
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:filename
|
||||||
|
isDirectory:&isDir];
|
||||||
|
if (exists && !isDir)
|
||||||
|
data->filenames.push_back(base::SysNSStringToUTF16(filename));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(pinkerton): Get file contents. http://crbug.com/34661
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
@@ -50,6 +50,8 @@ class WebViewHost : public WebWidgetHost {
|
|||||||
}
|
}
|
||||||
#elif defined(OS_MACOSX)
|
#elif defined(OS_MACOSX)
|
||||||
void SetIsActive(bool active);
|
void SetIsActive(bool active);
|
||||||
|
virtual void MouseEvent(NSEvent *);
|
||||||
|
virtual void SetFocus(bool enable);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include "webview_host.h"
|
#include "webview_host.h"
|
||||||
#include "browser_webview_delegate.h"
|
#include "browser_webview_delegate.h"
|
||||||
#include "browser_webview_mac.h"
|
#include "browser_webview_mac.h"
|
||||||
|
#include "cef_context.h"
|
||||||
|
|
||||||
#include "skia/ext/platform_canvas.h"
|
#include "skia/ext/platform_canvas.h"
|
||||||
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
|
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
|
||||||
@@ -56,3 +57,17 @@ WebView* WebViewHost::webview() const {
|
|||||||
void WebViewHost::SetIsActive(bool active) {
|
void WebViewHost::SetIsActive(bool active) {
|
||||||
webview()->setIsActive(active);
|
webview()->setIsActive(active);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WebViewHost::MouseEvent(NSEvent* event) {
|
||||||
|
_Context->set_current_webviewhost(this);
|
||||||
|
WebWidgetHost::MouseEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebViewHost::SetFocus(bool enable) {
|
||||||
|
if (enable) {
|
||||||
|
// Set the current WebViewHost in case a drag action is started before mouse
|
||||||
|
// events are detected for the window.
|
||||||
|
_Context->set_current_webviewhost(this);
|
||||||
|
}
|
||||||
|
WebWidgetHost::SetFocus(enable);
|
||||||
|
}
|
||||||
|
@@ -151,10 +151,10 @@ class WebWidgetHost {
|
|||||||
// These need to be called from a non-subclass, so they need to be public.
|
// These need to be called from a non-subclass, so they need to be public.
|
||||||
public:
|
public:
|
||||||
void Resize(const gfx::Rect& rect);
|
void Resize(const gfx::Rect& rect);
|
||||||
void MouseEvent(NSEvent *);
|
virtual void MouseEvent(NSEvent *);
|
||||||
void WheelEvent(NSEvent *);
|
void WheelEvent(NSEvent *);
|
||||||
void KeyEvent(NSEvent *);
|
void KeyEvent(NSEvent *);
|
||||||
void SetFocus(bool enable);
|
virtual void SetFocus(bool enable);
|
||||||
protected:
|
protected:
|
||||||
#elif defined(TOOLKIT_USES_GTK)
|
#elif defined(TOOLKIT_USES_GTK)
|
||||||
public:
|
public:
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
// found in the LICENSE file.
|
// found in the LICENSE file.
|
||||||
|
|
||||||
#include "include/cef.h"
|
#include "include/cef.h"
|
||||||
|
#import "include/cef_application_mac.h"
|
||||||
#include "cefclient.h"
|
#include "cefclient.h"
|
||||||
#include "binding_test.h"
|
#include "binding_test.h"
|
||||||
#include "client_handler.h"
|
#include "client_handler.h"
|
||||||
@@ -29,6 +30,31 @@ char szWorkingDir[512]; // The current working directory
|
|||||||
const int kWindowWidth = 800;
|
const int kWindowWidth = 800;
|
||||||
const int kWindowHeight = 600;
|
const int kWindowHeight = 600;
|
||||||
|
|
||||||
|
// Memory AutoRelease pool.
|
||||||
|
static NSAutoreleasePool* g_autopool = nil;
|
||||||
|
|
||||||
|
// Provide the CefAppProtocol implementation required by CEF.
|
||||||
|
@interface ClientApplication : NSApplication<CefAppProtocol> {
|
||||||
|
@private
|
||||||
|
BOOL handlingSendEvent_;
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ClientApplication
|
||||||
|
- (BOOL)isHandlingSendEvent {
|
||||||
|
return handlingSendEvent_;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)setHandlingSendEvent:(BOOL)handlingSendEvent {
|
||||||
|
handlingSendEvent_ = handlingSendEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)sendEvent:(NSEvent*)event {
|
||||||
|
CefScopedSendingEvent sendingEventScoper;
|
||||||
|
[super sendEvent:event];
|
||||||
|
}
|
||||||
|
@end
|
||||||
|
|
||||||
|
|
||||||
// Receives notifications from controls and the browser window. Will delete
|
// Receives notifications from controls and the browser window. Will delete
|
||||||
// itself when done.
|
// itself when done.
|
||||||
@@ -174,6 +200,7 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
|||||||
- (IBAction)testAcceleratedLayers:(id)sender;
|
- (IBAction)testAcceleratedLayers:(id)sender;
|
||||||
- (IBAction)testWebGL:(id)sender;
|
- (IBAction)testWebGL:(id)sender;
|
||||||
- (IBAction)testHTML5Video:(id)sender;
|
- (IBAction)testHTML5Video:(id)sender;
|
||||||
|
- (IBAction)testDragDrop:(id)sender;
|
||||||
- (IBAction)testZoomIn:(id)sender;
|
- (IBAction)testZoomIn:(id)sender;
|
||||||
- (IBAction)testZoomOut:(id)sender;
|
- (IBAction)testZoomOut:(id)sender;
|
||||||
- (IBAction)testZoomReset:(id)sender;
|
- (IBAction)testZoomReset:(id)sender;
|
||||||
@@ -243,6 +270,9 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
|||||||
[testMenu addItemWithTitle:@"HTML5 Video"
|
[testMenu addItemWithTitle:@"HTML5 Video"
|
||||||
action:@selector(testHTML5Video:)
|
action:@selector(testHTML5Video:)
|
||||||
keyEquivalent:@""];
|
keyEquivalent:@""];
|
||||||
|
[testMenu addItemWithTitle:@"Drag & Drop"
|
||||||
|
action:@selector(testDragDrop:)
|
||||||
|
keyEquivalent:@""];
|
||||||
[testMenu addItemWithTitle:@"Zoom In"
|
[testMenu addItemWithTitle:@"Zoom In"
|
||||||
action:@selector(testZoomIn:)
|
action:@selector(testZoomIn:)
|
||||||
keyEquivalent:@""];
|
keyEquivalent:@""];
|
||||||
@@ -419,6 +449,11 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
|||||||
RunHTML5VideoTest(g_handler->GetBrowser());
|
RunHTML5VideoTest(g_handler->GetBrowser());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (IBAction)testDragDrop:(id)sender {
|
||||||
|
if(g_handler.get() && g_handler->GetBrowserHwnd())
|
||||||
|
RunDragDropTest(g_handler->GetBrowser());
|
||||||
|
}
|
||||||
|
|
||||||
- (IBAction)testZoomIn:(id)sender {
|
- (IBAction)testZoomIn:(id)sender {
|
||||||
if(g_handler.get() && g_handler->GetBrowserHwnd()) {
|
if(g_handler.get() && g_handler->GetBrowserHwnd()) {
|
||||||
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
|
CefRefPtr<CefBrowser> browser = g_handler->GetBrowser();
|
||||||
@@ -448,6 +483,9 @@ NSButton* MakeButton(NSRect* rect, NSString* title, NSView* parent) {
|
|||||||
CefShutdown();
|
CefShutdown();
|
||||||
|
|
||||||
[self release];
|
[self release];
|
||||||
|
|
||||||
|
// Release the AutoRelease pool.
|
||||||
|
[g_autopool release];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -458,7 +496,13 @@ int main(int argc, char* argv[])
|
|||||||
// Retrieve the current working directory.
|
// Retrieve the current working directory.
|
||||||
getcwd(szWorkingDir, sizeof(szWorkingDir));
|
getcwd(szWorkingDir, sizeof(szWorkingDir));
|
||||||
|
|
||||||
// Initialize CEF. This will also create the NSApplication instance.
|
// Initialize the AutoRelease pool.
|
||||||
|
g_autopool = [[NSAutoreleasePool alloc] init];
|
||||||
|
|
||||||
|
// Initialize the ClientApplication instance.
|
||||||
|
[ClientApplication sharedApplication];
|
||||||
|
|
||||||
|
// Initialize CEF.
|
||||||
CefSettings settings;
|
CefSettings settings;
|
||||||
CefInitialize(settings);
|
CefInitialize(settings);
|
||||||
|
|
||||||
@@ -472,7 +516,7 @@ int main(int argc, char* argv[])
|
|||||||
waitUntilDone:NO];
|
waitUntilDone:NO];
|
||||||
|
|
||||||
// Run the application message loop.
|
// Run the application message loop.
|
||||||
[NSApp run];
|
CefRunMessageLoop();
|
||||||
|
|
||||||
// Don't put anything below this line because it won't be executed.
|
// Don't put anything below this line because it won't be executed.
|
||||||
return 0;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user