WebCore:
authoradele@apple.com <adele@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Apr 2008 01:30:20 +0000 (01:30 +0000)
committeradele@apple.com <adele@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 29 Apr 2008 01:30:20 +0000 (01:30 +0000)
2008-04-28  Adele Peterson  <adele@apple.com>

        Reviewed by Dan Bernstein, Tim Hatcher, Anders Carlsson, and Darin Adler.

        WebCore part of fix for <rdar://problem/3709505>
        Safari should have a way to upload bundles from the file upload control (as zip)

        * WebCore.base.exp: Added symbols.

        * html/HTMLFormElement.cpp: (WebCore::HTMLFormElement::formData): Ask the application if a file will need to be replaced before it's uploaded.
          It will also give the replacement filename which is used to determine the correct mime-type and to construct the correct header.

        * loader/FrameLoader.cpp:
        (WebCore::FrameLoader::submitForm): Asks the application to generate any files for the form data before a form submission starts.
        (WebCore::FrameLoader::loadItem): ditto.
        * loader/ResourceLoader.cpp:
        (WebCore::ResourceLoader::didReceiveResponse): Tells the FormData from the request to remove any generated files if it needs to.
        (WebCore::ResourceLoader::didCancel): ditto.
        (WebCore::ResourceLoader::didFail): ditto.

        * platform/network/FormData.cpp:
        (WebCore::FormData::FormData): Initializes m_hasGeneratedFiles, which keeps track of whether there are files that will need to be removed.
        (WebCore::FormData::~FormData): Added.  Assert that there are no files that need to be removed, but if there are, release builds will still remove them here.
        (WebCore::FormData::appendFile): Passes along a shouldGenerateFile flag to the FormDataElement.
        (WebCore::FormData::generateFiles): Added. Iterates through the FormDataElements, and using the ChromeClient pointer, asks the application to
         create any compressed files so the FormDataElements can store the paths.
        (WebCore::FormData::removeGeneratedFilesIfNeeded): Added.  Removes generated files and their directories (if empty).
        * platform/network/FormData.h:
        (WebCore::FormDataElement::FormDataElement): Added a boolean to track whether the file will need to be generated,
         and a string to hold the path of the generated file.

        * platform/network/mac/FormDataStreamMac.mm:
        (WebCore::advanceCurrentStream): Uses the generated file path instead of the original file path when streaming the file.
        (WebCore::setHTTPBody): Uses the generated file path when determining the size of the file to be uploaded.

        * platform/FileSystem.h: Added directoryName.
        * platform/posix/FileSystemPOSIX.cpp: (WebCore::directoryName): Added.
        * platform/gtk/FileSystemGtk.cpp: (WebCore::directoryName): Added empty implementation.
        * platform/qt/FileSystemQt.cpp: (WebCore::directoryName): ditto.
        * platform/win/FileSystemWin.cpp: (WebCore::directoryName): ditto.
        * platform/wx/FileSystemWx.cpp: (WebCore::directoryName): ditto.

        Added new ChromeClient methods to give the application control over the file compression for uploading.
        * page/Chrome.cpp:
        (WebCore::ChromeClient::shouldReplaceWithGeneratedFileForUpload): Added a default implementation.
        (WebCore::ChromeClient::generateReplacementFile): ditto.
        * page/ChromeClient.h:

WebKit/mac:

2008-04-28  Adele Peterson  <adele@apple.com>

        Reviewed by Dan Bernstein, Tim Hatcher, Anders Carlsson, and Darin Adler.

        WebKit part of fix for <rdar://problem/3709505>
        Safari should have a way to upload bundles from the file upload control (as zip)

        Added UIDelegate methods to let the application handle generating replacement files for uploads.
        In this case, Safari will create archived files for bundles so they can be uploaded properly.

        * DefaultDelegates/WebDefaultUIDelegate.m:
        (-[WebDefaultUIDelegate webView:shouldReplaceUploadFile:usingGeneratedFilename:]):
        (-[WebDefaultUIDelegate webView:generateReplacementFile:]):
        * WebCoreSupport/WebChromeClient.h:
        * WebCoreSupport/WebChromeClient.mm:
        (WebChromeClient::shouldReplaceWithGeneratedFileForUpload):
        (WebChromeClient::generateReplacementFile):
        * WebView/WebUIDelegatePrivate.h:

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

