WebCore:
authoradele@apple.com <adele@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 31 Oct 2008 23:25:48 +0000 (23:25 +0000)
committeradele@apple.com <adele@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 31 Oct 2008 23:25:48 +0000 (23:25 +0000)
2008-10-31  Adele Peterson  <adele@apple.com>

        Reviewed by Darin Adler.

        WebCore Windows part of fix for <rdar://problem/5839256> FILE CONTROL: multi-file upload.
        https://bugs.webkit.org/show_bug.cgi?id=22008

        * platform/FileChooser.cpp: (WebCore::FileChooser::chooseIcon):
        Rename newIconForFile and newIconForFiles to createIconForFile and createIconForFiles.
        * platform/graphics/Icon.h: ditto.
        * platform/graphics/gtk/IconGtk.cpp:
        (WebCore::Icon::createIconForFile): ditto.
        (WebCore::Icon::createIconForFiles): ditto.
        * platform/graphics/mac/IconMac.mm:
        (WebCore::Icon::createIconForFile): ditto.
        (WebCore::Icon::createIconForFiles): ditto.
        * platform/graphics/qt/IconQt.cpp:
        (WebCore::Icon::createIconForFile): ditto.
        (WebCore::Icon::createIconForFiles): ditto.
        * platform/wx/TemporaryLinkStubs.cpp:
        (Icon::createIconForFile): ditto.
        (Icon::createIconForFiles): ditto.
        * platform/graphics/win/IconWin.cpp:
        (WebCore::Icon::createIconForFile): ditto.
        (WebCore::Icon::createIconForFiles): Add creation of an icon for multiple files.

        * rendering/RenderThemeWin.cpp: (WebCore::RenderThemeWin::paintSearchFieldResultsDecoration):
        Improve icon creation code to match new code in Icon::createIconForFiles

WebKit/win:

2008-10-31  Adele Peterson  <adele@apple.com>

        Reviewed by Darin Adler.

        WebKit Windows part of fix for <rdar://problem/5839256> FILE CONTROL: multi-file upload.
        https://bugs.webkit.org/show_bug.cgi?id=22008

        * WebCoreSupport/WebChromeClient.cpp: (WebChromeClient::runOpenPanel):
        Add support for mulitple file selection.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@38057 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/platform/FileChooser.cpp
WebCore/platform/graphics/Icon.h
WebCore/platform/graphics/gtk/IconGtk.cpp
WebCore/platform/graphics/mac/IconMac.mm
WebCore/platform/graphics/qt/IconQt.cpp
WebCore/platform/graphics/win/IconWin.cpp
WebCore/platform/wx/TemporaryLinkStubs.cpp
WebCore/rendering/RenderThemeWin.cpp
WebKit/win/ChangeLog
WebKit/win/WebCoreSupport/WebChromeClient.cpp

index a66de10..cac847e 100644 (file)
@@ -1,3 +1,32 @@
+2008-10-31  Adele Peterson  <adele@apple.com>
+
+        Reviewed by Darin Adler.
+
+        WebCore Windows part of fix for <rdar://problem/5839256> FILE CONTROL: multi-file upload.
+        https://bugs.webkit.org/show_bug.cgi?id=22008
+
+        * platform/FileChooser.cpp: (WebCore::FileChooser::chooseIcon): 
+        Rename newIconForFile and newIconForFiles to createIconForFile and createIconForFiles.
+        * platform/graphics/Icon.h: ditto.
+        * platform/graphics/gtk/IconGtk.cpp:
+        (WebCore::Icon::createIconForFile): ditto.
+        (WebCore::Icon::createIconForFiles): ditto.
+        * platform/graphics/mac/IconMac.mm:
+        (WebCore::Icon::createIconForFile): ditto.
+        (WebCore::Icon::createIconForFiles): ditto.
+        * platform/graphics/qt/IconQt.cpp:
+        (WebCore::Icon::createIconForFile): ditto.
+        (WebCore::Icon::createIconForFiles): ditto.
+        * platform/wx/TemporaryLinkStubs.cpp:
+        (Icon::createIconForFile): ditto.
+        (Icon::createIconForFiles): ditto.
+        * platform/graphics/win/IconWin.cpp:
+        (WebCore::Icon::createIconForFile): ditto.
+        (WebCore::Icon::createIconForFiles): Add creation of an icon for multiple files.
+
+        * rendering/RenderThemeWin.cpp: (WebCore::RenderThemeWin::paintSearchFieldResultsDecoration):        
+        Improve icon creation code to match new code in Icon::createIconForFiles
+        
 2008-10-31  Timothy Hatcher  <timothy@apple.com>
 
         Add manual tests that check breakpoints on a blockless body of "for" loops.
