<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[182161] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/182161">182161</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2015-03-30 16:22:09 -0700 (Mon, 30 Mar 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Content Extensions] Flesh out the UserContentExtensionStore
https://bugs.webkit.org/show_bug.cgi?id=143123

Patch by Sam Weinig &lt;sam@webkit.org&gt; on 2015-03-30
Reviewed by Benjamin Poulain.

Source/WebCore:

- Adds a variant of getFileSize() that takes a PlatformFileHandle.
- Adds a new file system function, rename() which operates as the POSIX
  rename function does.

* platform/FileSystem.h:
Add new functions.

* platform/posix/FileSystemPOSIX.cpp:
(WebCore::renameFile):
(WebCore::getFileSize):
Add implementations.

* platform/gtk/FileSystemGtk.cpp:
(WebCore::renameFile):
(WebCore::getFileSize):
* platform/win/FileSystemWin.cpp:
(WebCore::getFileSize):
(WebCore::renameFile):
Add stubs.

Source/WebKit2:

* Shared/WebCompiledContentExtension.cpp:
(WebKit::WebCompiledContentExtension::createFromCompiledContentExtensionData):
* Shared/WebCompiledContentExtensionData.cpp:
(WebKit::WebCompiledContentExtensionData::encode):
(WebKit::WebCompiledContentExtensionData::decode):
* Shared/WebCompiledContentExtensionData.h:
(WebKit::WebCompiledContentExtensionData::WebCompiledContentExtensionData):
Switch the order in memory of actions and bytecode (and switch the order of the
variables as well, to keep it clear). This will become necessary when streaming
the data to disk, as actions are created before the bytecode and we would have to keep them
in memory until the bytecode was finished compiling if they didn't come before in the file.

* UIProcess/API/APIUserContentExtensionStore.h:
* UIProcess/API/APIUserContentExtensionStore.cpp:
(API::UserContentExtensionStore::defaultStore):
Add accessor for the processes default shared store.

(API::constructedPath):
Helper for constructing the path to a file in the store based on identifier.

(API::encodeContentExtensionMetaData):
(API::decodeContentExtensionMetaData):
Helpers for encoding/decoding the file metadata (version, bytecode size, actions size).

(API::openAndMapContentExtension):
Helper to open and map a filed back content extension.

(API::writeDataToFile):
Helper to write a Data object to a file.

(API::compiledToFile):
Helper to run the content extension compiler and write it to disk. It first
writes it to a temporary file and then does an atomic rename operation to put
the file in the final location. Doing this means that if the process crashes while
the compile is taking place, the partially written file won't end up in the cache,
but rather, will be cleaned up by the OS.

(API::UserContentExtensionStore::lookupContentExtension):
API entry point to lookup an extension that has been compiled to disk. On a background queue,
it attempts to open and map the extension (based on the identifier passed in) and return it
to the caller via the callback function passed in.

(API::UserContentExtensionStore::compileContentExtension):
API entry point to compile an extension and write it to store. On a background queue, it
compiles the file to disk and if successful, returns the memory mapped data via the callback
function passed in.

(API::UserContentExtensionStore::removeContentExtension):
API entry point to remove an extension from the store. On a background queue, it
unlinks the extension (based on the identifier passed in) and tells the caller it completed
the action vial the callback function passed in.

(API::UserContentExtensionStore::synchronousRemoveAllContentExtensions):
Helper for testing which synchronously unlinks all the files in the store.

(API::userContentExtensionStoreErrorCategory):
std::error_code adaptor for some generic errors that can happen in the store. We will want
to flesh these out further.

* UIProcess/API/Cocoa/APIUserContentExtensionStoreCocoa.mm: Added.
(API::UserContentExtensionStore::defaultStorePath):
Helper to get the platform specific path for the store.

* UIProcess/API/C/WKUserContentExtensionStoreRef.cpp:
(WKUserContentExtensionStoreGetTypeID):
Add ENABLE(CONTENT_EXTENSIONS) guards.

* UIProcess/API/Cocoa/_WKUserContentExtensionStore.h:
* UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm:
(-[_WKUserContentExtensionStore dealloc]):
(+[_WKUserContentExtensionStore defaultStore]):
(-[_WKUserContentExtensionStore compileContentExtensionForIdentifier:encodedContentExtension:completionHandler:]):
(-[_WKUserContentExtensionStore lookupContentExtensionForIdentifier:completionHandler:]):
(-[_WKUserContentExtensionStore removeContentExtensionForIdentifier:completionHandler:]):
(-[_WKUserContentExtensionStore _removeAllContentExtensions]):
(-[_WKUserContentExtensionStore init]): Deleted.
* UIProcess/API/Cocoa/_WKUserContentExtensionStoreInternal.h:
* UIProcess/API/Cocoa/_WKUserContentExtensionStorePrivate.h: Added.
SPI wrappers for the store.

