Hello noel,
I'd like you to do a code review. Please execute
g4 diff -c 9182088
or point your web browser to
http://mondrian/9182088
to review the following code:
Change 9182088 by [EMAIL PROTECTED] on 2008/11/27 17:39:26 *pending*
Implement desktop.getDragAndDropData(event) on IE.
R=noel
[EMAIL PROTECTED]
DELTA=375 (262 added, 89 deleted, 24 changed)
OCL=9182088
Affected files ...
... //depot/googleclient/gears/opensource/gears/Makefile#215 edit
... //depot/googleclient/gears/opensource/gears/desktop/desktop.cc#59 edit
...
//depot/googleclient/gears/opensource/gears/desktop/drag_and_drop_utils_ie.cc#1
add
...
//depot/googleclient/gears/opensource/gears/desktop/drag_and_drop_utils_ie.h#1
add
... //depot/googleclient/gears/opensource/gears/desktop/drop_target_ie.cc#13
edit
... //depot/googleclient/gears/opensource/gears/desktop/drop_target_ie.h#9 edit
...
//depot/googleclient/gears/opensource/gears/test/manual/drag_and_drop_fake_event_attack.html#2
edit
375 delta lines: 262 added, 89 deleted, 24 changed
Also consider running:
g4 lint -c 9182088
which verifies that the changelist doesn't introduce new style violations.
If you can't do the review, please let me know as soon as possible. During
your review, please ensure that all new code has corresponding unit tests and
that existing unit tests are updated appropriately. Visit
http://www/eng/code_review.html for more information.
This is a semiautomated message from "g4 mail". Complaints or suggestions?
Mail [EMAIL PROTECTED]
Change 9182088 by [EMAIL PROTECTED] on 2008/11/27 17:39:26 *pending*
Implement desktop.getDragAndDropData(event) on IE.
OCL=9182088
Affected files ...
... //depot/googleclient/gears/opensource/gears/Makefile#215 edit
... //depot/googleclient/gears/opensource/gears/desktop/desktop.cc#59 edit
...
//depot/googleclient/gears/opensource/gears/desktop/drag_and_drop_utils_ie.cc#1
add
...
//depot/googleclient/gears/opensource/gears/desktop/drag_and_drop_utils_ie.h#1
add
... //depot/googleclient/gears/opensource/gears/desktop/drop_target_ie.cc#13
edit
... //depot/googleclient/gears/opensource/gears/desktop/drop_target_ie.h#9 edit
...
//depot/googleclient/gears/opensource/gears/test/manual/drag_and_drop_fake_event_attack.html#2
edit
==== //depot/googleclient/gears/opensource/gears/Makefile#215 -
c:\devel\srcwingears2/googleclient/gears/opensource/gears/Makefile ====
# action=edit type=text
--- googleclient/gears/opensource/gears/Makefile 2008-11-27
17:13:15.000000000 +1100
+++ googleclient/gears/opensource/gears/Makefile 2008-11-27
10:33:47.000000000 +1100
@@ -1487,6 +1487,7 @@
$(NULL)
IE_CPPSRCS += \
+ drag_and_drop_utils_ie.cc \
drop_target_ie.cc \
$(NULL)
==== //depot/googleclient/gears/opensource/gears/desktop/desktop.cc#59 -
c:\devel\srcwingears2/googleclient/gears/opensource/gears/desktop/desktop.cc
====
# action=edit type=text
--- googleclient/gears/opensource/gears/desktop/desktop.cc 2008-11-27
17:13:15.000000000 +1100
+++ googleclient/gears/opensource/gears/desktop/desktop.cc 2008-11-27
10:35:17.000000000 +1100
@@ -57,6 +57,8 @@
#if BROWSER_FF
#include "gears/desktop/drag_and_drop_utils_ff.h"
+#elif BROWSER_IE
+#include "gears/desktop/drag_and_drop_utils_ie.h"
#elif BROWSER_WEBKIT
#include "gears/desktop/drag_and_drop_utils_sf.h"
#endif
@@ -1057,13 +1059,13 @@
result.get(),
&error);
#endif
-#elif BROWSER_WEBKIT
+#elif (BROWSER_IE && !defined(OS_WINCE)) || BROWSER_WEBKIT
::GetDragAndDropData(module_environment_.get(),
event_as_js_object.get(),
result.get(),
&error);
#else
- // TODO(nigeltao): implement on IE and Chromium.
+ // TODO(nigeltao): implement on Chromium.
error = STRING16(L"getDragAndDropData is not supported for this platform.");
#endif
====
//depot/googleclient/gears/opensource/gears/desktop/drag_and_drop_utils_ie.cc#1
-
c:\devel\srcwingears2/googleclient/gears/opensource/gears/desktop/drag_and_drop_utils_ie.cc
====
# action=add type=text
--- /dev/null 1970-01-01 11:00:00.000000000 +1100
+++ googleclient/gears/opensource/gears/desktop/drag_and_drop_utils_ie.cc
2008-11-27 17:19:34.000000000 +1100
@@ -0,0 +1,189 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. 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.
+// 3. Neither the name of Google Inc. 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 AUTHOR ``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 AUTHOR 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.
+
+#include <mshtmdid.h>
+#include <shlobj.h>
+#include <windows.h>
+
+#include "gears/desktop/drag_and_drop_utils_ie.h"
+
+#include "gears/base/ie/activex_utils.h"
+#include "gears/desktop/file_dialog.h"
+
+
+// This function overwrites buffer in-place.
+static HRESULT ResolveShortcut(TCHAR *buffer) {
+ static CComPtr<IShellLink> link;
+ if (!link && FAILED(link.CoCreateInstance(CLSID_ShellLink))) {
+ return E_FAIL;
+ }
+
+ CComQIPtr<IPersistFile> file(link);
+ if (!file) return E_FAIL;
+
+ // Open the shortcut file, load its content.
+ HRESULT hr = file->Load(buffer, STGM_READ);
+ if (FAILED(hr)) return hr;
+
+ // Resolve the target of the shortcut.
+ hr = link->Resolve(NULL, SLR_NO_UI);
+ if (FAILED(hr)) return hr;
+
+ // Read the target path.
+ hr = link->GetPath(buffer, MAX_PATH, 0, SLGP_UNCPRIORITY);
+ if (FAILED(hr)) return hr;
+
+ return S_OK;
+}
+
+
+HRESULT GetHtmlDataTransfer(
+ IHTMLWindow2 *html_window_2,
+ CComPtr<IHTMLEventObj> &html_event_obj,
+ CComPtr<IHTMLDataTransfer> &html_data_transfer)
+{
+ HRESULT hr;
+ hr = html_window_2->get_event(&html_event_obj);
+ if (FAILED(hr)) return hr;
+ CComQIPtr<IHTMLEventObj2> html_event_obj_2(html_event_obj);
+ if (!html_event_obj_2) return E_FAIL;
+ hr = html_event_obj_2->get_dataTransfer(&html_data_transfer);
+ return hr;
+}
+
+
+bool GetDroppedFiles(ModuleEnvironment *module_environment,
+ JsArray *files_out,
+ std::string16 *error_out) {
+ CComPtr<IHTMLWindow2> html_window_2;
+ if (FAILED(ActiveXUtils::GetHtmlWindow2(
+ module_environment->iunknown_site_, &html_window_2))) {
+ *error_out = STRING16(L"Could not access the IHtmlWindow2.");
+ return false;
+ }
+
+ CComPtr<IHTMLEventObj> html_event_obj;
+ CComPtr<IHTMLDataTransfer> html_data_transfer;
+ HRESULT hr = GetHtmlDataTransfer(
+ html_window_2, html_event_obj, html_data_transfer);
+ if (FAILED(hr)) return false;
+
+ CComPtr<IServiceProvider> service_provider;
+ hr = html_data_transfer->QueryInterface(&service_provider);
+ if (FAILED(hr)) return false;
+ CComPtr<IDataObject> data_object;
+ hr = service_provider->QueryService<IDataObject>(
+ IID_IDataObject, &data_object);
+ if (FAILED(hr)) return false;
+
+ FORMATETC desired_format_etc =
+ { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
+ STGMEDIUM stg_medium;
+ hr = data_object->GetData(&desired_format_etc, &stg_medium);
+ if (FAILED(hr)) return false;
+
+ HDROP hdrop = static_cast<HDROP>(GlobalLock(stg_medium.hGlobal));
+ if (hdrop == NULL) {
+ ReleaseStgMedium(&stg_medium);
+ return false;
+ }
+
+ std::vector<std::string16> filenames;
+ UINT num_files = DragQueryFile(hdrop, -1, 0, 0);
+ TCHAR buffer[MAX_PATH + 1];
+ for (UINT i = 0; i < num_files; i++) {
+ DragQueryFile(hdrop, i, buffer, sizeof(buffer));
+ SHFILEINFO sh_file_info;
+ if (!SHGetFileInfo(buffer, 0, &sh_file_info, sizeof(sh_file_info),
+ SHGFI_ATTRIBUTES) ||
+ !(sh_file_info.dwAttributes & SFGAO_FILESYSTEM) ||
+ (sh_file_info.dwAttributes & SFGAO_FOLDER)) {
+ continue;
+ }
+ if ((sh_file_info.dwAttributes & SFGAO_LINK) &&
+ FAILED(ResolveShortcut(buffer))) {
+ continue;
+ }
+ filenames.push_back(std::string16(buffer));
+ }
+
+ GlobalUnlock(stg_medium.hGlobal);
+ ReleaseStgMedium(&stg_medium);
+
+ return FileDialog::FilesToJsObjectArray(
+ filenames, module_environment, files_out, error_out);
+}
+
+
+void GetDragAndDropData(ModuleEnvironment *module_environment,
+ JsObject *event_as_js_object,
+ JsObject *data_out,
+ std::string16 *error_out) {
+ CComPtr<IHTMLWindow2> window;
+ if (FAILED(ActiveXUtils::GetHtmlWindow2(
+ module_environment->iunknown_site_, &window))) {
+ *error_out = STRING16(L"Could not access the IHtmlWindow2.");
+ return;
+ }
+
+ CComPtr<IHTMLEventObj> window_event;
+ if (FAILED(window->get_event(&window_event))) {
+ *error_out = STRING16(L"Could not access the IHtmlEventObj.");
+ return;
+ }
+
+ if (!window_event) {
+ *error_out = STRING16(L"The drag-and-drop event is invalid.");
+ return;
+ }
+
+ CComBSTR type;
+ if (FAILED(window_event->get_type(&type))) {
+ *error_out = STRING16(L"Could not access the event type.");
+ return;
+ }
+
+ if (type == STRING16(L"drop")) {
+ scoped_ptr<JsArray> file_array(
+ module_environment->js_runner_->NewArray());
+ if (!GetDroppedFiles(module_environment, file_array.get(), error_out)) {
+ return;
+ }
+ data_out->SetPropertyArray(STRING16(L"files"), file_array.get());
+ return;
+
+ } else if (type == STRING16(L"dragover") ||
+ type == STRING16(L"dragenter") ||
+ type == STRING16(L"dragleave")) {
+ // TODO(nigeltao): For all DnD events (including the non-drop events
+ // dragenter and dragover), we still should provide (1) MIME types,
+ // (2) file extensions, (3) total file size, and (4) file count.
+ return;
+
+ } else {
+ *error_out = STRING16(L"The drag-and-drop event is invalid.");
+ return;
+ }
+}
====
//depot/googleclient/gears/opensource/gears/desktop/drag_and_drop_utils_ie.h#1
-
c:\devel\srcwingears2/googleclient/gears/opensource/gears/desktop/drag_and_drop_utils_ie.h
====
# action=add type=text
--- /dev/null 1970-01-01 11:00:00.000000000 +1100
+++ googleclient/gears/opensource/gears/desktop/drag_and_drop_utils_ie.h
2008-11-27 17:43:38.000000000 +1100
@@ -0,0 +1,45 @@
+// Copyright 2008, Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// 2. 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.
+// 3. Neither the name of Google Inc. 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 AUTHOR ``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 AUTHOR 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 GEARS_DESKTOP_DRAG_AND_DROP_UTILS_IE_H__
+#define GEARS_DESKTOP_DRAG_AND_DROP_UTILS_IE_H__
+
+#include "gears/base/common/base_class.h"
+
+HRESULT GetHtmlDataTransfer(
+ IHTMLWindow2 *html_window_2,
+ CComPtr<IHTMLEventObj> &html_event_obj,
+ CComPtr<IHTMLDataTransfer> &html_data_transfer);
+
+bool GetDroppedFiles(ModuleEnvironment *module_environment,
+ JsArray *files_out,
+ std::string16 *error_out);
+
+void GetDragAndDropData(ModuleEnvironment *module_environment,
+ JsObject *event,
+ JsObject *data_out,
+ std::string16 *error_out);
+
+#endif // GEARS_DESKTOP_DRAG_AND_DROP_UTILS_IE_H__
==== //depot/googleclient/gears/opensource/gears/desktop/drop_target_ie.cc#13 -
c:\devel\srcwingears2/googleclient/gears/opensource/gears/desktop/drop_target_ie.cc
====
# action=edit type=text
--- googleclient/gears/opensource/gears/desktop/drop_target_ie.cc
2008-11-27 17:13:15.000000000 +1100
+++ googleclient/gears/opensource/gears/desktop/drop_target_ie.cc
2008-11-27 15:52:03.000000000 +1100
@@ -37,6 +37,7 @@
#include "gears/base/common/leak_counter.h"
#include "gears/base/common/string16.h"
#include "gears/base/ie/activex_utils.h"
+#include "gears/desktop/drag_and_drop_utils_ie.h"
#include "gears/desktop/file_dialog.h"
@@ -115,20 +116,6 @@
}
-HRESULT DropTarget::GetHtmlDataTransfer(
- CComPtr<IHTMLEventObj> &html_event_obj,
- CComPtr<IHTMLDataTransfer> &html_data_transfer)
-{
- HRESULT hr;
- hr = html_window_2_->get_event(&html_event_obj);
- if (FAILED(hr)) return hr;
- CComQIPtr<IHTMLEventObj2> html_event_obj_2(html_event_obj);
- if (!html_event_obj_2) return E_FAIL;
- hr = html_event_obj_2->get_dataTransfer(&html_data_transfer);
- return hr;
-}
-
-
HRESULT DropTarget::CancelEventBubble(
CComPtr<IHTMLEventObj> &html_event_obj,
CComPtr<IHTMLDataTransfer> &html_data_transfer)
@@ -150,7 +137,8 @@
ProvideDebugVisualFeedback(true);
CComPtr<IHTMLEventObj> html_event_obj;
CComPtr<IHTMLDataTransfer> html_data_transfer;
- HRESULT hr = GetHtmlDataTransfer(html_event_obj, html_data_transfer);
+ HRESULT hr = GetHtmlDataTransfer(
+ html_window_2_, html_event_obj, html_data_transfer);
if (FAILED(hr)) return hr;
CComPtr<IServiceProvider> service_provider;
@@ -206,7 +194,8 @@
will_accept_drop_ = false;
CComPtr<IHTMLEventObj> html_event_obj;
CComPtr<IHTMLDataTransfer> html_data_transfer;
- HRESULT hr = GetHtmlDataTransfer(html_event_obj, html_data_transfer);
+ HRESULT hr = GetHtmlDataTransfer(
+ html_window_2_, html_event_obj, html_data_transfer);
if (FAILED(hr)) return hr;
if (on_drag_over_.get()) {
@@ -237,7 +226,8 @@
will_accept_drop_ = false;
CComPtr<IHTMLEventObj> html_event_obj;
CComPtr<IHTMLDataTransfer> html_data_transfer;
- HRESULT hr = GetHtmlDataTransfer(html_event_obj, html_data_transfer);
+ HRESULT hr = GetHtmlDataTransfer(
+ html_window_2_, html_event_obj, html_data_transfer);
if (FAILED(hr)) return hr;
if (on_drag_leave_.get()) {
@@ -254,32 +244,6 @@
hr = CancelEventBubble(html_event_obj, html_data_transfer);
if (FAILED(hr)) return hr;
- return S_OK;
-}
-
-
-// This function overwrites buffer in-place.
-static HRESULT ResolveShortcut(TCHAR *buffer) {
- static CComPtr<IShellLink> link;
- if (!link && FAILED(link.CoCreateInstance(CLSID_ShellLink))) {
- return E_FAIL;
- }
-
- CComQIPtr<IPersistFile> file(link);
- if (!file) return E_FAIL;
-
- // Open the shortcut file, load its content.
- HRESULT hr = file->Load(buffer, STGM_READ);
- if (FAILED(hr)) return hr;
-
- // Resolve the target of the shortcut.
- hr = link->Resolve(NULL, SLR_NO_UI);
- if (FAILED(hr)) return hr;
-
- // Read the target path.
- hr = link->GetPath(buffer, MAX_PATH, 0, SLGP_UNCPRIORITY);
- if (FAILED(hr)) return hr;
-
return S_OK;
}
@@ -289,59 +253,12 @@
ProvideDebugVisualFeedback(false);
if (!will_accept_drop_) return S_OK;
will_accept_drop_ = false;
- CComPtr<IHTMLEventObj> html_event_obj;
- CComPtr<IHTMLDataTransfer> html_data_transfer;
- HRESULT hr = GetHtmlDataTransfer(html_event_obj, html_data_transfer);
- if (FAILED(hr)) return hr;
if (on_drop_.get()) {
- CComPtr<IServiceProvider> service_provider;
- hr = html_data_transfer->QueryInterface(&service_provider);
- if (FAILED(hr)) return hr;
- CComPtr<IDataObject> data_object;
- hr = service_provider->QueryService<IDataObject>(
- IID_IDataObject, &data_object);
- if (FAILED(hr)) return hr;
-
- FORMATETC desired_format_etc =
- { CF_HDROP, 0, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
- STGMEDIUM stg_medium;
- hr = data_object->GetData(&desired_format_etc, &stg_medium);
- if (FAILED(hr)) return hr;
-
- HDROP hdrop = static_cast<HDROP>(GlobalLock(stg_medium.hGlobal));
- if (hdrop == NULL) {
- ReleaseStgMedium(&stg_medium);
- return E_FAIL;
- }
-
- std::vector<std::string16> filenames;
- UINT num_files = DragQueryFile(hdrop, -1, 0, 0);
- TCHAR buffer[MAX_PATH + 1];
- for (UINT i = 0; i < num_files; i++) {
- DragQueryFile(hdrop, i, buffer, sizeof(buffer));
- SHFILEINFO sh_file_info;
- if (!SHGetFileInfo(buffer, 0, &sh_file_info, sizeof(sh_file_info),
- SHGFI_ATTRIBUTES) ||
- !(sh_file_info.dwAttributes & SFGAO_FILESYSTEM) ||
- (sh_file_info.dwAttributes & SFGAO_FOLDER)) {
- continue;
- }
- if ((sh_file_info.dwAttributes & SFGAO_LINK) &&
- FAILED(ResolveShortcut(buffer))) {
- continue;
- }
- filenames.push_back(std::string16(buffer));
- }
-
- GlobalUnlock(stg_medium.hGlobal);
- ReleaseStgMedium(&stg_medium);
-
std::string16 error;
scoped_ptr<JsArray> file_array(
module_environment_->js_runner_->NewArray());
- if (!FileDialog::FilesToJsObjectArray(
- filenames, module_environment_.get(), file_array.get(), &error)) {
+ if (!GetDroppedFiles(module_environment_.get(), file_array.get(), &error))
{
return E_FAIL;
}
==== //depot/googleclient/gears/opensource/gears/desktop/drop_target_ie.h#9 -
c:\devel\srcwingears2/googleclient/gears/opensource/gears/desktop/drop_target_ie.h
====
# action=edit type=text
--- googleclient/gears/opensource/gears/desktop/drop_target_ie.h
2008-11-13 12:01:20.000000000 +1100
+++ googleclient/gears/opensource/gears/desktop/drop_target_ie.h
2008-11-27 14:56:23.000000000 +1100
@@ -80,8 +80,6 @@
JsObject *options,
std::string16 *error_out);
- HRESULT GetHtmlDataTransfer(CComPtr<IHTMLEventObj> &html_event_obj,
- CComPtr<IHTMLDataTransfer> &html_data_transfer);
HRESULT CancelEventBubble(CComPtr<IHTMLEventObj> &html_event_obj,
CComPtr<IHTMLDataTransfer> &html_data_transfer);
====
//depot/googleclient/gears/opensource/gears/test/manual/drag_and_drop_fake_event_attack.html#2
-
c:\devel\srcwingears2/googleclient/gears/opensource/gears/test/manual/drag_and_drop_fake_event_attack.html
====
# action=edit type=text
---
googleclient/gears/opensource/gears/test/manual/drag_and_drop_fake_event_attack.html
2008-11-27 17:39:21.000000000 +1100
+++
googleclient/gears/opensource/gears/test/manual/drag_and_drop_fake_event_attack.html
2008-11-27 17:41:27.000000000 +1100
@@ -43,7 +43,7 @@
// we tryGetDragAndDropData that event, every 2 seconds.
var invalidEvent = fakeEvent;
-function handler(isDrop) {
+function handler(isDrop, isDragEnterOrDragOver) {
return function(evt) {
// We save the genuine nsIDOMEvent to a global variable, to again try and
// spoof the Gears API, this time with a genuine event after it has been
@@ -67,7 +67,7 @@
}
}
var s = '';
- if (data.files) {
+ if (data && data.files) {
for (i = 0; i < data.files.length; i++) {
var file = data.files[i];
s += '<b>' + file.name + '</b> has length <b>' +
@@ -75,11 +75,17 @@
}
}
document.getElementById('dropOutput').innerHTML = s;
- if (isFirefox) {
+ }
+ if (isFirefox) {
+ if (isDrop) {
evt.stopPropagation();
}
- }
- if (!isFirefox) {
+ } else if (isIE) {
+ if (isDragEnterOrDragOver) {
+ evt.returnValue = false;
+ evt.cancelBubble = true;
+ }
+ } else if (isSafari) {
evt.preventDefault();
}
};
@@ -90,17 +96,22 @@
if (isFirefox) {
// Firefox uses different event names than IE, WebKit, and HTML5.
// Specifically, dragexit instead of dragleave, and dragdrop for drop.
- document.addEventListener('dragenter', handler(false), false);
- document.addEventListener('dragover', handler(false), false);
- document.addEventListener('dragexit', handler(false), false);
- document.addEventListener('dragdrop', handler(true), false);
+ document.addEventListener('dragenter', handler(false, true), false);
+ document.addEventListener('dragover', handler(false, true), false);
+ document.addEventListener('dragexit', handler(false, false), false);
+ document.addEventListener('dragdrop', handler(true, false), false);
} else if (isSafari) {
- document.addEventListener('dragenter', handler(false), false);
- document.addEventListener('dragover', handler(false), false);
- document.addEventListener('dragleave', handler(false), false);
- document.addEventListener('drop', handler(true), false);
+ document.addEventListener('dragenter', handler(false, true), false);
+ document.addEventListener('dragover', handler(false, true), false);
+ document.addEventListener('dragleave', handler(false, false), false);
+ document.addEventListener('drop', handler(true, false), false);
+} else if (isIE) {
+ document.documentElement.attachEvent('ondragenter', handler(false, true));
+ document.documentElement.attachEvent('ondragover', handler(false, true));
+ document.documentElement.attachEvent('ondragleave', handler(false, false));
+ document.documentElement.attachEvent('ondrop', handler(true, false));
} else {
- // TODO(nigeltao): implement (and test) on IE and Chromium.
+ // TODO(nigeltao): implement (and test) on Chromium.
}
function tryGetDragAndDropData(evt) {
@@ -118,13 +129,21 @@
function tryDispatchEvent(evt) {
if (!evt) {
- evt = document.createEvent('MouseEvent');
- evt.initMouseEvent('mouseover', true, true, window,
- 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ if (isIE) {
+ evt = { 'type': 'onmouseover' };
+ } else {
+ evt = document.createEvent('MouseEvent');
+ evt.initMouseEvent('mouseover', true, true, window,
+ 0, 0, 0, 0, 0, false, false, false, false, 0, null);
+ }
}
isInManualDispatch = true;
try {
- document.dispatchEvent(evt);
+ if (isIE) {
+ document.fireEvent(evt.type);
+ } else {
+ document.dispatchEvent(evt);
+ }
} catch (ex) {
// Silently ignore exceptions.
}
@@ -135,6 +154,8 @@
// mouseover events dispatched by the tryDispatchEvent function above.
if (isFirefox || isSafari) {
document.addEventListener('mouseover', tryGetDragAndDropData, false);
+} else if (isIE) {
+ document.attachEvent('onmouseover', tryGetDragAndDropData);
}
window.setInterval(function() { tryGetDragAndDropData(invalidEvent); }, 2000);