index 128027a..1aeefb9 100644 (file)
@@ -80,14 +80,14 @@ void FileChooser::chooseFiles(const Vector<String>& filenames)
 
 PassRefPtr<Icon> FileChooser::chooseIcon(const String& filename)
 {
-    return Icon::newIconForFile(filename);
+    return Icon::createIconForFile(filename);
 }
 
 PassRefPtr<Icon> FileChooser::chooseIcon(Vector<String> filenames)
 {
     if (filenames.size() == 1)
-        return Icon::newIconForFile(filenames[0]);
-    return Icon::newIconForFiles(filenames);
+        return Icon::createIconForFile(filenames[0]);
+    return Icon::createIconForFiles(filenames);
 }
 
 }
index 65d0135..444c67c 100644 (file)
@@ -51,8 +51,8 @@ class String;
     
 class Icon : public RefCounted<Icon> {
 public:
-    static PassRefPtr<Icon> newIconForFile(const String& filename);
-    static PassRefPtr<Icon> newIconForFiles(const Vector<String>& filenames);
+    static PassRefPtr<Icon> createIconForFile(const String& filename);
+    static PassRefPtr<Icon> createIconForFiles(const Vector<String>& filenames);
 
     ~Icon();
 
index 1b1c3fc..d8b38a0 100644 (file)
@@ -88,7 +88,7 @@ static String lookupIconName(String MIMEType)
     return GTK_STOCK_FILE;
 }
 
-PassRefPtr<Icon> Icon::newIconForFile(const String& filename)
+PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
 {
     if (!g_path_skip_root(filename.utf8().data()))
         return 0;
@@ -103,7 +103,7 @@ PassRefPtr<Icon> Icon::newIconForFile(const String& filename)
     return icon.release();
 }
 
