18e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project/*
25af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke * Copyright (C) 2007, 2009, 2010 Apple Inc. All rights reserved.
38e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
48e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * Redistribution and use in source and binary forms, with or without
58e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * modification, are permitted provided that the following conditions
68e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * are met:
78e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 1. Redistributions of source code must retain the above copyright
88e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer.
98e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * 2. Redistributions in binary form must reproduce the above copyright
108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    notice, this list of conditions and the following disclaimer in the
118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *    documentation and/or other materials provided with the distribution.
128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project *
138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project */
258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "config.h"
278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DragController.h"
288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
29231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#if ENABLE(DRAG_SUPPORT)
308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "CSSStyleDeclaration.h"
318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Clipboard.h"
328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ClipboardAccessPolicy.h"
335abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick#include "CachedResourceLoader.h"
348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Document.h"
358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DocumentFragment.h"
368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DragActions.h"
378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DragClient.h"
388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "DragData.h"
398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Editor.h"
408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "EditorClient.h"
418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Element.h"
428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "EventHandler.h"
438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FloatRect.h"
448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Frame.h"
458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameLoader.h"
468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "FrameView.h"
478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLAnchorElement.h"
488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLInputElement.h"
498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HTMLNames.h"
50231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "HitTestRequest.h"
518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "HitTestResult.h"
528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Image.h"
538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "MoveSelectionCommand.h"
548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Node.h"
558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Page.h"
56dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block#include "PlatformKeyboardEvent.h"
578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderFileUploadControl.h"
588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "RenderImage.h"
59545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch#include "RenderLayer.h"
60231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "RenderView.h"
618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ReplaceSelectionCommand.h"
628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "ResourceRequest.h"
638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "SelectionController.h"
648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Settings.h"
658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "Text.h"
66f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick#include "TextEvent.h"
678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "htmlediting.h"
688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include "markup.h"
69635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project#include <wtf/CurrentTime.h>
708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#include <wtf/RefPtr.h>
718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectnamespace WebCore {
738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic PlatformMouseEvent createMouseEvent(DragData* dragData)
758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
76dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    bool shiftKey, ctrlKey, altKey, metaKey;
77dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    shiftKey = ctrlKey = altKey = metaKey = false;
78dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    PlatformKeyboardEvent::getCurrentModifierState(shiftKey, ctrlKey, altKey, metaKey);
798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return PlatformMouseEvent(dragData->clientPosition(), dragData->globalPosition(),
80dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                              LeftButton, MouseEventMoved, 0, shiftKey, ctrlKey, altKey,
81dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block                              metaKey, currentTime());
828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
830bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDragController::DragController(Page* page, DragClient* client)
858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    : m_page(page)
868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_client(client)
875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_documentUnderMouse(0)
888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_dragInitiator(0)
898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_dragDestinationAction(DragDestinationActionNone)
908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_dragSourceAction(DragSourceActionNone)
918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_didInitiateDrag(false)
928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    , m_isHandlingDrag(false)
935f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    , m_sourceDragOperation(DragOperationNone)
948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDragController::~DragController()
980bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_client->dragControllerDestroyed();
1008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
10265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochstatic PassRefPtr<DocumentFragment> documentFragmentFromDragData(DragData* dragData, Frame* frame, RefPtr<Range> context,
1038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                                          bool allowPlainText, bool& chosePlainText)
1048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(dragData);
1068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    chosePlainText = false;
1078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Document* document = context->ownerDocument();
1098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(document);
1108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (document && dragData->containsCompatibleContent()) {
11165f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (PassRefPtr<DocumentFragment> fragment = dragData->asFragment(frame, context, allowPlainText, chosePlainText))
1128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return fragment;
1138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
11465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (dragData->containsURL(frame, DragData::DoNotConvertFilenames)) {
1158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            String title;
11665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch            String url = dragData->asURL(frame, DragData::DoNotConvertFilenames, &title);
1178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (!url.isEmpty()) {
118231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block                RefPtr<HTMLAnchorElement> anchor = HTMLAnchorElement::create(document);
1198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                anchor->setHref(url);
12021939df44de1705786c545cd1bf519d47250322dBen Murdoch                if (title.isEmpty()) {
12121939df44de1705786c545cd1bf519d47250322dBen Murdoch                    // Try the plain text first because the url might be normalized or escaped.
12221939df44de1705786c545cd1bf519d47250322dBen Murdoch                    if (dragData->containsPlainText())
12365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch                        title = dragData->asPlainText(frame);
12421939df44de1705786c545cd1bf519d47250322dBen Murdoch                    if (title.isEmpty())
12521939df44de1705786c545cd1bf519d47250322dBen Murdoch                        title = url;
12621939df44de1705786c545cd1bf519d47250322dBen Murdoch                }
1278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                RefPtr<Node> anchorText = document->createTextNode(title);
12821939df44de1705786c545cd1bf519d47250322dBen Murdoch                ExceptionCode ec;
1298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                anchor->appendChild(anchorText, ec);
1308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                RefPtr<DocumentFragment> fragment = document->createDocumentFragment();
1318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                fragment->appendChild(anchor, ec);
1328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project                return fragment.get();
1338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            }
1348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
1358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (allowPlainText && dragData->containsPlainText()) {
1378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        chosePlainText = true;
13865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        return createFragmentFromText(context.get(), dragData->asPlainText(frame)).get();
1398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return 0;
1428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
14465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdochbool DragController::dragIsMove(SelectionController* selection, DragData* dragData)
1458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
14665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    return m_documentUnderMouse == m_dragInitiator && selection->isContentEditable() && !isCopyKeyDown(dragData);
1478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1495f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian// FIXME: This method is poorly named.  We're just clearing the selection from the document this drag is exiting.
1508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid DragController::cancelDrag()
1518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_page->dragCaretController()->clear();
1538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid DragController::dragEnded()
1568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_dragInitiator = 0;
1580bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_didInitiateDrag = false;
1590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_page->dragCaretController()->clear();
1600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch}
1618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
1620bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochDragOperation DragController::dragEntered(DragData* dragData)
1638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return dragEnteredOrUpdated(dragData);
1658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochvoid DragController::dragExited(DragData* dragData)
1680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(dragData);
1708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Frame* mainFrame = m_page->mainFrame();
1710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (RefPtr<FrameView> v = mainFrame->view()) {
1735f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        ClipboardAccessPolicy policy = (!m_documentUnderMouse || m_documentUnderMouse->securityOrigin()->isLocal()) ? ClipboardReadable : ClipboardTypesReadable;
1740617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen        RefPtr<Clipboard> clipboard = Clipboard::create(policy, dragData, mainFrame);
1758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        clipboard->setSourceOperation(dragData->draggingSourceOperationMask());
1768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        mainFrame->eventHandler()->cancelDragAndDrop(createMouseEvent(dragData), clipboard.get());
1778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        clipboard->setAccessPolicy(ClipboardNumb);    // invalidate clipboard here for security
1788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
1795f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    mouseMovedIntoDocument(0);
1808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1815f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
1820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben MurdochDragOperation DragController::dragUpdated(DragData* dragData)
1838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
1848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return dragEnteredOrUpdated(dragData);
1858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
1860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
1878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool DragController::performDrag(DragData* dragData)
1880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
1898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(dragData);
1905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_documentUnderMouse = m_page->mainFrame()->documentAtPoint(dragData->clientPosition());
1918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (m_isHandlingDrag) {
1928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(m_dragDestinationAction & DragDestinationActionDHTML);
1938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_client->willPerformDragDestinationAction(DragDestinationActionDHTML, dragData);
1948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        RefPtr<Frame> mainFrame = m_page->mainFrame();
1958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (mainFrame->view()) {
1968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Sending an event can result in the destruction of the view and part.
1970617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen            RefPtr<Clipboard> clipboard = Clipboard::create(ClipboardReadable, dragData, mainFrame.get());
1988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            clipboard->setSourceOperation(dragData->draggingSourceOperationMask());
1998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            mainFrame->eventHandler()->performDragAndDrop(createMouseEvent(dragData), clipboard.get());
2008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            clipboard->setAccessPolicy(ClipboardNumb);    // invalidate clipboard here for security
2018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
2025f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_documentUnderMouse = 0;
2038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
2040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
2050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
206635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if ((m_dragDestinationAction & DragDestinationActionEdit) && concludeEditDrag(dragData)) {
2075f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        m_documentUnderMouse = 0;
2088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
2098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2115f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_documentUnderMouse = 0;
2128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (operationForLoad(dragData) == DragOperationNone)
2148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
2158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_client->willPerformDragDestinationAction(DragDestinationActionLoad, dragData);
21765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_page->mainFrame()->loader()->load(ResourceRequest(dragData->asURL(m_page->mainFrame())), false);
2188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
2198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2205f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2215f1ab04193ad0130ca8204aadaceae083aca9881Feng Qianvoid DragController::mouseMovedIntoDocument(Document* newDocument)
2225f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian{
2235f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (m_documentUnderMouse == newDocument)
2245f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        return;
2255f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2265f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    // If we were over another document clear the selection
2275f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (m_documentUnderMouse)
2285f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        cancelDrag();
2295f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_documentUnderMouse = newDocument;
2305f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian}
2315f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDragOperation DragController::dragEnteredOrUpdated(DragData* dragData)
2338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(dragData);
2355f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ASSERT(m_page->mainFrame()); // It is not possible in Mac WebKit to have a Page without a mainFrame()
2365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    mouseMovedIntoDocument(m_page->mainFrame()->documentAtPoint(dragData->clientPosition()));
2375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
2388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_dragDestinationAction = m_client->actionMaskForDrag(dragData);
2390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_dragDestinationAction == DragDestinationActionNone) {
2405f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        cancelDrag(); // FIXME: Why not call mouseMovedIntoDocument(0)?
2410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return DragOperationNone;
2428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
2430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    DragOperation operation = DragOperationNone;
2450bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    bool handledByDocument = tryDocumentDrag(dragData, m_dragDestinationAction, operation);
2460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!handledByDocument && (m_dragDestinationAction & DragDestinationActionLoad))
2470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return operationForLoad(dragData);
2488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return operation;
2498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic HTMLInputElement* asFileInput(Node* node)
2528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(node);
2540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // The button for a FILE input is a sub element with no set input type
2568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // In order to get around this problem we assume any non-FILE input element
2578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // is this internal button, and try querying the shadow parent node.
258f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (node->hasTagName(HTMLNames::inputTag) && node->isShadowRoot() && !static_cast<HTMLInputElement*>(node)->isFileUpload())
259cad810f21b803229eb11403f9209855525a25d57Steve Block        node = node->shadowHost();
2600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!node || !node->hasTagName(HTMLNames::inputTag))
2628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
2630bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
26468513a70bcd92384395513322f1b801e7bf9c729Steve Block    HTMLInputElement* inputElement = static_cast<HTMLInputElement*>(node);
26568513a70bcd92384395513322f1b801e7bf9c729Steve Block    if (!inputElement->isFileUpload())
26668513a70bcd92384395513322f1b801e7bf9c729Steve Block        return 0;
2670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
26868513a70bcd92384395513322f1b801e7bf9c729Steve Block    return inputElement;
2698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
2700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
271f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// This can return null if an empty document is loaded.
272231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic Element* elementUnderMouse(Document* documentUnderMouse, const IntPoint& p)
273231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
27468513a70bcd92384395513322f1b801e7bf9c729Steve Block    Frame* frame = documentUnderMouse->frame();
27568513a70bcd92384395513322f1b801e7bf9c729Steve Block    float zoomFactor = frame ? frame->pageZoomFactor() : 1;
276231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    IntPoint point = roundedIntPoint(FloatPoint(p.x() * zoomFactor, p.y() * zoomFactor));
277231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
278231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active);
279231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    HitTestResult result(point);
280231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    documentUnderMouse->renderView()->layer()->hitTest(request, result);
281231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
282231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Node* n = result.innerNode();
283231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    while (n && !n->isElementNode())
284231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        n = n->parentNode();
285231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (n)
286231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        n = n->shadowAncestorNode();
287231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
288231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return static_cast<Element*>(n);
289231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
290231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
2910bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool DragController::tryDocumentDrag(DragData* dragData, DragDestinationAction actionMask, DragOperation& operation)
2928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
2938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(dragData);
2940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
2955f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!m_documentUnderMouse)
2960bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return false;
2978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
2986b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner    if (m_dragInitiator && !m_documentUnderMouse->securityOrigin()->canReceiveDragData(m_dragInitiator->securityOrigin()))
2996b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner        return false;
3006b70adc33054f8aee8c54d0f460458a9df11b8a5Russell Brenner
3010bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    m_isHandlingDrag = false;
3020bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (actionMask & DragDestinationActionDHTML) {
3030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_isHandlingDrag = tryDHTMLDrag(dragData, operation);
3040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Do not continue if m_documentUnderMouse has been reset by tryDHTMLDrag.
3050bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // tryDHTMLDrag fires dragenter event. The event listener that listens
3060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // to this event may create a nested message loop (open a modal dialog),
3070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // which could process dragleave event and reset m_documentUnderMouse in
3080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // dragExited.
3090bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (!m_documentUnderMouse)
3100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return false;
3110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
3120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // It's unclear why this check is after tryDHTMLDrag.
3140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // We send drag events in tryDHTMLDrag and that may be the reason.
3155f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    RefPtr<FrameView> frameView = m_documentUnderMouse->view();
3168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!frameView)
3170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return false;
3180bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (m_isHandlingDrag) {
3200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        m_page->dragCaretController()->clear();
3210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return true;
3220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    } else if ((actionMask & DragDestinationActionEdit) && canProcessDrag(dragData)) {
3230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        if (dragData->containsColor()) {
3240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            operation = DragOperationGeneric;
3250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            return true;
3260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
3270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
328231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        IntPoint point = frameView->windowToContents(dragData->clientPosition());
32921939df44de1705786c545cd1bf519d47250322dBen Murdoch        Element* element = elementUnderMouse(m_documentUnderMouse.get(), point);
330f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        if (!element)
331f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch            return false;
3328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!asFileInput(element)) {
3335f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian            VisibleSelection dragCaret = m_documentUnderMouse->frame()->visiblePositionForPoint(point);
3348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_page->dragCaretController()->setSelection(dragCaret);
3358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
3365f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian
3375f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        Frame* innerFrame = element->document()->frame();
33865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        operation = dragIsMove(innerFrame->selection(), dragData) ? DragOperationMove : DragOperationCopy;
3390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return true;
3400bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
3410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // If we're not over an editable region, make sure we're clearing any prior drag cursor.
3428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_page->dragCaretController()->clear();
3430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return false;
3448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDragSourceAction DragController::delegateDragSourceAction(const IntPoint& windowPoint)
3470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
3488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_dragSourceAction = m_client->dragSourceActionMaskForPoint(windowPoint);
3498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return m_dragSourceAction;
3508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3510bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source ProjectDragOperation DragController::operationForLoad(DragData* dragData)
3538e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(dragData);
3555f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    Document* doc = m_page->mainFrame()->documentAtPoint(dragData->clientPosition());
3562bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (doc && (m_didInitiateDrag || doc->isPluginDocument() || doc->rendererIsEditable()))
3578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return DragOperationNone;
3588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return dragOperation(dragData);
3598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3618f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qianstatic bool setSelectionToDragCaret(Frame* frame, VisibleSelection& dragCaret, RefPtr<Range>& range, const IntPoint& point)
3628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    frame->selection()->setSelection(dragCaret);
3648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (frame->selection()->isNone()) {
3658e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dragCaret = frame->visiblePositionForPoint(point);
3668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        frame->selection()->setSelection(dragCaret);
3678f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        range = dragCaret.toNormalizedRange();
3688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
3698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return !frame->selection()->isNone() && frame->selection()->isContentEditable();
3708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
3718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
372f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrickbool DragController::dispatchTextInputEventFor(Frame* innerFrame, DragData* dragData)
373f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick{
3742bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(!m_page->dragCaretController()->isNone());
375f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    VisibleSelection dragCaret(m_page->dragCaretController()->selection());
37665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    String text = dragCaret.isContentRichlyEditable() ? "" : dragData->asPlainText(innerFrame);
377f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    Node* target = innerFrame->editor()->findEventTargetFrom(dragCaret);
378f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    ExceptionCode ec = 0;
379f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick    return target->dispatchEvent(TextEvent::createForDrop(innerFrame->domWindow(), text), ec);
380f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick}
381f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
382635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Projectbool DragController::concludeEditDrag(DragData* dragData)
3838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
3848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(dragData);
3858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(!m_isHandlingDrag);
3860bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3875f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!m_documentUnderMouse)
3888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
3890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
3905f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    IntPoint point = m_documentUnderMouse->view()->windowToContents(dragData->clientPosition());
39121939df44de1705786c545cd1bf519d47250322dBen Murdoch    Element* element = elementUnderMouse(m_documentUnderMouse.get(), point);
392f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (!element)
393f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return false;
3948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Frame* innerFrame = element->ownerDocument()->frame();
3950bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(innerFrame);
3968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
3972bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!m_page->dragCaretController()->isNone() && !dispatchTextInputEventFor(innerFrame, dragData))
398f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick        return true;
399f486d19d62f1bc33246748b14b14a9dfa617b57fIain Merrick
4008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (dragData->containsColor()) {
4018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Color color = dragData->asColor();
4028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!color.isValid())
4038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
4048f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian        RefPtr<Range> innerRange = innerFrame->selection()->toNormalizedRange();
4055f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian        RefPtr<CSSStyleDeclaration> style = m_documentUnderMouse->createCSSStyleDeclaration();
4068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ExceptionCode ec;
40781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        style->setProperty("color", color.serialized(), ec);
4088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!innerFrame->editor()->shouldApplyStyle(style.get(), innerRange.get()))
4098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
4108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData);
4118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        innerFrame->editor()->applyStyle(style.get(), EditActionSetColor);
4128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
4138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4140bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_page->dragController()->canProcessDrag(dragData)) {
4168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_page->dragCaretController()->clear();
4178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4190bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (HTMLInputElement* fileInput = asFileInput(element)) {
4215af96e2c7b73ebc627c6894727826a7576d31758Leon Clarke        if (fileInput->disabled())
4228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
4230bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!dragData->containsFiles())
4258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
4260bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Vector<String> filenames;
4288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dragData->asFilenames(filenames);
4298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (filenames.isEmpty())
4308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
4310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4320bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // Ugly. For security none of the APIs available to us can set the input value
4330bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // on file inputs. Even forcing a change in HTMLInputElement doesn't work as
4340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // RenderFileUploadControl clears the file when doing updateFromElement().
4350bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        RenderFileUploadControl* renderer = toRenderFileUploadControl(fileInput->renderer());
4368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!renderer)
4378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
4380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        renderer->receiveDroppedFiles(filenames);
4408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
4418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4438f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    VisibleSelection dragCaret(m_page->dragCaretController()->selection());
4448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_page->dragCaretController()->clear();
4458f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    RefPtr<Range> range = dragCaret.toNormalizedRange();
4460bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // For range to be null a WebKit client must have done something bad while
4488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // manually controlling drag behaviour
4490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!range)
4508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
4515abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    CachedResourceLoader* cachedResourceLoader = range->ownerDocument()->cachedResourceLoader();
4525abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    cachedResourceLoader->setAllowStaleResources(true);
45365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    if (dragIsMove(innerFrame->selection(), dragData) || dragCaret.isContentRichlyEditable()) {
4548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        bool chosePlainText = false;
45565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        RefPtr<DocumentFragment> fragment = documentFragmentFromDragData(dragData, innerFrame, range, true, chosePlainText);
4568e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!fragment || !innerFrame->editor()->shouldInsertFragment(fragment, range, EditorInsertActionDropped)) {
4575abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            cachedResourceLoader->setAllowStaleResources(false);
4588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
4598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4600bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData);
46265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        if (dragIsMove(innerFrame->selection(), dragData)) {
463dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            // NSTextView behavior is to always smart delete on moving a selection,
464dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            // but only to smart insert if the selection granularity is word granularity.
465dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            bool smartDelete = innerFrame->editor()->smartInsertDeleteEnabled();
46668513a70bcd92384395513322f1b801e7bf9c729Steve Block            bool smartInsert = smartDelete && innerFrame->selection()->granularity() == WordGranularity && dragData->canSmartReplace();
467dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block            applyCommand(MoveSelectionCommand::create(fragment, dragCaret.base(), smartInsert, smartDelete));
4688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        } else {
46981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (setSelectionToDragCaret(innerFrame, dragCaret, range, point)) {
47081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                ReplaceSelectionCommand::CommandOptions options = ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::PreventNesting;
47181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                if (dragData->canSmartReplace())
47281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    options |= ReplaceSelectionCommand::SmartReplace;
47381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                if (chosePlainText)
47481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                    options |= ReplaceSelectionCommand::MatchStyle;
47581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch                applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse.get(), fragment, options));
47681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            }
4770bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
4788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
47965f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch        String text = dragData->asPlainText(innerFrame);
4808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (text.isEmpty() || !innerFrame->editor()->shouldInsertText(text, range.get(), EditorInsertActionDropped)) {
4815abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick            cachedResourceLoader->setAllowStaleResources(false);
4828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            return false;
4838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
4840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_client->willPerformDragDestinationAction(DragDestinationActionEdit, dragData);
4868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (setSelectionToDragCaret(innerFrame, dragCaret, range, point))
48781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            applyCommand(ReplaceSelectionCommand::create(m_documentUnderMouse.get(), createFragmentFromText(range.get(), text),  ReplaceSelectionCommand::SelectReplacement | ReplaceSelectionCommand::MatchStyle | ReplaceSelectionCommand::PreventNesting));
4888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
4895abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick    cachedResourceLoader->setAllowStaleResources(false);
4908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
4928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
4930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
4940bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool DragController::canProcessDrag(DragData* dragData)
4958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
4968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(dragData);
4978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
4988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!dragData->containsCompatibleContent())
4998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
5000bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IntPoint point = m_page->mainFrame()->view()->windowToContents(dragData->clientPosition());
5028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    HitTestResult result = HitTestResult(point);
5038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!m_page->mainFrame()->contentRenderer())
5048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
5058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    result = m_page->mainFrame()->eventHandler()->hitTestResultAtPoint(point, true);
5070bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!result.innerNonSharedNode())
5098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
5100bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (dragData->containsFiles() && asFileInput(result.innerNonSharedNode()))
5128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
5130bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5142bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (!result.innerNonSharedNode()->rendererIsEditable())
5158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
5160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5175f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (m_didInitiateDrag && m_documentUnderMouse == m_dragInitiator && result.isSelected())
5188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
5198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return true;
5218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
523dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockstatic DragOperation defaultOperationForDrag(DragOperation srcOpMask)
524dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block{
525dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // This is designed to match IE's operation fallback for the case where
526dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // the page calls preventDefault() in a drag event but doesn't set dropEffect.
527dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (srcOpMask == DragOperationEvery)
528dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return DragOperationCopy;
529dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (srcOpMask == DragOperationNone)
530dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return DragOperationNone;
531dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (srcOpMask & DragOperationMove || srcOpMask & DragOperationGeneric)
532dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return DragOperationMove;
533dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (srcOpMask & DragOperationCopy)
534dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return DragOperationCopy;
535dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (srcOpMask & DragOperationLink)
536dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        return DragOperationLink;
537dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
538dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    // FIXME: Does IE really return "generic" even if no operations were allowed by the source?
539dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    return DragOperationGeneric;
540dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block}
541dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block
5420bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdochbool DragController::tryDHTMLDrag(DragData* dragData, DragOperation& operation)
5430bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
5448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(dragData);
5455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ASSERT(m_documentUnderMouse);
5465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    RefPtr<Frame> mainFrame = m_page->mainFrame();
5475f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    RefPtr<FrameView> viewProtector = mainFrame->view();
5488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!viewProtector)
5490bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return false;
5500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5515f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    ClipboardAccessPolicy policy = m_documentUnderMouse->securityOrigin()->isLocal() ? ClipboardReadable : ClipboardTypesReadable;
5520617145a89917ae7735fe1c9538688ab9a577df5Kristian Monsen    RefPtr<Clipboard> clipboard = Clipboard::create(policy, dragData, mainFrame.get());
5530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    DragOperation srcOpMask = dragData->draggingSourceOperationMask();
5540bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    clipboard->setSourceOperation(srcOpMask);
5558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    PlatformMouseEvent event = createMouseEvent(dragData);
5570bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!mainFrame->eventHandler()->updateDragAndDrop(event, clipboard.get())) {
5588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        clipboard->setAccessPolicy(ClipboardNumb);    // invalidate clipboard here for security
5590bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        return false;
5608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
5610bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
562d0825bca7fe65beaee391d30da42e937db621564Steve Block    operation = clipboard->destinationOperation();
563dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (clipboard->dropEffectIsUninitialized())
564dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        operation = defaultOperationForDrag(srcOpMask);
565dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    else if (!(srcOpMask & operation)) {
5660bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // The element picked an operation which is not supported by the source
5670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        operation = DragOperationNone;
5680bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    }
5690bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
5700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    clipboard->setAccessPolicy(ClipboardNumb);    // invalidate clipboard here for security
5710bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    return true;
5728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
5738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
574dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Blockbool DragController::mayStartDragAtEventLocation(const Frame* frame, const IntPoint& framePos, Node* node)
5758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
5768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(frame);
5778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(frame->settings());
5788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!frame->view() || !frame->contentRenderer())
5808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
5818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    HitTestResult mouseDownTarget = HitTestResult(framePos);
5838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    mouseDownTarget = frame->eventHandler()->hitTestResultAtPoint(framePos, true);
585dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block    if (node)
586dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        mouseDownTarget.setInnerNonSharedNode(node);
5878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (mouseDownTarget.image()
5898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        && !mouseDownTarget.absoluteImageURL().isEmpty()
5908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        && frame->settings()->loadsImagesAutomatically()
5918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        && m_dragSourceAction & DragSourceActionImage)
5928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
5938e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
5948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!mouseDownTarget.absoluteLinkURL().isEmpty()
5958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        && m_dragSourceAction & DragSourceActionLink
596dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        && mouseDownTarget.isLiveLink()
597dcc8cf2e65d1aa555cce12431a16547e66b469eeSteve Block        && mouseDownTarget.URLElement()->renderer() && mouseDownTarget.URLElement()->renderer()->style()->userDrag() != DRAG_NONE)
5988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
5998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (mouseDownTarget.isSelected()
6018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        && m_dragSourceAction & DragSourceActionSelection)
6028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return true;
6038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
6048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return false;
6058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic CachedImage* getCachedImage(Element* element)
6088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(element);
6108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RenderObject* renderer = element->renderer();
6110bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (!renderer || !renderer->isImage())
6128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return 0;
6138f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian    RenderImage* image = toRenderImage(renderer);
6148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return image->cachedImage();
6158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6160bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic Image* getImage(Element* element)
6188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(element);
620692e5dbf12901edacf14812a6fae25462920af42Steve Block    CachedImage* cachedImage = getCachedImage(element);
621692e5dbf12901edacf14812a6fae25462920af42Steve Block    return (cachedImage && !cachedImage->errorOccurred()) ?
622692e5dbf12901edacf14812a6fae25462920af42Steve Block        cachedImage->image() : 0;
6238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6240bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic void prepareClipboardForImageDrag(Frame* src, Clipboard* clipboard, Element* node, const KURL& linkURL, const KURL& imageURL, const String& label)
6268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Range> range = src->document()->createRange();
6288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ExceptionCode ec = 0;
6298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    range->selectNode(node, ec);
6300bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    ASSERT(!ec);
6310bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    src->selection()->setSelection(VisibleSelection(range.get(), DOWNSTREAM));
6328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    clipboard->declareAndWriteDragImage(node, !linkURL.isEmpty() ? linkURL : imageURL, label, src);
6338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6340bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic IntPoint dragLocForDHTMLDrag(const IntPoint& mouseDraggedPoint, const IntPoint& dragOrigin, const IntPoint& dragImageOffset, bool isLinkImage)
6368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
6378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // dragImageOffset is the cursor position relative to the lower-left corner of the image.
6380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch#if PLATFORM(MAC)
6390bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    // We add in the Y dimension because we are a flipped view, so adding moves the image down.
6408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const int yOffset = dragImageOffset.y();
6418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
6428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    const int yOffset = -dragImageOffset.y();
6438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
6440bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (isLinkImage)
6468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return IntPoint(mouseDraggedPoint.x() - dragImageOffset.x(), mouseDraggedPoint.y() + yOffset);
6470bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return IntPoint(dragOrigin.x() - dragImageOffset.x(), dragOrigin.y() + yOffset);
6498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6500bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectstatic IntPoint dragLocForSelectionDrag(Frame* src)
6528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
65368513a70bcd92384395513322f1b801e7bf9c729Steve Block    IntRect draggingRect = enclosingIntRect(src->selection()->bounds());
6542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int xpos = draggingRect.maxX();
6558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    xpos = draggingRect.x() < xpos ? draggingRect.x() : xpos;
6562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    int ypos = draggingRect.maxY();
6578e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if PLATFORM(MAC)
6588e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Deal with flipped coordinates on Mac
6598e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ypos = draggingRect.y() > ypos ? draggingRect.y() : ypos;
6608e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#else
6618e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ypos = draggingRect.y() < ypos ? draggingRect.y() : ypos;
6628e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
6638e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return IntPoint(xpos, ypos);
6648e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
6650bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectbool DragController::startDrag(Frame* src, Clipboard* clipboard, DragOperation srcOp, const PlatformMouseEvent& dragEvent, const IntPoint& dragOrigin, bool isDHTMLDrag)
6670bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch{
6688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(src);
6698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    ASSERT(clipboard);
6700bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!src->view() || !src->contentRenderer())
6728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return false;
6730bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    HitTestResult dragSource = HitTestResult(dragOrigin);
6758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    dragSource = src->eventHandler()->hitTestResultAtPoint(dragOrigin, true);
6768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    KURL linkURL = dragSource.absoluteLinkURL();
6778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    KURL imageURL = dragSource.absoluteImageURL();
6788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool isSelected = dragSource.isSelected();
6790bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IntPoint mouseDraggedPoint = src->view()->windowToContents(dragEvent.pos());
6810bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6828e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_draggingImageURL = KURL();
6835f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    m_sourceDragOperation = srcOp;
6840bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    DragImageRef dragImage = 0;
6868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IntPoint dragLoc(0, 0);
6878e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IntPoint dragImageOffset(0, 0);
6880bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6890bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    if (isDHTMLDrag)
6908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dragImage = clipboard->createDragImage(dragImageOffset);
691231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    else {
692231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // This drag operation is not a DHTML drag and may go outside the WebView.
693231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // We provide a default set of allowed drag operations that follows from:
694231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // http://trac.webkit.org/browser/trunk/WebKit/mac/WebView/WebHTMLView.mm?rev=48526#L3430
695231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        m_sourceDragOperation = (DragOperation)(DragOperationGeneric | DragOperationCopy);
696231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
6970bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
6988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // We allow DHTML/JS to set the drag image, even if its a link, image or text we're dragging.
6998e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // This is in the spirit of the IE API, which allows overriding of pasteboard data and DragOp.
7008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (dragImage) {
7018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dragLoc = dragLocForDHTMLDrag(mouseDraggedPoint, dragOrigin, dragImageOffset, !linkURL.isEmpty());
7028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_dragOffset = dragImageOffset;
7038e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7040bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
7058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    bool startedDrag = true; // optimism - we almost always manage to start the drag
7060bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
7078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Node* node = dragSource.innerNonSharedNode();
7080bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
709635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    Image* image = getImage(static_cast<Element*>(node));
710635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    if (!imageURL.isEmpty() && node && node->isElementNode() && image
7118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            && (m_dragSourceAction & DragSourceActionImage)) {
7120bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        // We shouldn't be starting a drag for an image that can't provide an extension.
713635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        // This is an early detection for problems encountered later upon drop.
714635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project        ASSERT(!image->filenameExtension().isEmpty());
7158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        Element* element = static_cast<Element*>(node);
7168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!clipboard->hasData()) {
7170bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch            m_draggingImageURL = imageURL;
7188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            prepareClipboardForImageDrag(src, clipboard, element, linkURL, imageURL, dragSource.altDisplayString());
7198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
7200bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
7218e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_client->willPerformDragSourceAction(DragSourceActionImage, dragOrigin, clipboard);
7220bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
7238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!dragImage) {
7248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            IntRect imageRect = dragSource.imageRect();
7258e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            imageRect.setLocation(m_page->mainFrame()->view()->windowToContents(src->view()->contentsToWindow(imageRect.location())));
7268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            doImageDrag(element, dragOrigin, dragSource.imageRect(), clipboard, src, m_dragOffset);
7270bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        } else
7288e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // DHTML defined drag image
7298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
7308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (!linkURL.isEmpty() && (m_dragSourceAction & DragSourceActionLink)) {
7328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!clipboard->hasData())
7338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // Simplify whitespace so the title put on the clipboard resembles what the user sees
7348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // on the web page. This includes replacing newlines with spaces.
7358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            clipboard->writeURL(linkURL, dragSource.textContent().simplifyWhiteSpace(), src);
7368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (src->selection()->isCaret() && src->selection()->isContentEditable()) {
7388e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // a user can initiate a drag on a link without having any text
7398e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // selected.  In this case, we should expand the selection to
7408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            // the enclosing anchor element
7418e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            Position pos = src->selection()->base();
7428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            Node* node = enclosingAnchorElement(pos);
7438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            if (node)
7448f72e70a9fd78eec56623b3a62e68f16b7b27e28Feng Qian                src->selection()->setSelection(VisibleSelection::selectionFromContentsOfNode(node));
7458e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
7468e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project
7478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_client->willPerformDragSourceAction(DragSourceActionLink, dragOrigin, clipboard);
7488e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!dragImage) {
7492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block            dragImage = createDragImageForLink(linkURL, dragSource.textContent(), src);
7508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            IntSize size = dragImageSize(dragImage);
7518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_dragOffset = IntPoint(-size.width() / 2, -LinkDragBorderInset);
7528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            dragLoc = IntPoint(mouseDraggedPoint.x() + m_dragOffset.x(), mouseDraggedPoint.y() + m_dragOffset.y());
7530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch        }
7548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        doSystemDrag(dragImage, dragLoc, mouseDraggedPoint, clipboard, src, true);
7558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (isSelected && (m_dragSourceAction & DragSourceActionSelection)) {
7568a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        if (!clipboard->hasData()) {
75781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            if (isNodeInTextFormControl(src->selection()->start().deprecatedNode()))
7585abb8606fa57c3ebfc8b3c3dbc3fa4a25d2ae306Iain Merrick                clipboard->writePlainText(src->editor()->selectedText());
7598a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            else {
7608a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block                RefPtr<Range> selectionRange = src->selection()->toNormalizedRange();
7618a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block                ASSERT(selectionRange);
7628a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block
7638a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block                clipboard->writeRange(selectionRange.get(), src);
7648a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block            }
7658a0914b749bbe7da7768e07a7db5c6d4bb09472bSteve Block        }
7668e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_client->willPerformDragSourceAction(DragSourceActionSelection, dragOrigin, clipboard);
7678e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (!dragImage) {
7688e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            dragImage = createDragImageForSelection(src);
7698e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            dragLoc = dragLocForSelectionDrag(src);
7708e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            m_dragOffset = IntPoint((int)(dragOrigin.x() - dragLoc.x()), (int)(dragOrigin.y() - dragLoc.y()));
7718e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        }
7728e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
7738e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else if (isDHTMLDrag) {
7748e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        ASSERT(m_dragSourceAction & DragSourceActionDHTML);
7758e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        m_client->willPerformDragSourceAction(DragSourceActionDHTML, dragOrigin, clipboard);
7768e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        doSystemDrag(dragImage, dragLoc, dragOrigin, clipboard, src, false);
7778e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
7788e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Only way I know to get here is if to get here is if the original element clicked on in the mousedown is no longer
7798e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // under the mousedown point, so linkURL, imageURL and isSelected are all false/empty.
7808e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        startedDrag = false;
7818e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
7820bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
7838e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (dragImage)
7848e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        deleteDragImage(dragImage);
7858e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    return startedDrag;
7868e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
787635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project
7888e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid DragController::doImageDrag(Element* element, const IntPoint& dragOrigin, const IntRect& rect, Clipboard* clipboard, Frame* frame, IntPoint& dragImageOffset)
7898e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
7908e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IntPoint mouseDownPoint = dragOrigin;
7918e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    DragImageRef dragImage;
7928e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IntPoint origin;
7930bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
7948e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    Image* image = getImage(element);
7958e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (image && image->size().height() * image->size().width() <= MaxOriginalImageArea
7968e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        && (dragImage = createDragImageFromImage(image))) {
7978e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        IntSize originalSize = rect.size();
7988e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        origin = rect.location();
7990bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8008e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dragImage = fitDragImageToMaxSize(dragImage, rect.size(), maxDragImageSize());
8018e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dragImage = dissolveDragImageToFraction(dragImage, DragImageAlpha);
8028e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        IntSize newSize = dragImageSize(dragImage);
8030bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8048e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        // Properly orient the drag image and orient it differently if it's smaller than the original
8058e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        float scale = newSize.width() / (float)originalSize.width();
8068e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        float dx = origin.x() - mouseDownPoint.x();
8078e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dx *= scale;
8088e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        origin.setX((int)(dx + 0.5));
8098e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#if PLATFORM(MAC)
8108e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        //Compensate for accursed flipped coordinates in cocoa
8118e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        origin.setY(origin.y() + originalSize.height());
8128e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project#endif
8138e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        float dy = origin.y() - mouseDownPoint.y();
8148e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dy *= scale;
8158e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        origin.setY((int)(dy + 0.5));
8168e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    } else {
8178e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        dragImage = createDragImageIconForCachedImage(getCachedImage(element));
8188e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        if (dragImage)
8198e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project            origin = IntPoint(DragIconRightInset - dragImageSize(dragImage).width(), DragIconBottomInset);
8208e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    }
8210bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8228e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    dragImageOffset.setX(mouseDownPoint.x() + origin.x());
8238e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    dragImageOffset.setY(mouseDownPoint.y() + origin.y());
8248e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    doSystemDrag(dragImage, dragImageOffset, dragOrigin, clipboard, frame, false);
8250bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8268e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    deleteDragImage(dragImage);
8278e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8280bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8298e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid DragController::doSystemDrag(DragImageRef image, const IntPoint& dragLoc, const IntPoint& eventPos, Clipboard* clipboard, Frame* frame, bool forLink)
8308e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8318e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_didInitiateDrag = true;
8328e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_dragInitiator = frame->document();
8338e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    // Protect this frame and view, as a load may occur mid drag and attempt to unload this frame
8348e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<Frame> frameProtector = m_page->mainFrame();
8358e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    RefPtr<FrameView> viewProtector = frameProtector->view();
8368e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_client->startDrag(image, viewProtector->windowToContents(frame->view()->contentsToWindow(dragLoc)),
8378e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        viewProtector->windowToContents(frame->view()->contentsToWindow(eventPos)), clipboard, frameProtector.get(), forLink);
8380bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
839635860845790a19bf50bbc51ba8fb66a96dde068The Android Open Source Project    cleanupAfterSystemDrag();
8408e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8410bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8428e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project// Manual drag caret manipulation
8438e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Projectvoid DragController::placeDragCaret(const IntPoint& windowPoint)
8448e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project{
8455f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    mouseMovedIntoDocument(m_page->mainFrame()->documentAtPoint(windowPoint));
8465f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    if (!m_documentUnderMouse)
8478e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
8485f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian    Frame* frame = m_documentUnderMouse->frame();
8498e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    FrameView* frameView = frame->view();
8508e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    if (!frameView)
8518e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project        return;
8528e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    IntPoint framePoint = frameView->windowToContents(windowPoint);
8530bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch    VisibleSelection dragCaret(frame->visiblePositionForPoint(framePoint));
8548e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project    m_page->dragCaretController()->setSelection(dragCaret);
8558e35f3cfc7fba1d1c829dc557ebad6409cbe16a2The Android Open Source Project}
8560bf48ef3be53ddaa52bbead65dfd75bf90e7a2b5Ben Murdoch
8575f1ab04193ad0130ca8204aadaceae083aca9881Feng Qian} // namespace WebCore
858231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
859231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#endif // ENABLE(DRAG_SUPPORT)
860