Home | History | Annotate | Download | only in win
      1 /*
      2  * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1. Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  * 2. Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "DragData.h"
     28 
     29 #include "COMPtr.h"
     30 #include "ClipboardUtilitiesWin.h"
     31 #include "Frame.h"
     32 #include "DocumentFragment.h"
     33 #include "PlatformString.h"
     34 #include "Markup.h"
     35 #include "TextEncoding.h"
     36 #include <objidl.h>
     37 #include <shlwapi.h>
     38 #include <wininet.h>
     39 #include <wtf/Forward.h>
     40 #include <wtf/Hashmap.h>
     41 #include <wtf/PassRefPtr.h>
     42 #include <wtf/RefPtr.h>
     43 
     44 namespace WebCore {
     45 
     46 DragData::DragData(const DragDataMap& data, const IntPoint& clientPosition, const IntPoint& globalPosition,
     47     DragOperation sourceOperationMask, DragApplicationFlags flags)
     48     : m_clientPosition(clientPosition)
     49     , m_globalPosition(globalPosition)
     50     , m_platformDragData(0)
     51     , m_draggingSourceOperationMask(sourceOperationMask)
     52     , m_applicationFlags(flags)
     53     , m_dragDataMap(data)
     54 {
     55 }
     56 
     57 bool DragData::containsURL(Frame*, FilenameConversionPolicy filenamePolicy) const
     58 {
     59     if (m_platformDragData)
     60         return SUCCEEDED(m_platformDragData->QueryGetData(urlWFormat()))
     61             || SUCCEEDED(m_platformDragData->QueryGetData(urlFormat()))
     62             || (filenamePolicy == ConvertFilenames
     63                 && (SUCCEEDED(m_platformDragData->QueryGetData(filenameWFormat()))
     64                     || SUCCEEDED(m_platformDragData->QueryGetData(filenameFormat()))));
     65     return m_dragDataMap.contains(urlWFormat()->cfFormat) || m_dragDataMap.contains(urlFormat()->cfFormat)
     66         || (filenamePolicy == ConvertFilenames && (m_dragDataMap.contains(filenameWFormat()->cfFormat) || m_dragDataMap.contains(filenameFormat()->cfFormat)));
     67 }
     68 
     69 const DragDataMap& DragData::dragDataMap()
     70 {
     71     if (!m_dragDataMap.isEmpty() || !m_platformDragData)
     72         return m_dragDataMap;
     73     // Enumerate clipboard content and load it in the map.
     74     COMPtr<IEnumFORMATETC> itr;
     75 
     76     if (FAILED(m_platformDragData->EnumFormatEtc(DATADIR_GET, &itr)) || !itr)
     77         return m_dragDataMap;
     78 
     79     FORMATETC dataFormat;
     80     while (itr->Next(1, &dataFormat, 0) == S_OK) {
     81         Vector<String> dataStrings;
     82         getClipboardData(m_platformDragData, &dataFormat, dataStrings);
     83         if (!dataStrings.isEmpty())
     84             m_dragDataMap.set(dataFormat.cfFormat, dataStrings);
     85     }
     86     return m_dragDataMap;
     87 }
     88 
     89 String DragData::asURL(Frame*, FilenameConversionPolicy filenamePolicy, String* title) const
     90 {
     91     bool success;
     92     return (m_platformDragData) ? getURL(m_platformDragData, filenamePolicy, success, title) : getURL(&m_dragDataMap, filenamePolicy, title);
     93 }
     94 
     95 bool DragData::containsFiles() const
     96 {
     97     return (m_platformDragData) ? SUCCEEDED(m_platformDragData->QueryGetData(cfHDropFormat())) : m_dragDataMap.contains(cfHDropFormat()->cfFormat);
     98 }
     99 
    100 void DragData::asFilenames(Vector<String>& result) const
    101 {
    102     if (m_platformDragData) {
    103         WCHAR filename[MAX_PATH];
    104 
    105         STGMEDIUM medium;
    106         if (FAILED(m_platformDragData->GetData(cfHDropFormat(), &medium)))
    107             return;
    108 
    109         HDROP hdrop = (HDROP)GlobalLock(medium.hGlobal);
    110 
    111         if (!hdrop)
    112             return;
    113 
    114         const unsigned numFiles = DragQueryFileW(hdrop, 0xFFFFFFFF, 0, 0);
    115         for (unsigned i = 0; i < numFiles; i++) {
    116             if (!DragQueryFileW(hdrop, 0, filename, WTF_ARRAY_LENGTH(filename)))
    117                 continue;
    118             result.append((UChar*)filename);
    119         }
    120 
    121         // Free up memory from drag
    122         DragFinish(hdrop);
    123 
    124         GlobalUnlock(medium.hGlobal);
    125         return;
    126     }
    127     result = m_dragDataMap.get(cfHDropFormat()->cfFormat);
    128 }
    129 
    130 bool DragData::containsPlainText() const
    131 {
    132     if (m_platformDragData)
    133         return SUCCEEDED(m_platformDragData->QueryGetData(plainTextWFormat()))
    134             || SUCCEEDED(m_platformDragData->QueryGetData(plainTextFormat()));
    135     return m_dragDataMap.contains(plainTextWFormat()->cfFormat) || m_dragDataMap.contains(plainTextFormat()->cfFormat);
    136 }
    137 
    138 String DragData::asPlainText(Frame*) const
    139 {
    140     bool success;
    141     return (m_platformDragData) ? getPlainText(m_platformDragData, success) : getPlainText(&m_dragDataMap);
    142 }
    143 
    144 bool DragData::containsColor() const
    145 {
    146     return false;
    147 }
    148 
    149 bool DragData::canSmartReplace() const
    150 {
    151     if (m_platformDragData)
    152         return SUCCEEDED(m_platformDragData->QueryGetData(smartPasteFormat()));
    153     return m_dragDataMap.contains(smartPasteFormat()->cfFormat);
    154 }
    155 
    156 bool DragData::containsCompatibleContent() const
    157 {
    158     return containsPlainText() || containsURL(0)
    159         || ((m_platformDragData) ? (containsHTML(m_platformDragData) || containsFilenames(m_platformDragData))
    160             : (containsHTML(&m_dragDataMap) || containsFilenames(&m_dragDataMap)))
    161         || containsColor();
    162 }
    163 
    164 PassRefPtr<DocumentFragment> DragData::asFragment(Frame* frame, PassRefPtr<Range>, bool, bool&) const
    165 {
    166     /*
    167      * Order is richest format first. On OSX this is:
    168      * * Web Archive
    169      * * Filenames
    170      * * HTML
    171      * * RTF
    172      * * TIFF
    173      * * PICT
    174      */
    175 
    176     if (m_platformDragData) {
    177         if (containsFilenames(m_platformDragData)) {
    178             if (PassRefPtr<DocumentFragment> fragment = fragmentFromFilenames(frame->document(), m_platformDragData))
    179                 return fragment;
    180         }
    181 
    182         if (containsHTML(m_platformDragData)) {
    183             if (PassRefPtr<DocumentFragment> fragment = fragmentFromHTML(frame->document(), m_platformDragData))
    184                 return fragment;
    185         }
    186     } else {
    187         if (containsFilenames(&m_dragDataMap)) {
    188             if (PassRefPtr<DocumentFragment> fragment = fragmentFromFilenames(frame->document(), &m_dragDataMap))
    189                 return fragment;
    190         }
    191 
    192         if (containsHTML(&m_dragDataMap)) {
    193             if (PassRefPtr<DocumentFragment> fragment = fragmentFromHTML(frame->document(), &m_dragDataMap))
    194                 return fragment;
    195         }
    196     }
    197     return 0;
    198 }
    199 
    200 Color DragData::asColor() const
    201 {
    202     return Color();
    203 }
    204 
    205 }
    206