-PassRefPtr<Icon> Icon::newIconForFiles(const Vector<String>& filenames)
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
 {
     //FIXME: Implement this
     return 0;
index a6e668d..63abe59 100644 (file)
@@ -39,7 +39,7 @@ Icon::~Icon()
 {
 }
 
-PassRefPtr<Icon> Icon::newIconForFile(const String& filename)
+PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
 {
     // Don't pass relative filenames -- we don't want a result that depends on the current directory.
     // Need 0U here to disambiguate String::operator[] from operator(NSString*, int)[]
@@ -53,13 +53,13 @@ PassRefPtr<Icon> Icon::newIconForFile(const String& filename)
     return adoptRef(new Icon(image));
 }
 
-PassRefPtr<Icon> Icon::newIconForFiles(const Vector<String>& filenames)
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
 {
     if (filenames.isEmpty())
         return 0;
 #ifdef BUILDING_ON_TIGER
     // FIXME: find a better image to use on Tiger.
-    return newIconForFile(filenames[0]);
+    return createIconForFile(filenames[0]);
 #else
     NSImage* image = [NSImage imageNamed:NSImageNameMultipleDocuments];
     if (!image)
index 84f18f7..b04668c 100644 (file)
@@ -41,14 +41,14 @@ Icon::~Icon()
 {
 }
     
-PassRefPtr<Icon> Icon::newIconForFile(const String& filename)
+PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
 {
     RefPtr<Icon> i = adoptRef(new Icon);
     i->m_icon = QIcon(filename);
     return i.release();
 }
 
-PassRefPtr<Icon> Icon::newIconForFiles(const Vector<String>& filenames)
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames)
 {
     //FIXME: Implement this
     return 0;
index d2b26e8..c02b56e 100644 (file)
 
 #include "GraphicsContext.h"
 #include "PlatformString.h"
+#include <tchar.h>
 #include <windows.h>
 
 namespace WebCore {
 
+static const int shell32MultipleFileIconIndex = 54;
+
 Icon::Icon(HICON icon)
     : m_hIcon(icon)
 {
@@ -38,7 +41,7 @@ Icon::~Icon()
     DestroyIcon(m_hIcon);
 }
 
-PassRefPtr<Icon> Icon::newIconForFile(const String& filename)
+PassRefPtr<Icon> Icon::createIconForFile(const String& filename)
 {
     SHFILEINFO sfi;
     memset(&sfi, 0, sizeof(sfi));
@@ -50,10 +53,20 @@ PassRefPtr<Icon> Icon::newIconForFile(const String& filename)
     return adoptRef(new Icon(sfi.hIcon));
 }
 
-PassRefPtr<Icon> Icon::newIconForFiles(const Vector<String>& filenames)
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>&)
 {
-    //FIXME: Implement this
-    return 0;
+    TCHAR buffer[MAX_PATH];    
+    UINT length = ::GetSystemDirectory(buffer, ARRAYSIZE(buffer));
+    if (!length)
+        return 0;
+    
+    if (_tcscat_s(buffer, TEXT("\\shell32.dll")))
+        return 0;
+
+    HICON hIcon;
+    if (!::ExtractIconEx(buffer, shell32MultipleFileIconIndex, 0, &hIcon, 1))
+        return 0;
+    return adoptRef(new Icon(hIcon));
 }
 
 void Icon::paint(GraphicsContext* context, const IntRect& r)
index 3a8803c..d8c6046 100644 (file)
@@ -132,8 +132,8 @@ ScrollbarTheme* ScrollbarTheme::nativeTheme() { notImplemented(); static Scrollb
 String FileChooser::basenameForWidth(const Font&, int width) const { notImplemented(); return String(); }
 
 Icon::~Icon() { }
-PassRefPtr<Icon> Icon::newIconForFile(const String& filename) { notImplemented(); return 0; }
-PassRefPtr<Icon> Icon::newIconForFiles(const Vector<String>& filenames) { notImplemented(); return 0; }
+PassRefPtr<Icon> Icon::createIconForFile(const String& filename) { notImplemented(); return 0; }
+PassRefPtr<Icon> Icon::createIconForFiles(const Vector<String>& filenames) { notImplemented(); return 0; }
 void Icon::paint(GraphicsContext*, const IntRect&) { notImplemented(); }
 
 ContextMenu::ContextMenu(const HitTestResult& result) : m_hitTestResult(result) { notImplemented(); }
index 8f29eee..14dcbf1 100644 (file)
@@ -84,6 +84,8 @@
 // This is the fixed width IE and Firefox use for buttons on dropdown menus
 static const int dropDownButtonWidth = 17;
 
+static const int shell32MagnifierIconIndex = 22;
+
 SOFT_LINK_LIBRARY(uxtheme)
 SOFT_LINK(uxtheme, OpenThemeData, HANDLE, WINAPI, (HWND hwnd, LPCWSTR pszClassList), (hwnd, pszClassList))
 SOFT_LINK(uxtheme, CloseThemeData, HRESULT, WINAPI, (HANDLE hTheme), (hTheme))
@@ -730,18 +732,19 @@ bool RenderThemeWin::paintSearchFieldResultsDecoration(RenderObject* o, const Re
 {
     IntRect bounds = r;
     bounds.setWidth(bounds.height());
-    LPCTSTR shell32 = _T("\\shell32.dll");
-    int shell32Length = _tcslen(shell32);
+
     TCHAR buffer[MAX_PATH];
-    UINT length = ::GetSystemDirectory(buffer, MAX_PATH);
+    UINT length = ::GetSystemDirectory(buffer, ARRAYSIZE(buffer));
     if (!length)
-        return false;
-    _tcsncpy_s(buffer + length, MAX_PATH - length, shell32, shell32Length);
-    buffer[length + shell32Length] = 0;
+        return 0;
+    
+    if (_tcscat_s(buffer, TEXT("\\shell32.dll")))
+        return 0;
+
     HICON hIcon;
-    const int shell32MagnifierIndex = 22;
-    if (!::ExtractIconEx(buffer, shell32MagnifierIndex, 0, &hIcon, 1))
-        return false;
+    if (!::ExtractIconEx(buffer, shell32MagnifierIconIndex, 0, &hIcon, 1))
+        return 0;
+
     RefPtr<Icon> icon = Icon::create(hIcon);
     icon->paint(paintInfo.context, bounds);
     return false;
index 57462cf..c26adab 100644 (file)
@@ -1,3 +1,13 @@
+2008-10-31  Adele Peterson  <adele@apple.com>
+
+        Reviewed by Darin Adler.
+
+        WebKit Windows part of fix for <rdar://problem/5839256> FILE CONTROL: multi-file upload.
+        https://bugs.webkit.org/show_bug.cgi?id=22008
+        
+        * WebCoreSupport/WebChromeClient.cpp: (WebChromeClient::runOpenPanel): 
+        Add support for mulitple file selection.
+
 2008-10-31  Darin Adler  <darin@apple.com>
 
         - try to fix build
index fdcb557..dba87e5 100644 (file)
 
 using namespace WebCore;
 
+// When you call GetOpenFileName, if the size of the buffer is too small,
+// MSDN says that the first two bytes of the buffer contain the required size for the file selection, in bytes or characters
+// So we can assume the required size can't be more than the maximum value for a short.
+static const size_t maxFilePathsListSize = USHRT_MAX;
+
 WebChromeClient::WebChromeClient(WebView* webView)
     : m_webView(webView)
 {
@@ -625,15 +630,15 @@ bool WebChromeClient::paintCustomScrollCorner(GraphicsContext* context, const Fl
 
 void WebChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser)
 {
-    // FIXME: Support multiple files.
-
     RefPtr<FileChooser> fileChooser = prpFileChooser;
 
     HWND viewWindow;
     if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&viewWindow))))
         return;
 
-    TCHAR fileBuf[MAX_PATH];
+    bool multiFile = fileChooser->allowsMultipleFiles();
+    Vector<TCHAR> fileBuf(multiFile ? maxFilePathsListSize : MAX_PATH);
+
     OPENFILENAME ofn;
 
     memset(&ofn, 0, sizeof(ofn));
@@ -646,14 +651,39 @@ void WebChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChoose
     String allFiles = allFilesText();
     allFiles.append(TEXT("\0*.*\0\0"), 6);
     ofn.lpstrFilter = allFiles.charactersWithNullTermination();
-    ofn.lpstrFile = fileBuf;
-    ofn.nMaxFile = sizeof(fileBuf);
+    ofn.lpstrFile = fileBuf.data();
+    ofn.nMaxFile = fileBuf.size();
     String dialogTitle = uploadFileText();
     ofn.lpstrTitle = dialogTitle.charactersWithNullTermination();
-    ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
-
-    if (GetOpenFileName(&ofn))
-        fileChooser->chooseFile(String(fileBuf));
+    ofn.Flags = OFN_ENABLESIZING | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST | OFN_EXPLORER;
+    if (multiFile)
+        ofn.Flags = ofn.Flags | OFN_ALLOWMULTISELECT;
+
+    if (GetOpenFileName(&ofn)) {
+        TCHAR* files = fileBuf.data();
+        Vector<String> fileList;
+        String file(files);
+        if (multiFile) {
+            while (!file.isEmpty()) {
+                // When using the OFN_EXPLORER flag, the file list is null delimited.
+                // When you create a String from a ptr to this list, it will use strlen to look for the null character.
+                // Then we find the next file path string by using the length of the string we just created.
+                TCHAR* nextFilePtr = files + file.length() + 1;
+                String nextFile(nextFilePtr);
+                // If multiple files are selected, there will be a directory name first, which we don't want to add to the vector.
+                // We know a single file was selected if there is only one filename in the list.  
+                // In that case, we don't want to skip adding the first (and only) name.
+                if (files != fileBuf.data() || nextFile.isEmpty())
+                    fileList.append(file);
+                files = nextFilePtr;
+                file = nextFile;
+            }
+        } else
+            fileList.append(file);
+        ASSERT(fileList.size());
+        fileChooser->chooseFiles(fileList);
+    }
+    // FIXME: Show some sort of error if too many files are selected and the buffer is too small.  For now, this will fail silently.
 }
 
 COMPtr<IWebUIDelegate> WebChromeClient::uiDelegate()