Changeset 232318 in webkit


Ignore:
Timestamp:
May 30, 2018 4:42:36 PM (6 years ago)
Author:
dbates@webkit.org
Message:

Web Inspector: Annotate Same-Site cookies
https://bugs.webkit.org/show_bug.cgi?id=184897
<rdar://problem/35178209>

Reviewed by Brian Burg.

Source/JavaScriptCore:

Update protocol to include cookie Same-Site policy.

  • inspector/protocol/Page.json:

Source/WebCore:

Store and retrieve the Same-Site cookie policy from CFNetwork.

  • inspector/agents/InspectorPageAgent.cpp:

(WebCore::cookieSameSitePolicyJSON): Added.
(WebCore::buildObjectForCookie): Modified to include cookie Same-Site policy.

  • platform/Cookie.h:

(WebCore::Cookie::encode const): Encode Same-Site policy.
(WebCore::Cookie::decode): Decode Same-Site policy.

  • platform/network/cocoa/CookieCocoa.mm:

(WebCore::portStringFromVector):
(WebCore::coreSameSitePolicy):
(WebCore::nsSameSitePolicy):
(WebCore::Cookie::operator NSHTTPCookie * _Nullable const):
(WebCore::Cookie::operator NSHTTPCookie * const): Deleted.

Source/WebInspectorUI:

Add a new column for the value of the Same-Site cookie attribute to the resource cookie content
view (shown for a resource under the Network tab) and cookie storage content view (shown under
the Storage tab).

The SameSite column in the resource cookie content view reflects the parsing of the Same-Site
attribute from the HTTP response by Web Inspector. This parsing is materially consistent with
the parsing of the SameSite atttribute in CFNetwork. The Same-Site column in the cookie storage
content view reflects the Same-Site cookie policy associated with the cookies provided by the
network stack, if supported. This column will be blank on systems whose network stack does not
support Same-Site cookies (e.g libsoup).

  • Localizations/en.lproj/localizedStrings.js:
  • UserInterface/Controllers/HARBuilder.js:

(WI.HARBuilder.cookies):

  • UserInterface/Models/Cookie.js:

(WI.Cookie):
(WI.Cookie.displayNameForSameSiteType):
(WI.Cookie.parseSameSiteAttributeValue):
(WI.Cookie.parseSetCookieResponseHeader):

  • UserInterface/Views/CookieStorageContentView.js:

(WI.CookieStorageContentView.prototype._rebuildTable):
(WI.CookieStorageContentView.prototype._sortDataGrid):

  • UserInterface/Views/ResourceCookiesContentView.js:

(WI.ResourceCookiesContentView.prototype.tablePopulateCell):
(WI.ResourceCookiesContentView.prototype._generateSortComparator):
(WI.ResourceCookiesContentView.prototype._refreshResponseCookiesSection):

LayoutTests:

Update an existing test to ensure we include cookie details in the HTTP Archive (HAR) report.

  • http/tests/inspector/network/har/har-page-expected.txt:
  • http/tests/inspector/network/har/har-page.html:
