<!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>[171661] 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/171661">171661</a></dd>
<dt>Author</dt> <dd>dbates@webkit.org</dd>
<dt>Date</dt> <dd>2014-07-27 16:33:10 -0700 (Sun, 27 Jul 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>[WK2] Crash when accessing window.localStorage after calling window.close()
https://bugs.webkit.org/show_bug.cgi?id=135328
&lt;rdar://problem/17315237&gt;

Reviewed by Sam Weinig.

Source/WebCore:
Fixes an issue where accessing local storage for the first time after calling window.close()
causes a crash.

For now, we should disallow accessing local storage after calling window.close() regardless of
whether it's the first access to local storage as this seems like a bad idiom to support. Note,
this represents a change in behavior from WebKit1. If such usage of window.localStorage turns
out to be reasonable then we can visit this decision again in &lt;https://bugs.webkit.org/show_bug.cgi?id=135330&gt;.

Tests: storage/domstorage/localstorage/access-storage-after-window-close.html
       storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close.html
       storage/domstorage/localstorage/set-value-in-storage-after-window-close.html

* page/DOMWindow.cpp:
(WebCore::DOMWindow::localStorage): Modified to only return the cached local storage or
create a new local storage so long as the page isn't being closed. Also, substitute nullptr
for 0.
(WebCore::DOMWindow::close): Call Page::setIsClosing() to mark that the page is closing.
* page/Page.cpp:
(WebCore::Page::Page): Initialize m_isClosing to false.
* page/Page.h:
(WebCore::Page::setIsClosing): Added.
(WebCore::Page::isClosing): Added.

LayoutTests:
Added test by Andy Estes, LayoutTests/storage/domstorage/localstorage/access-storage-after-window-close.html,
to ensure that we don't crash when accessing local storage for the first time after calling window.close().

Additionally added tests that ensure that updates to local storage are ignored after calling
window.close() regardless of whether local storage was accessed before the call to window.close().

* storage/domstorage/localstorage/access-storage-after-window-close-expected.txt: Added.
* storage/domstorage/localstorage/access-storage-after-window-close.html: Added.
* storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close-expected.txt: Added.
* storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close.html: Added.
* storage/domstorage/localstorage/resources/access-storage-close-window-and-set-value-in-storage.html: Added.
* storage/domstorage/localstorage/resources/close-window-and-access-storage.html: Added.
* storage/domstorage/localstorage/resources/close-window-and-set-value-in-storage.html: Added.
* storage/domstorage/localstorage/set-value-in-storage-after-window-close-expected.txt: Added.
* storage/domstorage/localstorage/set-value-in-storage-after-window-close.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorepageDOMWindowcpp">trunk/Source/WebCore/page/DOMWindow.cpp</a></li>
<li><a href="#trunkSourceWebCorepagePagecpp">trunk/Source/WebCore/page/Page.cpp</a></li>
<li><a href="#trunkSourceWebCorepagePageh">trunk/Source/WebCore/page/Page.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsstoragedomstoragelocalstorageaccessstorageafterwindowcloseexpectedtxt">trunk/LayoutTests/storage/domstorage/localstorage/access-storage-after-window-close-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstoragedomstoragelocalstorageaccessstorageafterwindowclosehtml">trunk/LayoutTests/storage/domstorage/localstorage/access-storage-after-window-close.html</a></li>
<li><a href="#trunkLayoutTestsstoragedomstoragelocalstorageaccessstoragethensetvalueinstorageafterwindowcloseexpectedtxt">trunk/LayoutTests/storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstoragedomstoragelocalstorageaccessstoragethensetvalueinstorageafterwindowclosehtml">trunk/LayoutTests/storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close.html</a></li>
<li><a href="#trunkLayoutTestsstoragedomstoragelocalstorageresourcesaccessstorageclosewindowandsetvalueinstoragehtml">trunk/LayoutTests/storage/domstorage/localstorage/resources/access-storage-close-window-and-set-value-in-storage.html</a></li>
<li><a href="#trunkLayoutTestsstoragedomstoragelocalstorageresourcesclosewindowandaccessstoragehtml">trunk/LayoutTests/storage/domstorage/localstorage/resources/close-window-and-access-storage.html</a></li>
<li><a href="#trunkLayoutTestsstoragedomstoragelocalstorageresourcesclosewindowandsetvalueinstoragehtml">trunk/LayoutTests/storage/domstorage/localstorage/resources/close-window-and-set-value-in-storage.html</a></li>
<li><a href="#trunkLayoutTestsstoragedomstoragelocalstoragesetvalueinstorageafterwindowcloseexpectedtxt">trunk/LayoutTests/storage/domstorage/localstorage/set-value-in-storage-after-window-close-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstoragedomstoragelocalstoragesetvalueinstorageafterwindowclosehtml">trunk/LayoutTests/storage/domstorage/localstorage/set-value-in-storage-after-window-close.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (171660 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-07-27 23:14:40 UTC (rev 171660)
+++ trunk/LayoutTests/ChangeLog        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -1,3 +1,27 @@
</span><ins>+2014-07-27  Daniel Bates  &lt;dabates@apple.com&gt;
+
+        [WK2] Crash when accessing window.localStorage after calling window.close()
+        https://bugs.webkit.org/show_bug.cgi?id=135328
+        &lt;rdar://problem/17315237&gt;
+
+        Reviewed by Sam Weinig.
+
+        Added test by Andy Estes, LayoutTests/storage/domstorage/localstorage/access-storage-after-window-close.html,
+        to ensure that we don't crash when accessing local storage for the first time after calling window.close().
+
+        Additionally added tests that ensure that updates to local storage are ignored after calling
+        window.close() regardless of whether local storage was accessed before the call to window.close().
+
+        * storage/domstorage/localstorage/access-storage-after-window-close-expected.txt: Added.
+        * storage/domstorage/localstorage/access-storage-after-window-close.html: Added.
+        * storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close-expected.txt: Added.
+        * storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close.html: Added.
+        * storage/domstorage/localstorage/resources/access-storage-close-window-and-set-value-in-storage.html: Added.
+        * storage/domstorage/localstorage/resources/close-window-and-access-storage.html: Added.
+        * storage/domstorage/localstorage/resources/close-window-and-set-value-in-storage.html: Added.
+        * storage/domstorage/localstorage/set-value-in-storage-after-window-close-expected.txt: Added.
+        * storage/domstorage/localstorage/set-value-in-storage-after-window-close.html: Added.
+
</ins><span class="cx"> 2014-07-27  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Merge r170090, r170092, r170129, r170141, r170161, r170215, r170275, r170375, r170376, r170382, r170383, r170399, r170436, r170489, r170490, r170556 from ftlopt.
</span></span></pre></div>
<a id="trunkLayoutTestsstoragedomstoragelocalstorageaccessstorageafterwindowcloseexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/domstorage/localstorage/access-storage-after-window-close-expected.txt (0 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/domstorage/localstorage/access-storage-after-window-close-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/domstorage/localstorage/access-storage-after-window-close-expected.txt        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -0,0 +1,2 @@
</span><ins>+Test that WebKit does not crash when accessing localStorage after calling window.close().
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstoragedomstoragelocalstorageaccessstorageafterwindowclosehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/domstorage/localstorage/access-storage-after-window-close.html (0 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/domstorage/localstorage/access-storage-after-window-close.html                                (rev 0)
+++ trunk/LayoutTests/storage/domstorage/localstorage/access-storage-after-window-close.html        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -0,0 +1,14 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;script&gt;
+if (window.testRunner) {
+    testRunner.dumpAsText();
+    testRunner.setCanOpenWindows();
+    testRunner.waitUntilDone();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body onload=&quot;window.open('resources/close-window-and-access-storage.html');&quot;&gt;
+Test that WebKit does not crash when accessing localStorage after calling window.close().&lt;br&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstoragedomstoragelocalstorageaccessstoragethensetvalueinstorageafterwindowcloseexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close-expected.txt (0 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close-expected.txt        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+Tests that we can't store a value in local storage after calling window.close() even if we created the local storage before the call to window.close().
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS window.localStorage is defined.
+PASS window.localStorage[&quot;test&quot;] is undefined.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstoragedomstoragelocalstorageaccessstoragethensetvalueinstorageafterwindowclosehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close.html (0 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close.html                                (rev 0)
+++ trunk/LayoutTests/storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close.html        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+window.jsTestIsAsync = true;
+
+if (window.testRunner) {
+    testRunner.setCanOpenWindows();
+
+    // We explicitly call testRunner.waitUntilDone() because we call window.open() before
+    // js-test-post.js is processed.
+    testRunner.waitUntilDone();
+}
+
+function checkResultAndNotifyDone()
+{
+    shouldBeDefined('window.localStorage');
+    shouldBeUndefined('window.localStorage[&quot;test&quot;]');
+    window.localStorage.clear();
+    finishJSTest();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script&gt;
+description(&quot;Tests that we can't store a value in local storage after calling window.close() even if we created the local storage before the call to window.close().&quot;);
+window.open(&quot;resources/access-storage-close-window-and-set-value-in-storage.html&quot;);
+&lt;/script&gt;
+&lt;script src=&quot;../../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstoragedomstoragelocalstorageresourcesaccessstorageclosewindowandsetvalueinstoragehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/domstorage/localstorage/resources/access-storage-close-window-and-set-value-in-storage.html (0 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/domstorage/localstorage/resources/access-storage-close-window-and-set-value-in-storage.html                                (rev 0)
+++ trunk/LayoutTests/storage/domstorage/localstorage/resources/access-storage-close-window-and-set-value-in-storage.html        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script&gt;
+window.localStorage; // Creates local storage
+window.close();
+if (window.localStorage)
+    localStorage[&quot;test&quot;] = &quot;DidSetValueAfterCallingWindowClose&quot;;
+window.opener.checkResultAndNotifyDone();
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstoragedomstoragelocalstorageresourcesclosewindowandaccessstoragehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/domstorage/localstorage/resources/close-window-and-access-storage.html (0 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/domstorage/localstorage/resources/close-window-and-access-storage.html                                (rev 0)
+++ trunk/LayoutTests/storage/domstorage/localstorage/resources/close-window-and-access-storage.html        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;script&gt;
+window.close();
+window.localStorage;
+if (window.testRunner)
+    testRunner.notifyDone();
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstoragedomstoragelocalstorageresourcesclosewindowandsetvalueinstoragehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/domstorage/localstorage/resources/close-window-and-set-value-in-storage.html (0 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/domstorage/localstorage/resources/close-window-and-set-value-in-storage.html                                (rev 0)
+++ trunk/LayoutTests/storage/domstorage/localstorage/resources/close-window-and-set-value-in-storage.html        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script&gt;
+window.close();
+if (window.localStorage)
+    localStorage[&quot;test&quot;] = &quot;DidSetValueAfterCallingWindowClose&quot;;
+window.opener.checkResultAndNotifyDone();
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstoragedomstoragelocalstoragesetvalueinstorageafterwindowcloseexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/domstorage/localstorage/set-value-in-storage-after-window-close-expected.txt (0 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/domstorage/localstorage/set-value-in-storage-after-window-close-expected.txt                                (rev 0)
+++ trunk/LayoutTests/storage/domstorage/localstorage/set-value-in-storage-after-window-close-expected.txt        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+Tests that we can't store a value in local storage after calling window.close().
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS window.localStorage is defined.
+PASS window.localStorage[&quot;test&quot;] is undefined.
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstoragedomstoragelocalstoragesetvalueinstorageafterwindowclosehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/storage/domstorage/localstorage/set-value-in-storage-after-window-close.html (0 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/storage/domstorage/localstorage/set-value-in-storage-after-window-close.html                                (rev 0)
+++ trunk/LayoutTests/storage/domstorage/localstorage/set-value-in-storage-after-window-close.html        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -0,0 +1,31 @@
</span><ins>+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script&gt;
+window.jsTestIsAsync = true;
+
+if (window.testRunner) {
+    testRunner.setCanOpenWindows();
+
+    // We explicitly call testRunner.waitUntilDone() because we call window.open() before
+    // js-test-post.js is processed.
+    testRunner.waitUntilDone();
+}
+
+function checkResultAndNotifyDone()
+{
+    shouldBeDefined('window.localStorage');
+    shouldBeUndefined('window.localStorage[&quot;test&quot;]');
+    window.localStorage.clear();
+    finishJSTest();
+}
+&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script&gt;
+description(&quot;Tests that we can't store a value in local storage after calling window.close().&quot;);
+window.open(&quot;resources/close-window-and-set-value-in-storage.html&quot;);
+&lt;/script&gt;
+&lt;script src=&quot;../../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (171660 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-07-27 23:14:40 UTC (rev 171660)
+++ trunk/Source/WebCore/ChangeLog        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2014-07-27  Daniel Bates  &lt;dabates@apple.com&gt;
+
+        [WK2] Crash when accessing window.localStorage after calling window.close()
+        https://bugs.webkit.org/show_bug.cgi?id=135328
+        &lt;rdar://problem/17315237&gt;
+
+        Reviewed by Sam Weinig.
+
+        Fixes an issue where accessing local storage for the first time after calling window.close()
+        causes a crash.
+
+        For now, we should disallow accessing local storage after calling window.close() regardless of
+        whether it's the first access to local storage as this seems like a bad idiom to support. Note,
+        this represents a change in behavior from WebKit1. If such usage of window.localStorage turns
+        out to be reasonable then we can visit this decision again in &lt;https://bugs.webkit.org/show_bug.cgi?id=135330&gt;.
+
+        Tests: storage/domstorage/localstorage/access-storage-after-window-close.html
+               storage/domstorage/localstorage/access-storage-then-set-value-in-storage-after-window-close.html
+               storage/domstorage/localstorage/set-value-in-storage-after-window-close.html
+
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::localStorage): Modified to only return the cached local storage or
+        create a new local storage so long as the page isn't being closed. Also, substitute nullptr
+        for 0.
+        (WebCore::DOMWindow::close): Call Page::setIsClosing() to mark that the page is closing.
+        * page/Page.cpp:
+        (WebCore::Page::Page): Initialize m_isClosing to false.
+        * page/Page.h:
+        (WebCore::Page::setIsClosing): Added.
+        (WebCore::Page::isClosing): Added.
+
</ins><span class="cx"> 2014-07-27  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Merge r170090, r170092, r170129, r170141, r170161, r170215, r170275, r170375, r170376, r170382, r170383, r170399, r170436, r170489, r170490, r170556 from ftlopt.
</span></span></pre></div>
<a id="trunkSourceWebCorepageDOMWindowcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/DOMWindow.cpp (171660 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/DOMWindow.cpp        2014-07-27 23:14:40 UTC (rev 171660)
+++ trunk/Source/WebCore/page/DOMWindow.cpp        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -821,31 +821,38 @@
</span><span class="cx"> Storage* DOMWindow::localStorage(ExceptionCode&amp; ec) const
</span><span class="cx"> {
</span><span class="cx">     if (!isCurrentlyDisplayedInFrame())
</span><del>-        return 0;
</del><ins>+        return nullptr;
</ins><span class="cx"> 
</span><span class="cx">     Document* document = this-&gt;document();
</span><span class="cx">     if (!document)
</span><del>-        return 0;
</del><ins>+        return nullptr;
</ins><span class="cx"> 
</span><span class="cx">     if (!document-&gt;securityOrigin()-&gt;canAccessLocalStorage(0)) {
</span><span class="cx">         ec = SECURITY_ERR;
</span><del>-        return 0;
</del><ins>+        return nullptr;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    if (m_localStorage) {
-        if (!m_localStorage-&gt;area().canAccessStorage(m_frame)) {
-            ec = SECURITY_ERR;
-            return 0;
</del><ins>+    Page* page = document-&gt;page();
+    // FIXME: We should consider supporting access/modification to local storage
+    // after calling window.close(). See &lt;https://bugs.webkit.org/show_bug.cgi?id=135330&gt;.
+    if (!page || !page-&gt;isClosing()) {
+        if (m_localStorage) {
+            if (!m_localStorage-&gt;area().canAccessStorage(m_frame)) {
+                ec = SECURITY_ERR;
+                return nullptr;
+            }
+            return m_localStorage.get();
</ins><span class="cx">         }
</span><del>-        return m_localStorage.get();
</del><span class="cx">     }
</span><span class="cx"> 
</span><del>-    Page* page = document-&gt;page();
</del><span class="cx">     if (!page)
</span><del>-        return 0;
</del><ins>+        return nullptr;
</ins><span class="cx"> 
</span><ins>+    if (page-&gt;isClosing())
+        return nullptr;
+
</ins><span class="cx">     if (!page-&gt;settings().localStorageEnabled())
</span><del>-        return 0;
</del><ins>+        return nullptr;
</ins><span class="cx"> 
</span><span class="cx">     RefPtr&lt;StorageArea&gt; storageArea;
</span><span class="cx">     if (!document-&gt;securityOrigin()-&gt;canAccessLocalStorage(document-&gt;topOrigin()))
</span><span class="lines">@@ -855,7 +862,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (!storageArea-&gt;canAccessStorage(m_frame)) {
</span><span class="cx">         ec = SECURITY_ERR;
</span><del>-        return 0;
</del><ins>+        return nullptr;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     m_localStorage = Storage::create(m_frame, storageArea.release());
</span><span class="lines">@@ -1035,6 +1042,7 @@
</span><span class="cx">     if (!m_frame-&gt;loader().shouldClose())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><ins>+    page-&gt;setIsClosing();
</ins><span class="cx">     page-&gt;chrome().closeWindowSoon();
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorepagePagecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Page.cpp (171660 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Page.cpp        2014-07-27 23:14:40 UTC (rev 171660)
+++ trunk/Source/WebCore/page/Page.cpp        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -201,6 +201,7 @@
</span><span class="cx">     , m_userContentController(WTF::move(pageClients.userContentController))
</span><span class="cx">     , m_visitedLinkStore(WTF::move(pageClients.visitedLinkStore))
</span><span class="cx">     , m_sessionID(SessionID::defaultSessionID())
</span><ins>+    , m_isClosing(false)
</ins><span class="cx"> {
</span><span class="cx">     ASSERT(m_editorClient);
</span><span class="cx">     
</span></span></pre></div>
<a id="trunkSourceWebCorepagePageh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/page/Page.h (171660 => 171661)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/page/Page.h        2014-07-27 23:14:40 UTC (rev 171660)
+++ trunk/Source/WebCore/page/Page.h        2014-07-27 23:33:10 UTC (rev 171661)
</span><span class="lines">@@ -320,6 +320,9 @@
</span><span class="cx">     void setIsInWindow(bool);
</span><span class="cx">     bool isInWindow() const { return m_viewState &amp; ViewState::IsInWindow; }
</span><span class="cx"> 
</span><ins>+    void setIsClosing() { m_isClosing = true; }
+    bool isClosing() const { return m_isClosing; }
+
</ins><span class="cx">     void addViewStateChangeObserver(ViewStateChangeObserver&amp;);
</span><span class="cx">     void removeViewStateChangeObserver(ViewStateChangeObserver&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -585,6 +588,8 @@
</span><span class="cx">     HashSet&lt;ViewStateChangeObserver*&gt; m_viewStateChangeObservers;
</span><span class="cx"> 
</span><span class="cx">     SessionID m_sessionID;
</span><ins>+
+    bool m_isClosing;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> inline PageGroup&amp; Page::group()
</span></span></pre>
</div>
</div>

</body>
</html>