Changeset 173252 in webkit


Ignore:
Timestamp:
Sep 3, 2014 11:43:35 PM (10 years ago)
Author:
commit-queue@webkit.org
Message:

[SOUP] Race condition when downloading a file due to the intermediate temporary file
https://bugs.webkit.org/show_bug.cgi?id=136423

Patch by Michael Catanzaro <Michael Catanzaro> on 2014-09-03
Reviewed by Carlos Garcia Campos.

  • Shared/Downloads/soup/DownloadSoup.cpp:

(WebKit::DownloadClient::DownloadClient): Replace m_destinationURI with
m_destinationFile and add m_createdDestination.
(WebKit::DownloadClient::deleteFilesIfNeeded): Added.
(WebKit::DownloadClient::downloadFailed): Call deleteFilesIfNeeded.
(WebKit::DownloadClient::didReceiveResponse): Attempt to create the
destination file before the intermediate file. Fail here if the file
exists and overwrite is not allowed, so we don't erroneously fire the
didCreateDestination event or waste time downloading the file when we
know the download will fail.
(WebKit::DownloadClient::didFinishLoading): Unconditionally overwrite
the empty destination file.
(WebKit::DownloadClient::cancel): Call deleteFilesIfNeeded.
(WebKit::DownloadClient::deleteIntermediateFileInNeeded): Deleted.