21 files changed:
WebCore/ChangeLog
WebCore/WebCore.base.exp
WebCore/html/HTMLFormElement.cpp
WebCore/loader/FrameLoader.cpp
WebCore/loader/ResourceLoader.cpp
WebCore/page/Chrome.cpp
WebCore/page/ChromeClient.h
WebCore/platform/FileSystem.h
WebCore/platform/gtk/FileSystemGtk.cpp
WebCore/platform/network/FormData.cpp
WebCore/platform/network/FormData.h
WebCore/platform/network/mac/FormDataStreamMac.mm
WebCore/platform/posix/FileSystemPOSIX.cpp
WebCore/platform/qt/FileSystemQt.cpp
WebCore/platform/win/FileSystemWin.cpp
WebCore/platform/wx/FileSystemWx.cpp
WebKit/mac/ChangeLog
WebKit/mac/DefaultDelegates/WebDefaultUIDelegate.m
WebKit/mac/WebCoreSupport/WebChromeClient.h
WebKit/mac/WebCoreSupport/WebChromeClient.mm
WebKit/mac/WebView/WebUIDelegatePrivate.h

index 0928ffb..702572d 100644 (file)
@@ -1,3 +1,51 @@
+2008-04-28  Adele Peterson  <adele@apple.com>
+
+        Reviewed by Dan Bernstein, Tim Hatcher, Anders Carlsson, and Darin Adler.
+
+        WebCore part of fix for <rdar://problem/3709505>
+        Safari should have a way to upload bundles from the file upload control (as zip)
+
+        * WebCore.base.exp: Added symbols.
+
+        * html/HTMLFormElement.cpp: (WebCore::HTMLFormElement::formData): Ask the application if a file will need to be replaced before it's uploaded.
+          It will also give the replacement filename which is used to determine the correct mime-type and to construct the correct header.
+
+        * loader/FrameLoader.cpp:
+        (WebCore::FrameLoader::submitForm): Asks the application to generate any files for the form data before a form submission starts.
+        (WebCore::FrameLoader::loadItem): ditto.
+        * loader/ResourceLoader.cpp:
+        (WebCore::ResourceLoader::didReceiveResponse): Tells the FormData from the request to remove any generated files if it needs to.
+        (WebCore::ResourceLoader::didCancel): ditto.
+        (WebCore::ResourceLoader::didFail): ditto.
+
+        * platform/network/FormData.cpp:
+        (WebCore::FormData::FormData): Initializes m_hasGeneratedFiles, which keeps track of whether there are files that will need to be removed.
+        (WebCore::FormData::~FormData): Added.  Assert that there are no files that need to be removed, but if there are, release builds will still remove them here.
+        (WebCore::FormData::appendFile): Passes along a shouldGenerateFile flag to the FormDataElement.
+        (WebCore::FormData::generateFiles): Added. Iterates through the FormDataElements, and using the ChromeClient pointer, asks the application to
+         create any compressed files so the FormDataElements can store the paths.
+        (WebCore::FormData::removeGeneratedFilesIfNeeded): Added.  Removes generated files and their directories (if empty).
+        * platform/network/FormData.h:
+        (WebCore::FormDataElement::FormDataElement): Added a boolean to track whether the file will need to be generated,
+         and a string to hold the path of the generated file.
+
+        * platform/network/mac/FormDataStreamMac.mm:
+        (WebCore::advanceCurrentStream): Uses the generated file path instead of the original file path when streaming the file.
+        (WebCore::setHTTPBody): Uses the generated file path when determining the size of the file to be uploaded.
+
+        * platform/FileSystem.h: Added directoryName.
+        * platform/posix/FileSystemPOSIX.cpp: (WebCore::directoryName): Added.
+        * platform/gtk/FileSystemGtk.cpp: (WebCore::directoryName): Added empty implementation.
+        * platform/qt/FileSystemQt.cpp: (WebCore::directoryName): ditto.
+        * platform/win/FileSystemWin.cpp: (WebCore::directoryName): ditto.
+        * platform/wx/FileSystemWx.cpp: (WebCore::directoryName): ditto.
+
+        Added new ChromeClient methods to give the application control over the file compression for uploading.
+        * page/Chrome.cpp:
+        (WebCore::ChromeClient::shouldReplaceWithGeneratedFileForUpload): Added a default implementation.
+        (WebCore::ChromeClient::generateReplacementFile): ditto.
+        * page/ChromeClient.h:
+
 2008-04-28  Anders Carlsson  <andersca@apple.com>
 
         Reviewed by Sam, Mark, Adele and Darin.