* WebKit2.xcodeproj/project.pbxproj:
Add new files.

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKit2Cocoa/_WKUserContentExtensionStore.mm: Added.
Add tests for _WKUserContentExtensionStore.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformFileSystemh">trunk/Source/WebCore/platform/FileSystem.h</a></li>
<li><a href="#trunkSourceWebCoreplatformgtkFileSystemGtkcpp">trunk/Source/WebCore/platform/gtk/FileSystemGtk.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformposixFileSystemPOSIXcpp">trunk/Source/WebCore/platform/posix/FileSystemPOSIX.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformwinFileSystemWincpp">trunk/Source/WebCore/platform/win/FileSystemWin.cpp</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2SharedWebCompiledContentExtensioncpp">trunk/Source/WebKit2/Shared/WebCompiledContentExtension.cpp</a></li>
<li><a href="#trunkSourceWebKit2SharedWebCompiledContentExtensionDatacpp">trunk/Source/WebKit2/Shared/WebCompiledContentExtensionData.cpp</a></li>
<li><a href="#trunkSourceWebKit2SharedWebCompiledContentExtensionDatah">trunk/Source/WebKit2/Shared/WebCompiledContentExtensionData.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIAPIUserContentExtensionStorecpp">trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPIAPIUserContentExtensionStoreh">trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICWKUserContentExtensionStoreRefcpp">trunk/Source/WebKit2/UIProcess/API/C/WKUserContentExtensionStoreRef.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoa_WKUserContentExtensionStoreh">trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoa_WKUserContentExtensionStoremm">trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoa_WKUserContentExtensionStoreInternalh">trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStoreInternal.h</a></li>
<li><a href="#trunkSourceWebKit2WebKit2xcodeprojprojectpbxproj">trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkToolsChangeLog">trunk/Tools/ChangeLog</a></li>
<li><a href="#trunkToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj">trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoaAPIUserContentExtensionStoreCocoamm">trunk/Source/WebKit2/UIProcess/API/Cocoa/APIUserContentExtensionStoreCocoa.mm</a></li>
<li><a href="#trunkSourceWebKit2UIProcessAPICocoa_WKUserContentExtensionStorePrivateh">trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStorePrivate.h</a></li>
<li><a href="#trunkToolsTestWebKitAPITestsWebKit2Cocoa_WKUserContentExtensionStoremm">trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/_WKUserContentExtensionStore.mm</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebCore/ChangeLog        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2015-03-30  Sam Weinig  &lt;sam@webkit.org&gt;
+
+        [Content Extensions] Flesh out the UserContentExtensionStore
+        https://bugs.webkit.org/show_bug.cgi?id=143123
+
+        Reviewed by Benjamin Poulain.
+
+        - Adds a variant of getFileSize() that takes a PlatformFileHandle.
+        - Adds a new file system function, rename() which operates as the POSIX
+          rename function does.
+
+        * platform/FileSystem.h:
+        Add new functions.
+
+        * platform/posix/FileSystemPOSIX.cpp:
+        (WebCore::renameFile):
+        (WebCore::getFileSize):
+        Add implementations.
+
+        * platform/gtk/FileSystemGtk.cpp:
+        (WebCore::renameFile):
+        (WebCore::getFileSize):
+        * platform/win/FileSystemWin.cpp:
+        (WebCore::getFileSize):
+        (WebCore::renameFile):
+        Add stubs.
+
</ins><span class="cx"> 2015-03-30  Per Arne Vollan  &lt;peavo@outlook.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [WinCairo] Crash when closing window while video is loading
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformFileSystemh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/FileSystem.h (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/FileSystem.h        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebCore/platform/FileSystem.h        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -137,7 +137,9 @@
</span><span class="cx"> WEBCORE_EXPORT bool fileExists(const String&amp;);
</span><span class="cx"> WEBCORE_EXPORT bool deleteFile(const String&amp;);
</span><span class="cx"> WEBCORE_EXPORT bool deleteEmptyDirectory(const String&amp;);
</span><ins>+WEBCORE_EXPORT bool renameFile(const String&amp; oldPath, const String&amp; newPath);
</ins><span class="cx"> WEBCORE_EXPORT bool getFileSize(const String&amp;, long long&amp; result);
</span><ins>+WEBCORE_EXPORT bool getFileSize(PlatformFileHandle, long long&amp; result);
</ins><span class="cx"> WEBCORE_EXPORT bool getFileModificationTime(const String&amp;, time_t&amp; result);
</span><span class="cx"> WEBCORE_EXPORT bool getFileCreationTime(const String&amp;, time_t&amp; result); // Not all platforms store file creation time.
</span><span class="cx"> bool getFileMetadata(const String&amp;, FileMetadata&amp;);
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformgtkFileSystemGtkcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/gtk/FileSystemGtk.cpp (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/gtk/FileSystemGtk.cpp        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebCore/platform/gtk/FileSystemGtk.cpp        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -24,6 +24,7 @@
</span><span class="cx"> #include &quot;FileSystem.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #include &quot;FileMetadata.h&quot;
</span><ins>+#include &quot;NotImplemented.h&quot;
</ins><span class="cx"> #include &quot;UUID.h&quot;
</span><span class="cx"> #include &lt;gio/gio.h&gt;
</span><span class="cx"> #include &lt;glib.h&gt;
</span><span class="lines">@@ -110,6 +111,12 @@
</span><span class="cx">     return filename ? g_rmdir(filename.get()) != -1 : false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool renameFile(const String&amp;, const String&amp;)
+{
+    notImplemented();
+    return false;
+}
+
</ins><span class="cx"> static bool getFileStat(const String&amp; path, GStatBuf* statBuffer)
</span><span class="cx"> {
</span><span class="cx">     GUniquePtr&lt;gchar&gt; filename = unescapedFilename(path);
</span><span class="lines">@@ -129,6 +136,12 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool getFileSize(PlatformFileHandle, long long&amp;)
+{
+    notImplemented();
+    return false;
+}
+
</ins><span class="cx"> bool getFileCreationTime(const String&amp;, time_t&amp;)
</span><span class="cx"> {
</span><span class="cx">     // FIXME: Is there a way to retrieve file creation time with Gtk on platforms that support it?
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformposixFileSystemPOSIXcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/posix/FileSystemPOSIX.cpp (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/posix/FileSystemPOSIX.cpp        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebCore/platform/posix/FileSystemPOSIX.cpp        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -71,6 +71,19 @@
</span><span class="cx">     return !unlink(fsRep.data());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool renameFile(const String&amp; oldPath, const String&amp; newPath)
+{
+    CString oldPathFsRep = fileSystemRepresentation(oldPath);
+    if (!oldPathFsRep.data() || oldPathFsRep.data()[0] == '\0')
+        return false;
+
+    CString newPathFsRep = fileSystemRepresentation(newPath);
+    if (!newPathFsRep.data() || newPathFsRep.data()[0] == '\0')
+        return false;
+
+    return !rename(oldPathFsRep.data(), newPathFsRep.data());
+}
+
</ins><span class="cx"> PlatformFileHandle openFile(const String&amp; path, FileOpenMode mode)
</span><span class="cx"> {
</span><span class="cx">     CString fsRep = fileSystemRepresentation(path);
</span><span class="lines">@@ -183,6 +196,16 @@
</span><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool getFileSize(PlatformFileHandle handle, long long&amp; result)
+{
+    struct stat fileInfo;
+    if (fstat(handle, &amp;fileInfo))
+        return false;
+
+    result = fileInfo.st_size;
+    return true;
+}
+
</ins><span class="cx"> bool getFileCreationTime(const String&amp; path, time_t&amp; result)
</span><span class="cx"> {
</span><span class="cx"> #if OS(DARWIN) || OS(OPENBSD) || OS(NETBSD) || OS(FREEBSD)
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformwinFileSystemWincpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/win/FileSystemWin.cpp (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/win/FileSystemWin.cpp        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebCore/platform/win/FileSystemWin.cpp        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -98,6 +98,12 @@
</span><span class="cx">     return getFileSizeFromFindData(findData, size);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool getFileSize(PlatformFileHandle, long long&amp;)
+{
+    notImplemented();
+    return false;
+}
+
</ins><span class="cx"> bool getFileModificationTime(const String&amp; path, time_t&amp; time)
</span><span class="cx"> {
</span><span class="cx">     WIN32_FIND_DATAW findData;
</span><span class="lines">@@ -154,6 +160,12 @@
</span><span class="cx">     return !!RemoveDirectoryW(filename.charactersWithNullTermination().data());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool renameFile(const String&amp;, const String&amp;)
+{
+    notImplemented();
+    return false;
+}
+
</ins><span class="cx"> String pathByAppendingComponent(const String&amp; path, const String&amp; component)
</span><span class="cx"> {
</span><span class="cx">     Vector&lt;UChar&gt; buffer(MAX_PATH);
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebKit2/ChangeLog        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -1,3 +1,93 @@
</span><ins>+2015-03-30  Sam Weinig  &lt;sam@webkit.org&gt;
+
+        [Content Extensions] Flesh out the UserContentExtensionStore
+        https://bugs.webkit.org/show_bug.cgi?id=143123
+
+        Reviewed by Benjamin Poulain.
+
+        * Shared/WebCompiledContentExtension.cpp:
+        (WebKit::WebCompiledContentExtension::createFromCompiledContentExtensionData):
+        * Shared/WebCompiledContentExtensionData.cpp:
+        (WebKit::WebCompiledContentExtensionData::encode):
+        (WebKit::WebCompiledContentExtensionData::decode):
+        * Shared/WebCompiledContentExtensionData.h:
+        (WebKit::WebCompiledContentExtensionData::WebCompiledContentExtensionData):
+        Switch the order in memory of actions and bytecode (and switch the order of the
+        variables as well, to keep it clear). This will become necessary when streaming
+        the data to disk, as actions are created before the bytecode and we would have to keep them
+        in memory until the bytecode was finished compiling if they didn't come before in the file.
+
+        * UIProcess/API/APIUserContentExtensionStore.h:
+        * UIProcess/API/APIUserContentExtensionStore.cpp:
+        (API::UserContentExtensionStore::defaultStore):
+        Add accessor for the processes default shared store.
+
+        (API::constructedPath):
+        Helper for constructing the path to a file in the store based on identifier.
+
+        (API::encodeContentExtensionMetaData):
+        (API::decodeContentExtensionMetaData):
+        Helpers for encoding/decoding the file metadata (version, bytecode size, actions size).
+
+        (API::openAndMapContentExtension):
+        Helper to open and map a filed back content extension.
+
+        (API::writeDataToFile):
+        Helper to write a Data object to a file.
+
+        (API::compiledToFile):
+        Helper to run the content extension compiler and write it to disk. It first
+        writes it to a temporary file and then does an atomic rename operation to put
+        the file in the final location. Doing this means that if the process crashes while
+        the compile is taking place, the partially written file won't end up in the cache, 
+        but rather, will be cleaned up by the OS.

+        (API::UserContentExtensionStore::lookupContentExtension):
+        API entry point to lookup an extension that has been compiled to disk. On a background queue,
+        it attempts to open and map the extension (based on the identifier passed in) and return it
+        to the caller via the callback function passed in.
+        
+        (API::UserContentExtensionStore::compileContentExtension):
+        API entry point to compile an extension and write it to store. On a background queue, it 
+        compiles the file to disk and if successful, returns the memory mapped data via the callback
+        function passed in.
+
+        (API::UserContentExtensionStore::removeContentExtension):
+        API entry point to remove an extension from the store. On a background queue, it 
+        unlinks the extension (based on the identifier passed in) and tells the caller it completed
+        the action vial the callback function passed in.
+
+        (API::UserContentExtensionStore::synchronousRemoveAllContentExtensions):
+        Helper for testing which synchronously unlinks all the files in the store.
+
+        (API::userContentExtensionStoreErrorCategory):
+        std::error_code adaptor for some generic errors that can happen in the store. We will want
+        to flesh these out further.
+
+        * UIProcess/API/Cocoa/APIUserContentExtensionStoreCocoa.mm: Added.
+        (API::UserContentExtensionStore::defaultStorePath):
+        Helper to get the platform specific path for the store.
+
+        * UIProcess/API/C/WKUserContentExtensionStoreRef.cpp:
+        (WKUserContentExtensionStoreGetTypeID):
+        Add ENABLE(CONTENT_EXTENSIONS) guards.
+
+        * UIProcess/API/Cocoa/_WKUserContentExtensionStore.h:
+        * UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm:
+        (-[_WKUserContentExtensionStore dealloc]):
+        (+[_WKUserContentExtensionStore defaultStore]):
+        (-[_WKUserContentExtensionStore compileContentExtensionForIdentifier:encodedContentExtension:completionHandler:]):
+        (-[_WKUserContentExtensionStore lookupContentExtensionForIdentifier:completionHandler:]):
+        (-[_WKUserContentExtensionStore removeContentExtensionForIdentifier:completionHandler:]):
+        (-[_WKUserContentExtensionStore _removeAllContentExtensions]):
+        (-[_WKUserContentExtensionStore init]): Deleted.
+        * UIProcess/API/Cocoa/_WKUserContentExtensionStoreInternal.h:
+        * UIProcess/API/Cocoa/_WKUserContentExtensionStorePrivate.h: Added.
+        SPI wrappers for the store.
+
+        * WebKit2.xcodeproj/project.pbxproj:
+        Add new files.
+
</ins><span class="cx"> 2015-03-30  Antti Koivisto  &lt;antti@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Don't cache resources that are very unlikely to be reused
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedWebCompiledContentExtensioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/WebCompiledContentExtension.cpp (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/WebCompiledContentExtension.cpp        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebKit2/Shared/WebCompiledContentExtension.cpp        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -49,15 +49,15 @@
</span><span class="cx"> Ref&lt;WebCompiledContentExtension&gt; WebCompiledContentExtension::createFromCompiledContentExtensionData(const WebCore::ContentExtensions::CompiledContentExtensionData&amp; compilerData)
</span><span class="cx"> {
</span><span class="cx">     RefPtr&lt;SharedMemory&gt; sharedMemory = SharedMemory::create(compilerData.bytecode.size() + compilerData.actions.size());
</span><del>-    memcpy(static_cast&lt;char*&gt;(sharedMemory-&gt;data()), compilerData.bytecode.data(), compilerData.bytecode.size());
-    memcpy(static_cast&lt;char*&gt;(sharedMemory-&gt;data()) + compilerData.bytecode.size(), compilerData.actions.data(), compilerData.actions.size());
</del><ins>+    memcpy(static_cast&lt;char*&gt;(sharedMemory-&gt;data()), compilerData.actions.data(), compilerData.actions.size());
+    memcpy(static_cast&lt;char*&gt;(sharedMemory-&gt;data()) + compilerData.actions.size(), compilerData.bytecode.data(), compilerData.bytecode.size());
</ins><span class="cx"> 
</span><span class="cx">     WebCompiledContentExtensionData data;
</span><span class="cx">     data.data = WTF::move(sharedMemory);
</span><del>-    data.bytecodeOffset = 0;
</del><ins>+    data.actionsOffset = 0;
+    data.actionsSize = compilerData.actions.size();
+    data.bytecodeOffset = compilerData.actions.size();
</ins><span class="cx">     data.bytecodeSize = compilerData.bytecode.size();
</span><del>-    data.actionsOffset = compilerData.bytecode.size();
-    data.actionsSize = compilerData.actions.size();
</del><span class="cx"> 
</span><span class="cx">     return create(WTF::move(data));
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedWebCompiledContentExtensionDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/WebCompiledContentExtensionData.cpp (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/WebCompiledContentExtensionData.cpp        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebKit2/Shared/WebCompiledContentExtensionData.cpp        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -38,10 +38,10 @@
</span><span class="cx">     data-&gt;createHandle(handle, SharedMemory::ReadOnly);
</span><span class="cx">     encoder &lt;&lt; handle;
</span><span class="cx"> 
</span><del>-    encoder &lt;&lt; bytecodeOffset;
-    encoder &lt;&lt; bytecodeSize;
</del><span class="cx">     encoder &lt;&lt; actionsOffset;
</span><span class="cx">     encoder &lt;&lt; actionsSize;
</span><ins>+    encoder &lt;&lt; bytecodeOffset;
+    encoder &lt;&lt; bytecodeSize;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool WebCompiledContentExtensionData::decode(IPC::ArgumentDecoder&amp; decoder, WebCompiledContentExtensionData&amp; compiledContentExtensionData)
</span><span class="lines">@@ -51,16 +51,15 @@
</span><span class="cx">         return false;
</span><span class="cx">     compiledContentExtensionData.data = SharedMemory::create(handle, SharedMemory::ReadOnly);
</span><span class="cx"> 
</span><del>-    if (!decoder.decode(compiledContentExtensionData.bytecodeOffset))
-        return false;
-    if (!decoder.decode(compiledContentExtensionData.bytecodeSize))
-        return false;
</del><span class="cx">     if (!decoder.decode(compiledContentExtensionData.actionsOffset))
</span><span class="cx">         return false;
</span><span class="cx">     if (!decoder.decode(compiledContentExtensionData.actionsSize))
</span><span class="cx">         return false;
</span><ins>+    if (!decoder.decode(compiledContentExtensionData.bytecodeOffset))
+        return false;
+    if (!decoder.decode(compiledContentExtensionData.bytecodeSize))
+        return false;
</ins><span class="cx"> 
</span><del>-
</del><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedWebCompiledContentExtensionDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/WebCompiledContentExtensionData.h (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/WebCompiledContentExtensionData.h        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebKit2/Shared/WebCompiledContentExtensionData.h        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -44,12 +44,12 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    WebCompiledContentExtensionData(RefPtr&lt;SharedMemory&gt; data, unsigned bytecodeOffset, unsigned bytecodeSize, unsigned actionsOffset, unsigned actionsSize)
</del><ins>+    WebCompiledContentExtensionData(RefPtr&lt;SharedMemory&gt; data, unsigned actionsOffset, unsigned actionsSize, unsigned bytecodeOffset, unsigned bytecodeSize)
</ins><span class="cx">         : data(data)
</span><ins>+        , actionsOffset(actionsOffset)
+        , actionsSize(actionsSize)
</ins><span class="cx">         , bytecodeOffset(bytecodeOffset)
</span><span class="cx">         , bytecodeSize(bytecodeSize)
</span><del>-        , actionsOffset(actionsOffset)
-        , actionsSize(actionsSize)
</del><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -57,10 +57,10 @@
</span><span class="cx">     static bool decode(IPC::ArgumentDecoder&amp;, WebCompiledContentExtensionData&amp;);
</span><span class="cx"> 
</span><span class="cx">     RefPtr&lt;SharedMemory&gt; data;
</span><ins>+    unsigned actionsOffset { 0 };
+    unsigned actionsSize { 0 };
</ins><span class="cx">     unsigned bytecodeOffset { 0 };
</span><span class="cx">     unsigned bytecodeSize { 0 };
</span><del>-    unsigned actionsOffset { 0 };
-    unsigned actionsSize { 0 };
</del><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIAPIUserContentExtensionStorecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.cpp (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.cpp        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.cpp        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -26,14 +26,332 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;APIUserContentExtensionStore.h&quot;
</span><span class="cx"> 
</span><ins>+#if ENABLE(CONTENT_EXTENSIONS)
+
+#include &quot;APIUserContentExtension.h&quot;
+#include &quot;NetworkCacheData.h&quot;
+#include &quot;NetworkCacheDecoder.h&quot;
+#include &quot;NetworkCacheEncoder.h&quot;
+#include &quot;NetworkCacheFileSystemPosix.h&quot;
+#include &quot;SharedMemory.h&quot;
+#include &quot;WebCompiledContentExtension.h&quot;
+#include &lt;WebCore/ContentExtensionCompiler.h&gt;
+#include &lt;WebCore/ContentExtensionError.h&gt;
+#include &lt;string&gt;
+#include &lt;wtf/NeverDestroyed.h&gt;
+#include &lt;wtf/RunLoop.h&gt;
+#include &lt;wtf/WorkQueue.h&gt;
+
+using namespace WebKit::NetworkCache;
+
</ins><span class="cx"> namespace API {
</span><span class="cx"> 
</span><ins>+UserContentExtensionStore&amp; UserContentExtensionStore::defaultStore()
+{
+    static UserContentExtensionStore* defaultStore = adoptRef(new UserContentExtensionStore).leakRef();
+    return *defaultStore;
+}
+
</ins><span class="cx"> UserContentExtensionStore::UserContentExtensionStore()
</span><ins>+    : UserContentExtensionStore(defaultStorePath())
</ins><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+UserContentExtensionStore::UserContentExtensionStore(const WTF::String&amp; storePath)
+    : m_storePath(storePath)
+    , m_compileQueue(WorkQueue::create(&quot;UserContentExtensionStore Compile Queue&quot;, WorkQueue::Type::Concurrent))
+    , m_readQueue(WorkQueue::create(&quot;UserContentExtensionStore Read Queue&quot;))
+    , m_removeQueue(WorkQueue::create(&quot;UserContentExtensionStore Remove Queue&quot;))
+{
+}
+
</ins><span class="cx"> UserContentExtensionStore::~UserContentExtensionStore()
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static String constructedPath(const String&amp; base, const String&amp; identifier)
+{
+    return WebCore::pathByAppendingComponent(base, &quot;ContentExtension-&quot; + WebCore::encodeForFileName(identifier));
+}
+
+struct ContentExtensionMetaData {
+    uint32_t version;
+    uint64_t actionsOffset;
+    uint64_t actionsSize;
+    uint64_t bytecodeOffset;
+    uint64_t bytecodeSize;
+};
+
+static Data encodeContentExtensionMetaData(const ContentExtensionMetaData&amp; metaData)
+{
+    WebKit::NetworkCache::Encoder encoder;
+
+    encoder &lt;&lt; metaData.version;
+    encoder &lt;&lt; metaData.actionsSize;
+    encoder &lt;&lt; metaData.bytecodeSize;
+
+    return Data(encoder.buffer(), encoder.bufferSize());
+}
+
+static bool decodeContentExtensionMetaData(ContentExtensionMetaData&amp; metaData, const Data&amp; fileData)
+{
+    bool success = false;
+    fileData.apply([&amp;metaData, &amp;success, &amp;fileData](const uint8_t* data, size_t size) {
+        // The file data should be mapped into one continuous memory segment so the size
+        // passed to the applier should always equal the data size.
+        if (size != fileData.size())
+            return false;
+
+        WebKit::NetworkCache::Decoder decoder(data, size);
+        if (!decoder.decode(metaData.version))
+            return false;
+        if (!decoder.decode(metaData.actionsSize))
+            return false;
+        if (!decoder.decode(metaData.bytecodeSize))
+            return false;
+        metaData.actionsOffset = decoder.currentOffset();
+        metaData.bytecodeOffset = metaData.actionsOffset + metaData.actionsSize;
+        success = true;
+        return false;
+    });
+    return success;
+}
+
+static bool openAndMapContentExtension(const String&amp; path, ContentExtensionMetaData&amp; metaData, Data&amp; fileData)
+{
+    auto fd = WebCore::openFile(path, WebCore::OpenForRead);
+    if (fd == WebCore::invalidPlatformFileHandle)
+        return false;
+
+    long long fileSize = 0;
+    if (!WebCore::getFileSize(fd, fileSize)) {
+        WebCore::closeFile(fd);
+        return false;
+    }
+
+    fileData = mapFile(fd, 0, static_cast&lt;size_t&gt;(fileSize));
+    WebCore::closeFile(fd);
+
+    if (fileData.isNull())
+        return false;
+
+    if (!decodeContentExtensionMetaData(metaData, fileData))
+        return false;
+
+    return true;
+}
+
+static bool writeDataToFile(Data&amp; fileData, WebCore::PlatformFileHandle fd)
+{
+    bool success = true;
+    fileData.apply([fd, &amp;success](const uint8_t* data, size_t size) {
+        if (WebCore::writeToFile(fd, (const char*)data, size) == -1) {
+            success = false;
+            return false;
+        }
+        return true;
+    });
+    
+    return success;
+}
+
+static std::error_code compiledToFile(const String&amp; json, const String&amp; finalFilePath, ContentExtensionMetaData&amp; metaData, Data&amp; mappedData)
+{
+    using namespace WebCore::ContentExtensions;
+
+    class CompilationClient final : public ContentExtensionCompilationClient {
+    public:
+        CompilationClient(Data&amp; bytecodeData, Data&amp; actionsData)
+            : m_bytecodeData(bytecodeData)
+            , m_actionsData(actionsData)
+        {
+        }
+
+        virtual void writeBytecode(Vector&lt;DFABytecode&gt;&amp;&amp; bytecode) override
+        {
+            m_bytecodeData = Data(bytecode.data(), bytecode.size());
+        }
+
+        virtual void writeActions(Vector&lt;SerializedActionByte&gt;&amp;&amp; actions) override
+        {
+            m_actionsData = Data(actions.data(), actions.size());
+        }
+
+    private:
+        Data&amp; m_bytecodeData;
+        Data&amp; m_actionsData;
+    };
+
+    Data bytecode;
+    Data actions;
+    CompilationClient compilationClient(bytecode, actions);
+
+    // FIXME: This copies the data. Instead, we should be passing an interface
+    // to the compiler that can write directly to a file.
+
+    auto compilerError = compileRuleList(compilationClient, json);
+    if (compilerError)
+        return compilerError;
+
+    auto actionsAndBytecode = concatenate(actions, bytecode);
+
+    metaData.version = 1;
+    metaData.actionsSize = actions.size();
+    metaData.bytecodeSize = bytecode.size();
+
+    auto encodedMetaData = encodeContentExtensionMetaData(metaData);
+
+    metaData.actionsOffset = encodedMetaData.size();
+    metaData.bytecodeOffset = encodedMetaData.size() + metaData.actionsSize;
+
+    auto data = concatenate(encodedMetaData, actionsAndBytecode);
+    auto dataSize = data.size();
+
+    ASSERT(metaData.actionsOffset + metaData.actionsSize + metaData.bytecodeSize == dataSize);
+
+    auto temporaryFileHandle = WebCore::invalidPlatformFileHandle;
+    String temporaryFilePath = WebCore::openTemporaryFile(&quot;ContentExtension&quot;, temporaryFileHandle);
+    if (temporaryFileHandle == WebCore::invalidPlatformFileHandle)
+        return UserContentExtensionStore::Error::CompileFailed;
+
+    if (!writeDataToFile(data, temporaryFileHandle)) {
+        WebCore::closeFile(temporaryFileHandle);
+        return UserContentExtensionStore::Error::CompileFailed;
+    }
+
+    mappedData = mapFile(temporaryFileHandle, 0, dataSize);
+    WebCore::closeFile(temporaryFileHandle);
+
+    if (mappedData.isNull())
+        return UserContentExtensionStore::Error::CompileFailed;
+
+    if (!WebCore::renameFile(temporaryFilePath, finalFilePath))
+        return UserContentExtensionStore::Error::CompileFailed;
+
+    return { };
+}
+
+static RefPtr&lt;API::UserContentExtension&gt; createExtension(const String&amp; identifier, const ContentExtensionMetaData&amp; metaData, const Data&amp; fileData)
+{
+    auto sharedMemory = WebKit::SharedMemory::createFromVMBuffer(const_cast&lt;uint8_t*&gt;(fileData.data()), fileData.size());
+    auto compiledContentExtensionData = WebKit::WebCompiledContentExtensionData(
+        sharedMemory,
+        metaData.actionsOffset,
+        metaData.actionsSize,
+        metaData.bytecodeOffset,
+        metaData.bytecodeSize
+    );
+    auto compiledContentExtension = WebKit::WebCompiledContentExtension::create(WTF::move(compiledContentExtensionData));
+    return API::UserContentExtension::create(identifier, WTF::move(compiledContentExtension));
+}
+
+void UserContentExtensionStore::lookupContentExtension(const WTF::String&amp; identifier, std::function&lt;void(RefPtr&lt;API::UserContentExtension&gt;, std::error_code)&gt; completionHandler)
+{
+    RefPtr&lt;UserContentExtensionStore&gt; self(this);
+    StringCapture identifierCapture(identifier);
+    StringCapture pathCapture(m_storePath);
+
+    m_readQueue-&gt;dispatch([self, identifierCapture, pathCapture, completionHandler] {
+        auto path = constructedPath(pathCapture.string(), identifierCapture.string());
+        
+        ContentExtensionMetaData metaData;
+        Data fileData;
+        if (!openAndMapContentExtension(path, metaData, fileData)) {
+            RunLoop::main().dispatch([self, completionHandler] {
+                completionHandler(nullptr, Error::LookupFailed);
+            });
+            return;
+        }
+        
+        RunLoop::main().dispatch([self, identifierCapture, fileData, metaData, completionHandler] {
+            RefPtr&lt;API::UserContentExtension&gt; userContentExtension = createExtension(identifierCapture.string(), metaData, fileData);
+            completionHandler(userContentExtension, { });
+        });
+    });
+}
+
+void UserContentExtensionStore::compileContentExtension(const WTF::String&amp; identifier, const WTF::String&amp; json, std::function&lt;void(RefPtr&lt;API::UserContentExtension&gt;, std::error_code)&gt; completionHandler)
+{
+    RefPtr&lt;UserContentExtensionStore&gt; self(this);
+    StringCapture identifierCapture(identifier);
+    StringCapture jsonCapture(json);
+    StringCapture pathCapture(m_storePath);
+
+    m_compileQueue-&gt;dispatch([self, identifierCapture, jsonCapture, pathCapture, completionHandler] {
+        auto path = constructedPath(pathCapture.string(), identifierCapture.string());
+
+        ContentExtensionMetaData metaData;
+        Data fileData;
+        auto error = compiledToFile(jsonCapture.string(), path, metaData, fileData);
+        if (error) {
+            RunLoop::main().dispatch([self, error, completionHandler] {
+                completionHandler(nullptr, error);
+            });
+            return;
+        }
+
+        RunLoop::main().dispatch([self, identifierCapture, fileData, metaData, completionHandler] {
+            RefPtr&lt;API::UserContentExtension&gt; userContentExtension = createExtension(identifierCapture.string(), metaData, fileData);
+            completionHandler(userContentExtension, { });
+        });
+    });
+}
+
+void UserContentExtensionStore::removeContentExtension(const WTF::String&amp; identifier, std::function&lt;void(std::error_code)&gt; completionHandler)
+{
+    RefPtr&lt;UserContentExtensionStore&gt; self(this);
+    StringCapture identifierCapture(identifier);
+    StringCapture pathCapture(m_storePath);
+
+    m_removeQueue-&gt;dispatch([self, identifierCapture, pathCapture, completionHandler] {
+        auto path = constructedPath(pathCapture.string(), identifierCapture.string());
+
+        if (!WebCore::deleteFile(path)) {
+            RunLoop::main().dispatch([self, completionHandler] {
+                completionHandler(Error::RemoveFailed);
+            });
+            return;
+        }
+
+        RunLoop::main().dispatch([self, completionHandler] {
+            completionHandler({ });
+        });
+    });
+}
+
+void UserContentExtensionStore::synchronousRemoveAllContentExtensions()
+{
+    for (const auto&amp; path : WebCore::listDirectory(m_storePath, &quot;*&quot;))
+        WebCore::deleteFile(path);
+}
+
+const std::error_category&amp; userContentExtensionStoreErrorCategory()
+{
+    class UserContentExtensionStoreErrorCategory : public std::error_category {
+        const char* name() const noexcept override
+        {
+            return &quot;user content extension store&quot;;
+        }
+
+        virtual std::string message(int errorCode) const override
+        {
+            switch (static_cast&lt;UserContentExtensionStore::Error&gt;(errorCode)) {
+            case UserContentExtensionStore::Error::LookupFailed:
+                return &quot;Unspecified error during lookup.&quot;;
+            case UserContentExtensionStore::Error::CompileFailed:
+                return &quot;Unspecified error during compile.&quot;;
+            case UserContentExtensionStore::Error::RemoveFailed:
+                return &quot;Unspecified error during remove.&quot;;
+            }
+
+            return std::string();
+        }
+    };
+
+    static NeverDestroyed&lt;UserContentExtensionStoreErrorCategory&gt; contentExtensionErrorCategory;
+    return contentExtensionErrorCategory;
+}
+
</ins><span class="cx"> } // namespace API
</span><ins>+
+#endif // ENABLE(CONTENT_EXTENSIONS)
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPIAPIUserContentExtensionStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.h (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.h        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.h        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -26,16 +26,62 @@
</span><span class="cx"> #ifndef APIUserContentExtensionStore_h
</span><span class="cx"> #define APIUserContentExtensionStore_h
</span><span class="cx"> 
</span><ins>+#if ENABLE(CONTENT_EXTENSIONS)
+
</ins><span class="cx"> #include &quot;APIObject.h&quot;
</span><ins>+#include &lt;system_error&gt;
+#include &lt;wtf/text/WTFString.h&gt;
</ins><span class="cx"> 
</span><ins>+namespace WTF {
+class WorkQueue;
+}
+
</ins><span class="cx"> namespace API {
</span><span class="cx"> 
</span><ins>+class UserContentExtension;
+
</ins><span class="cx"> class UserContentExtensionStore final : public ObjectImpl&lt;Object::Type::UserContentExtensionStore&gt; {
</span><span class="cx"> public:
</span><ins>+    enum class Error {
+        LookupFailed = 1,
+        CompileFailed,
+        RemoveFailed
+    };
+
+    static UserContentExtensionStore&amp; defaultStore();
+
</ins><span class="cx">     explicit UserContentExtensionStore();
</span><ins>+    explicit UserContentExtensionStore(const WTF::String&amp; storePath);
</ins><span class="cx">     virtual ~UserContentExtensionStore();
</span><ins>+
+    void compileContentExtension(const WTF::String&amp; identifier, const WTF::String&amp; json, std::function&lt;void(RefPtr&lt;API::UserContentExtension&gt;, std::error_code)&gt;);
+    void lookupContentExtension(const WTF::String&amp; identifier, std::function&lt;void(RefPtr&lt;API::UserContentExtension&gt;, std::error_code)&gt;);
+    void removeContentExtension(const WTF::String&amp; identifier, std::function&lt;void(std::error_code)&gt;);
+
+    // For testing only.
+    void synchronousRemoveAllContentExtensions();
+
+private:
+    WTF::String defaultStorePath();
+
+    const WTF::String m_storePath;
+    Ref&lt;WTF::WorkQueue&gt; m_compileQueue;
+    Ref&lt;WTF::WorkQueue&gt; m_readQueue;
+    Ref&lt;WTF::WorkQueue&gt; m_removeQueue;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><ins>+const std::error_category&amp; userContentExtensionStoreErrorCategory();
+
+inline std::error_code make_error_code(UserContentExtensionStore::Error error)
+{
+    return { static_cast&lt;int&gt;(error), userContentExtensionStoreErrorCategory() };
+}
+
</ins><span class="cx"> } // namespace API
</span><span class="cx"> 
</span><ins>+namespace std {
+    template&lt;&gt; struct is_error_code_enum&lt;API::UserContentExtensionStore::Error&gt; : public true_type { };
+}
+
+#endif // ENABLE(CONTENT_EXTENSIONS)
</ins><span class="cx"> #endif // APIUserContentExtensionStore_h
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICWKUserContentExtensionStoreRefcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/C/WKUserContentExtensionStoreRef.cpp (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/C/WKUserContentExtensionStoreRef.cpp        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebKit2/UIProcess/API/C/WKUserContentExtensionStoreRef.cpp        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -33,5 +33,9 @@
</span><span class="cx"> 
</span><span class="cx"> WKTypeID WKUserContentExtensionStoreGetTypeID()
</span><span class="cx"> {
</span><ins>+#if ENABLE(CONTENT_EXTENSIONS)
</ins><span class="cx">     return toAPI(API::UserContentExtensionStore::APIType);
</span><ins>+#else
+    return 0;
+#endif
</ins><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoaAPIUserContentExtensionStoreCocoammfromrev182160trunkSourceWebKit2UIProcessAPIAPIUserContentExtensionStorecpp"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebKit2/UIProcess/API/Cocoa/APIUserContentExtensionStoreCocoa.mm (from rev 182160, trunk/Source/WebKit2/UIProcess/API/APIUserContentExtensionStore.cpp) (0 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/APIUserContentExtensionStoreCocoa.mm                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/APIUserContentExtensionStoreCocoa.mm        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -0,0 +1,65 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;APIUserContentExtensionStore.h&quot;
+
+#if ENABLE(CONTENT_EXTENSIONS)
+
+#include &quot;SandboxUtilities.h&quot;
+
+namespace API {
+
+String UserContentExtensionStore::defaultStorePath()
+{
+    static dispatch_once_t onceToken;
+    static NSURL *contentExtensionStoreURL;
+
+    dispatch_once(&amp;onceToken, ^{
+        NSURL *url = [[NSFileManager defaultManager] URLForDirectory:NSLibraryDirectory inDomain:NSUserDomainMask appropriateForURL:nullptr create:NO error:nullptr];
+        if (!url)
+            RELEASE_ASSERT_NOT_REACHED();
+
+        url = [url URLByAppendingPathComponent:@&quot;WebKit&quot; isDirectory:YES];
+
+        if (!WebKit::processHasContainer()) {
+            NSString *bundleIdentifier = [NSBundle mainBundle].bundleIdentifier;
+            if (!bundleIdentifier)
+                bundleIdentifier = [NSProcessInfo processInfo].processName;
+            url = [url URLByAppendingPathComponent:bundleIdentifier isDirectory:YES];
+        }
+
+        contentExtensionStoreURL = [[url URLByAppendingPathComponent:@&quot;ContentExtensions&quot; isDirectory:YES] retain];
+    });
+
+    if (![[NSFileManager defaultManager] createDirectoryAtURL:contentExtensionStoreURL withIntermediateDirectories:YES attributes:nil error:nullptr])
+        LOG_ERROR(&quot;Failed to create directory %@&quot;, contentExtensionStoreURL);
+
+    return contentExtensionStoreURL.absoluteURL.path.fileSystemRepresentation;
+}
+
+} // namespace API
+
+#endif // ENABLE(CONTENT_EXTENSIONS)
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoa_WKUserContentExtensionStoreh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.h (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.h        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.h        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -27,9 +27,17 @@
</span><span class="cx"> 
</span><span class="cx"> #if WK_API_ENABLED
</span><span class="cx"> 
</span><ins>+@class _WKUserContentFilter;
+
</ins><span class="cx"> WK_CLASS_AVAILABLE(WK_MAC_TBA, WK_IOS_TBA)
</span><span class="cx"> @interface _WKUserContentExtensionStore : NSObject
</span><span class="cx"> 
</span><ins>++ (instancetype)defaultStore;
+
+- (void)compileContentExtensionForIdentifier:(NSString *)identifier encodedContentExtension:(NSString *)encodedContentExtension completionHandler:(void (^)(_WKUserContentFilter *, NSError *))completionHandler;
+- (void)lookupContentExtensionForIdentifier:(NSString *)identifier completionHandler:(void (^)(_WKUserContentFilter *, NSError *))completionHandler;
+- (void)removeContentExtensionForIdentifier:(NSString *)identifier completionHandler:(void (^)(NSError *))completionHandler;
+
</ins><span class="cx"> @end
</span><span class="cx"> 
</span><span class="cx"> #endif // WK_API_ENABLED
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoa_WKUserContentExtensionStoremm"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.mm        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -28,25 +28,80 @@
</span><span class="cx"> 
</span><span class="cx"> #if WK_API_ENABLED
</span><span class="cx"> 
</span><ins>+#import &quot;WKErrorInternal.h&quot;
+#import &quot;_WKUserContentFilterInternal.h&quot;
+
</ins><span class="cx"> @implementation _WKUserContentExtensionStore
</span><span class="cx"> 
</span><del>-- (instancetype)init
</del><ins>+- (void)dealloc
</ins><span class="cx"> {
</span><del>-    if (!(self = [super init]))
-        return nil;
</del><ins>+    _userContentExtensionStore-&gt;~UserContentExtensionStore();
</ins><span class="cx"> 
</span><del>-    API::Object::constructInWrapper&lt;API::UserContentExtensionStore&gt;(self);
</del><ins>+    [super dealloc];
+}
</ins><span class="cx"> 
</span><del>-    return self;
</del><ins>++ (instancetype)defaultStore
+{
+    return WebKit::wrapper(API::UserContentExtensionStore::defaultStore());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-- (void)dealloc
</del><ins>+- (void)compileContentExtensionForIdentifier:(NSString *)identifier encodedContentExtension:(NSString *)encodedContentExtension completionHandler:(void (^)(_WKUserContentFilter *, NSError *))completionHandler
</ins><span class="cx"> {
</span><del>-    _userContentExtensionStore-&gt;~UserContentExtensionStore();
</del><ins>+    auto handler = adoptNS([completionHandler copy]);
</ins><span class="cx"> 
</span><del>-    [super dealloc];
</del><ins>+    _userContentExtensionStore-&gt;compileContentExtension(identifier, encodedContentExtension, [handler](RefPtr&lt;API::UserContentExtension&gt; contentExtension, std::error_code error) {
+        if (error) {
+            auto rawHandler = (void (^)(_WKUserContentFilter *, NSError *))handler.get();
+            
+            // FIXME: Pass real error.
+            auto error = createNSError(WKErrorUnknown);
+            rawHandler(nil, error.get());
+            return;
+        }
+
+        auto rawHandler = (void (^)(_WKUserContentFilter *, NSError *))handler.get();
+        rawHandler(WebKit::wrapper(*contentExtension.get()), nil);
+    });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+- (void)lookupContentExtensionForIdentifier:(NSString *)identifier completionHandler:(void (^)(_WKUserContentFilter *, NSError *))completionHandler
+{
+    auto handler = adoptNS([completionHandler copy]);
+
+    _userContentExtensionStore-&gt;lookupContentExtension(identifier, [handler](RefPtr&lt;API::UserContentExtension&gt; contentExtension, std::error_code error) {
+        if (error) {
+            auto rawHandler = (void (^)(_WKUserContentFilter *, NSError *))handler.get();
+
+            // FIXME: Pass real error.
+            auto error = createNSError(WKErrorUnknown);
+            rawHandler(nil, error.get());
+            return;
+        }
+
+        auto rawHandler = (void (^)(_WKUserContentFilter *, NSError *))handler.get();
+        rawHandler(WebKit::wrapper(*contentExtension.get()), nil);
+    });
+}
+
+- (void)removeContentExtensionForIdentifier:(NSString *)identifier completionHandler:(void (^)(NSError *))completionHandler
+{
+    auto handler = adoptNS([completionHandler copy]);
+
+    _userContentExtensionStore-&gt;removeContentExtension(identifier, [handler](std::error_code error) {
+        if (error) {
+            auto rawHandler = (void (^)(NSError *))handler.get();
+
+            // FIXME: Pass real error.
+            auto error = createNSError(WKErrorUnknown);
+            rawHandler(error.get());
+            return;
+        }
+
+        auto rawHandler = (void (^)(NSError *))handler.get();
+        rawHandler(nil);
+    });
+}
+
</ins><span class="cx"> #pragma mark WKObject protocol implementation
</span><span class="cx"> 
</span><span class="cx"> - (API::Object&amp;)_apiObject
</span><span class="lines">@@ -56,4 +111,15 @@
</span><span class="cx"> 
</span><span class="cx"> @end
</span><span class="cx"> 
</span><ins>+@implementation _WKUserContentExtensionStore (WKPrivate)
+
+// For testing only.
+
+- (void)_removeAllContentExtensions
+{
+    _userContentExtensionStore-&gt;synchronousRemoveAllContentExtensions();
+}
+
+@end
+
</ins><span class="cx"> #endif // WK_API_ENABLED
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoa_WKUserContentExtensionStoreInternalh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStoreInternal.h (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStoreInternal.h        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStoreInternal.h        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -23,7 +23,7 @@
</span><span class="cx">  * THE POSSIBILITY OF SUCH DAMAGE.
</span><span class="cx">  */
</span><span class="cx"> 
</span><del>-#import &quot;_WKUserContentExtensionStore.h&quot;
</del><ins>+#import &quot;_WKUserContentExtensionStorePrivate.h&quot;
</ins><span class="cx"> 
</span><span class="cx"> #if WK_API_ENABLED
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessAPICocoa_WKUserContentExtensionStorePrivatehfromrev182160trunkSourceWebKit2UIProcessAPICocoa_WKUserContentExtensionStoreh"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStorePrivate.h (from rev 182160, trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStore.h) (0 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStorePrivate.h                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/API/Cocoa/_WKUserContentExtensionStorePrivate.h        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -0,0 +1,37 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import &lt;WebKit/_WKUserContentExtensionStore.h&gt;
+
+#if WK_API_ENABLED
+
+@interface _WKUserContentExtensionStore (WKPrivate)
+
+// For testing only.
+- (void)_removeAllContentExtensions;
+
+@end
+
+#endif
</ins></span></pre></div>
<a id="trunkSourceWebKit2WebKit2xcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Source/WebKit2/WebKit2.xcodeproj/project.pbxproj        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -1138,6 +1138,7 @@
</span><span class="cx">                 7C8EB11718DB6A19007917C2 /* WKPreferencesPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C8EB11618DB6A19007917C2 /* WKPreferencesPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 7C9D1537184584DA009D3918 /* WKBrowsingContextGroupInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C9D1536184584DA009D3918 /* WKBrowsingContextGroupInternal.h */; };
</span><span class="cx">                 7CA254EB182993CE00FC8A41 /* WKBrowsingContextPolicyDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CA254EA182993CE00FC8A41 /* WKBrowsingContextPolicyDelegate.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                7CA3793E1AC378B30079DC37 /* _WKUserContentExtensionStorePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CA3793D1AC378B30079DC37 /* _WKUserContentExtensionStorePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 7CB16FEF1724BA23007A0A95 /* com.apple.ist.ds.appleconnect.webplugin.sb in Copy Plug-in Sandbox Profiles */ = {isa = PBXBuildFile; fileRef = 7CB16FE21724B9B5007A0A95 /* com.apple.ist.ds.appleconnect.webplugin.sb */; };
</span><span class="cx">                 7CB16FF01724BA24007A0A95 /* com.apple.QuickTime Plugin.plugin.sb in Copy Plug-in Sandbox Profiles */ = {isa = PBXBuildFile; fileRef = 7CB16FE31724B9B5007A0A95 /* com.apple.QuickTime Plugin.plugin.sb */; };
</span><span class="cx">                 7CB16FF11724BA26007A0A95 /* com.apple.WebKit.plugin-common.sb in Copy Plug-in Sandbox Profiles */ = {isa = PBXBuildFile; fileRef = 7CB16FE41724B9B5007A0A95 /* com.apple.WebKit.plugin-common.sb */; };
</span><span class="lines">@@ -1169,6 +1170,7 @@
</span><span class="cx">                 7CE4D2201A4914CA00C7F152 /* APIProcessPoolConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CE4D21E1A4914CA00C7F152 /* APIProcessPoolConfiguration.h */; };
</span><span class="cx">                 7CE4D2271A4916C200C7F152 /* WebProcessPoolMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CE4D2251A4916C200C7F152 /* WebProcessPoolMessageReceiver.cpp */; };
</span><span class="cx">                 7CE4D2281A4916C200C7F152 /* WebProcessPoolMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CE4D2261A4916C200C7F152 /* WebProcessPoolMessages.h */; };
</span><ins>+                7CEFA9621AC0999300B910FD /* APIUserContentExtensionStoreCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7CEFA9601AC0999300B910FD /* APIUserContentExtensionStoreCocoa.mm */; };
</ins><span class="cx">                 7CF47FF617275B71008ACB91 /* WKBundlePageBanner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CF47FF417275B71008ACB91 /* WKBundlePageBanner.cpp */; };
</span><span class="cx">                 7CF47FF717275B71008ACB91 /* WKBundlePageBanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CF47FF517275B71008ACB91 /* WKBundlePageBanner.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 7CF47FFB17275C57008ACB91 /* PageBanner.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CF47FF917275C57008ACB91 /* PageBanner.h */; };
</span><span class="lines">@@ -3345,6 +3347,7 @@
</span><span class="cx">                 7C8EB11618DB6A19007917C2 /* WKPreferencesPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKPreferencesPrivate.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7C9D1536184584DA009D3918 /* WKBrowsingContextGroupInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBrowsingContextGroupInternal.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7CA254EA182993CE00FC8A41 /* WKBrowsingContextPolicyDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBrowsingContextPolicyDelegate.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                7CA3793D1AC378B30079DC37 /* _WKUserContentExtensionStorePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKUserContentExtensionStorePrivate.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 7CB16FE21724B9B5007A0A95 /* com.apple.ist.ds.appleconnect.webplugin.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = com.apple.ist.ds.appleconnect.webplugin.sb; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7CB16FE31724B9B5007A0A95 /* com.apple.QuickTime Plugin.plugin.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = &quot;com.apple.QuickTime Plugin.plugin.sb&quot;; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7CB16FE41724B9B5007A0A95 /* com.apple.WebKit.plugin-common.sb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = &quot;com.apple.WebKit.plugin-common.sb&quot;; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -3377,6 +3380,7 @@
</span><span class="cx">                 7CE4D21E1A4914CA00C7F152 /* APIProcessPoolConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = APIProcessPoolConfiguration.h; path = UIProcess/API/APIProcessPoolConfiguration.h; sourceTree = SOURCE_ROOT; };
</span><span class="cx">                 7CE4D2251A4916C200C7F152 /* WebProcessPoolMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebProcessPoolMessageReceiver.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7CE4D2261A4916C200C7F152 /* WebProcessPoolMessages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebProcessPoolMessages.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                7CEFA9601AC0999300B910FD /* APIUserContentExtensionStoreCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = APIUserContentExtensionStoreCocoa.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 7CF47FF417275B71008ACB91 /* WKBundlePageBanner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKBundlePageBanner.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7CF47FF517275B71008ACB91 /* WKBundlePageBanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBundlePageBanner.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7CF47FF917275C57008ACB91 /* PageBanner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PageBanner.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -5343,6 +5347,7 @@
</span><span class="cx">                                 7C2413011AACFA7500A58C15 /* _WKUserContentExtensionStore.h */,
</span><span class="cx">                                 7C2413001AACFA7500A58C15 /* _WKUserContentExtensionStore.mm */,
</span><span class="cx">                                 7C2413041AACFA9C00A58C15 /* _WKUserContentExtensionStoreInternal.h */,
</span><ins>+                                7CA3793D1AC378B30079DC37 /* _WKUserContentExtensionStorePrivate.h */,
</ins><span class="cx">                                 7C89D2B81A6B0F2C003A5FDE /* _WKUserContentFilter.h */,
</span><span class="cx">                                 7C89D2B71A6B0F2C003A5FDE /* _WKUserContentFilter.mm */,
</span><span class="cx">                                 7C89D2BB1A6B0F5B003A5FDE /* _WKUserContentFilterInternal.h */,
</span><span class="lines">@@ -5355,6 +5360,7 @@
</span><span class="cx">                                 75A8D2C4187CCF9F00C39C9E /* _WKWebsiteDataStore.h */,
</span><span class="cx">                                 75A8D2C5187CCF9F00C39C9E /* _WKWebsiteDataStore.mm */,
</span><span class="cx">                                 75A8D2D4187D1C0100C39C9E /* _WKWebsiteDataStoreInternal.h */,
</span><ins>+                                7CEFA9601AC0999300B910FD /* APIUserContentExtensionStoreCocoa.mm */,
</ins><span class="cx">                                 1A3635AB1A3145E500ED6197 /* APIWebsiteDataStoreCocoa.mm */,
</span><span class="cx">                                 1AFDE64319510B5500C48FFA /* LegacyBundleForClass.mm */,
</span><span class="cx">                                 37C4C08B1814AC5C003688B9 /* WKBackForwardList.h */,
</span><span class="lines">@@ -7813,6 +7819,7 @@
</span><span class="cx">                                 BC8780FC1161C2B800CC2768 /* PlatformProcessIdentifier.h in Headers */,
</span><span class="cx">                                 1A6FB7D311E651E200DB1371 /* Plugin.h in Headers */,
</span><span class="cx">                                 31A67E0D165B2A99006CBA66 /* PlugInAutoStartProvider.h in Headers */,
</span><ins>+                                7CA3793E1AC378B30079DC37 /* _WKUserContentExtensionStorePrivate.h in Headers */,
</ins><span class="cx">                                 1A9FBA8D13FF04E600DEED67 /* PluginComplexTextInputState.h in Headers */,
</span><span class="cx">                                 1AA56F2911E92BC80061B882 /* PluginController.h in Headers */,
</span><span class="cx">                                 1A8EF4CB1252403700F7067F /* PluginControllerProxy.h in Headers */,
</span><span class="lines">@@ -9596,6 +9603,7 @@
</span><span class="cx">                                 1A0EC907124C0AB8007EF4A5 /* PluginProcessConnection.cpp in Sources */,
</span><span class="cx">                                 1A0EC910124C0AF5007EF4A5 /* PluginProcessConnectionManager.cpp in Sources */,
</span><span class="cx">                                 1A7865B916CAC71500ACE83A /* PluginProcessConnectionManagerMessageReceiver.cpp in Sources */,
</span><ins>+                                7CEFA9621AC0999300B910FD /* APIUserContentExtensionStoreCocoa.mm in Sources */,
</ins><span class="cx">                                 1A2BB6D014117B4D000F35D4 /* PluginProcessConnectionMessageReceiver.cpp in Sources */,
</span><span class="cx">                                 1A2D90D31281C966001EB962 /* PluginProcessCreationParameters.cpp in Sources */,
</span><span class="cx">                                 1AA4792312A59FD9008236C3 /* PluginProcessMac.mm in Sources */,
</span></span></pre></div>
<a id="trunkToolsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Tools/ChangeLog (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/ChangeLog        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Tools/ChangeLog        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -1,3 +1,14 @@
</span><ins>+2015-03-30  Sam Weinig  &lt;sam@webkit.org&gt;
+
+        [Content Extensions] Flesh out the UserContentExtensionStore
+        https://bugs.webkit.org/show_bug.cgi?id=143123
+
+        Reviewed by Benjamin Poulain.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKit2Cocoa/_WKUserContentExtensionStore.mm: Added.
+        Add tests for _WKUserContentExtensionStore.
+
</ins><span class="cx"> 2015-03-30  Marcos Chavarría Teijeiro  &lt;chavarria1991@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Update install-dependencies Fedora packages after r181624
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestWebKitAPIxcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (182160 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj        2015-03-30 23:01:51 UTC (rev 182160)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -235,6 +235,7 @@
</span><span class="cx">                 7CCE7F4D1A411B9F00447C4C /* RetainPtr.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC029B1B1486B25900817DA9 /* RetainPtr.mm */; };
</span><span class="cx">                 7CCE7F4E1A411BA400447C4C /* RetainPtr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC029B161486AD6400817DA9 /* RetainPtr.cpp */; };
</span><span class="cx">                 7CCE7F4F1A411BA400447C4C /* RetainPtrHashing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C0991C50143C7D68007998F2 /* RetainPtrHashing.cpp */; };
</span><ins>+                7CEFA9661AC0B9E200B910FD /* _WKUserContentExtensionStore.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7CEFA9641AC0B9E200B910FD /* _WKUserContentExtensionStore.mm */; };
</ins><span class="cx">                 7CFBCAE51743238F00B2BFCF /* WillLoad_Bundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7CFBCAE31743238E00B2BFCF /* WillLoad_Bundle.cpp */; };
</span><span class="cx">                 930AD402150698D00067970F /* lots-of-text.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 930AD401150698B30067970F /* lots-of-text.html */; };
</span><span class="cx">                 9361002914DC95A70061379D /* lots-of-iframes.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 9361002814DC957B0061379D /* lots-of-iframes.html */; };
</span><span class="lines">@@ -533,6 +534,7 @@
</span><span class="cx">                 7CC3E1FA197E234100BE6252 /* UserContentController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UserContentController.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7CCE7E8C1A41144E00447C4C /* libTestWebKitAPI.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTestWebKitAPI.a; sourceTree = BUILT_PRODUCTS_DIR; };
</span><span class="cx">                 7CCE7EA31A4115CB00447C4C /* TestWebKitAPILibrary.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = TestWebKitAPILibrary.xcconfig; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                7CEFA9641AC0B9E200B910FD /* _WKUserContentExtensionStore.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKUserContentExtensionStore.mm; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 7CFBCADD1743234F00B2BFCF /* WillLoad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WillLoad.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 7CFBCAE31743238E00B2BFCF /* WillLoad_Bundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WillLoad_Bundle.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 81B50192140F232300D9EB58 /* StringBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StringBuilder.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -805,6 +807,7 @@
</span><span class="cx">                 1ABC3DEC1899BE55004F0626 /* WebKit2 Cocoa */ = {
</span><span class="cx">                         isa = PBXGroup;
</span><span class="cx">                         children = (
</span><ins>+                                7CEFA9641AC0B9E200B910FD /* _WKUserContentExtensionStore.mm */,
</ins><span class="cx">                                 A1A4FE5D18DD3DB700B5EA8A /* Download.mm */,
</span><span class="cx">                                 1ABC3DED1899BE6D004F0626 /* Navigation.mm */,
</span><span class="cx">                                 CEA6CF2219CCF5BD0064F5A7 /* OpenAndCloseWindow.mm */,
</span><span class="lines">@@ -1404,6 +1407,7 @@
</span><span class="cx">                                 7CCE7F231A411AF600447C4C /* Download.mm in Sources */,
</span><span class="cx">                                 7CCE7EEE1A411AE600447C4C /* DownloadDecideDestinationCrash.cpp in Sources */,
</span><span class="cx">                                 7CCE7EBE1A411A7E00447C4C /* DynamicDeviceScaleFactor.mm in Sources */,
</span><ins>+                                7CEFA9661AC0B9E200B910FD /* _WKUserContentExtensionStore.mm in Sources */,
</ins><span class="cx">                                 7CCE7EE01A411A9A00447C4C /* EditorCommands.mm in Sources */,
</span><span class="cx">                                 7CCE7EBF1A411A7E00447C4C /* ElementAtPointInWebFrame.mm in Sources */,
</span><span class="cx">                                 7CCE7EEF1A411AE600447C4C /* EphemeralSessionPushStateNoHistoryCallback.cpp in Sources */,
</span></span></pre></div>
<a id="trunkToolsTestWebKitAPITestsWebKit2Cocoa_WKUserContentExtensionStoremm"></a>
<div class="addfile"><h4>Added: trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/_WKUserContentExtensionStore.mm (0 => 182161)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/_WKUserContentExtensionStore.mm                                (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKit2Cocoa/_WKUserContentExtensionStore.mm        2015-03-30 23:22:09 UTC (rev 182161)
</span><span class="lines">@@ -0,0 +1,143 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#import &quot;config.h&quot;
+#import &lt;WebKit/WKFoundation.h&gt;
+
+#if WK_API_ENABLED
+
+#import &quot;PlatformUtilities.h&quot;
+#import &quot;Test.h&quot;
+#import &lt;WebKit/_WKUserContentExtensionStorePrivate.h&gt;
+#import &lt;WebKit/_WKUserContentFilter.h&gt;
+#import &lt;wtf/RetainPtr.h&gt;
+
+class _WKUserContentExtensionStoreTest : public testing::Test {
+public:
+    virtual void SetUp()
+    {
+        [[_WKUserContentExtensionStore defaultStore] _removeAllContentExtensions];
+    }
+};
+
+static NSString *basicFilter = @&quot;[{\&quot;action\&quot;:{\&quot;type\&quot;:\&quot;block\&quot;},\&quot;trigger\&quot;:{\&quot;url-filter\&quot;:\&quot;.*webkit.org\&quot;}}]&quot;;
+
+TEST_F(_WKUserContentExtensionStoreTest, Compile)
+{
+    __block bool doneCompiling = false;
+    [[_WKUserContentExtensionStore defaultStore] compileContentExtensionForIdentifier:@&quot;TestExtension&quot; encodedContentExtension:basicFilter completionHandler:^(_WKUserContentFilter *filter, NSError *error) {
+    
+        EXPECT_NOT_NULL(filter);
+        EXPECT_NULL(error);
+
+        doneCompiling = true;
+    }];
+    TestWebKitAPI::Util::run(&amp;doneCompiling);
+}
+
+static NSString *invalidFilter = @&quot;[&quot;;
+
+TEST_F(_WKUserContentExtensionStoreTest, InvalidExtension)
+{
+    __block bool doneCompiling = false;
+    [[_WKUserContentExtensionStore defaultStore] compileContentExtensionForIdentifier:@&quot;TestExtension&quot; encodedContentExtension:invalidFilter completionHandler:^(_WKUserContentFilter *filter, NSError *error) {
+    
+        EXPECT_NULL(filter);
+        EXPECT_NOT_NULL(error);
+
+        doneCompiling = true;
+    }];
+    TestWebKitAPI::Util::run(&amp;doneCompiling);
+}
+
+TEST_F(_WKUserContentExtensionStoreTest, Lookup)
+{
+    __block bool doneCompiling = false;
+    [[_WKUserContentExtensionStore defaultStore] compileContentExtensionForIdentifier:@&quot;TestExtension&quot; encodedContentExtension:basicFilter completionHandler:^(_WKUserContentFilter *filter, NSError *error) {
+    
+        EXPECT_NOT_NULL(filter);
+        EXPECT_NULL(error);
+
+        doneCompiling = true;
+    }];
+    TestWebKitAPI::Util::run(&amp;doneCompiling);
+
+    __block bool doneLookingUp = false;
+    [[_WKUserContentExtensionStore defaultStore] lookupContentExtensionForIdentifier:@&quot;TestExtension&quot; completionHandler:^(_WKUserContentFilter *filter, NSError *error) {
+    
+        EXPECT_NOT_NULL(filter);
+        EXPECT_NULL(error);
+
+        doneLookingUp = true;
+    }];
+    TestWebKitAPI::Util::run(&amp;doneLookingUp);
+}
+
+TEST_F(_WKUserContentExtensionStoreTest, NonExistingIdentifierLookup)
+{
+    __block bool doneLookingUp = false;
+    [[_WKUserContentExtensionStore defaultStore] lookupContentExtensionForIdentifier:@&quot;DoesNotExist&quot; completionHandler:^(_WKUserContentFilter *filter, NSError *error) {
+    
+        EXPECT_NULL(filter);
+        EXPECT_NOT_NULL(error);
+
+        doneLookingUp = true;
+    }];
+    TestWebKitAPI::Util::run(&amp;doneLookingUp);
+}
+
+TEST_F(_WKUserContentExtensionStoreTest, Removal)
+{
+    __block bool doneCompiling = false;
+    [[_WKUserContentExtensionStore defaultStore] compileContentExtensionForIdentifier:@&quot;TestExtension&quot; encodedContentExtension:basicFilter completionHandler:^(_WKUserContentFilter *filter, NSError *error) {
+    
+        EXPECT_NOT_NULL(filter);
+        EXPECT_NULL(error);
+
+        doneCompiling = true;
+    }];
+    TestWebKitAPI::Util::run(&amp;doneCompiling);
+
+    __block bool doneRemoving = false;
+    [[_WKUserContentExtensionStore defaultStore] removeContentExtensionForIdentifier:@&quot;TestExtension&quot; completionHandler:^(NSError *error) {
+        EXPECT_NULL(error);
+
+        doneRemoving = true;
+    }];
+    TestWebKitAPI::Util::run(&amp;doneRemoving);
+}
+
+TEST_F(_WKUserContentExtensionStoreTest, NonExistingIdentifierRemove)
+{
+    __block bool doneRemoving = false;
+    [[_WKUserContentExtensionStore defaultStore] removeContentExtensionForIdentifier:@&quot;DoesNotExist&quot; completionHandler:^(NSError *error) {
+        EXPECT_NOT_NULL(error);
+
+        doneRemoving = true;
+    }];
+    TestWebKitAPI::Util::run(&amp;doneRemoving);
+}
+
+#endif
</ins></span></pre>
</div>
</div>

</body>
</html>