Factor platform I/O out from NetworkCacheStorage
[WebKit-https.git] / Source / WebKit2 / NetworkProcess / cache / NetworkCacheIOChannelCocoa.mm
1 /*
2  * Copyright (C) 2014-2015 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 INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "NetworkCacheIOChannel.h"
28
29 #if ENABLE(NETWORK_CACHE)
30
31 #include "NetworkCacheFileSystemPosix.h"
32 #include <dispatch/dispatch.h>
33 #include <mach/vm_param.h>
34 #include <sys/mman.h>
35 #include <sys/stat.h>
36 #include <wtf/text/CString.h>
37 #include <wtf/text/StringBuilder.h>
38
39 namespace WebKit {
40
41 NetworkCacheIOChannel::NetworkCacheIOChannel(int fd)
42     : m_fileDescriptor(fd)
43 {
44     m_dispatchIO = adoptDispatch(dispatch_io_create(DISPATCH_IO_RANDOM, fd, dispatch_get_main_queue(), [fd](int) {
45         close(fd);
46     }));
47     ASSERT(m_dispatchIO.get());
48     // This makes the channel read/write all data before invoking the handlers.
49     dispatch_io_set_low_water(m_dispatchIO.get(), std::numeric_limits<size_t>::max());
50 }
51
52 Ref<NetworkCacheIOChannel> NetworkCacheIOChannel::open(const String& filePath, NetworkCacheIOChannel::Type type)
53 {
54     int oflag;
55     mode_t mode;
56
57     switch (type) {
58     case Type::Create:
59         oflag = O_RDWR | O_CREAT | O_TRUNC | O_NONBLOCK;
60         mode = S_IRUSR | S_IWUSR;
61         break;
62     case Type::Write:
63         oflag = O_WRONLY | O_NONBLOCK;
64         mode = S_IRUSR | S_IWUSR;
65         break;
66     case Type::Read:
67         oflag = O_RDONLY | O_NONBLOCK;
68         mode = 0;
69     }
70
71     CString path = WebCore::fileSystemRepresentation(filePath);
72     int fd = ::open(path.data(), oflag, mode);
73
74     return adoptRef(*new NetworkCacheIOChannel(fd));
75 }
76
77 void NetworkCacheIOChannel::read(size_t offset, size_t size, std::function<void ( NetworkCacheData&, int error)> completionHandler)
78 {
79     RefPtr<NetworkCacheIOChannel> channel(this);
80     bool didCallCompletionHandler = false;
81     dispatch_io_read(m_dispatchIO.get(), offset, size, dispatch_get_main_queue(), [channel, completionHandler, didCallCompletionHandler](bool done, dispatch_data_t fileData, int error) mutable {
82         if (done) {
83             if (!didCallCompletionHandler) {
84                 NetworkCacheData nullData;
85                 completionHandler(nullData, error);
86             }
87             return;
88         }
89         ASSERT(!didCallCompletionHandler);
90         NetworkCacheData data(fileData);
91         completionHandler(data, error);
92         didCallCompletionHandler = true;
93     });
94 }
95
96 void NetworkCacheIOChannel::write(size_t offset, const NetworkCacheData& data, std::function<void (int error)> completionHandler)
97 {
98     RefPtr<NetworkCacheIOChannel> channel(this);
99     auto dispatchData = data.dispatchData();
100     dispatch_io_write(m_dispatchIO.get(), offset, dispatchData, dispatch_get_main_queue(), [channel, completionHandler](bool done, dispatch_data_t fileData, int error) {
101         ASSERT_UNUSED(done, done);
102         completionHandler(error);
103     });
104 }
105
106 }
107 #endif