index eb8fced..28d4a90 100644 (file)
@@ -123,6 +123,7 @@ _WebCoreSetShouldUseFontSmoothing
 _WebCoreShouldUseFontSmoothing
 _WebCoreTextFloatWidth
 __Z26ReportBlockedObjCExceptionP11NSException
+__ZN3WTF10RefCountedIN7WebCore8FormDataEE5derefEv
 __ZN7WebCore10CachedPage14documentLoaderEv
 __ZN7WebCore10CachedPage22cachedPagePlatformDataEv
 __ZN7WebCore10CachedPage25setCachedPagePlatformDataEPNS_22CachedPagePlatformDataE
@@ -526,6 +527,7 @@ __ZN7WebCore8Document24setShouldCreateRenderersEb
 __ZN7WebCore8Document36updateLayoutIgnorePendingStylesheetsEv
 __ZN7WebCore8Document4bodyEv
 __ZN7WebCore8DragDataC1EP11objc_objectRKNS_8IntPointES5_NS_13DragOperationEPNS_16PasteboardHelperE
+__ZN7WebCore8FormDataD1Ev
 __ZN7WebCore8IntPointC1ERK8_NSPoint
 __ZN7WebCore8KJSProxy10initScriptEv
 __ZN7WebCore8Settings14setJavaEnabledEb
index b15c62d..8786505 100644 (file)
@@ -26,6 +26,8 @@
 #include "HTMLFormElement.h"
 
 #include "CSSHelper.h"
+#include "ChromeClient.h"
+#include "Document.h"
 #include "Event.h"
 #include "EventNames.h"
 #include "FileSystem.h"
@@ -39,6 +41,7 @@
 #include "HTMLInputElement.h"
 #include "HTMLNames.h"
 #include "MIMETypeRegistry.h"
+#include "Page.h"
 #include "RenderTextControl.h"
 
 #if PLATFORM(QT)
@@ -263,6 +266,7 @@ PassRefPtr<FormData> HTMLFormElement::formData(const char* boundary) const
                     header.append(item.m_data.data(), item.m_data.length());
                     header.append('"');
 
