OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2010 Google Inc. All rights reserved. | 2 * Copyright (C) 2010 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 #include "modules/filesystem/EntryCallback.h" | 44 #include "modules/filesystem/EntryCallback.h" |
45 #include "modules/filesystem/ErrorCallback.h" | 45 #include "modules/filesystem/ErrorCallback.h" |
46 #include "modules/filesystem/FileEntry.h" | 46 #include "modules/filesystem/FileEntry.h" |
47 #include "modules/filesystem/FileSystemCallback.h" | 47 #include "modules/filesystem/FileSystemCallback.h" |
48 #include "modules/filesystem/FileWriterBase.h" | 48 #include "modules/filesystem/FileWriterBase.h" |
49 #include "modules/filesystem/FileWriterBaseCallback.h" | 49 #include "modules/filesystem/FileWriterBaseCallback.h" |
50 #include "modules/filesystem/Metadata.h" | 50 #include "modules/filesystem/Metadata.h" |
51 #include "modules/filesystem/MetadataCallback.h" | 51 #include "modules/filesystem/MetadataCallback.h" |
52 #include "platform/FileMetadata.h" | 52 #include "platform/FileMetadata.h" |
53 #include "public/platform/WebFileWriter.h" | 53 #include "public/platform/WebFileWriter.h" |
| 54 #include "wtf/PtrUtil.h" |
| 55 #include <memory> |
54 | 56 |
55 namespace blink { | 57 namespace blink { |
56 | 58 |
57 FileSystemCallbacksBase::FileSystemCallbacksBase(ErrorCallback* errorCallback, D
OMFileSystemBase* fileSystem, ExecutionContext* context) | 59 FileSystemCallbacksBase::FileSystemCallbacksBase(ErrorCallback* errorCallback, D
OMFileSystemBase* fileSystem, ExecutionContext* context) |
58 : m_errorCallback(errorCallback) | 60 : m_errorCallback(errorCallback) |
59 , m_fileSystem(fileSystem) | 61 , m_fileSystem(fileSystem) |
60 , m_executionContext(context) | 62 , m_executionContext(context) |
61 { | 63 { |
62 if (m_fileSystem) | 64 if (m_fileSystem) |
63 m_fileSystem->addPendingCallbacks(); | 65 m_fileSystem->addPendingCallbacks(); |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
97 ASSERT(callback); | 99 ASSERT(callback); |
98 if (shouldScheduleCallback()) | 100 if (shouldScheduleCallback()) |
99 DOMFileSystem::scheduleCallback(m_executionContext.get(), callback); | 101 DOMFileSystem::scheduleCallback(m_executionContext.get(), callback); |
100 else if (callback) | 102 else if (callback) |
101 callback->handleEvent(); | 103 callback->handleEvent(); |
102 m_executionContext.clear(); | 104 m_executionContext.clear(); |
103 } | 105 } |
104 | 106 |
105 // EntryCallbacks ------------------------------------------------------------- | 107 // EntryCallbacks ------------------------------------------------------------- |
106 | 108 |
107 PassOwnPtr<AsyncFileSystemCallbacks> EntryCallbacks::create(EntryCallback* succe
ssCallback, ErrorCallback* errorCallback, ExecutionContext* context, DOMFileSyst
emBase* fileSystem, const String& expectedPath, bool isDirectory) | 109 std::unique_ptr<AsyncFileSystemCallbacks> EntryCallbacks::create(EntryCallback*
successCallback, ErrorCallback* errorCallback, ExecutionContext* context, DOMFil
eSystemBase* fileSystem, const String& expectedPath, bool isDirectory) |
108 { | 110 { |
109 return adoptPtr(new EntryCallbacks(successCallback, errorCallback, context,
fileSystem, expectedPath, isDirectory)); | 111 return wrapUnique(new EntryCallbacks(successCallback, errorCallback, context
, fileSystem, expectedPath, isDirectory)); |
110 } | 112 } |
111 | 113 |
112 EntryCallbacks::EntryCallbacks(EntryCallback* successCallback, ErrorCallback* er
rorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem, const Str
ing& expectedPath, bool isDirectory) | 114 EntryCallbacks::EntryCallbacks(EntryCallback* successCallback, ErrorCallback* er
rorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem, const Str
ing& expectedPath, bool isDirectory) |
113 : FileSystemCallbacksBase(errorCallback, fileSystem, context) | 115 : FileSystemCallbacksBase(errorCallback, fileSystem, context) |
114 , m_successCallback(successCallback) | 116 , m_successCallback(successCallback) |
115 , m_expectedPath(expectedPath) | 117 , m_expectedPath(expectedPath) |
116 , m_isDirectory(isDirectory) | 118 , m_isDirectory(isDirectory) |
117 { | 119 { |
118 } | 120 } |
119 | 121 |
120 void EntryCallbacks::didSucceed() | 122 void EntryCallbacks::didSucceed() |
121 { | 123 { |
122 if (m_successCallback) { | 124 if (m_successCallback) { |
123 if (m_isDirectory) | 125 if (m_isDirectory) |
124 handleEventOrScheduleCallback(m_successCallback.release(), Directory
Entry::create(m_fileSystem, m_expectedPath)); | 126 handleEventOrScheduleCallback(m_successCallback.release(), Directory
Entry::create(m_fileSystem, m_expectedPath)); |
125 else | 127 else |
126 handleEventOrScheduleCallback(m_successCallback.release(), FileEntry
::create(m_fileSystem, m_expectedPath)); | 128 handleEventOrScheduleCallback(m_successCallback.release(), FileEntry
::create(m_fileSystem, m_expectedPath)); |
127 } | 129 } |
128 } | 130 } |
129 | 131 |
130 // EntriesCallbacks ----------------------------------------------------------- | 132 // EntriesCallbacks ----------------------------------------------------------- |
131 | 133 |
132 PassOwnPtr<AsyncFileSystemCallbacks> EntriesCallbacks::create(EntriesCallback* s
uccessCallback, ErrorCallback* errorCallback, ExecutionContext* context, Directo
ryReaderBase* directoryReader, const String& basePath) | 134 std::unique_ptr<AsyncFileSystemCallbacks> EntriesCallbacks::create(EntriesCallba
ck* successCallback, ErrorCallback* errorCallback, ExecutionContext* context, Di
rectoryReaderBase* directoryReader, const String& basePath) |
133 { | 135 { |
134 return adoptPtr(new EntriesCallbacks(successCallback, errorCallback, context
, directoryReader, basePath)); | 136 return wrapUnique(new EntriesCallbacks(successCallback, errorCallback, conte
xt, directoryReader, basePath)); |
135 } | 137 } |
136 | 138 |
137 EntriesCallbacks::EntriesCallbacks(EntriesCallback* successCallback, ErrorCallba
ck* errorCallback, ExecutionContext* context, DirectoryReaderBase* directoryRead
er, const String& basePath) | 139 EntriesCallbacks::EntriesCallbacks(EntriesCallback* successCallback, ErrorCallba
ck* errorCallback, ExecutionContext* context, DirectoryReaderBase* directoryRead
er, const String& basePath) |
138 : FileSystemCallbacksBase(errorCallback, directoryReader->filesystem(), cont
ext) | 140 : FileSystemCallbacksBase(errorCallback, directoryReader->filesystem(), cont
ext) |
139 , m_successCallback(successCallback) | 141 , m_successCallback(successCallback) |
140 , m_directoryReader(directoryReader) | 142 , m_directoryReader(directoryReader) |
141 , m_basePath(basePath) | 143 , m_basePath(basePath) |
142 { | 144 { |
143 ASSERT(m_directoryReader); | 145 ASSERT(m_directoryReader); |
144 } | 146 } |
(...skipping 11 matching lines...) Expand all Loading... |
156 m_directoryReader->setHasMoreEntries(hasMore); | 158 m_directoryReader->setHasMoreEntries(hasMore); |
157 EntryHeapVector entries; | 159 EntryHeapVector entries; |
158 entries.swap(m_entries); | 160 entries.swap(m_entries); |
159 // FIXME: delay the callback iff shouldScheduleCallback() is true. | 161 // FIXME: delay the callback iff shouldScheduleCallback() is true. |
160 if (m_successCallback) | 162 if (m_successCallback) |
161 m_successCallback->handleEvent(entries); | 163 m_successCallback->handleEvent(entries); |
162 } | 164 } |
163 | 165 |
164 // FileSystemCallbacks -------------------------------------------------------- | 166 // FileSystemCallbacks -------------------------------------------------------- |
165 | 167 |
166 PassOwnPtr<AsyncFileSystemCallbacks> FileSystemCallbacks::create(FileSystemCallb
ack* successCallback, ErrorCallback* errorCallback, ExecutionContext* context, F
ileSystemType type) | 168 std::unique_ptr<AsyncFileSystemCallbacks> FileSystemCallbacks::create(FileSystem
Callback* successCallback, ErrorCallback* errorCallback, ExecutionContext* conte
xt, FileSystemType type) |
167 { | 169 { |
168 return adoptPtr(new FileSystemCallbacks(successCallback, errorCallback, cont
ext, type)); | 170 return wrapUnique(new FileSystemCallbacks(successCallback, errorCallback, co
ntext, type)); |
169 } | 171 } |
170 | 172 |
171 FileSystemCallbacks::FileSystemCallbacks(FileSystemCallback* successCallback, Er
rorCallback* errorCallback, ExecutionContext* context, FileSystemType type) | 173 FileSystemCallbacks::FileSystemCallbacks(FileSystemCallback* successCallback, Er
rorCallback* errorCallback, ExecutionContext* context, FileSystemType type) |
172 : FileSystemCallbacksBase(errorCallback, nullptr, context) | 174 : FileSystemCallbacksBase(errorCallback, nullptr, context) |
173 , m_successCallback(successCallback) | 175 , m_successCallback(successCallback) |
174 , m_type(type) | 176 , m_type(type) |
175 { | 177 { |
176 } | 178 } |
177 | 179 |
178 void FileSystemCallbacks::didOpenFileSystem(const String& name, const KURL& root
URL) | 180 void FileSystemCallbacks::didOpenFileSystem(const String& name, const KURL& root
URL) |
179 { | 181 { |
180 if (m_successCallback) | 182 if (m_successCallback) |
181 handleEventOrScheduleCallback(m_successCallback.release(), DOMFileSystem
::create(m_executionContext.get(), name, m_type, rootURL)); | 183 handleEventOrScheduleCallback(m_successCallback.release(), DOMFileSystem
::create(m_executionContext.get(), name, m_type, rootURL)); |
182 } | 184 } |
183 | 185 |
184 // ResolveURICallbacks -------------------------------------------------------- | 186 // ResolveURICallbacks -------------------------------------------------------- |
185 | 187 |
186 PassOwnPtr<AsyncFileSystemCallbacks> ResolveURICallbacks::create(EntryCallback*
successCallback, ErrorCallback* errorCallback, ExecutionContext* context) | 188 std::unique_ptr<AsyncFileSystemCallbacks> ResolveURICallbacks::create(EntryCallb
ack* successCallback, ErrorCallback* errorCallback, ExecutionContext* context) |
187 { | 189 { |
188 return adoptPtr(new ResolveURICallbacks(successCallback, errorCallback, cont
ext)); | 190 return wrapUnique(new ResolveURICallbacks(successCallback, errorCallback, co
ntext)); |
189 } | 191 } |
190 | 192 |
191 ResolveURICallbacks::ResolveURICallbacks(EntryCallback* successCallback, ErrorCa
llback* errorCallback, ExecutionContext* context) | 193 ResolveURICallbacks::ResolveURICallbacks(EntryCallback* successCallback, ErrorCa
llback* errorCallback, ExecutionContext* context) |
192 : FileSystemCallbacksBase(errorCallback, nullptr, context) | 194 : FileSystemCallbacksBase(errorCallback, nullptr, context) |
193 , m_successCallback(successCallback) | 195 , m_successCallback(successCallback) |
194 { | 196 { |
195 } | 197 } |
196 | 198 |
197 void ResolveURICallbacks::didResolveURL(const String& name, const KURL& rootURL,
FileSystemType type, const String& filePath, bool isDirectory) | 199 void ResolveURICallbacks::didResolveURL(const String& name, const KURL& rootURL,
FileSystemType type, const String& filePath, bool isDirectory) |
198 { | 200 { |
199 DOMFileSystem* filesystem = DOMFileSystem::create(m_executionContext.get(),
name, type, rootURL); | 201 DOMFileSystem* filesystem = DOMFileSystem::create(m_executionContext.get(),
name, type, rootURL); |
200 DirectoryEntry* root = filesystem->root(); | 202 DirectoryEntry* root = filesystem->root(); |
201 | 203 |
202 String absolutePath; | 204 String absolutePath; |
203 if (!DOMFileSystemBase::pathToAbsolutePath(type, root, filePath, absolutePat
h)) { | 205 if (!DOMFileSystemBase::pathToAbsolutePath(type, root, filePath, absolutePat
h)) { |
204 handleEventOrScheduleCallback(m_errorCallback.release(), FileError::crea
te(FileError::INVALID_MODIFICATION_ERR)); | 206 handleEventOrScheduleCallback(m_errorCallback.release(), FileError::crea
te(FileError::INVALID_MODIFICATION_ERR)); |
205 return; | 207 return; |
206 } | 208 } |
207 | 209 |
208 if (isDirectory) | 210 if (isDirectory) |
209 handleEventOrScheduleCallback(m_successCallback.release(), DirectoryEntr
y::create(filesystem, absolutePath)); | 211 handleEventOrScheduleCallback(m_successCallback.release(), DirectoryEntr
y::create(filesystem, absolutePath)); |
210 else | 212 else |
211 handleEventOrScheduleCallback(m_successCallback.release(), FileEntry::cr
eate(filesystem, absolutePath)); | 213 handleEventOrScheduleCallback(m_successCallback.release(), FileEntry::cr
eate(filesystem, absolutePath)); |
212 } | 214 } |
213 | 215 |
214 // MetadataCallbacks ---------------------------------------------------------- | 216 // MetadataCallbacks ---------------------------------------------------------- |
215 | 217 |
216 PassOwnPtr<AsyncFileSystemCallbacks> MetadataCallbacks::create(MetadataCallback*
successCallback, ErrorCallback* errorCallback, ExecutionContext* context, DOMFi
leSystemBase* fileSystem) | 218 std::unique_ptr<AsyncFileSystemCallbacks> MetadataCallbacks::create(MetadataCall
back* successCallback, ErrorCallback* errorCallback, ExecutionContext* context,
DOMFileSystemBase* fileSystem) |
217 { | 219 { |
218 return adoptPtr(new MetadataCallbacks(successCallback, errorCallback, contex
t, fileSystem)); | 220 return wrapUnique(new MetadataCallbacks(successCallback, errorCallback, cont
ext, fileSystem)); |
219 } | 221 } |
220 | 222 |
221 MetadataCallbacks::MetadataCallbacks(MetadataCallback* successCallback, ErrorCal
lback* errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem) | 223 MetadataCallbacks::MetadataCallbacks(MetadataCallback* successCallback, ErrorCal
lback* errorCallback, ExecutionContext* context, DOMFileSystemBase* fileSystem) |
222 : FileSystemCallbacksBase(errorCallback, fileSystem, context) | 224 : FileSystemCallbacksBase(errorCallback, fileSystem, context) |
223 , m_successCallback(successCallback) | 225 , m_successCallback(successCallback) |
224 { | 226 { |
225 } | 227 } |
226 | 228 |
227 void MetadataCallbacks::didReadMetadata(const FileMetadata& metadata) | 229 void MetadataCallbacks::didReadMetadata(const FileMetadata& metadata) |
228 { | 230 { |
229 if (m_successCallback) | 231 if (m_successCallback) |
230 handleEventOrScheduleCallback(m_successCallback.release(), Metadata::cre
ate(metadata)); | 232 handleEventOrScheduleCallback(m_successCallback.release(), Metadata::cre
ate(metadata)); |
231 } | 233 } |
232 | 234 |
233 // FileWriterBaseCallbacks ---------------------------------------------------- | 235 // FileWriterBaseCallbacks ---------------------------------------------------- |
234 | 236 |
235 PassOwnPtr<AsyncFileSystemCallbacks> FileWriterBaseCallbacks::create(FileWriterB
ase* fileWriter, FileWriterBaseCallback* successCallback, ErrorCallback* errorCa
llback, ExecutionContext* context) | 237 std::unique_ptr<AsyncFileSystemCallbacks> FileWriterBaseCallbacks::create(FileWr
iterBase* fileWriter, FileWriterBaseCallback* successCallback, ErrorCallback* er
rorCallback, ExecutionContext* context) |
236 { | 238 { |
237 return adoptPtr(new FileWriterBaseCallbacks(fileWriter, successCallback, err
orCallback, context)); | 239 return wrapUnique(new FileWriterBaseCallbacks(fileWriter, successCallback, e
rrorCallback, context)); |
238 } | 240 } |
239 | 241 |
240 FileWriterBaseCallbacks::FileWriterBaseCallbacks(FileWriterBase* fileWriter, Fil
eWriterBaseCallback* successCallback, ErrorCallback* errorCallback, ExecutionCon
text* context) | 242 FileWriterBaseCallbacks::FileWriterBaseCallbacks(FileWriterBase* fileWriter, Fil
eWriterBaseCallback* successCallback, ErrorCallback* errorCallback, ExecutionCon
text* context) |
241 : FileSystemCallbacksBase(errorCallback, nullptr, context) | 243 : FileSystemCallbacksBase(errorCallback, nullptr, context) |
242 , m_fileWriter(fileWriter) | 244 , m_fileWriter(fileWriter) |
243 , m_successCallback(successCallback) | 245 , m_successCallback(successCallback) |
244 { | 246 { |
245 } | 247 } |
246 | 248 |
247 void FileWriterBaseCallbacks::didCreateFileWriter(PassOwnPtr<WebFileWriter> file
Writer, long long length) | 249 void FileWriterBaseCallbacks::didCreateFileWriter(std::unique_ptr<WebFileWriter>
fileWriter, long long length) |
248 { | 250 { |
249 m_fileWriter->initialize(std::move(fileWriter), length); | 251 m_fileWriter->initialize(std::move(fileWriter), length); |
250 if (m_successCallback) | 252 if (m_successCallback) |
251 handleEventOrScheduleCallback(m_successCallback.release(), m_fileWriter.
release()); | 253 handleEventOrScheduleCallback(m_successCallback.release(), m_fileWriter.
release()); |
252 } | 254 } |
253 | 255 |
254 // SnapshotFileCallback ------------------------------------------------------- | 256 // SnapshotFileCallback ------------------------------------------------------- |
255 | 257 |
256 PassOwnPtr<AsyncFileSystemCallbacks> SnapshotFileCallback::create(DOMFileSystemB
ase* filesystem, const String& name, const KURL& url, BlobCallback* successCallb
ack, ErrorCallback* errorCallback, ExecutionContext* context) | 258 std::unique_ptr<AsyncFileSystemCallbacks> SnapshotFileCallback::create(DOMFileSy
stemBase* filesystem, const String& name, const KURL& url, BlobCallback* success
Callback, ErrorCallback* errorCallback, ExecutionContext* context) |
257 { | 259 { |
258 return adoptPtr(new SnapshotFileCallback(filesystem, name, url, successCallb
ack, errorCallback, context)); | 260 return wrapUnique(new SnapshotFileCallback(filesystem, name, url, successCal
lback, errorCallback, context)); |
259 } | 261 } |
260 | 262 |
261 SnapshotFileCallback::SnapshotFileCallback(DOMFileSystemBase* filesystem, const
String& name, const KURL& url, BlobCallback* successCallback, ErrorCallback* err
orCallback, ExecutionContext* context) | 263 SnapshotFileCallback::SnapshotFileCallback(DOMFileSystemBase* filesystem, const
String& name, const KURL& url, BlobCallback* successCallback, ErrorCallback* err
orCallback, ExecutionContext* context) |
262 : FileSystemCallbacksBase(errorCallback, filesystem, context) | 264 : FileSystemCallbacksBase(errorCallback, filesystem, context) |
263 , m_name(name) | 265 , m_name(name) |
264 , m_url(url) | 266 , m_url(url) |
265 , m_successCallback(successCallback) | 267 , m_successCallback(successCallback) |
266 { | 268 { |
267 } | 269 } |
268 | 270 |
269 void SnapshotFileCallback::didCreateSnapshotFile(const FileMetadata& metadata, P
assRefPtr<BlobDataHandle> snapshot) | 271 void SnapshotFileCallback::didCreateSnapshotFile(const FileMetadata& metadata, P
assRefPtr<BlobDataHandle> snapshot) |
270 { | 272 { |
271 if (!m_successCallback) | 273 if (!m_successCallback) |
272 return; | 274 return; |
273 | 275 |
274 // We can't directly use the snapshot blob data handle because the content t
ype on it hasn't been set. | 276 // We can't directly use the snapshot blob data handle because the content t
ype on it hasn't been set. |
275 // The |snapshot| param is here to provide a a chain of custody thru thread
bridging that is held onto until | 277 // The |snapshot| param is here to provide a a chain of custody thru thread
bridging that is held onto until |
276 // *after* we've coined a File with a new handle that has the correct type s
et on it. This allows the | 278 // *after* we've coined a File with a new handle that has the correct type s
et on it. This allows the |
277 // blob storage system to track when a temp file can and can't be safely del
eted. | 279 // blob storage system to track when a temp file can and can't be safely del
eted. |
278 | 280 |
279 handleEventOrScheduleCallback(m_successCallback.release(), DOMFileSystemBase
::createFile(metadata, m_url, m_fileSystem->type(), m_name)); | 281 handleEventOrScheduleCallback(m_successCallback.release(), DOMFileSystemBase
::createFile(metadata, m_url, m_fileSystem->type(), m_name)); |
280 } | 282 } |
281 | 283 |
282 // VoidCallbacks -------------------------------------------------------------- | 284 // VoidCallbacks -------------------------------------------------------------- |
283 | 285 |
284 PassOwnPtr<AsyncFileSystemCallbacks> VoidCallbacks::create(VoidCallback* success
Callback, ErrorCallback* errorCallback, ExecutionContext* context, DOMFileSystem
Base* fileSystem) | 286 std::unique_ptr<AsyncFileSystemCallbacks> VoidCallbacks::create(VoidCallback* su
ccessCallback, ErrorCallback* errorCallback, ExecutionContext* context, DOMFileS
ystemBase* fileSystem) |
285 { | 287 { |
286 return adoptPtr(new VoidCallbacks(successCallback, errorCallback, context, f
ileSystem)); | 288 return wrapUnique(new VoidCallbacks(successCallback, errorCallback, context,
fileSystem)); |
287 } | 289 } |
288 | 290 |
289 VoidCallbacks::VoidCallbacks(VoidCallback* successCallback, ErrorCallback* error
Callback, ExecutionContext* context, DOMFileSystemBase* fileSystem) | 291 VoidCallbacks::VoidCallbacks(VoidCallback* successCallback, ErrorCallback* error
Callback, ExecutionContext* context, DOMFileSystemBase* fileSystem) |
290 : FileSystemCallbacksBase(errorCallback, fileSystem, context) | 292 : FileSystemCallbacksBase(errorCallback, fileSystem, context) |
291 , m_successCallback(successCallback) | 293 , m_successCallback(successCallback) |
292 { | 294 { |
293 } | 295 } |
294 | 296 |
295 void VoidCallbacks::didSucceed() | 297 void VoidCallbacks::didSucceed() |
296 { | 298 { |
297 if (m_successCallback) | 299 if (m_successCallback) |
298 handleEventOrScheduleCallback(m_successCallback.release()); | 300 handleEventOrScheduleCallback(m_successCallback.release()); |
299 } | 301 } |
300 | 302 |
301 } // namespace blink | 303 } // namespace blink |
OLD | NEW |