Location:
trunk/Source/WebKit2
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r173245 r173252  
     12014-09-03  Michael Catanzaro  <mcatanzaro@igalia.com>
     2
     3        [SOUP] Race condition when downloading a file due to the intermediate temporary file
     4        https://bugs.webkit.org/show_bug.cgi?id=136423
     5
     6        Reviewed by Carlos Garcia Campos.
     7
     8        * Shared/Downloads/soup/DownloadSoup.cpp:
     9        (WebKit::DownloadClient::DownloadClient): Replace m_destinationURI with
     10        m_destinationFile and add m_createdDestination.
     11        (WebKit::DownloadClient::deleteFilesIfNeeded): Added.
     12        (WebKit::DownloadClient::downloadFailed): Call deleteFilesIfNeeded.
     13        (WebKit::DownloadClient::didReceiveResponse): Attempt to create the
     14        destination file before the intermediate file. Fail here if the file
     15        exists and overwrite is not allowed, so we don't erroneously fire the
     16        didCreateDestination event or waste time downloading the file when we
     17        know the download will fail.
     18        (WebKit::DownloadClient::didFinishLoading): Unconditionally overwrite
     19        the empty destination file.
     20        (WebKit::DownloadClient::cancel): Call deleteFilesIfNeeded.
     21        (WebKit::DownloadClient::deleteIntermediateFileInNeeded): Deleted.
     22
    1232014-09-03  David Kilzer  <ddkilzer@apple.com>
    224
  • trunk/Source/WebKit2/Shared/Downloads/soup/DownloadSoup.cpp

    r173154 r173252  
    5959    }
    6060
    61     void deleteIntermediateFileInNeeded()
    62     {
    63         if (!m_intermediateFile)
    64             return;
    65         g_file_delete(m_intermediateFile.get(), nullptr, nullptr);
     61    void deleteFilesIfNeeded()
     62    {
     63        if (m_destinationFile)
     64            g_file_delete(m_destinationFile.get(), nullptr, nullptr);
     65
     66        if (m_intermediateFile) {
     67            ASSERT(m_destinationFile);
     68            g_file_delete(m_intermediateFile.get(), nullptr, nullptr);
     69        }
    6670    }
    6771
    6872    void downloadFailed(const ResourceError& error)
    6973    {
    70         deleteIntermediateFileInNeeded();
     74        deleteFilesIfNeeded();
    7175        m_download->didFail(error, IPC::DataReference());
    7276    }
     
    9094        }
    9195
    92         m_destinationURI = m_download->decideDestinationWithSuggestedFilename(suggestedFilename, m_allowOverwrite);
    93         if (m_destinationURI.isEmpty()) {
     96        String destinationURI = m_download->decideDestinationWithSuggestedFilename(suggestedFilename, m_allowOverwrite);
     97        if (destinationURI.isEmpty()) {
    9498#if PLATFORM(GTK)
    9599            GUniquePtr<char> buffer(g_strdup_printf(_("Cannot determine destination URI for download with suggested filename %s"), suggestedFilename.utf8().data()));
     
    102106        }
    103107
    104         String intermediateURI = m_destinationURI + ".wkdownload";
     108        m_destinationFile = adoptGRef(g_file_new_for_uri(destinationURI.utf8().data()));
     109        GRefPtr<GFileOutputStream> outputStream;
     110        GUniqueOutPtr<GError> error;
     111        if (m_allowOverwrite)
     112            outputStream = adoptGRef(g_file_replace(m_destinationFile.get(), nullptr, FALSE, G_FILE_CREATE_NONE, nullptr, &error.outPtr()));
     113        else
     114            outputStream = adoptGRef(g_file_create(m_destinationFile.get(), G_FILE_CREATE_NONE, nullptr, &error.outPtr()));
     115        if (!outputStream) {
     116            m_destinationFile.clear();
     117            downloadFailed(platformDownloadDestinationError(response, error->message));
     118            return;
     119        }
     120
     121        String intermediateURI = destinationURI + ".wkdownload";
    105122        m_intermediateFile = adoptGRef(g_file_new_for_uri(intermediateURI.utf8().data()));
    106         GUniqueOutPtr<GError> error;
    107123        m_outputStream = adoptGRef(g_file_replace(m_intermediateFile.get(), 0, TRUE, G_FILE_CREATE_NONE, 0, &error.outPtr()));
    108124        if (!m_outputStream) {
     
    111127        }
    112128
    113         m_download->didCreateDestination(m_destinationURI);
     129        m_download->didCreateDestination(destinationURI);
    114130    }
    115131
     
    135151        m_outputStream = 0;
    136152
     153        ASSERT(m_destinationFile);
    137154        ASSERT(m_intermediateFile);
    138         GRefPtr<GFile> destinationFile = adoptGRef(g_file_new_for_uri(m_destinationURI.utf8().data()));
    139155        GUniqueOutPtr<GError> error;
    140         if (!g_file_move(m_intermediateFile.get(), destinationFile.get(), m_allowOverwrite ? G_FILE_COPY_OVERWRITE : G_FILE_COPY_NONE, nullptr, nullptr, nullptr, &error.outPtr())) {
     156        if (!g_file_move(m_intermediateFile.get(), m_destinationFile.get(), G_FILE_COPY_OVERWRITE, nullptr, nullptr, nullptr, &error.outPtr())) {
    141157            downloadFailed(platformDownloadDestinationError(m_response, error->message));
    142158            return;
     
    147163        g_file_info_set_attribute_string(info.get(), "metadata::download-uri", uri.data());
    148164        g_file_info_set_attribute_string(info.get(), "xattr::xdg.origin.url", uri.data());
    149         g_file_set_attributes_async(destinationFile.get(), info.get(), G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, nullptr, nullptr, nullptr);
     165        g_file_set_attributes_async(m_destinationFile.get(), info.get(), G_FILE_QUERY_INFO_NONE, G_PRIORITY_DEFAULT, nullptr, nullptr, nullptr);
    150166
    151167        m_download->didFinish();
     
    170186    {
    171187        handle->cancel();
    172         deleteIntermediateFileInNeeded();
     188        deleteFilesIfNeeded();
    173189        m_download->didCancel(IPC::DataReference());
    174190    }
     
    194210    GRefPtr<GFileOutputStream> m_outputStream;
    195211    ResourceResponse m_response;
    196     String m_destinationURI;
     212    GRefPtr<GFile> m_destinationFile;
    197213    GRefPtr<GFile> m_intermediateFile;
    198214    ResourceResponse m_delayedResponse;
Note: See TracChangeset for help on using the changeset viewer.