+                    bool shouldGenerateFile = false;
                     // if the current type is FILE, then we also need to
                     // include the filename
                     if (control->hasLocalName(inputTag)
@@ -270,6 +274,15 @@ PassRefPtr<FormData> HTMLFormElement::formData(const char* boundary) const
                         String path = static_cast<HTMLInputElement*>(control)->value();
                         String filename = pathGetFileName(path);
 
+                        // Let the application specify a filename if its going to generate a replacement file for the upload
+                        if (Page* page = document()->page()) {
+                            String generatedFilename;
+                            shouldGenerateFile = page->chrome()->client()->shouldReplaceWithGeneratedFileForUpload(path, generatedFilename);
+                            if (shouldGenerateFile)
+                                filename = generatedFilename;
+                        }
+                        
+
                         // FIXME: This won't work if the filename includes a " mark,
                         // or control characters like CR or LF. This also does strange
                         // things if the filename includes characters you can't encode
@@ -278,8 +291,8 @@ PassRefPtr<FormData> HTMLFormElement::formData(const char* boundary) const
                         appendString(header, encoding.encode(filename.characters(), filename.length(), QuestionMarksForUnencodables));
                         header.append('"');
 
-                        if (!path.isEmpty()) {
-                            String mimeType = MIMETypeRegistry::getMIMETypeForPath(path);
+                        if (!filename.isEmpty()) {
+                            String mimeType = MIMETypeRegistry::getMIMETypeForPath(filename);
                             if (!mimeType.isEmpty()) {
                                 appendString(header, "\r\nContent-Type: ");
                                 appendString(header, mimeType.latin1());
@@ -295,7 +308,7 @@ PassRefPtr<FormData> HTMLFormElement::formData(const char* boundary) const
                     if (size_t dataSize = item.m_data.length())
                         result->appendData(item.m_data.data(), dataSize);
                     else if (!item.m_path.isEmpty())
-                        result->appendFile(item.m_path);
+                        result->appendFile(item.m_path, shouldGenerateFile);
                     result->appendData("\r\n", 2);
 
                     ++j;
index 86af3e6..491def5 100644 (file)
@@ -504,6 +504,9 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F
 {
     ASSERT(formData);
     
+    if (!m_frame->page())
+        return;
+    
     KURL u = completeURL(url.isNull() ? "" : url);
     // FIXME: Do we really need to special-case an empty URL?
     // Would it be better to just go on with the form submisson and let the I/O fail?
@@ -525,6 +528,8 @@ void FrameLoader::submitForm(const char* action, const String& url, PassRefPtr<F
         return;
     }
 
+    formData->generateFiles(m_frame->page()->chrome()->client());
+    
     FrameLoadRequest frameRequest;
 
     if (!m_outgoingReferrer.isEmpty())
@@ -4115,6 +4120,9 @@ void FrameLoader::saveDocumentState()
 // Loads content into this frame, as specified by history item
 void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
 {
+    if (!m_frame->page())
+        return;
+
     KURL itemURL = item->url();
     KURL itemOriginalURL = item->originalURL();
     KURL currentURL;
@@ -4186,6 +4194,9 @@ void FrameLoader::loadItem(HistoryItem* item, FrameLoadType loadType)
             // If this was a repost that failed the page cache, we might try to repost the form.
             NavigationAction action;
             if (formData) {
+                
+                formData->generateFiles(m_frame->page()->chrome()->client());
+
                 request.setHTTPMethod("POST");
                 request.setHTTPReferrer(item->formReferrer());
                 request.setHTTPBody(formData);
index a3d6f59..e0bdf63 100644 (file)
@@ -225,6 +225,9 @@ void ResourceLoader::didReceiveResponse(const ResourceResponse& r)
 
     m_response = r;
 
+    if (FormData* data = m_request.httpBody())
+        data->removeGeneratedFilesIfNeeded();
+        
     if (m_sendResourceLoadCallbacks)
         frameLoader()->didReceiveResponse(this, m_response);
 }
@@ -293,6 +296,9 @@ void ResourceLoader::didFail(const ResourceError& error)
     // anything including possibly derefing this; one example of this is Radar 3266216.
     RefPtr<ResourceLoader> protector(this);
 
+    if (FormData* data = m_request.httpBody())
+        data->removeGeneratedFilesIfNeeded();
+
     if (m_sendResourceLoadCallbacks && !m_calledDidFinishLoad)
         frameLoader()->didFailToLoad(this, error);
 
@@ -304,6 +310,9 @@ void ResourceLoader::didCancel(const ResourceError& error)
     ASSERT(!m_cancelled);
     ASSERT(!m_reachedTerminalState);
 
+    if (FormData* data = m_request.httpBody())
+        data->removeGeneratedFilesIfNeeded();
+
     // This flag prevents bad behavior when loads that finish cause the
     // load itself to be cancelled (which could happen with a javascript that 
     // changes the window location). This is used to prevent both the body
index e2f086f..ca1a0cb 100644 (file)
@@ -366,6 +366,17 @@ void ChromeClient::paintCustomHighlight(Node*, const AtomicString&, const FloatR
 {
 }
 
+bool ChromeClient::shouldReplaceWithGeneratedFileForUpload(const String&, String&)
+{
+    return false;
+}
+
+String ChromeClient::generateReplacementFile(const String&)
+{
+    ASSERT_NOT_REACHED();
+    return String(); 
+}
+
 // --------
 
 PageGroupLoadDeferrer::PageGroupLoadDeferrer(Page* page, bool deferSelf)
index 25b7a8c..8c751b5 100644 (file)
@@ -127,6 +127,9 @@ namespace WebCore {
         virtual FloatRect customHighlightRect(Node*, const AtomicString& type, const FloatRect& lineRect);
         virtual void paintCustomHighlight(Node*, const AtomicString& type, const FloatRect& boxRect, const FloatRect& lineRect,
             bool behindText, bool entireLine);
+            
+        virtual bool shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename);
+        virtual String generateReplacementFile(const String& path);
 
 #if PLATFORM(MAC)
         virtual void runOpenPanel(PassRefPtr<FileChooser>);
index f1b7ea6..c5ad47f 100644 (file)
@@ -88,6 +88,7 @@ String pathByAppendingComponent(const String& path, const String& component);
 bool makeAllDirectories(const String& path);
 String homeDirectoryPath();
 String pathGetFileName(const String&);
+String directoryName(const String&);
 
 CString fileSystemRepresentation(const String&);
 
index d4f32d2..d79f2cd 100644 (file)
@@ -140,6 +140,12 @@ String pathGetFileName(const String& pathName)
     return fileName;
 }
 
+String directoryName(const String& path)
+{
+    notImplemented();
+    return String();
+}
+
 CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
 {
     gchar* filename = g_strdup_printf("%sXXXXXX", prefix);
index 3453169..1810534 100644 (file)
 #include "FormData.h"
 
 #include "CString.h"
+#include "ChromeClient.h"
+#include "FileSystem.h"
 #include "TextEncoding.h"
 
 namespace WebCore {
 
-inline FormData::FormData()
+inline FormData::FormData() : m_hasGeneratedFiles(false)
 {
 }
 
+inline FormData::FormData(const FormData& data)
+    : RefCounted<FormData>(1)
+    , m_elements(data.m_elements)
+    , m_hasGeneratedFiles(false)
+{
+    // We shouldn't be copying FormData that hasn't already removed its generated files
+    // but just in case, make sure the new FormData is ready to generate its own files.
+    if (data.m_hasGeneratedFiles) {
+        size_t n = m_elements.size();
+        for (size_t i = 0; i < n; ++i) {
+            FormDataElement& e = m_elements[i];
+            if (e.m_type == FormDataElement::encodedFile)
+                e.m_generatedFilename = String();
+        }
+    }
+}
+
+FormData::~FormData()
+{
+    // This cleanup should've happened when the form submission finished.
+    // Just in case, let's assert, and do the cleanup anyway in release builds.
+    ASSERT(!m_hasGeneratedFiles);
+    removeGeneratedFilesIfNeeded();
+}
+
 PassRefPtr<FormData> FormData::create()
 {
     return adoptRef(new FormData);
@@ -55,12 +82,6 @@ PassRefPtr<FormData> FormData::create(const Vector<char>& vector)
     return result.release();
 }
 
-inline FormData::FormData(const FormData& data)
-    : RefCounted<FormData>(1)
-    , m_elements(data.m_elements)
-{
-}
-
 PassRefPtr<FormData> FormData::copy() const
 {
     return adoptRef(new FormData(*this));
@@ -76,9 +97,9 @@ void FormData::appendData(const void* data, size_t size)
     memcpy(e.m_data.data() + oldSize, data, size);
 }
 
-void FormData::appendFile(const String& filename)
+void FormData::appendFile(const String& filename, bool shouldGenerateFile)
 {
-    m_elements.append(filename);
+    m_elements.append(FormDataElement(filename, shouldGenerateFile));
 }
 
 void FormData::flatten(Vector<char>& data) const
@@ -104,4 +125,40 @@ String FormData::flattenToString() const
     return Latin1Encoding().decode(bytes.data(), bytes.size());
 }
 
+void FormData::generateFiles(ChromeClient* client)
+{
+    ASSERT(!m_hasGeneratedFiles);
+    
+    if (m_hasGeneratedFiles)
+        return;
+    
+    size_t n = m_elements.size();
+    for (size_t i = 0; i < n; ++i) {
+        FormDataElement& e = m_elements[i];
+        if (e.m_type == FormDataElement::encodedFile && e.m_shouldGenerateFile) {
+            e.m_generatedFilename = client->generateReplacementFile(e.m_filename);
+            m_hasGeneratedFiles = true;
+        }
+    }
+}
+
+void FormData::removeGeneratedFilesIfNeeded()
+{
+    if (!m_hasGeneratedFiles)
+        return;
+        
+    size_t n = m_elements.size();
+    for (size_t i = 0; i < n; ++i) {
+        FormDataElement& e = m_elements[i];
+        if (e.m_type == FormDataElement::encodedFile && !e.m_generatedFilename.isEmpty()) {
+            ASSERT(e.m_shouldGenerateFile);
+            String directory = directoryName(e.m_generatedFilename);
+            deleteFile(e.m_generatedFilename);
+            deleteEmptyDirectory(directory);
+            e.m_generatedFilename = String();
+        }
+    }
+    m_hasGeneratedFiles = false;
+}
+
 } // namespace WebCore
index 168020e..c1518c8 100644 (file)
 
 namespace WebCore {
 
+class ChromeClient;
+
 class FormDataElement {
 public:
     FormDataElement() : m_type(data) { }
     FormDataElement(const Vector<char>& array) : m_type(data), m_data(array) { }
-    FormDataElement(const String& filename) : m_type(encodedFile), m_filename(filename) { }
+    FormDataElement(const String& filename, bool shouldGenerateFile) : m_type(encodedFile), m_filename(filename), m_shouldGenerateFile(shouldGenerateFile) { }
 
     enum { data, encodedFile } m_type;
     Vector<char> m_data;
     String m_filename;
+    String m_generatedFilename;
+    bool m_shouldGenerateFile;
 };
 
 inline bool operator==(const FormDataElement& a, const FormDataElement& b)
@@ -64,9 +68,10 @@ public:
     static PassRefPtr<FormData> create(const CString&);
     static PassRefPtr<FormData> create(const Vector<char>&);
     PassRefPtr<FormData> copy() const;
+    ~FormData();
     
     void appendData(const void* data, size_t);
-    void appendFile(const String& filename);
+    void appendFile(const String& filename, bool shouldGenerateFile = false);
 
     void flatten(Vector<char>&) const; // omits files
     String flattenToString() const; // omits files
@@ -74,11 +79,15 @@ public:
     bool isEmpty() const { return m_elements.isEmpty(); }
     const Vector<FormDataElement>& elements() const { return m_elements; }
 
+    void generateFiles(ChromeClient*);
+    void removeGeneratedFilesIfNeeded();
+
 private:
     FormData();
     FormData(const FormData&);
      
     Vector<FormDataElement> m_elements;
+    bool m_hasGeneratedFiles;
 };
 
 inline bool operator==(const FormData& a, const FormData& b)
index efd09b0..a393fca 100644 (file)
@@ -87,7 +87,8 @@ static void advanceCurrentStream(FormStreamFields *form)
         form->currentStream = CFReadStreamCreateWithBytesNoCopy(0, reinterpret_cast<const UInt8*>(data), size, kCFAllocatorNull);
         form->currentData = data;
     } else {
-        CFStringRef filename = nextInput.m_filename.createCFString();
+        const String& path = nextInput.m_shouldGenerateFile ? nextInput.m_generatedFilename : nextInput.m_filename;
+        CFStringRef filename = path.createCFString();
         CFURLRef fileURL = CFURLCreateWithFileSystemPath(0, filename, kCFURLPOSIXPathStyle, FALSE);
         CFRelease(filename);
         form->currentStream = CFReadStreamCreateWithFile(0, fileURL);
@@ -275,8 +276,9 @@ void setHTTPBody(NSMutableURLRequest *request, PassRefPtr<FormData> formData)
         if (element.m_type == FormDataElement::data)
             length += element.m_data.size();
         else {
+            const String& filename = element.m_shouldGenerateFile ? element.m_generatedFilename : element.m_filename;
             struct stat sb;
-            int statResult = stat(element.m_filename.utf8().data(), &sb);
+            int statResult = stat(filename.utf8().data(), &sb);
             if (statResult == 0 && (sb.st_mode & S_IFMT) == S_IFREG)
                 length += sb.st_size;
         }
index fd7fdc9..7d6da64 100644 (file)
@@ -33,6 +33,7 @@
 #include "PlatformString.h"
 
 #include <sys/stat.h>
+#include <libgen.h>
 #include <unistd.h>
 
 namespace WebCore {
@@ -146,4 +147,14 @@ String pathGetFileName(const String& path)
     return path.substring(path.reverseFind('/') + 1);
 }
 
+String directoryName(const String& path)
+{
+    CString fsRep = fileSystemRepresentation(path);
+
+    if (!fsRep.data() || fsRep.data()[0] == '\0')
+        return String();
+
+    return dirname(fsRep.mutableData());
+}
+
 } // namespace WebCore
index be04db9..aee8141 100644 (file)
@@ -88,6 +88,12 @@ String pathGetFileName(const String& path)
     return QFileInfo(path).fileName();
 }
 
+String directoryName(const String& path)
+{
+    notImplemented();
+    return String();
+}
+
 bool unloadModule(PlatformModule)
 {
     notImplemented();
index 26219f3..12fcab7 100644 (file)
@@ -131,6 +131,12 @@ String pathGetFileName(const String& path)
     return String(::PathFindFileName(String(path).charactersWithNullTermination()));
 }
 
+String directoryName(const String& path)
+{
+    notImplemented();
+    return String();
+}
+
 static String bundleName()
 {
     static bool initialized;
index d330c48..4bb77d3 100644 (file)
@@ -91,6 +91,12 @@ String pathGetFileName(const String& path)
     return wxFileName(path).GetFullName();
 }
 
+String directoryName(const String& path)
+{
+    notImplemented();
+    return String();
+}
+
 CString openTemporaryFile(const char* prefix, PlatformFileHandle& handle)
 {
     notImplemented();
index 0779e16..6a6a7c9 100644 (file)
@@ -1,3 +1,22 @@
+2008-04-28  Adele Peterson  <adele@apple.com>
+
+        Reviewed by Dan Bernstein, Tim Hatcher, Anders Carlsson, and Darin Adler.
+
+        WebKit part of fix for <rdar://problem/3709505>
+        Safari should have a way to upload bundles from the file upload control (as zip)
+
+        Added UIDelegate methods to let the application handle generating replacement files for uploads.
+        In this case, Safari will create archived files for bundles so they can be uploaded properly.
+
+        * DefaultDelegates/WebDefaultUIDelegate.m:
+        (-[WebDefaultUIDelegate webView:shouldReplaceUploadFile:usingGeneratedFilename:]):
+        (-[WebDefaultUIDelegate webView:generateReplacementFile:]):
+        * WebCoreSupport/WebChromeClient.h:
+        * WebCoreSupport/WebChromeClient.mm:
+        (WebChromeClient::shouldReplaceWithGeneratedFileForUpload):
+        (WebChromeClient::generateReplacementFile):
+        * WebView/WebUIDelegatePrivate.h:
+
 2008-04-28  Anders Carlsson  <andersca@apple.com>
 
         Reviewed by Sam, Mark, Adele and Darin.
index 04e24e1..a6e1a2f 100644 (file)
@@ -227,4 +227,14 @@ static WebDefaultUIDelegate *sharedDelegate = nil;
 {
 }
 
+- (BOOL)webView:(WebView *)sender shouldReplaceUploadFile:(NSString *)path usingGeneratedFilename:(NSString **)filename
+{
+    return NO;
+}
+
+- (NSString *)webView:(WebView *)sender generateReplacementFile:(NSString *)path
+{
+    return nil;
+}
+
 @end
index b73ff5d..d22662b 100644 (file)
@@ -120,6 +120,9 @@ public:
     virtual void makeFirstResponder(NSResponder *);
 
     virtual void willPopUpMenu(NSMenu *);
+    
+    virtual bool shouldReplaceWithGeneratedFileForUpload(const WebCore::String& path, WebCore::String &generatedFilename);
+    virtual WebCore::String generateReplacementFile(const WebCore::String& path);
 
 private:
     WebView *m_webView;
index 8eb8b0d..898ec02 100644 (file)
@@ -541,6 +541,20 @@ void WebChromeClient::willPopUpMenu(NSMenu *menu)
     END_BLOCK_OBJC_EXCEPTIONS;
 }
 
+bool WebChromeClient::shouldReplaceWithGeneratedFileForUpload(const String& path, String& generatedFilename)
+{
+    NSString* filename;
+    if (![[m_webView _UIDelegateForwarder] webView:m_webView shouldReplaceUploadFile:path usingGeneratedFilename:&filename])
+        return false;
+    generatedFilename = filename;
+    return true;
+}
+
+String WebChromeClient::generateReplacementFile(const String& path)
+{
+    return [[m_webView _UIDelegateForwarder] webView:m_webView generateReplacementFile:path];
+}
+
 @implementation WebOpenPanelResultListener
 
 - (id)initWithChooser:(PassRefPtr<FileChooser>)chooser
index 62ef3f9..72c66c7 100644 (file)
@@ -97,4 +97,7 @@ enum {
 
 - (WebView *)webView:(WebView *)sender createWebViewWithRequest:(NSURLRequest *)request windowFeatures:(NSDictionary *)features;
 
+- (BOOL)webView:(WebView *)sender shouldReplaceUploadFile:(NSString *)path usingGeneratedFilename:(NSString **)filename;
+- (NSString *)webView:(WebView *)sender generateReplacementFile:(NSString *)path;
 @end