Location:
trunk
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r232317 r232318  
     12018-05-30  Daniel Bates  <dabates@apple.com>
     2
     3        Web Inspector: Annotate Same-Site cookies
     4        https://bugs.webkit.org/show_bug.cgi?id=184897
     5        <rdar://problem/35178209>
     6
     7        Reviewed by Brian Burg.
     8
     9        Update an existing test to ensure we include cookie details in the HTTP Archive (HAR) report.
     10
     11        * http/tests/inspector/network/har/har-page-expected.txt:
     12        * http/tests/inspector/network/har/har-page.html:
     13
    1142018-05-30  John Wilander  <wilander@apple.com>
    215
  • trunk/LayoutTests/http/tests/inspector/network/har/har-page-expected.txt

    r231391 r232318  
    104104          "receive": "<filtered>"
    105105        }
     106      },
     107      {
     108        "pageref": "page_0",
     109        "startedDateTime": "<filtered>",
     110        "time": "<filtered>",
     111        "request": {
     112          "method": "GET",
     113          "url": "http://127.0.0.1:8000/cookies/resources/cookie-utilities.js",
     114          "httpVersion": "<filtered>",
     115          "cookies": [],
     116          "headers": "<filtered>",
     117          "queryString": [],
     118          "headersSize": "<filtered>",
     119          "bodySize": "<filtered>"
     120        },
     121        "response": {
     122          "status": 200,
     123          "statusText": "OK",
     124          "httpVersion": "<filtered>",
     125          "cookies": [],
     126          "headers": "<filtered>",
     127          "content": {
     128            "size": "<filtered>",
     129            "compression": 0,
     130            "mimeType": "application/x-javascript",
     131            "text": "<filtered>"
     132          },
     133          "redirectURL": "",
     134          "headersSize": "<filtered>",
     135          "bodySize": "<filtered>"
     136        },
     137        "cache": {},
     138        "timings": {
     139          "blocked": "<filtered>",
     140          "dns": "<filtered>",
     141          "connect": "<filtered>",
     142          "ssl": -1,
     143          "send": "<filtered>",
     144          "wait": "<filtered>",
     145          "receive": "<filtered>"
     146        }
     147      },
     148      {
     149        "pageref": "page_0",
     150        "startedDateTime": "<filtered>",
     151        "time": "<filtered>",
     152        "request": {
     153          "method": "GET",
     154          "url": "http://127.0.0.1:8000/cookies/resources/setCookies.cgi",
     155          "httpVersion": "<filtered>",
     156          "cookies": [],
     157          "headers": "<filtered>",
     158          "queryString": [],
     159          "headersSize": "<filtered>",
     160          "bodySize": "<filtered>"
     161        },
     162        "response": {
     163          "status": 200,
     164          "statusText": "OK",
     165          "httpVersion": "<filtered>",
     166          "cookies": [
     167            {
     168              "name": "simple",
     169              "value": "simple",
     170              "expires": "",
     171              "httpOnly": false,
     172              "secure": false
     173            }
     174          ],
     175          "headers": "<filtered>",
     176          "content": {
     177            "size": "<filtered>",
     178            "compression": 0,
     179            "mimeType": "text/plain"
     180          },
     181          "redirectURL": "",
     182          "headersSize": "<filtered>",
     183          "bodySize": "<filtered>"
     184        },
     185        "cache": {},
     186        "timings": {
     187          "blocked": "<filtered>",
     188          "dns": "<filtered>",
     189          "connect": "<filtered>",
     190          "ssl": -1,
     191          "send": "<filtered>",
     192          "wait": "<filtered>",
     193          "receive": "<filtered>"
     194        }
     195      },
     196      {
     197        "pageref": "page_0",
     198        "startedDateTime": "<filtered>",
     199        "time": "<filtered>",
     200        "request": {
     201          "method": "GET",
     202          "url": "http://127.0.0.1:8000/cookies/resources/setCookies.cgi",
     203          "httpVersion": "<filtered>",
     204          "cookies": [
     205            {
     206              "name": "simple",
     207              "value": "simple"
     208            }
     209          ],
     210          "headers": "<filtered>",
     211          "queryString": [],
     212          "headersSize": "<filtered>",
     213          "bodySize": "<filtered>"
     214        },
     215        "response": {
     216          "status": 200,
     217          "statusText": "OK",
     218          "httpVersion": "<filtered>",
     219          "cookies": [
     220            {
     221              "name": "path",
     222              "value": "path",
     223              "path": "/A/B/C",
     224              "expires": "",
     225              "httpOnly": false,
     226              "secure": false
     227            }
     228          ],
     229          "headers": "<filtered>",
     230          "content": {
     231            "size": "<filtered>",
     232            "compression": 0,
     233            "mimeType": "text/plain"
     234          },
     235          "redirectURL": "",
     236          "headersSize": "<filtered>",
     237          "bodySize": "<filtered>"
     238        },
     239        "cache": {},
     240        "timings": {
     241          "blocked": "<filtered>",
     242          "dns": "<filtered>",
     243          "connect": "<filtered>",
     244          "ssl": -1,
     245          "send": "<filtered>",
     246          "wait": "<filtered>",
     247          "receive": "<filtered>"
     248        }
     249      },
     250      {
     251        "pageref": "page_0",
     252        "startedDateTime": "<filtered>",
     253        "time": "<filtered>",
     254        "request": {
     255          "method": "GET",
     256          "url": "http://127.0.0.1:8000/cookies/resources/setCookies.cgi",
     257          "httpVersion": "<filtered>",
     258          "cookies": [
     259            {
     260              "name": "simple",
     261              "value": "simple"
     262            }
     263          ],
     264          "headers": "<filtered>",
     265          "queryString": [],
     266          "headersSize": "<filtered>",
     267          "bodySize": "<filtered>"
     268        },
     269        "response": {
     270          "status": 200,
     271          "statusText": "OK",
     272          "httpVersion": "<filtered>",
     273          "cookies": [
     274            {
     275              "name": "secure",
     276              "value": "secure",
     277              "expires": "",
     278              "httpOnly": false,
     279              "secure": true
     280            }
     281          ],
     282          "headers": "<filtered>",
     283          "content": {
     284            "size": "<filtered>",
     285            "compression": 0,
     286            "mimeType": "text/plain"
     287          },
     288          "redirectURL": "",
     289          "headersSize": "<filtered>",
     290          "bodySize": "<filtered>"
     291        },
     292        "cache": {},
     293        "timings": {
     294          "blocked": "<filtered>",
     295          "dns": "<filtered>",
     296          "connect": "<filtered>",
     297          "ssl": -1,
     298          "send": "<filtered>",
     299          "wait": "<filtered>",
     300          "receive": "<filtered>"
     301        }
     302      },
     303      {
     304        "pageref": "page_0",
     305        "startedDateTime": "<filtered>",
     306        "time": "<filtered>",
     307        "request": {
     308          "method": "GET",
     309          "url": "http://127.0.0.1:8000/cookies/resources/setCookies.cgi",
     310          "httpVersion": "<filtered>",
     311          "cookies": [
     312            {
     313              "name": "simple",
     314              "value": "simple"
     315            }
     316          ],
     317          "headers": "<filtered>",
     318          "queryString": [],
     319          "headersSize": "<filtered>",
     320          "bodySize": "<filtered>"
     321        },
     322        "response": {
     323          "status": 200,
     324          "statusText": "OK",
     325          "httpVersion": "<filtered>",
     326          "cookies": [
     327            {
     328              "name": "secure-and-http-only",
     329              "value": "secure-and-http-only",
     330              "expires": "",
     331              "httpOnly": true,
     332              "secure": true
     333            }
     334          ],
     335          "headers": "<filtered>",
     336          "content": {
     337            "size": "<filtered>",
     338            "compression": 0,
     339            "mimeType": "text/plain"
     340          },
     341          "redirectURL": "",
     342          "headersSize": "<filtered>",
     343          "bodySize": "<filtered>"
     344        },
     345        "cache": {},
     346        "timings": {
     347          "blocked": "<filtered>",
     348          "dns": "<filtered>",
     349          "connect": "<filtered>",
     350          "ssl": -1,
     351          "send": "<filtered>",
     352          "wait": "<filtered>",
     353          "receive": "<filtered>"
     354        }
     355      },
     356      {
     357        "pageref": "page_0",
     358        "startedDateTime": "<filtered>",
     359        "time": "<filtered>",
     360        "request": {
     361          "method": "GET",
     362          "url": "http://127.0.0.1:8000/cookies/resources/setCookies.cgi",
     363          "httpVersion": "<filtered>",
     364          "cookies": [
     365            {
     366              "name": "simple",
     367              "value": "simple"
     368            }
     369          ],
     370          "headers": "<filtered>",
     371          "queryString": [],
     372          "headersSize": "<filtered>",
     373          "bodySize": "<filtered>"
     374        },
     375        "response": {
     376          "status": 200,
     377          "statusText": "OK",
     378          "httpVersion": "<filtered>",
     379          "cookies": [
     380            {
     381              "name": "with-expiration",
     382              "value": "with-expiration",
     383              "expires": "5000-01-04T08:00:00.000Z",
     384              "httpOnly": false,
     385              "secure": false
     386            }
     387          ],
     388          "headers": "<filtered>",
     389          "content": {
     390            "size": "<filtered>",
     391            "compression": 0,
     392            "mimeType": "text/plain"
     393          },
     394          "redirectURL": "",
     395          "headersSize": "<filtered>",
     396          "bodySize": "<filtered>"
     397        },
     398        "cache": {},
     399        "timings": {
     400          "blocked": "<filtered>",
     401          "dns": "<filtered>",
     402          "connect": "<filtered>",
     403          "ssl": -1,
     404          "send": "<filtered>",
     405          "wait": "<filtered>",
     406          "receive": "<filtered>"
     407        }
     408      },
     409      {
     410        "pageref": "page_0",
     411        "startedDateTime": "<filtered>",
     412        "time": "<filtered>",
     413        "request": {
     414          "method": "GET",
     415          "url": "http://127.0.0.1:8000/cookies/resources/setCookies.cgi",
     416          "httpVersion": "<filtered>",
     417          "cookies": [
     418            {
     419              "name": "simple",
     420              "value": "simple"
     421            },
     422            {
     423              "name": "with-expiration",
     424              "value": "with-expiration"
     425            }
     426          ],
     427          "headers": "<filtered>",
     428          "queryString": [],
     429          "headersSize": "<filtered>",
     430          "bodySize": "<filtered>"
     431        },
     432        "response": {
     433          "status": 200,
     434          "statusText": "OK",
     435          "httpVersion": "<filtered>",
     436          "cookies": [
     437            {
     438              "name": "http-only",
     439              "value": "http-only",
     440              "expires": "",
     441              "httpOnly": true,
     442              "secure": false
     443            }
     444          ],
     445          "headers": "<filtered>",
     446          "content": {
     447            "size": "<filtered>",
     448            "compression": 0,
     449            "mimeType": "text/plain"
     450          },
     451          "redirectURL": "",
     452          "headersSize": "<filtered>",
     453          "bodySize": "<filtered>"
     454        },
     455        "cache": {},
     456        "timings": {
     457          "blocked": "<filtered>",
     458          "dns": "<filtered>",
     459          "connect": "<filtered>",
     460          "ssl": -1,
     461          "send": "<filtered>",
     462          "wait": "<filtered>",
     463          "receive": "<filtered>"
     464        }
     465      },
     466      {
     467        "pageref": "page_0",
     468        "startedDateTime": "<filtered>",
     469        "time": "<filtered>",
     470        "request": {
     471          "method": "GET",
     472          "url": "http://127.0.0.1:8000/cookies/resources/setCookies.cgi",
     473          "httpVersion": "<filtered>",
     474          "cookies": [
     475            {
     476              "name": "http-only",
     477              "value": "http-only"
     478            },
     479            {
     480              "name": "simple",
     481              "value": "simple"
     482            },
     483            {
     484              "name": "with-expiration",
     485              "value": "with-expiration"
     486            }
     487          ],
     488          "headers": "<filtered>",
     489          "queryString": [],
     490          "headersSize": "<filtered>",
     491          "bodySize": "<filtered>"
     492        },
     493        "response": {
     494          "status": 200,
     495          "statusText": "OK",
     496          "httpVersion": "<filtered>",
     497          "cookies": [
     498            {
     499              "name": "same-site-strict",
     500              "value": "same-site-strict",
     501              "path": "/",
     502              "expires": "",
     503              "httpOnly": false,
     504              "secure": false,
     505              "sameSite": "Strict"
     506            }
     507          ],
     508          "headers": "<filtered>",
     509          "content": {
     510            "size": "<filtered>",
     511            "compression": 0,
     512            "mimeType": "text/plain"
     513          },
     514          "redirectURL": "",
     515          "headersSize": "<filtered>",
     516          "bodySize": "<filtered>"
     517        },
     518        "cache": {},
     519        "timings": {
     520          "blocked": "<filtered>",
     521          "dns": "<filtered>",
     522          "connect": "<filtered>",
     523          "ssl": -1,
     524          "send": "<filtered>",
     525          "wait": "<filtered>",
     526          "receive": "<filtered>"
     527        }
     528      },
     529      {
     530        "pageref": "page_0",
     531        "startedDateTime": "<filtered>",
     532        "time": "<filtered>",
     533        "request": {
     534          "method": "GET",
     535          "url": "http://127.0.0.1:8000/cookies/resources/setCookies.cgi",
     536          "httpVersion": "<filtered>",
     537          "cookies": [
     538            {
     539              "name": "http-only",
     540              "value": "http-only"
     541            },
     542            {
     543              "name": "simple",
     544              "value": "simple"
     545            },
     546            {
     547              "name": "with-expiration",
     548              "value": "with-expiration"
     549            },
     550            {
     551              "name": "same-site-strict",
     552              "value": "same-site-strict"
     553            }
     554          ],
     555          "headers": "<filtered>",
     556          "queryString": [],
     557          "headersSize": "<filtered>",
     558          "bodySize": "<filtered>"
     559        },
     560        "response": {
     561          "status": 200,
     562          "statusText": "OK",
     563          "httpVersion": "<filtered>",
     564          "cookies": [
     565            {
     566              "name": "same-site-implicit-strict",
     567              "value": "same-site-implicit-strict",
     568              "path": "/",
     569              "expires": "",
     570              "httpOnly": false,
     571              "secure": false,
     572              "sameSite": "Strict"
     573            }
     574          ],
     575          "headers": "<filtered>",
     576          "content": {
     577            "size": "<filtered>",
     578            "compression": 0,
     579            "mimeType": "text/plain"
     580          },
     581          "redirectURL": "",
     582          "headersSize": "<filtered>",
     583          "bodySize": "<filtered>"
     584        },
     585        "cache": {},
     586        "timings": {
     587          "blocked": "<filtered>",
     588          "dns": "<filtered>",
     589          "connect": "<filtered>",
     590          "ssl": -1,
     591          "send": "<filtered>",
     592          "wait": "<filtered>",
     593          "receive": "<filtered>"
     594        }
     595      },
     596      {
     597        "pageref": "page_0",
     598        "startedDateTime": "<filtered>",
     599        "time": "<filtered>",
     600        "request": {
     601          "method": "GET",
     602          "url": "http://127.0.0.1:8000/cookies/resources/setCookies.cgi",
     603          "httpVersion": "<filtered>",
     604          "cookies": [
     605            {
     606              "name": "http-only",
     607              "value": "http-only"
     608            },
     609            {
     610              "name": "simple",
     611              "value": "simple"
     612            },
     613            {
     614              "name": "with-expiration",
     615              "value": "with-expiration"
     616            },
     617            {
     618              "name": "same-site-implicit-strict",
     619              "value": "same-site-implicit-strict"
     620            },
     621            {
     622              "name": "same-site-strict",
     623              "value": "same-site-strict"
     624            }
     625          ],
     626          "headers": "<filtered>",
     627          "queryString": [],
     628          "headersSize": "<filtered>",
     629          "bodySize": "<filtered>"
     630        },
     631        "response": {
     632          "status": 200,
     633          "statusText": "OK",
     634          "httpVersion": "<filtered>",
     635          "cookies": [
     636            {
     637              "name": "same-site-strict-because-invalid-SameSite-value",
     638              "value": "same-site-strict-because-invalid-SameSite-value",
     639              "path": "/",
     640              "expires": "",
     641              "httpOnly": false,
     642              "secure": false,
     643              "sameSite": "Strict"
     644            }
     645          ],
     646          "headers": "<filtered>",
     647          "content": {
     648            "size": "<filtered>",
     649            "compression": 0,
     650            "mimeType": "text/plain"
     651          },
     652          "redirectURL": "",
     653          "headersSize": "<filtered>",
     654          "bodySize": "<filtered>"
     655        },
     656        "cache": {},
     657        "timings": {
     658          "blocked": "<filtered>",
     659          "dns": "<filtered>",
     660          "connect": "<filtered>",
     661          "ssl": -1,
     662          "send": "<filtered>",
     663          "wait": "<filtered>",
     664          "receive": "<filtered>"
     665        }
     666      },
     667      {
     668        "pageref": "page_0",
     669        "startedDateTime": "<filtered>",
     670        "time": "<filtered>",
     671        "request": {
     672          "method": "GET",
     673          "url": "http://127.0.0.1:8000/cookies/resources/setCookies.cgi",
     674          "httpVersion": "<filtered>",
     675          "cookies": [
     676            {
     677              "name": "http-only",
     678              "value": "http-only"
     679            },
     680            {
     681              "name": "simple",
     682              "value": "simple"
     683            },
     684            {
     685              "name": "with-expiration",
     686              "value": "with-expiration"
     687            },
     688            {
     689              "name": "same-site-implicit-strict",
     690              "value": "same-site-implicit-strict"
     691            },
     692            {
     693              "name": "same-site-strict",
     694              "value": "same-site-strict"
     695            },
     696            {
     697              "name": "same-site-strict-because-invalid-SameSite-value",
     698              "value": "same-site-strict-because-invalid-SameSite-value"
     699            }
     700          ],
     701          "headers": "<filtered>",
     702          "queryString": [],
     703          "headersSize": "<filtered>",
     704          "bodySize": "<filtered>"
     705        },
     706        "response": {
     707          "status": 200,
     708          "statusText": "OK",
     709          "httpVersion": "<filtered>",
     710          "cookies": [
     711            {
     712              "name": "same-site-lax",
     713              "value": "same-site-lax",
     714              "path": "/",
     715              "expires": "",
     716              "httpOnly": false,
     717              "secure": false,
     718              "sameSite": "Lax"
     719            }
     720          ],
     721          "headers": "<filtered>",
     722          "content": {
     723            "size": "<filtered>",
     724            "compression": 0,
     725            "mimeType": "text/plain"
     726          },
     727          "redirectURL": "",
     728          "headersSize": "<filtered>",
     729          "bodySize": "<filtered>"
     730        },
     731        "cache": {},
     732        "timings": {
     733          "blocked": "<filtered>",
     734          "dns": "<filtered>",
     735          "connect": "<filtered>",
     736          "ssl": -1,
     737          "send": "<filtered>",
     738          "wait": "<filtered>",
     739          "receive": "<filtered>"
     740        }
    106741      }
    107742    ]
  • trunk/LayoutTests/http/tests/inspector/network/har/har-page.html

    r231391 r232318  
    44<meta charset="utf-8">
    55<script src="../../resources/inspector-test.js"></script>
     6<script src="../../../cookies/resources/cookie-utilities.js"></script>
    67<script>
    78function test()
     
    5051        }
    5152
     53        // Sort cookies by name to make cookie order deterministic between test runs.
     54        if (key === "cookies")
     55            value.sort((a, b) => { return a.name - b.name; });
     56
    5257        // Since cache may or may not be used, timing data may be variable.
    5358        // NOTE: SSL should always be -1 for this test case.
     
    7883            InspectorTest.reloadPage({ignoreCache: true});
    7984            await InspectorTest.awaitEvent("LoadComplete");
     85            InspectorTest.evaluateInPage("setup()");
     86            await InspectorTest.awaitEvent("SetupComplete");
    8087
    8188            let resources = [WI.frameResourceManager.mainFrame.mainResource, ...WI.frameResourceManager.mainFrame.resourceCollection];
    8289            let har = await WI.HARBuilder.buildArchive(resources);
    8390            InspectorTest.json(har, HARJSONFilter);
     91            InspectorTest.evaluateInPage("cleanup()");
     92            await InspectorTest.awaitEvent("CleanComplete");
    8493        }
    8594    });
     
    92101<p>HAR Page Test.</p>
    93102<script>
     103async function setup()
     104{
     105    await resetCookies();
     106    await setCookie("simple", "simple");
     107    await setCookie("path", "path", {"path": "/A/B/C"}); // This cookie will not be sent in subsequent requests from this page.
     108
     109    // Secure cookies will only be sent in subsequent requests from this page if the page was served over HTTPS.
     110    await setCookie("secure", "secure", {"secure": null});
     111    await setCookie("secure-and-http-only", "secure-and-http-only", {"secure": null, "HttpOnly": null});
     112
     113    await setCookie("with-expiration", "with-expiration", {"Expires": new Date("01/04/5000").toGMTString()});
     114    await setCookie("http-only", "http-only", {"HttpOnly": null});
     115    await setCookie("same-site-strict", "same-site-strict", {"SameSite": "Strict", "path": "/"});
     116    await setCookie("same-site-implicit-strict", "same-site-implicit-strict", {"SameSite": null, "path": "/"});
     117    await setCookie("same-site-strict-because-invalid-SameSite-value", "same-site-strict-because-invalid-SameSite-value", {"SameSite": "invalid", "path": "/"});
     118    await setCookie("same-site-lax", "same-site-lax", {"SameSite": "Lax", "path": "/"});
     119    TestPage.dispatchEventToFrontend("SetupComplete");
     120}
     121
     122async function cleanup()
     123{
     124    await resetCookies();
     125    TestPage.dispatchEventToFrontend("CleanComplete");
     126}
     127
    94128window.addEventListener("load", () => {
    95129    TestPage.dispatchEventToFrontend("LoadComplete");
  • trunk/Source/JavaScriptCore/ChangeLog

    r232314 r232318  
     12018-05-30  Daniel Bates  <dabates@apple.com>
     2
     3        Web Inspector: Annotate Same-Site cookies
     4        https://bugs.webkit.org/show_bug.cgi?id=184897
     5        <rdar://problem/35178209>
     6
     7        Reviewed by Brian Burg.
     8
     9        Update protocol to include cookie Same-Site policy.
     10
     11        * inspector/protocol/Page.json:
     12
    1132018-05-29  Keith Miller  <keith_miller@apple.com>
    214
  • trunk/Source/JavaScriptCore/inspector/protocol/Page.json

    r231881 r232318  
    1515            "enum": ["Viewport", "Page"],
    1616            "description": "Coordinate system used by supplied coordinates."
     17        },
     18        {
     19            "id": "CookieSameSitePolicy",
     20            "type": "string",
     21            "enum": ["None", "Lax", "Strict"],
     22            "description": "Same-Site policy of a cookie."
    1723        },
    1824        {
     
    7783                { "name": "httpOnly", "type": "boolean", "description": "True if cookie is http-only." },
    7884                { "name": "secure", "type": "boolean", "description": "True if cookie is secure." },
    79                 { "name": "session", "type": "boolean", "description": "True in case of session cookie." }
     85                { "name": "session", "type": "boolean", "description": "True in case of session cookie." },
     86                { "name": "sameSite", "$ref": "CookieSameSitePolicy", "description": "Cookie Same-Site policy." }
    8087            ]
    8188        }
  • trunk/Source/WebCore/ChangeLog

    r232316 r232318  
     12018-05-30  Daniel Bates  <dabates@apple.com>
     2
     3        Web Inspector: Annotate Same-Site cookies
     4        https://bugs.webkit.org/show_bug.cgi?id=184897
     5        <rdar://problem/35178209>
     6
     7        Reviewed by Brian Burg.
     8
     9        Store and retrieve the Same-Site cookie policy from CFNetwork.
     10
     11        * inspector/agents/InspectorPageAgent.cpp:
     12        (WebCore::cookieSameSitePolicyJSON): Added.
     13        (WebCore::buildObjectForCookie): Modified to include cookie Same-Site policy.
     14        * platform/Cookie.h:
     15        (WebCore::Cookie::encode const): Encode Same-Site policy.
     16        (WebCore::Cookie::decode): Decode Same-Site policy.
     17        * platform/network/cocoa/CookieCocoa.mm:
     18        (WebCore::portStringFromVector):
     19        (WebCore::coreSameSitePolicy):
     20        (WebCore::nsSameSitePolicy):
     21        (WebCore::Cookie::operator NSHTTPCookie * _Nullable  const):
     22        (WebCore::Cookie::operator NSHTTPCookie * const): Deleted.
     23
    1242018-05-30  Daniel Bates  <dabates@apple.com>
    225
  • trunk/Source/WebCore/inspector/agents/InspectorPageAgent.cpp

    r232278 r232318  
    337337}
    338338
     339static Inspector::Protocol::Page::CookieSameSitePolicy cookieSameSitePolicyJSON(Cookie::SameSitePolicy policy)
     340{
     341    switch (policy) {
     342    case Cookie::SameSitePolicy::None:
     343        return Inspector::Protocol::Page::CookieSameSitePolicy::None;
     344    case Cookie::SameSitePolicy::Lax:
     345        return Inspector::Protocol::Page::CookieSameSitePolicy::Lax;
     346    case Cookie::SameSitePolicy::Strict:
     347        return Inspector::Protocol::Page::CookieSameSitePolicy::Strict;
     348    }
     349    ASSERT_NOT_REACHED();
     350    return Inspector::Protocol::Page::CookieSameSitePolicy::None;
     351}
     352
    339353static Ref<Inspector::Protocol::Page::Cookie> buildObjectForCookie(const Cookie& cookie)
    340354{
     
    349363        .setSecure(cookie.secure)
    350364        .setSession(cookie.session)
     365        .setSameSite(cookieSameSitePolicyJSON(cookie.sameSite))
    351366        .release();
    352367}
  • trunk/Source/WebCore/platform/Cookie.h

    r231859 r232318  
    11/*
    22 * Copyright (C) 2009 Joseph Pecoraro. All rights reserved.
    3  * Copyright (C) 2017 Apple Inc. All rights reserved.
     3 * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
    44 *
    55 * Redistribution and use in source and binary forms, with or without
     
    2828
    2929#include "URL.h"
     30#include <wtf/EnumTraits.h>
    3031#include <wtf/text/StringHash.h>
    3132#include <wtf/text/WTFString.h>
     
    8687    URL commentURL;
    8788    Vector<uint16_t> ports;
     89
     90    enum class SameSitePolicy { None, Lax, Strict };
     91    SameSitePolicy sameSite { SameSitePolicy::None };
    8892};
    8993
     
    116120    encoder << commentURL;
    117121    encoder << ports;
     122    encoder << sameSite;
    118123}
    119124
     
    146151    if (!decoder.decode(cookie.ports))
    147152        return std::nullopt;
     153    if (!decoder.decode(cookie.sameSite))
     154        return std::nullopt;
    148155    return cookie;
    149156}
     
    161168        static bool isDeletedValue(const WebCore::Cookie& slot) { return slot.name.isHashTableDeletedValue(); }
    162169    };
     170    template<> struct EnumTraits<WebCore::Cookie::SameSitePolicy> {
     171    using values = EnumValues<
     172        WebCore::Cookie::SameSitePolicy,
     173        WebCore::Cookie::SameSitePolicy::None,
     174        WebCore::Cookie::SameSitePolicy::Lax,
     175        WebCore::Cookie::SameSitePolicy::Strict
     176    >;
     177};
    163178}
  • trunk/Source/WebCore/platform/network/cocoa/CookieCocoa.mm

    r232191 r232318  
    2727#import "Cookie.h"
    2828
     29// FIXME: Remove NS_ASSUME_NONNULL_BEGIN/END and all _Nullable annotations once we remove the NSHTTPCookie forward declaration below.
     30NS_ASSUME_NONNULL_BEGIN
     31
     32#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400 && __MAC_OS_X_VERSION_MAX_ALLOWED < 101500) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000 && __IPHONE_OS_VERSION_MAX_ALLOWED < 130000)
     33typedef NSString * NSHTTPCookieStringPolicy;
     34@interface NSHTTPCookie (Staging)
     35@property (nullable, readonly, copy) NSHTTPCookieStringPolicy sameSitePolicy;
     36@end
     37
     38static NSString * const NSHTTPCookieSameSiteLax = @"lax";
     39static NSString * const NSHTTPCookieSameSiteStrict = @"strict";
     40#endif
     41
    2942namespace WebCore {
    3043
     
    4053}
    4154
    42 static NSString *portStringFromVector(const Vector<uint16_t>& ports)
     55static NSString * _Nullable portStringFromVector(const Vector<uint16_t>& ports)
    4356{
    4457    if (ports.isEmpty())
     
    7184    return 0;
    7285}
     86
     87#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000)
     88static Cookie::SameSitePolicy coreSameSitePolicy(NSHTTPCookieStringPolicy _Nullable policy)
     89{
     90    if (!policy)
     91        return Cookie::SameSitePolicy::None;
     92    if ([policy isEqualToString:NSHTTPCookieSameSiteLax])
     93        return Cookie::SameSitePolicy::Lax;
     94    if ([policy isEqualToString:NSHTTPCookieSameSiteStrict])
     95        return Cookie::SameSitePolicy::Strict;
     96    ASSERT_NOT_REACHED();
     97    return Cookie::SameSitePolicy::None;
     98}
     99
     100static NSHTTPCookieStringPolicy _Nullable nsSameSitePolicy(Cookie::SameSitePolicy policy)
     101{
     102    switch (policy) {
     103    case Cookie::SameSitePolicy::None:
     104        return nil;
     105    case Cookie::SameSitePolicy::Lax:
     106        return NSHTTPCookieSameSiteLax;
     107    case Cookie::SameSitePolicy::Strict:
     108        return NSHTTPCookieSameSiteStrict;
     109    }
     110}
     111#endif
    73112
    74113Cookie::Cookie(NSHTTPCookie *cookie)
     
    86125    , ports { portVectorFromList(cookie.portList) }
    87126{
    88 }
    89 
    90 Cookie::operator NSHTTPCookie *() const
     127#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000)
     128    if ([cookie respondsToSelector:@selector(sameSitePolicy)])
     129        sameSite = coreSameSitePolicy(cookie.sameSitePolicy);
     130#endif
     131}
     132
     133Cookie::operator NSHTTPCookie * _Nullable () const
    91134{
    92135    if (isNull())
    93136        return nil;
    94137
    95     NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithCapacity:13];
     138    NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithCapacity:14];
    96139
    97140    if (!comment.isNull())
     
    134177    if (httpOnly)
    135178        [properties setObject:@YES forKey:@"HttpOnly"];
     179
     180#if (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400) || (PLATFORM(IOS) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 120000)
     181    if (auto* sameSitePolicy = nsSameSitePolicy(sameSite))
     182        [properties setObject:sameSitePolicy forKey:@"SameSite"];
     183#endif
    136184
    137185    [properties setObject:@"1" forKey:NSHTTPCookieVersion];
     
    157205}
    158206
     207NS_ASSUME_NONNULL_END
     208
    159209} // namespace WebCore
  • trunk/Source/WebInspectorUI/ChangeLog

    r232189 r232318  
     12018-05-30  Daniel Bates  <dabates@apple.com>
     2
     3        Web Inspector: Annotate Same-Site cookies
     4        https://bugs.webkit.org/show_bug.cgi?id=184897
     5        <rdar://problem/35178209>
     6
     7        Reviewed by Brian Burg.
     8
     9        Add a new column for the value of the Same-Site cookie attribute to the resource cookie content
     10        view (shown for a resource under the Network tab) and cookie storage content view (shown under
     11        the Storage tab).
     12
     13        The SameSite column in the resource cookie content view reflects the parsing of the Same-Site
     14        attribute from the HTTP response by Web Inspector. This parsing is materially consistent with
     15        the parsing of the SameSite atttribute in CFNetwork. The Same-Site column in the cookie storage
     16        content view reflects the Same-Site cookie policy associated with the cookies provided by the
     17        network stack, if supported. This column will be blank on systems whose network stack does not
     18        support Same-Site cookies (e.g libsoup).
     19
     20        * Localizations/en.lproj/localizedStrings.js:
     21        * UserInterface/Controllers/HARBuilder.js:
     22        (WI.HARBuilder.cookies):
     23        * UserInterface/Models/Cookie.js:
     24        (WI.Cookie):
     25        (WI.Cookie.displayNameForSameSiteType):
     26        (WI.Cookie.parseSameSiteAttributeValue):
     27        (WI.Cookie.parseSetCookieResponseHeader):
     28        * UserInterface/Views/CookieStorageContentView.js:
     29        (WI.CookieStorageContentView.prototype._rebuildTable):
     30        (WI.CookieStorageContentView.prototype._sortDataGrid):
     31        * UserInterface/Views/ResourceCookiesContentView.js:
     32        (WI.ResourceCookiesContentView.prototype.tablePopulateCell):
     33        (WI.ResourceCookiesContentView.prototype._generateSortComparator):
     34        (WI.ResourceCookiesContentView.prototype._refreshResponseCookiesSection):
     35
    1362018-05-25  Matt Baker  <mattbaker@apple.com>
    237
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r231981 r232318  
    812812localizedStrings["Role"] = "Role";
    813813localizedStrings["Rule"] = "Rule";
     814localizedStrings["Same-Site"] = "Same-Site";
    814815localizedStrings["Samples"] = "Samples";
    815816localizedStrings["Save File"] = "Save File";
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/HARBuilder.js

    r224357 r232318  
    11/*
    2  * Copyright (C) 2017 Apple Inc. All rights reserved.
     2 * Copyright (C) 2017-2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    178178                json.httpOnly = cookie.httpOnly;
    179179                json.secure = cookie.secure;
     180                if (cookie.sameSite !== WI.Cookie.SameSiteType.None)
     181                    json.sameSite = cookie.sameSite;
    180182            }
    181183
  • trunk/Source/WebInspectorUI/UserInterface/Models/Cookie.js

    r223856 r232318  
    2626WI.Cookie = class Cookie
    2727{
    28     constructor(type, name, value, raw, expires, maxAge, path, domain, secure, httpOnly)
     28    constructor(type, name, value, raw, expires, maxAge, path, domain, secure, httpOnly, sameSite)
    2929    {
    3030        console.assert(Object.values(WI.Cookie.Type).includes(type));
     
    3838        console.assert(!secure || typeof secure === "boolean");
    3939        console.assert(!httpOnly || typeof httpOnly === "boolean");
     40        console.assert(!sameSite || Object.values(WI.Cookie.SameSiteType).includes(sameSite));
    4041
    4142        this.type = type;
     
    5152            this.secure = secure || false;
    5253            this.httpOnly = httpOnly || false;
     54            this.sameSite = sameSite || WI.Cookie.SameSiteType.None;
    5355        }
    5456    }
     
    100102    }
    101103
     104    static displayNameForSameSiteType(sameSiteType)
     105    {
     106        switch (sameSiteType) {
     107        case WI.Cookie.SameSiteType.None:
     108            return WI.unlocalizedString("None");
     109        case WI.Cookie.SameSiteType.Lax:
     110            return WI.unlocalizedString("Lax");
     111        case WI.Cookie.SameSiteType.Strict:
     112            return WI.unlocalizedString("Strict");
     113        default:
     114            console.error("Invalid SameSite type", sameSiteType);
     115            return sameSiteType;
     116        }
     117    }
     118
     119    // Derived from <https://tools.ietf.org/html/draft-west-first-party-cookies-06#section-3.2>.
     120    static parseSameSiteAttributeValue(attributeValue)
     121    {
     122        if (!attributeValue)
     123            return WI.Cookie.SameSiteType.Strict;
     124        switch (attributeValue.toLowerCase()) {
     125        case "lax":
     126            return WI.Cookie.SameSiteType.Lax;
     127        case "strict":
     128        default:
     129            return WI.Cookie.SameSiteType.Strict;
     130        }
     131    }
     132
    102133    static parseSetCookieResponseHeader(header)
    103134    {
     
    123154        let secure = false;
    124155        let httpOnly = false;
     156        let sameSite = WI.Cookie.SameSiteType.None;
    125157
    126158        // Parse Attributes
     
    172204                httpOnly = true;
    173205                break;
     206            case "samesite":
     207                sameSite = WI.Cookie.parseSameSiteAttributeValue(attributeValue);
     208                break;
    174209            default:
    175210                console.warn("Unknown Cookie attribute:", attribute);
     
    178213        }
    179214
    180         return new WI.Cookie(WI.Cookie.Type.Response, name, value, header, expires, maxAge, path, domain, secure, httpOnly);
     215        return new WI.Cookie(WI.Cookie.Type.Response, name, value, header, expires, maxAge, path, domain, secure, httpOnly, sameSite);
    181216    }
    182217}
     
    186221    Response: "response",
    187222};
     223
     224// Keep these in sync with the "CookieSameSitePolicy" enum defined by the "Page" domain.
     225WI.Cookie.SameSiteType = {
     226    None: "None",
     227    Lax: "Lax",
     228    Strict: "Strict",
     229};
  • trunk/Source/WebInspectorUI/UserInterface/Views/CookieStorageContentView.js

    r231391 r232318  
    11/*
    2  * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2015, 2018 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    7474        // FIXME <https://webkit.org/b/151400>: If there are no cookies, add placeholder explanatory text.
    7575        if (!this._dataGrid) {
    76             var columns = {name: {}, value: {}, domain: {}, path: {}, expires: {}, size: {}, http: {}, secure: {}};
     76            var columns = {name: {}, value: {}, domain: {}, path: {}, expires: {}, size: {}, http: {}, secure: {}, sameSite: {} };
    7777
    7878            columns.name.title = WI.UIString("Name");
     
    8888            columns.domain.title = WI.UIString("Domain");
    8989            columns.domain.sortable = true;
    90             columns.domain.width = "7%";
     90            columns.domain.width = "6%";
    9191
    9292            columns.path.title = WI.UIString("Path");
    9393            columns.path.sortable = true;
    94             columns.path.width = "7%";
     94            columns.path.width = "6%";
    9595
    9696            columns.expires.title = WI.UIString("Expires");
    9797            columns.expires.sortable = true;
    98             columns.expires.width = "7%";
     98            columns.expires.width = "6%";
    9999
    100100            columns.size.title = WI.UIString("Size");
    101101            columns.size.aligned = "right";
    102102            columns.size.sortable = true;
    103             columns.size.width = "7%";
     103            columns.size.width = "6%";
    104104
    105105            columns.http.title = WI.UIString("HTTP");
    106106            columns.http.aligned = "centered";
    107107            columns.http.sortable = true;
    108             columns.http.width = "7%";
     108            columns.http.width = "6%";
    109109
    110110            columns.secure.title = WI.UIString("Secure");
    111111            columns.secure.aligned = "centered";
    112112            columns.secure.sortable = true;
    113             columns.secure.width = "7%";
     113            columns.secure.width = "6%";
     114
     115            columns.sameSite.title = WI.UIString("Same-Site");
     116            columns.sameSite.sortable = true;
     117            columns.sameSite.width = "6%";
    114118
    115119            this._dataGrid = new WI.DataGrid(columns, null, this._deleteCallback.bind(this));
     
    126130        this._dataGrid.removeChildren();
    127131
    128         for (var cookie of this._cookies) {
     132        for (let cookie of this._cookies) {
    129133            const checkmark = "\u2713";
    130134            var data = {
     
    137141                http: cookie.httpOnly ? checkmark : "",
    138142                secure: cookie.secure ? checkmark : "",
     143                sameSite: cookie.sameSite ? WI.Cookie.displayNameForSameSiteType(WI.Cookie.parseSameSiteAttributeValue(cookie.sameSite)) : "",
    139144            };
    140145
     
    204209            case "http": comparator = localeCompare.bind(this, "http"); break;
    205210            case "secure": comparator = localeCompare.bind(this, "secure"); break;
     211            case "sameSite": comparator = localeCompare.bind(this, "sameSite"); break;
    206212            case "name":
    207213            default: comparator = localeCompare.bind(this, "name"); break;
  • trunk/Source/WebInspectorUI/UserInterface/Views/ResourceCookiesContentView.js

    r223308 r232318  
    9090            cell.textContent = cookie.httpOnly ? checkmark : zeroWidthSpace;
    9191            break;
     92        case "sameSite":
     93            cell.textContent = cookie.sameSite === WI.Cookie.SameSiteType.None ? emDash : WI.Cookie.displayNameForSameSiteType(cookie.sameSite);
     94            break;
    9295        }
    9396
     
    147150        case "domain":
    148151        case "path":
     152        case "sameSite":
    149153            // String.
    150154            comparator = (a, b) => (a[sortColumnIdentifier] || "").extendedLocaleCompare(b[sortColumnIdentifier] || "");
     
    249253            this._responseCookiesTable.addColumn(new WI.TableColumn("secure", WI.unlocalizedString("Secure"), {minWidth: 55, maxWidth: 65, align: "center"}));
    250254            this._responseCookiesTable.addColumn(new WI.TableColumn("httpOnly", WI.unlocalizedString("HttpOnly"), {minWidth: 55, maxWidth: 65, align: "center"}));
     255            this._responseCookiesTable.addColumn(new WI.TableColumn("sameSite", WI.unlocalizedString("SameSite"), {minWidth: 55, maxWidth: 65}));
    251256            if (!this._responseCookiesTable.sortColumnIdentifier) {
    252257                this._responseCookiesTable.sortOrder = WI.Table.SortOrder.Ascending;
Note: See TracChangeset for help on using the changeset viewer.